Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
RE: [aspectj-dev] Selective method calls and returns

Thanks Ron, this is what I needed.

-----Original Message-----
From: aspectj-dev-bounces@xxxxxxxxxxx
[mailto:aspectj-dev-bounces@xxxxxxxxxxx] On Behalf Of Ron Bodkin
Sent: Tuesday, May 17, 2005 12:15 PM
To: 'AspectJ developer discussions'
Subject: RE: [aspectj-dev] Selective method calls and returns


There is one small caveat here: you do need to weave into any *aspects*
that might call the target with either solution (that's the only AspectJ
way to track where the calls are coming from, excluding the really ugly
hack of examining stack traces...)

-----Original Message-----
From: aspectj-dev-bounces@xxxxxxxxxxx
[mailto:aspectj-dev-bounces@xxxxxxxxxxx] On Behalf Of Ron Bodkin
Sent: Tuesday, May 17, 2005 11:06 AM
To: 'AspectJ developer discussions'
Subject: RE: [aspectj-dev] Selective method calls and returns

This is an interesting problem. You can handle this by excluding the
CALLS from adviceexecution. You could also just exclude calls from
aspect types (see method 2 below). Note that my example now uses around
advice to match your problem.

Method 1 (using cflow):

import org.aspectj.lang.*;
class Target {
    public void methodA() {
	System.out.println("a");
	methodB();
    }
    public void methodB() {
	System.out.println("b");
    }
}

aspect MonitorTarget {
    public pointcut targetExec() :
	execution(public * Target.*(..));

    public pointcut topLevelTargetExec():
	targetExec() && !cflowbelow(targetExec());

    public pointcut targetCall() :
	call(public * Target.*(..));

    public pointcut adviceCall() :
	targetCall() &&
if(thisEnclosingJoinPointStaticPart.getKind()==JoinPoint.ADVICE_EXECUTIO
N);

    void around() : topLevelTargetExec() && !cflow(adviceCall()) {
	System.out.println("before top level "+thisJoinPoint);
	proceed();
    }
}


aspect OtherAspect {
    after() returning : execution(* methodA()) {
	(new Target()).methodB();
    }
    after() returning : call(* methodA()) {
	(new Target()).methodB();
    }
}

public class Main {
    public static void main(String args[]) {
	(new Target()).methodA();
	(new Target()).methodB();
    }
}

Note that you can't put if lexically inside cflow, i.e., if you tried to
write

topLevelTargetExec() && !cflow(call(public * Target.*(..)) &&
 
if(thisEnclosingJoinPointStaticPart.getKind()==JoinPoint.ADVICE_EXECUTIO
N))


the compiler says:

 [error] if not supported lexically within cflow (compiler limitation) 
