You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openwebbeans.apache.org by "Alexander Zapletal (JIRA)" <ji...@apache.org> on 2018/03/01 16:53:00 UTC

[jira] [Created] (OWB-1234) generic classes are not correctly proxied when bridge methods are involved

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)