Bug 549437 - @Inherited annotation matching not working as expected
Summary: @Inherited annotation matching not working as expected
Status: NEW
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.9.2   Edit
Hardware: PC Windows 10
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-07-20 01:36 EDT by Alexander Kriegisch CLA
Modified: 2020-01-31 13:07 EST (History)
1 user (show)

See Also:


Attachments
Sample code (2.38 KB, application/x-zip-compressed)
2019-07-20 01:36 EDT, Alexander Kriegisch CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Alexander Kriegisch CLA 2019-07-20 01:36:51 EDT
Created attachment 279347 [details]
Sample code

This scenario works nicely:
https://stackoverflow.com/a/48543096/1082681

But this one does not:
https://stackoverflow.com/q/57005199/1082681

Here is some code adapted from the second link that should work but does not:

------------------------------------------------------------

package de.scrum_master.app;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Annotation2 {}

------------------------------------------------------------

package de.scrum_master.app;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@Annotation2
public @interface Annotation1 {}

------------------------------------------------------------

package de.scrum_master.app;

@Annotation1
abstract class BaseService {}

------------------------------------------------------------

package de.scrum_master.app;

import java.lang.annotation.Annotation;

//@Annotation1
public class TestService extends BaseService {
  private void testMethod() {
    System.out.println("Doing something");
  }

  public static void main(String[] args) {
    System.out.println("Annotations found on class TestService:");
    for (Annotation annotation : TestService.class.getAnnotations())
      System.out.println("  " + annotation);

    new TestService().testMethod();
  }
}

------------------------------------------------------------

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class TestAspect {
  @Before(
    "execution(* *(..)) && (" +
      "within(@de.scrum_master.app.Annotation2 *) || " +
      "within(@(@de.scrum_master.app.Annotation2 *) *) || " +
      "within(@(@(@de.scrum_master.app.Annotation2 *) *) *)" +
    ")"
  )
  public void myAdvice1(JoinPoint joinPoint) {
    System.out.println(joinPoint);
  }

  @Before(
    "execution(* (@de.scrum_master.app.Annotation2 *)+.*(..)) || " +
    "execution(* (@(@de.scrum_master.app.Annotation2 *) *)+.*(..)) || " +
    "execution(* (@(@(@de.scrum_master.app.Annotation2 *) *) *)+.*(..))"
  )
  public void myAdvice2(JoinPoint joinPoint) {
    System.out.println(joinPoint);
  }
  
}

------------------------------------------------------------

The console log when running TestService.main(..) is:

Annotations found on class TestService:
  @de.scrum_master.app.Annotation1()
Doing something

I.e. TestService does indeed inherit the (meta-annotated) annotation from BaseService but AspectJ pointcut matching does not work.

------------------------------------------------------------

Now if I uncomment the annotation @Annotation1 directly in TestService, it works as I would have expected with the inherited annotation already:

execution(void de.scrum_master.app.TestService.main(String[]))
execution(void de.scrum_master.app.TestService.main(String[]))
Annotations found on class TestService:
  @de.scrum_master.app.Annotation1()
execution(void de.scrum_master.app.TestService.testMethod())
execution(void de.scrum_master.app.TestService.testMethod())
Doing something

The same annotation is found on TestService and suddenly both advices get triggered.
Comment 1 Alexander Kriegisch CLA 2020-01-30 02:04:09 EST
I just stumbled upon this one again. After quite a while without reaction, some feedback would be nice.
Comment 2 Andrew Clement CLA 2020-01-31 13:07:35 EST
Sorry about that, I'm swamped, probably have to wait until I am digging into what to fix for next release (which right now follow Java releases). I don't want to give you a quick answer that is wrong.