Uploaded image for project: 'Spring Framework'
  1. Spring Framework
  2. SPR-11108

Support composed annotations declared on interfaces

    Details

    • Last commented by a User:
      false

      Description

      Status Quo

      The findAnnotation() methods in AnnotationUtils currently support searching for meta-annotations declared on composed annotations that are declared on interfaces; however, various parts of the framework – for example, code that relies on AnnotationAttributes – only support composed annotations on classes or methods (not on interfaces or interface methods).

      For example, given the following:

      @Target({ElementType.TYPE, ElementType.METHOD})
      @Retention(RetentionPolicy.RUNTIME)
      @Transactional(rollbackFor=Exception.class, noRollbackFor={IOException.class})
      public @interface TxWithAttribute {
       
      	boolean readOnly();
      }
       
      @TxWithAttribute(readOnly = true)
      public static interface TestInterface9 {
       
      	public int getAge();
      }
       
      public static class TestBean9 implements TestInterface9 {
       
      	@Override
      	public int getAge() {
      		return 10;
      	}
      }
       
      public static interface TestInterface10 {
       
      	@TxWithAttribute(readOnly=true)
      	public int getAge();
      }
       
      public static class TestBean10 implements TestInterface10 {
       
      	@Override
      	public int getAge() {
      		return 10;
      	}
      }

      Spring's support for resolving transaction attributes (e.g., the AbstractFallbackTransactionAttributeSource.computeTransactionAttribute() to SpringTransactionAnnotationParser.parseTransactionAnnotation() call stack) fails to find @Transactional which is declared via @TxWithAttribute on interfaces.

      Proposal

      Introduce support for composable stereotype annotations declared on interfaces.

        Issue Links

          Activity

          Hide
          sbrannen Sam Brannen added a comment -

          To reproduce this lacking support, see the customClassAttributeWithReadOnlyOverrideOnInterface() and customMethodAttributeWithReadOnlyOverrideOnInterface() tests introduced in AnnotationTransactionAttributeSourceTests from GitHub commit ad402dc.

          Show
          sbrannen Sam Brannen added a comment - To reproduce this lacking support, see the customClassAttributeWithReadOnlyOverrideOnInterface() and customMethodAttributeWithReadOnlyOverrideOnInterface() tests introduced in AnnotationTransactionAttributeSourceTests from GitHub commit ad402dc .
          Hide
          juergen.hoeller Juergen Hoeller added a comment -

          Good point. Alright, let's try to roll this into 4.0 RC2 still...

          Juergen

          Show
          juergen.hoeller Juergen Hoeller added a comment - Good point. Alright, let's try to roll this into 4.0 RC2 still... Juergen
          Hide
          juergen.hoeller Juergen Hoeller added a comment -

          Sam, this doesn't seem to have much to do with AnnotationAttributes or the like...

          It's rather that we generally only detect @Transactional annotations on an interface if the invocation comes in through that interface. So in those unit tests, you simply need to pass in the interface method instead of the target class method (which I've just changed and committed). If that's the case, both direct lookups and meta-annotation lookups work. So with JDK proxies, all should be fine. With CGLIB proxies, neither of those two variants works - just like before. It's generally arguable whether CGLIB proxies should also check interfaces there, but anyway, it doesn't seem to be an inconsistency between direct and meta use of @Transactional.

          Let me know if I'm missing something...

          Juergen

          Show
          juergen.hoeller Juergen Hoeller added a comment - Sam, this doesn't seem to have much to do with AnnotationAttributes or the like... It's rather that we generally only detect @Transactional annotations on an interface if the invocation comes in through that interface. So in those unit tests, you simply need to pass in the interface method instead of the target class method (which I've just changed and committed). If that's the case, both direct lookups and meta-annotation lookups work. So with JDK proxies, all should be fine. With CGLIB proxies, neither of those two variants works - just like before. It's generally arguable whether CGLIB proxies should also check interfaces there, but anyway, it doesn't seem to be an inconsistency between direct and meta use of @Transactional. Let me know if I'm missing something... Juergen
          Hide
          sbrannen Sam Brannen added a comment -

          Juergen, just to recap on our discussion...

          I mentioned support for @Transactional only as an example to demonstrate the issue. The crux of the issue is described in the opening sentence:

          The findAnnotation() methods in AnnotationUtils currently support searching for meta-annotations declared on composed annotations that are declared on interfaces; however, various parts of the framework – for example, code that relies on AnnotationAttributes – only support composed annotations on classes or methods (not on interfaces or interface methods).

          So there is in fact a difference in the behavior of AnnotatedElementUtils and AnnotationUtils with regard to traversal of interfaces. Whether or not this difference poses an actual problem for end users' code at runtime will require further analysis of current use of AnnotationAttributes, AnnotatedElementUtils, etc. across the code base.

          Regards,

          Sam

          Show
          sbrannen Sam Brannen added a comment - Juergen, just to recap on our discussion... I mentioned support for @Transactional only as an example to demonstrate the issue. The crux of the issue is described in the opening sentence: The findAnnotation() methods in AnnotationUtils currently support searching for meta-annotations declared on composed annotations that are declared on interfaces; however, various parts of the framework – for example, code that relies on AnnotationAttributes – only support composed annotations on classes or methods (not on interfaces or interface methods). So there is in fact a difference in the behavior of AnnotatedElementUtils and AnnotationUtils with regard to traversal of interfaces. Whether or not this difference poses an actual problem for end users' code at runtime will require further analysis of current use of AnnotationAttributes , AnnotatedElementUtils , etc. across the code base. Regards, Sam
          Hide
          sbrannen Sam Brannen added a comment -

          Update: SPR-12703 covers interface support in AnnotatedElementUtils; however, I am leaving this issue open for the time being in order to ensure we cover the same use cases for Spring's ASM-based annotation processing support (e.g., AnnotationAttributesReadingVisitor, etc.).

          Show
          sbrannen Sam Brannen added a comment - Update: SPR-12703 covers interface support in AnnotatedElementUtils ; however, I am leaving this issue open for the time being in order to ensure we cover the same use cases for Spring's ASM-based annotation processing support (e.g., AnnotationAttributesReadingVisitor , etc.).

            People

            • Assignee:
              sbrannen Sam Brannen
              Reporter:
              sbrannen Sam Brannen
              Last updater:
              Juergen Hoeller
            • Votes:
              1 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Days since last comment:
                2 years, 39 weeks ago