6 Replies Latest reply on Dec 26, 2015 6:53 PM by shamoh

    Proxy classes lose original class annotations

    shamoh

      Hello all.

      I would like to ask transparent support of annotation propagated to proxy classes from original class.

      (This post is originally comment on CDI-10 issue.)

      I hope it will work transparently. It seams to me strange to check if some application class instance is proxy or not to get Annotation instances written on class I've injected. I know I could write utility method for my code (and hope it correctly detects proxies):

       

      public static <A extends Annotation> A getAnnotationProxyReady(Class<?> clazz, Class<A> annotationClass) {
         final A annotation = clazz.getAnnotation(annotationClass);
       
         if (annotation == null
        && (clazz.isSynthetic())) { //OK, this is probably proxy
         return getAnnotationProxyReady(clazz.getSuperclass(), annotationClass);
        } else {
         return annotation;
        }
      } 

       

      and now I can access annotation written on bean:

       

      @Target({ TYPE, METHOD, FIELD })
      @Retention(RUNTIME)
      @Documented
      public @interface MyAnnotation {
        String attr1();
         int attr2;
      }
      @MyAnnotation(attr1="aaa", attr2=42)
      public class MyBean {
         //...
      }
      @Inject
      private MyBean myBean;
       
      public void methodA() throws NoSuchMethodException {
        MyAnnotation myAnn = getAnnotationProxyReady(myBean.getClass(), MyAnnotation.class);
         //use my bean annotations ...
      } 

       

      But I can not expect 3rd party libraries support such approach. 3rd party libraries just works with objects and classes and its annotations. They don't what to care about any proxy objects or different proxy implementations to do their business.

      Note: It works with Annotations annotated by @Inherited what is expected.

       

      @Target({ TYPE, METHOD, FIELD })
      @Retention(RUNTIME)
      @Documented
      @Inherited
      public @interface MyAnnotation {
        String attr1();
         int attr2;
      } 

       

      So I would like to vote for: The proxy bean contains same annotations as original class. And exactly that class not its super-classes.
      Note: It is necessary to say that it already works for method annotations, see WELD-1131. So the issue remains just on class itself.

        • 1. Re: Proxy classes lose original class annotations
          meetoblivion

          If you know you're dealing with MyBean, why not pass in MyBean.class instead of myBean.getClass() ?

          • 2. Re: Proxy classes lose original class annotations
            shamoh

            This is just an simplified example. In real application I don't use MyBean class name and use interfaces or "search" all sub-classes using @Instance annotation.

            • 3. Re: Proxy classes lose original class annotations
              meetoblivion

              Could you maybe provide more information about your use case?  My hunch is that this is a case for annotation processing within a CDI extension, instead of the way you may be doing it.

               

              And actually, based on what you're describing, it seems like the issue is fixed w/ @Inherited.  What you're requesting goes against the intention of @Inherited - you're trying to make annotations always inherited.

              • 4. Re: Proxy classes lose original class annotations
                shamoh

                Let's say I want to "find" / inject all instances of JAX-RS Application implementations. And then and I would like to read JAX-RS ApplicationPath annotation on it.

                 

                In this example the ApplicationPath is not my annotation and is not annotated by @Inherited. I think that this should be implementation detail of CDI implementation that it uses some proxy technology. It does not look transparent to me that injected instance of MyBean does not contain same annotations as written by developer directly on the MyBean class.

                • 5. Re: Proxy classes lose original class annotations
                  meetoblivion

                  This definitely sounds like a case for using a CDI extension, instead of runtime lookup.  Your extension can subscribe to

                   

                  @Observes @WithAnnotation(ApplicationPath.class) ProcessAnnotatedType pat

                   

                  and then get the real runtime configuration there, making it accessible from your extension instead of looked up here.   

                   

                  Here's how its done in the ResteasyCdiExtension.

                  • 6. Re: Proxy classes lose original class annotations
                    shamoh

                    Hello.

                     

                    JAX-RS Application was just an example. I would like to expect that each injected proxy bean contains same annotations as written at original bean. (As well as 3rd party libraries that are not CDI aware.)

                     

                    I tried to write myself CDI extension but was not able to pass original bean annotation instances to proxy bean. I'm not sure it is even possible. Or I have used it wrong way.

                     

                    Thanks,

                    Libor