!cflow(call(public * Target.*(..)) &&
if(thisEnclosingJoinPointStaticPart.getKind()==JoinPoint.ADVICE_EXECUTIO
N))
{
                                      
Method 2: You can also add a marker interface on any of your aspects
(e.g., with declare parents). When AspectJ supports built in tests for
types (e.g., an isAspect() type pattern), this would be even easier
(i.e., you wouldn't have to mark your aspects!) 

import org.aspectj.lang.*;
class Target {
    public void methodA() {
	System.out.println("a");
	methodB();
    }
    public void methodB() {
	System.out.println("b");
    }
}

aspect MonitorTarget {
    public pointcut targetExec() :
	execution(public * Target.*(..));

    public pointcut topLevelTargetExec():
	targetExec() && !cflowbelow(targetExec());

    protected interface AspectType {}
    declare parents: OtherAspect || MonitorTarget implements AspectType;

    void around() : topLevelTargetExec() && 
	!cflow(call(public * Target.*(..)) && within(AspectType+)) {
	System.out.println("before top level "+thisJoinPoint);
	proceed();
    }
}


aspect OtherAspect {
    after() returning : execution(* methodA()) {
	(new Target()).methodB();
    }
    after() returning : call(* methodA()) {
	(new Target()).methodB();
    }
}

public class Direct {
    public static void main(String args[]) {
	(new Target()).methodA();
	(new Target()).methodB();
    }
}

Output (for both):
before top level execution(void Target.methodA())
a
b
b
b
before top level execution(void Target.methodB())
b



-----Original Message-----
From: aspectj-dev-bounces@xxxxxxxxxxx
[mailto:aspectj-dev-bounces@xxxxxxxxxxx] On Behalf Of Oleg Lebedev
Sent: Saturday, May 14, 2005 11:49 AM
To: AspectJ developer discussions
Subject: RE: [aspectj-dev] Selective method calls and returns

Ron,
 
the idea that I am trying to implement is to be able to track all public
method executions invoked during testing. This way it will be very easy
to reproduce the bugs found and actions taken by testers. Basically, I
am trying to automate components testing. I want to be able to apply an
aspect to a given component and give it to testing. The aspects will
then track all the component method executions so that when we change
the component implementation we could rerun the same tests. In other
words, the aspect will be building the use test case base, which can
then be used to verify that the new component implementation works at
least as good as the old one.
 
I want to track method executions, because the aspect will be applied to
the component code before it's used. In most cases I wouldn't know in
which context the component will be used, therefore I can't apply the
aspect to method calls.
 
I got it to work relatively well when no other aspects are applied to
the component. I must admit AOP was a really good fit for this problem
 
I would appreciate any feedback.
 
Thanks.
 
Oleg

________________________________

From: aspectj-dev-bounces@xxxxxxxxxxx on behalf of Ron Bodkin
Sent: Fri 5/13/2005 7:52 PM
To: 'AspectJ developer discussions'
Subject: RE: [aspectj-dev] Selective method calls and returns



Aha. In this case your methodA will always be running in the cflow of
the around advice from OtherAspect (as you discovered).

Could you change your pointcut to refer to calls instead of executions?
It sounds like the real reason you want to exclude advice execution is
that it's in the cflow of a top level *call*, so you don't want calls to
B to match if their in the cflow of a call to A.

You could also refactor your around advice to be before and after advice
and keep a threadlocal stack (that's what I do for monitoring, in part
so I can write around advice to ensure that exceptions in the monitor
never affect base code).

In general, I am nervous about trying to write aspects that don't apply
to other aspects categorically. I'd rather rethink the problem so I can
think in terms of not advising my own implementation. I'd be interested
to better understand what the aspect in question is trying to achieve...


-----Original Message-----
From: aspectj-dev-bounces@xxxxxxxxxxx
[mailto:aspectj-dev-bounces@xxxxxxxxxxx] On Behalf Of Oleg Lebedev
Sent: Friday, May 13, 2005 4:44 PM
To: AspectJ developer discussions
Subject: RE: [aspectj-dev] Selective method calls and returns

This is a great example, Ron.

I couldn't figure out why I was getting this problem untill it struck me
that I had an around() advice. So, if you change your OtherAspect as
follows, then you wouldn't see any print outs from MonitorTarget. What I
need is to get the same output as you got before with the new OtherAspec
as follows:

aspect OtherAspect {
    after() returning : call(* methodA()) {
        (new Target()).methodB();
    }
    after() returning : execution(* methodA()) {
        (new Target()).methodB();
    }
        /**
     * Record to execute a method.
     */
    Object around() : call(* Target.methodA()) {
        long start = System.currentTimeMillis();
        try {
            return proceed();
        } finally {
            long end = System.currentTimeMillis();
                        System.out.println("call(* Target.methodA()): "
+ (end - start) + "ms.");
        }
    }
}


The output is:
     a
     b
     b
     b
     call(* Target.methodA()): 0ms.

I would like to see "before top level execution(void Target.methodA())
from execution(void Target.methodA())" as the first line of the output.

Thanks.

Oleg


-----Original Message-----
From: aspectj-dev-bounces@xxxxxxxxxxx
[mailto:aspectj-dev-bounces@xxxxxxxxxxx] On Behalf Of Ron Bodkin
Sent: Friday, May 13, 2005 4:23 PM
To: 'AspectJ developer discussions'
Subject: RE: [aspectj-dev] Selective method calls and returns


Hi Oleg,

I'm not clear on what you are after. Here's an example program showing
the pointcut I suggested with output that seems to match your
requirements. What's different about your case?

class Target {
    public void methodA() {
        System.out.println("a");
        methodB();
    }
    public void methodB() {
        System.out.println("b");
    }
}

aspect MonitorTarget {
    public pointcut targetExec() :
        execution(public * Target.*(..));

    public pointcut topLevelTargetExec():
        targetExec() && !cflowbelow(targetExec());

    before() : topLevelTargetExec() && !cflow(adviceexecution() &&
!within(MonitorTarget)) {
        System.out.println("before top level "+thisJoinPoint);
    }
}


aspect OtherAspect {
    after() returning : call(* methodA()) {
        (new Target()).methodB();
    }
    after() returning : execution(* methodA()) {
        (new Target()).methodB();
    }
}

public class Main {
    public static void main(String args[]) {
        (new Target()).methodA();
    }
}

C:\devel\scratch\topLevelNotAdvised>java Main
before top level execution(void Target.methodA()) from execution(void
Target.methodA())
a
b
b
b


-----Original Message-----
From: aspectj-dev-bounces@xxxxxxxxxxx
[mailto:aspectj-dev-bounces@xxxxxxxxxxx] On Behalf Of Oleg Lebedev
Sent: Friday, May 13, 2005 10:23 AM
To: AspectJ developer discussions
Subject: RE: [aspectj-dev] Selective method calls and returns

Some clarifications. In the running case, method B gets called by method
A and also by some other aspect, which is triggered right before method
A returns.

BTW, please note that if I apply only the current aspect to my code it
works fine, i.e. only method A execution is picked out. The problem only
manifests itself, i.e. execution of B gets picked out, when another
aspect invoking B is weaved in at the end of method A.

Regards.

Oleg

-----Original Message-----
From: aspectj-dev-bounces@xxxxxxxxxxx
[mailto:aspectj-dev-bounces@xxxxxxxxxxx] On Behalf Of Oleg Lebedev
Sent: Friday, May 13, 2005 11:17 AM
To: AspectJ developer discussions
Subject: RE: [aspectj-dev] Selective method calls and returns



Ron,

I tested your suggestion and wasn't doing what I wanted.

Consider the running case.

1. Method A gets called, which in turn calls method B.
2. Method B is called by some other aspect OtherAspect.
3. Both of the methods A and B are picked out by the methods() pointcut.

Desired result: pick out the entry and end points of execution of A, and
ignore any execution of B

Note that the following methods() pointcut picks out executions, not
calls! public pointcut methods() : execution(public * TargetClass.*(..))
||

The followng will pick out the original execution of A and execution of
B triggered by OtherAspect call: before () : methods () &&
!cflowbelow(methods())

The following (your suggestion) does not pick out either the original
execution of A or any execution of B: before () : methods () &&
!cflowbelow(methods()) &&
!cflow(adviceexecution() && !within(CurrentAspect))

I think picking out executions instead of calls makes this problem
tricky.

Do you have any other ideas?

Thanks.

Oleg




-----Original Message-----
From: aspectj-dev-bounces@xxxxxxxxxxx
[mailto:aspectj-dev-bounces@xxxxxxxxxxx] On Behalf Of Ron Bodkin
Sent: Friday, May 13, 2005 10:26 AM
To: 'AspectJ developer discussions'
Subject: RE: [aspectj-dev] Selective method calls and returns


Oleg,

I'm curious why you want to capture calls from methods but not from
adviceexecutions? Do you have inter-type declarations? Are calls from
those valid in your definition.

To pick out public calls that aren't in the control flow of
adviceexecution of other aspects you'd want call(public * *(..)) &&
!cflow(adviceexecution() &&
!within(CurrentAspect))

By the way, this type of AspectJ usage questions should be posted to
aspectj-users.

-----Original Message-----
From: aspectj-dev-bounces@xxxxxxxxxxx
[mailto:aspectj-dev-bounces@xxxxxxxxxxx] On Behalf Of Oleg Lebedev
Sent: Friday, May 13, 2005 9:18 AM
To: AspectJ developer discussions
Subject: RE: [aspectj-dev] Selective method calls and returns


Is there a way to ignore all advice executions except for the ones
within the current aspect.

I have some external aspects calling public methods on my target class.
These method calls are picked up by my pointcut, which I don't want. I
just want to pick out only those public method calls, which are not
invoked by other aspects.

Something like:

!cflow(adviceexecution()) && within(CurrentAspect)

Thanks.

Oleg

-----Original Message-----
From: aspectj-dev-bounces@xxxxxxxxxxx
[mailto:aspectj-dev-bounces@xxxxxxxxxxx] On Behalf Of Matthew Webster
Sent: Friday, May 13, 2005 1:45 AM
To: AspectJ developer discussions
Subject: Re: [aspectj-dev] Selective method calls and returns






Oleg,

Try:

      after () returning : allPublic() && !cflowbelow(allPublic()) {}

Matthew Webster
AOSD Project
Java Technology Centre, MP146
IBM Hursley Park, Winchester,  SO21 2JN, England
Telephone: +44 196 2816139 (external) 246139 (internal)
Email: Matthew Webster/UK/IBM @ IBMGB, matthew_webster@xxxxxxxxxx
http://w3.hursley.ibm.com/~websterm/

"Oleg Lebedev" <oleglebedev@xxxxxxxxxxxxx>@eclipse.org on 13/05/2005
00:00:41

Please respond to AspectJ developer discussions
<aspectj-dev@xxxxxxxxxxx>

Sent by:    aspectj-dev-bounces@xxxxxxxxxxx


To:    "AspectJ developer discussions" <aspectj-dev@xxxxxxxxxxx>
cc:
Subject:    [aspectj-dev] Selective method calls and returns


Greetings.

I am wondering if you could help me with the following interesting
problem.

I need to track executions of all public methods in a given class. Some
of the public methods call other public methods, but only the top ones
should be tracked when called. So, if methods A and B are public and A
calls B internally, then when A is called only A execution should be
tracked and B execution should not be tracked. However, if B is directly
called by some external class, then it should be tracked as well.

Suppose allPublic() pointcut describes all public method executions in
the class, then the following advice will do what I want:

before () : allPublic() && !cflowbelow(allPublic()) {}

Here is the tricky part. I also need to track when methods picked up by
this advice return. So, in the case above, if method A is called, and
then internally calls method B, I only want to know when method A
returns, and ignore the return of method B. However, if method B is
called by some external class (and therefore is picked up by the advice
above), then I need to know when B returns as well.

Any ideas?

Thanks.

Oleg
_______________________________________________
aspectj-dev mailing list
aspectj-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-dev


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

--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
If you have questions about this email, please
contact the IT Help Desk.

Mail

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


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

--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
If you have questions about this email, please
contact the IT Help Desk.

Mail

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

--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
If you have questions about this email, please
contact the IT Help Desk.

Mail

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


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

--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
If you have questions about this email, please
contact the IT Help Desk.

Mail

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


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

--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
If you have questions about this email, please
contact the IT Help Desk.

Mail



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


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


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

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
If you have questions about this email, please
contact the IT Help Desk.

Mail



Back to the top