Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] [newbie] General help needed here.....

There was a discussion around this issue:
   http://dev.eclipse.org/mhonarc/lists/aspectj-users/msg01536.html

The suggestion was to introduce the - wildcard to capture supertypes including the type itself (just exactly opposed of the + wildcard). I think the refactoring use case is quite important to consider. I will like to see a way to define a statically-determinable pointcut that captures exactly the same join points as "execution(* method(..)) && this(Type)". While this form itself may be deemed statically determinable, I think the form using - wildcard, "execution(* Type-.method(..))", is clearer (and easy to teach).

On a related note:

The - wildcard would solve yet another use case described in:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=34054#c2

I could define the loggedOperations() pointcut as follows (see Note 3 is the same comment for context of this issue).

pointcut loggedOperations()
   : (execution(* *.*(..)) || execution(*.new(..)))
&& !within(MyAspect-);
-Ramnivas


Ron Bodkin wrote:

... But there is a difference between the join points picked out by

execution(* Type.method(..)) and
 execution(* method(..)) && this(Type)

Can you explain the situations where they would differ?
Naturally, and I almost raised this as another benefit of the dynamic test. Consider:

class Base { void method() }
class Derived extends Base {}

The dynamic test execution(* method()) && this(Derived) pick out executions of method on instances of Derived, but the static test execution(* Derived.method()) won't. It's a rare case (so I didn't mention it) but if someone does write execution(* Derived.method()) they are likely to be confused on the difference between using static declaring type and the dynamic instance of the class in question. Even worse, AspectJ 1.2's lint warnings don't catch this case to say it isn't matching. (yes, you could use the static form in declare warning/error for something that shouldn't be overridden, but that's much less common).
for new users it's helpful to get in the mindset of using this to specify types instead of doing it in the method
signature,
instead of trying to remember that using declaring types with call is
problematic and using them with execution is ok
I'm sorry but I have to disagree, if I may.
We'll have to agree to disagree.

The right way to think about it is stated in the programming guide:
a pointcut signature matches a join point signature.  Users, new
and experienced, will find it much easier if they follow this model
rather than the rule "always use a dynamic test and avoid specifying the type," (particularly since that rule violates the rule "given two pointcuts that match the same join points, prefer the static form").
I don't agree with this latter rule, not when it conflicts with robust pointcuts that are most likely to remain accurate as the system evolve, which really comes down to writing the most natural expression of the pointcut. In general, this will mean matching based on dynamic types rather than static definition properties. In our specific example, if you use a pull up refactoring to move method from Derived to a new intermediate superclass, then the test based on the dynamic type remains correct, and the test based on static signatures breaks.

Another reason I prefer using the dynamic form for the execution pointcut is parallelism between writing call and execution pointcuts. Since it is normal to use the dynamic form for calls, it's more natural to use a similar construct for execution.

Here, the issue turns on the difference between call and execution,
which is to say the difference between the join point signature
for call and execution. The type in the method-call signature is the compile-time type of reference being used to make the call.
Which hasn't always been intuitive (Javac for 1.3 and earlier would generate bytecode that called using the type of the base class).

The type in method-execution is the declaring type of the method
(which might not be the defining type).  Understanding that gives
the developer the answer to this issue, even if they forget all else.
And following this procedure, of mentally matching the pointcut
signature to the join point signature, will work for *any* signature-based pointcut (even in AOP systems yet-to-come). It does mean users have to learn what the join point signatures are. The AspectJ pointcut language is clear enough that users can jump in and start to write code based on their guesses about what's happening, so they (unfortunately?) get pretty far before their guesses don't work. When they ask for help,
it's much better to point them back to the programming guide
semantic section and reinforce the idea of signature matching
than to promote an ad-hoc rule that works in some cases for some pointcuts. As far as I'm concerned, no AspectJ developer should ever be "in the mindset of using this to
specify types"; but they should always be in the mindset of
signature-matching for signature-based pointcuts and instanceof (-like) tests for dynamic pointcuts, since that's
how the semantics are defined.
It seems that we have a different view about how people learn. I think it's reasonable and healthy for people to start applying AspectJ and to learn it a bit at a time. To me, emphasizing typical patterns like using dynamic matching for types is helpful and appropriate. I would naturally like everyone to become AspectJ experts and to understand all the cases as defined in the programmer's guide. But I don't think everyone will do so, and even those who do get there will benefit by learning incrementally.

I will agree that I should have been more careful in formulating my original statement. I'd rephrase it as:

The original call pointcut should be changed to target(Logon_Action) && call(...) so it matches cases where a logon action is being invoked on a base class type. In general, using dynamic tests with call pointcuts gives you the behavior you'd expect whereas putting the method in the signature tests based on the compile-time type of the reference being called (which you rarely want). I also prefer using dynamic tests with execution pointcuts because it is the most natural and robust in the face of refactorings, but there are good arguments against this too.

Sorry to go on at length. I've always found you great about presenting AspectJ in a way users can understand, so I hope to convince you to make this one tiny adjustment.

Thanks -
Wes

P.S. - The implementation papers have to be written, but one
of the dangers of doing so is that people will start to
base semantic discussions on the (current) implementation.
The rule "prefer static forms" is good because it should be
true for all implementations of AspectJ.  The optimization for
this(Type) will not be, and the practice of decompiling
code to understand or demonstrate semantics should be avoided.
I understand that you were proving that this(Type) has been
optimized (in which cases?), but users might start trying
to prove things using decompilers, and then we'll be talking
in bytecode.  Not yummy!
I view this very differently too. It's important to write robust code that has good software engineering properties, and to rely on AOP implementations that make this strategy perform well. I prefer to write natural code and then to optimize for performance based on tests that show bottlenecks. This isn't an AOP idea, it's an consequence of Hoare's dictum "Premature optimization is the root of all evil"

I disassembled (not decompiled) to show that your assertion about performance isn't true for AspectJ 1.2 (in this case). I agree that talking in bytecode is dangerous, although I think reasoning about static types tends to get into more reasoning about bytecodes and into more complexity.

------------Original Message------------
From: "Ron Bodkin" <rbodkin@xxxxxxxxxxxxxx>
To: aspectj-users@xxxxxxxxxxx
Date: Sat, Jul-17-2004 8:45 AM
Subject: RE: [aspectj-users] [newbie] General help needed here.....

Yes Wes, it is true that using the declaring type in the signature is useful and can be appropriate for those who have some experience with AspectJ. However, for new users it's helpful to get in the mindset of using this to specify types instead of doing it in the method
signature,
instead of trying to remember that using declaring types with call is problematic and using them with execution is ok (remember that Jerry started off using call with a static type in the signature!) And it
is also
a good rule because it's binding the currently executing object in
your
pointcut is commonly done.

By the way, this(Type) && execution(...) has *no* dynamic test (+),
and
with the AspectJ 1.2 compiler optimizations should be compiled about equally quickly (e.g., slide 96 from Andy Clement's data at
http://newaspects.com/presentations/Enterprise%20AOP%20AOSD%202004.ppt which shows
some related improvements, although not the performance of this(..)
&&
execution(..)). It is true that it's not statically resolvable for declare warning/error (although I'd like to see the compiler restriction
eased to allow use
pointcuts for any special cases where no dynamic test would be
required
to resolve a pointcut; maybe some day). And it also isn't useful for statics (clearly). But these are specialized scenarios, not the
general
rule.

Re: configuring AspectJ with Struts, the aTrack project is a working example that uses Struts with AspectJ.

Ron

(+) See section 4.1.2 in "Advice Weaving in AspectJ" http://www.hugunin.net/papers/aosd-2004-cameraReady.pdf. Also I
compiled two versions of
an aspect with AspectJ 1.2 and found identical bytecode:

public aspect ExecBytecode {
   void foo() {}
   before() : this(ExecBytecode) && execution(* foo()) {}
}

Then from "javap -c ExecBytecode"

foo();
 Code:
  0:	invokestatic	#49; //Method aspectOf:()LExecBytecode;
3: invokevirtual #51; //Method ajc$before$ExecBytecode$1$eb4dac00:()V
  6:	return

public void ajc$before$ExecBytecode$1$eb4dac00();
 Code:
  0:	return

public aspect ExecBytecode {
   void foo() {}
   before() : execution(* ExecBytecode.foo()) {}
}

Produces:
void foo();
 Code:
  0:	invokestatic	#49; //Method aspectOf:()LExecBytecode;
3: invokevirtual #51; //Method ajc$before$ExecBytecode$1$b5db75e4:()V
  6:	return

public void ajc$before$ExecBytecode$1$b5db75e4();
 Code:
  0:	return

Ron Bodkin
Chief Technology Officer
New Aspects of Software
o: (415) 824-4690
m: (415) 509-2895

