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.