Bug 57993 - Use AspectJ 1.0.x message for circular advice precedence
Summary: Use AspectJ 1.0.x message for circular advice precedence
Status: RESOLVED DUPLICATE of bug 30439
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P4 enhancement (vote)
Target Milestone: 1.2.1   Edit
Assignee: Adrian Colyer CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-04-09 04:26 EDT by Ron Bodkin CLA
Modified: 2004-10-21 04:32 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ron Bodkin CLA 2004-04-09 04:26:55 EDT
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"); } 
    }
}
Comment 1 Ron Bodkin CLA 2004-04-09 04:32:53 EDT
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"); }


}
Comment 2 Wes Isberg CLA 2004-04-09 07:00:13 EDT
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.)
Comment 3 Ron Bodkin CLA 2004-04-09 11:10:46 EDT
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[]))
Comment 4 Adrian Colyer CLA 2004-07-29 11:17:18 EDT
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 ***
Comment 5 Adrian Colyer CLA 2004-10-21 04:32:36 EDT
Fix released as part of AspectJ 1.2.1