------------Original Message------------
From: "Wes Isberg" <wes@xxxxxxxxxxxxxx>
To: aspectj-users@xxxxxxxxxxx
Date: Fri, Jul-16-2004 11:06 PM
Subject: RE: [aspectj-users] [newbie] General help needed here.....

Hi Ron (, Jerry) -

re:
As a general rule, you probably don't want to use the form of
signature
you have in that pointcut (which matches based on static types
instead
of runtime instances).
I've never heard this rule and I believe it is not correct;
The original form

   execution(ReturnType DeclaringType.methodName(..))

is better than

   execution(ReturnType methodName(..)) && this(DeclaringType)

*because* it can be resolved staticly and requires no dynamic test
(faster compile, faster implementation, and better IDE support).

You might be confusing this situation with the suggestion for
the call pointcut not to use the declaring type in the call. This suggestion is because the signature of a call join point refers to the type of the reference (at the call site), not the type of the referent class (at run time). So when people
write

  call(ReturnType DeclaringType.methodName(..))

they usually mean

  call(ReturnType methodName(..)) && target(DeclaringType)

(hence the suggestion).

Wes

P.S. - If someone does figure out how to configure AspectJ
with Struts, etc, it would be great to contribute back a
description to the mailing list or a bug, for inclusion in
the sample code repository...


------------Original Message------------
From: "Ron Bodkin" <rbodkin@xxxxxxxxxxxxxx>
To: aspectj-users@xxxxxxxxxxx
Date: Fri, Jul-16-2004 4:09 PM
Subject: RE: [aspectj-users] [newbie] General help needed
here.....
Jerry,

A couple of things to try:
1) Make sure that you are opening the affected file with the
AspectJ
editor and not the Java editor. You should go into window |
preferences |
file associations and make sure that AspectJ is set the the
default
for
.java files
2) Try adding this line, to see if the pointcut is matching:

declare warning: actionCall() : "in action execution";

As a general rule, you probably don't want to use the form of
signature
you have in that pointcut (which matches based on static types
instead
of runtime instances). It should work for executions, but a
better
version is:

pointcut actionExecute() : execution(public ActionForward execute(ActionMapping, ActionForm, HttpServletRequest, HttpServletResponse))) && this(Logon_Action);

Ron

p.s. there's an already defined, debugged version of a pointcut
for
struts action execution in the aTrack project: see ajee.component.StrutsPointcuts. aTrack is at
https://atrack.dev.java.net/
public pointcut actionExecute(Action action, ActionMapping
mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse response)
:
execution(ActionForward Action.execute(ActionMapping, ActionForm, HttpServletRequest, HttpServletResponse)) &&
this(action)
&& args(mapping, form, request, response);


Ron Bodkin
Chief Technology Officer
New Aspects of Software
o: (415) 824-4690
m: (415) 509-2895

------------Original Message------------
From: "Jerry Jalenak" <Jerry.Jalenak@xxxxxxxxxx>
To: "'aspectj-users@xxxxxxxxxxx'" <aspectj-users@xxxxxxxxxxx>
Date: Fri, Jul-16-2004 1:07 PM
Subject: RE: [aspectj-users] [newbie] General help needed
here.....
Another possibility that just occurred to me....

Since Logon_Action extends Action, do I need to 'expose' the
org.apache.struts.action.Action class to the aspect?

Jerry Jalenak
Development Manager, Web Publishing
LabOne, Inc.
10101 Renner Blvd.
Lenexa, KS  66219
(913) 577-1496

jerry.jalenak@xxxxxxxxxx


-----Original Message-----
From: Ramnivas Laddad [mailto:ramnivas@xxxxxxxxxxxxxxx]
Sent: Friday, July 16, 2004 2:29 PM
To: aspectj-users@xxxxxxxxxxx
Subject: Re: [aspectj-users] [newbie] General help needed
here.....
Hi Jerry,

Otávio's suggestion of using execution() PCD is the right
one.
It is okay to use any number of aspects crosscutting a class. Just a guess: Do you have every referred type in the pointcut definition (in your case ActionMapping, ActionForm, HttpServletRequest, HttpServletResponse) appropriately
imported.
-Ramnivas

===

Ramnivas Laddad,
Author, AspectJ in Action
http://ramnivas.com

