Alexander Zapletal created OWB-1234:
---------------------------------------

             Summary: generic classes are not correctly proxied when bridge 
methods are involved
                 Key: OWB-1234
                 URL: https://issues.apache.org/jira/browse/OWB-1234
             Project: OpenWebBeans
          Issue Type: Bug
          Components: Interceptor and Decorators
    Affects Versions: 2.0.4
            Reporter: Alexander Zapletal


The proxy generated by _NormalScopeProxyFactory_ does not contain (overriding) 
proxy methods for bridge methods, because brdige methods are generally ignored 
by the proxy generation, see _AbstractProxyFactory.unproxyableMethod()_ and 
_ClassUtil.addNonPrivateMethods()_ .

(See also OWP-923)

But this can lead to wrong proxies:
{code:java}
interface Contract {
  void doIt(Integer param);
}
{code}
{code:java}
public class BaseBean<T extends Number> {
  public void doIt(T param) {
  }
}
{code}
{code:java}
@ApplicationScoped
public class MyBean extends BaseBean<Integer> implements Contract { 
}
{code}
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:
{code:java}
public class BaseBean {
  public void doIt(Number param) {
  }
}
{code}
{code:java}
public class MyBean {

  // bridge method!
  public void doIt(Integer param) {
        super.doIt(param);
  }
}
{code}
_NormalScopeProxyFactory_ generates a proxy class that (roughly) corresponds to 
the following code:
{code:java}
public class MyBean$$OwbNormalScopeProxy extends MyBean {
  
  public void doIt(Number var1) {
    ((MyBean)this.owbContextualInstanceProvider.get()).doIt(var1);
  }
}
{code}
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!
{code:java}
  @Inject Contract handler;
  handler.doIt(4711) 
{code}
Reason: When _NormalScopeProxyFactory_ generated the proxy for _MyBean,_ it 
found the following two methods (amongst others):
{code:java}
void doIt(Number var1)  // inherited from BaseBean
void doIt(Integer var1) // bridge method
{code}
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
{code:java}
@ApplicationScoped
public class MyBean extends BaseBean<Integer> implements Contract { 
  @Override
  public void doIt(Integer param) {
    super.doIt(param);
  }
}
{code}
Now, the method _doIt(Integer)_ is not a bridge method anymore and 
_NormalScopeProxyFactory_ will generate a proxy method for it.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to