Community
Participate
Working Groups
It should be legal to define before, after returning, and around advice for the same join point regardless of the order specified. I would expect the following program to compile and run, producing the output: A C B The following sample program will not compile with AspectJ 1.1.1, nor with AspectJ from cvs head (nor with AspectJ 1.0.6!): public class Circular { public static void main(String args[]) { } } aspect ThreeAdvices { pointcut mainExec() : execution(* main(..)); before() : mainExec() { System.out.println("A"); } after() returning : mainExec() { System.out.println("B"); } void around() : mainExec() { System.out.println("C"); } } C:\devel\test\Circular.aj:9 error circular advice dependency at method- execution (void Circular.main(java.lang.String[])) before() : mainExec() {} ^^^^^^^^^^^^^^^^ C:\devel\test\Circular.aj:10 error circular advice dependency at method- executio n(void Circular.main(java.lang.String[])) after() returning : mainExec() {} ^^^^^^^^^^^^^^^^^^^^^^^^^ C:\devel\test\Circular.aj:11 error circular advice dependency at method- executio n(void Circular.main(java.lang.String[])) void around() : mainExec() {} ^^^^^^^^^^^^^^^^ 3 errors --- The following alternative version will compile and produce the desired output: public class Circular { public static void main(String args[]) { } } aspect ThreeAdvices { pointcut mainExec() : execution(* main(..)); before() : mainExec() { System.out.println("A"); } after() returning : mainExec() { System.out.println("B"); } static aspect Baz { void around() : mainExec() { System.out.println("C"); } } }
If you change the order so the around advice is first, it compiles, but it doesn't produce the output I expected; it says C \n B; I expected just C since the around doesn't proceed, so the lower precedence after returning shouldn't run: public class Circular { public static void main(String args[]) { } } aspect ThreeAdvices { pointcut mainExec() : execution(* main(..)); void around() : mainExec() { System.out.println("C"); } before() : mainExec() { System.out.println("A"); } after() returning : mainExec() { System.out.println("B"); } }
To repeat what I said on the mail list... --------------- I don't think this is a bug. The docs say: ----- If the two pieces of advice are defined in the same aspect, then there are two cases: (1) If either are after advice, then the one that appears later in the aspect has precedence over the one that appears earlier. (2) Otherwise, then the one that appears earlier in the aspect has precedence over the one that appears later. These rules can lead to circularity, such as aspect A { before(): execution(void main(String[] args)) {} // X after(): execution(void main(String[] args)) {} // Y before(): execution(void main(String[] args)) {} // Z } ----- Put another way: (a) Y > X by (1) (b) Z > Y by (1) (c) X > Z by (2) but Z > X by (b) & (a) That seem to apply directly to your code: aspect ThreeAdvices { before() : mainExec() { ... } after() returning : mainExec() { ... } void around() : mainExec() { ... } } As a general rule, put after advice last to avoid advice circularity. That's how you'd get the order you were looking for in the bug. (Also, I wouldn't hold up the release for any non-crashing bug that has a workaround.)
This follows the rules for advice precedence; it is a cycle. The phrasing of the compiler output here led me to believe that the compiler was trying to run advice on advice, which didn't make sense. I would much rather get the AspectJ 1.0.6 output: .\Circular.aj:9:5: circularity in advice precedence applied to method-execution (public static void Circular.main(String[])) before() : mainExec() { System.out.println("A"); } Rather than this output: C:\devel\test\Circular.aj:12 error circular advice dependency at method- execution(void Circular.main(java.lang.String[]))
Resolving as a duplicate of 30439, for which I just checked a fix into the tree. *** This bug has been marked as a duplicate of 30439 ***
Fix released as part of AspectJ 1.2.1