Jerry Jalenak wrote:

Otavio,

Thanks for the reply. Change the PCD from call to execution
didn't seem to
change anything. However, I starting to think I have
something else wrong.
In the AspectJ Visualizer perspective, I am only seeing
where one aspect has
been applied (I have two). Is it not possible to have more
than one aspect
class?

Thanks....

Jerry Jalenak
Development Manager, Web Publishing
LabOne, Inc.
10101 Renner Blvd.
Lenexa, KS  66219
(913) 577-1496

jerry.jalenak@xxxxxxxxxx




-----Original Message-----
From: Otávio Augusto Lazzarini Lemos
[mailto:oall@xxxxxxxxxxx]
Sent: Friday, July 16, 2004 1:31 PM
To: aspectj-users@xxxxxxxxxxx
Subject: Re: [aspectj-users] [newbie] General help needed
here.....
You should use an execution PCD. In your example the calls
to
Logon_action.execute(ActionMapping, ActionForm,
HttpServletRequest,
HttpServletResponse) are the intercepted join points, and
not the actual
execution of the method (try to look at the places where
you
call the method).
Tell me if it works with the execution instead of the call
PCD.
Otávio

Citando Jerry Jalenak <Jerry.Jalenak@xxxxxxxxxx>:

First, thanks to Rod, Adrian, and Ramnivas for their help
the other day.  I
think I'm starting to get the hang of this....

That being said, I'm stuck as to why the following doesn't
work.  I've just
upgraded to the AJDT 1.1.11 plug-in, if it matters.

Here's the aspect :

	public aspect MemberSolutions_BaseActionAspect
	{
	    // ~ Pointcut definitions
pointcut actionCall() : (call(public ActionForward Logon_Action.execute(ActionMapping, ActionForm,
HttpServletRequest,
HttpServletResponse)));
// ~ Advice definitions before() : actionCall()
	    {
	        System.out.println("here i am");
	    }
	}

and the class I'm trying to weave it into :

	public class Logon_Action extends Action
	{
public ActionForward execute(ActionMapping
_actionMapping,
ActionForm _actionForm, HttpServletRequest
_request,
	            HttpServletResponse _response)
	    {
Logon_ActionForm form = (Logon_ActionForm)
_actionForm;
	        return null;
	    }
	}

Everything compiles OK (no errors, anyway), but when I
check the class I
don't see any indication that the aspect is being applied.

I expect to see
an indicator on the first statement of the class....

I'm probably being dense on this, and it's something
really
stupid, but I
can't seem to figure it out.  Any help?

Thanks guys!

Jerry Jalenak
Development Manager, Web Publishing
LabOne, Inc.
10101 Renner Blvd.
Lenexa, KS  66219
(913) 577-1496

jerry.jalenak@xxxxxxxxxx


This transmission (and any information attached to it) may
be confidential
and
is intended solely for the use of the individual or entity
to which it is
addressed. If you are not the intended recipient or the
person responsible
for
delivering the transmission to the intended recipient, be
advised that you
have received this transmission in error and that any use,
dissemination,
forwarding, printing, or copying of this information is
strictly prohibited.
If you have received this transmission in error, please
immediately notify
LabOne at the following email address:
securityincidentreporting@xxxxxxxxxx
_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/aspectj-users

_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/aspectj-users

This transmission (and any information attached to it) may
be confidential and is intended solely for the use of the individual or entity to which it is addressed. If you are not the intended recipient or the person responsible for delivering the transmission to the intended recipient, be advised that you have received this transmission in error and that any use, dissemination, forwarding, printing, or copying of this information is strictly prohibited. If you have received this transmission in error, please immediately notify LabOne at the following email address: securityincidentreporting@xxxxxxxxxx
_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/aspectj-users



_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/aspectj-users

This transmission (and any information attached to it) may be confidential and is intended solely for the use of the
individual
or
entity to
which it is addressed. If you are not the intended recipient or
the
person responsible for delivering the transmission to the
intended
recipient, be advised that you have received this transmission
in
error and
that any use, dissemination, forwarding, printing, or copying
of
this
information is strictly prohibited. If you have received this
transmission
in error, please immediately notify LabOne at the following
email
address: securityincidentreporting@xxxxxxxxxx

_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/aspectj-users


_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/aspectj-users

_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/aspectj-users


_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/aspectj-users

_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/aspectj-users



_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/aspectj-users



Back to the top