Uploaded image for project: 'Weld'
  1. Weld
  2. WELD-2673

@Decorated Bean<> injection point can get populated with wrong meta data

XMLWordPrintable

    • Hide

       

      Define two Decorators like so

      public interface MyInterface {
          String someMethod();
      }
      
      @Decorator
      @Priority(Interceptor.Priority.APPLICATION)
      public class OuterDecorator implements MyInterface {
          @Inject @Delegate MyInterface delegate;
      
          @Inject @Decorated Bean<MyInterface> beanMetaData;
      
          @Override
          public String someMethod() {
              System.out.println("Outer,bean="+beanMetaData.getBeanClass().getName());
              return delegate.someMethod();
          }
      }
      
      
      @Decorator
      @Priority(Interceptor.Priority.APPLICATION+1)
      public class InnerDecorator implements MyInterface {
          @Inject @Delegate
          MyInterface delegate;
      
          @Inject @Decorated
          Bean<MyInterface> beanMetaData;
      
          @Override
          public String someMethod() {
              System.out.println("Inner,bean="+beanMetaData.getBeanClass().getName());
              return delegate.someMethod();
          }
      }
      

       

      Then the following program

      public class Main {
          public static void main(String[] args) {
              try (WeldContainer seContainer = createCdiContainer()) {
                  MyDummyBean myDummyBean = seContainer.select(MyDummyBean.class).get();
                  System.out.println("Hello "+ myDummyBean.someMethod());
              }
          }
          private static WeldContainer createCdiContainer() {
              return new Weld().disableDiscovery()
                      .addBeanClasses(MyDummyBean.class,
                          InnerDecorator.class,
                          OuterDecorator.class)
                      .initialize();
          }
      
          @Dependent
          public static class MyDummyBean implements MyInterface{
              @Override
              public String someMethod() {
                  return "World";
              }
          }
      }
      
      

      prints

      Outer,bean=org.example.Main$MyDummyBean
      Inner,bean=org.example.OuterDecorator
      Hello World

       

      This indicates and debugging indeed shows: OuterDecorator gets the right Bean<MyInterface> object injected into its beanMetaData field, while InnerDecorator gets a Decorator<OuterDecorator> instance injected into it.

      To me, this is a violation of the CDI Spec. At the very least it breaks my expectations what @Inject @Decorated Bean<> should to. It should give access to meta-data about the decorated managed bean/session bean but not other decorators. Even if one is to assume that in cases of decorator stacking, the outer decorator only gets information about the bean of the immediately injected object which the delegate field points to, the example has the wrong behaviour, because the OuterDecorator has (a proxy version of) InnerDecorator injected and InnerDecorator has (a proxy version of) MyDummyBean  injected.

      In situations where decorators from independent sources are applied to the same bean (say a software with some sort of plugin-system), this almost certainly causes a bug, because each decorator expects to have access to the decorated bean and wouldn't even know what to do with information about unrelated decorator beans which may or may not be present.

       

      Show
        Define two Decorators like so public interface MyInterface { String someMethod(); } @Decorator @Priority(Interceptor.Priority.APPLICATION) public class OuterDecorator implements MyInterface { @Inject @Delegate MyInterface delegate; @Inject @Decorated Bean<MyInterface> beanMetaData; @Override public String someMethod() { System .out.println( "Outer,bean=" +beanMetaData.getBeanClass().getName()); return delegate.someMethod(); } } @Decorator @Priority(Interceptor.Priority.APPLICATION+1) public class InnerDecorator implements MyInterface { @Inject @Delegate MyInterface delegate; @Inject @Decorated Bean<MyInterface> beanMetaData; @Override public String someMethod() { System .out.println( "Inner,bean=" +beanMetaData.getBeanClass().getName()); return delegate.someMethod(); } }   Then the following program public class Main { public static void main( String [] args) { try (WeldContainer seContainer = createCdiContainer()) { MyDummyBean myDummyBean = seContainer.select(MyDummyBean.class).get(); System .out.println( "Hello " + myDummyBean.someMethod()); } } private static WeldContainer createCdiContainer() { return new Weld().disableDiscovery() .addBeanClasses(MyDummyBean.class, InnerDecorator.class, OuterDecorator.class) .initialize(); } @Dependent public static class MyDummyBean implements MyInterface{ @Override public String someMethod() { return "World" ; } } } prints Outer,bean=org.example.Main$MyDummyBean Inner,bean=org.example.OuterDecorator Hello World   This indicates and debugging indeed shows: OuterDecorator gets the right Bean<MyInterface> object injected into its beanMetaData field, while InnerDecorator gets a Decorator<OuterDecorator> instance injected into it. To me, this is a violation of the CDI Spec. At the very least it breaks my expectations what @Inject @Decorated Bean<> should to. It should give access to meta-data about the decorated managed bean/session bean but not other decorators. Even if one is to assume that in cases of decorator stacking, the outer decorator only gets information about the bean of the immediately injected object which the delegate field points to, the example has the wrong behaviour, because the OuterDecorator has (a proxy version of) InnerDecorator injected and InnerDecorator has (a proxy version of) MyDummyBean  injected. In situations where decorators from independent sources are applied to the same bean (say a software with some sort of plugin-system), this almost certainly causes a bug, because each decorator expects to have access to the decorated bean and wouldn't even know what to do with information about unrelated decorator beans which may or may not be present.  
    • Undefined

      In a situation where the same beans has multiple Decorators stacked on top of each other, it is possible that one of them gets the wrong @Decorated Bean<> meta data injected into it.

            manovotn Matěj Novotný
            johannes-hahn Johannes Hahn (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: