Community
Participate
Working Groups
If you create an object that is a subclass of interface implementation and reference it via the superclass or interface the compiler does not recognize the poincut on the child/implementation. In the attachment set: Foo is the aspect that defines a pointcut on the annotation Bar. Bar is a method-based annotation. Baz is a simple class. ChildOfBaz extends Baz, overriding Baz' only method execute and annotating it with Bar. Test runs some execute methods. Test produces the following output: In Baz. In ChildOfBaz call(void ChildOfBaz.execute()) In ChildOfBaz
Created attachment 55543 [details] Annotation based aspect.
Created attachment 55544 [details] The sample annotation.
Created attachment 55545 [details] A simple class.
Created attachment 55546 [details] Baz' subclass.
Created attachment 55547 [details] Example test demonstrating the reference problem
Created attachment 55561 [details] Complete Test Case
Created an all-in-one test case and added some better output. Test case now returns: false Baz true ChildOfBaz call(void ChildOfBaz.execute()) true ChildOfBaz
the program is working as designed. In your example the 'baz' variable is of type 'Baz'. The pointcut is matching based on the static type information available at the call join points. You make 3 calls to execute - only at the last one, after the cast, do we statically know that you are calling execute on the subclass, hence it matches. Your second call to execute is identified as a call to Baz.execute() because that is the type of the variable 'baz'. I know the subclass implementation runs because the runtime type held in baz is ChildOfBaz, but at compile time we don't know that and it isn't used in the matching process.
OK. Expected for you, not for me. I guess I had some faulty assumptions about how the compiling was done. Here's the problem perhaps you can provide a solution. I have a Command interface with an execute method. I have many commands that implement this interface and I have an annotation for security checks. I want to not have to annotate the interface execute method since some commands should just work, and even if I wanted to, I'm having difficulty imagining the correct "generic" annotation. However, I typically pass these back and forth as Command instances, so how do I get this to work as I expected it to (ie supertype references still allow subtype annotation pointcuts to work)?
Better late than never.... If you want to match based on runtime information, then you need to use a runtime matching pointcut, like @annotation(). Here is a sample program where the @Secured execute method is checked. import java.lang.annotation.*; public class Secure { public static void main(String []argv) { new SecureCommand().execute(); new NormalCommand().execute(); } } interface ICommand { void execute(); } class SecureCommand implements ICommand { @Secured public void execute() {System.out.println("Secure command running"); } } class NormalCommand implements ICommand { public void execute() {System.out.println("Normal command running"); } } @Retention(RetentionPolicy.RUNTIME) @interface Secured {} aspect X { before(): execution(* ICommand.execute(..)) && @annotation(Secured) { System.out.println("Running security check"); } } However, i'm not sure how that would work in the face of your super calls... I doubt you still care after all this time, but I thought I'd comment before I close it :) Let me know if you still want to discuss by reopening this.