Uploaded image for project: 'OpenWebBeans'
  1. OpenWebBeans
  2. OWB-1234

generic classes are not correctly proxied when bridge methods are involved

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 2.0.4
    • None
    • None

    Description

      Proxies generated by NormalScopeProxyFactory do not contain (overriding) proxy methods for bridge methods, because bridge methods are generally ignored by the proxy generation, see AbstractProxyFactory.unproxyableMethod() and ClassUtil.addNonPrivateMethods() .

      (See also OWB-923)

      But this can lead to wrong proxies:

      interface Contract {
        void doIt(Integer param);
      }
      
      public class BaseBean<T extends Number> {
        public void doIt(T param) {
        }
      }
      
      @ApplicationScoped
      public class MyBean extends BaseBean<Integer> implements Contract { 
      }
      

      When compiling this code the compiler performs type erasure and needs to generate a bridge method. The generated byte code corresponds (roughly) to the following code:

      public class BaseBean {
        public void doIt(Number param) {
        }
      }
      
      public class MyBean {
      
        // bridge method!
        public void doIt(Integer param) {
      	super.doIt(param);
        }
      }
      

      NormalScopeProxyFactory generates a proxy class that (roughly) corresponds to the following code:

      public class MyBean$$OwbNormalScopeProxy extends MyBean {
        
        public void doIt(Number var1) {
          ((MyBean)this.owbContextualInstanceProvider.get()).doIt(var1);
        }
      }
      

      But when we now call, for instance, doIt(4711) on an injected instance of Contract , we actually call MyBean.doIt(Integer) and thereby we bypass the proxy!

        @Inject Contract handler;
        handler.doIt(4711) 
      

      Reason: When NormalScopeProxyFactory generated the proxy for MyBean, it found the following two methods (amongst others):

      void doIt(Number var1)  // inherited from BaseBean
      void doIt(Integer var1) // bridge method
      

      Since NormalScopeProxyFactory ignores bridge methods, it only generated a proxy method for doIt(Number) . This method overloads MyBean.doIt(Integer) , it does not override it. So, handler.doIt(4711) actually calls MyBean.doIt(Integer) .

       

      IMPORTANT NOTE: There is a quite simple workaround for this problem: Just implement the bridge method yourself. I.e. in the example above use the following implementation

      @ApplicationScoped
      public class MyBean extends BaseBean<Integer> implements Contract { 
        @Override
        public void doIt(Integer param) {
          super.doIt(param);
        }
      }
      

      Now, the method doIt(Integer) is not a bridge method anymore and NormalScopeProxyFactory will generate a proxy method for it.

      Attachments

        Activity

          People

            struberg Mark Struberg
            azapletal Alexander Zapletal
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated: