[weld-dev] Bridge methods & proxies & interceptors

Stuart Douglas stuart.w.douglas at gmail.com
Mon Sep 24 20:06:39 EDT 2012


I think this is actually in AS7 bug. AS7 should never send a bridge 
method through the interceptor context.

The code in question is

https://github.com/jbossas/jboss-as/blob/master/ee/src/main/java/org/jboss/as/ee/component/ViewDescription.java#L199

My code finding the 'real' method does not take into account that the 
method parameters could change as well as the return type.

Stuart

Marko Lukša wrote:
> Hey
>
> I need someone to take a look at https://github.com/weld/core/pull/225
>
> My initial change was to add bridge methods to the proxy (when proxying
> an interface), but later realized this could never work, because the
> interceptors expect a Method object that would have to point to a
> non-existing method (the method exists only on the proxy, but not on the
> interface).
>
> That's why the only solution was to make Beans.getInterceptableMethods()
> return the bridge methods also. The reason why you guys had problems
> with this in the past was the fact that MethodReference was missing the
> return type and thus treated two methods with the same name and
> parameters but different return types as equal, when they clearly
> aren't. This is why Weld was throwing the duplicate interceptor
> definition errors.
>
> Marko
>
> On 7.9.2012 17:43, Marko Lukša wrote:
>> Yes, when the proxy extends a class, everything is taken care of by
>> the bridge method in the superclass. But, when dealing with local EJB
>> interfaces, the proxy's superclass is Object, so there is no bridge
>> method at all.
>>
>> For EJBs, the stacktrace would look something like this:
>>     StringFooImpl.doSth(String)
>>     StringFooImpl.doSth(Object)
>>     methodHandler.invoke("doSth(Object)")
>>     StringFoo$Proxy.doSth(Object) <-- proxy extends Object, implements
>> StringFoo interface (no bridge method)
>>
>> For regular managed beans, the stacktrace would look like this:
>>     StringFooImpl.doSth(String)
>>     methodHandler.invoke("doSth(String)")
>>     StringFooImpl$Proxy.doSth(String)
>>     StringFooImpl$Proxy.doSth(Object) <-- proxy extends StringFooImpl
>> (and has bridge method)
>>
>> Note the different methods methodHandler is handling.
>>
>> Marko
>>
>>
>> On 7.9.2012 17:27, Stuart Douglas wrote:
>>> IMHO the correct way to deal with this is to simply make bridge
>>> methods delegate to super(), which will then result in the actual
>>> intercepted method being called.
>>>
>>> To be honest I thought we already did this, as we have had multiple
>>> related bugs in the past. Do you have a test case that I can look at?
>>>
>>> Stuart
>>>
>>>> Marko Lukša <mailto:marko.luksa at gmail.com>
>>>> 7 September 2012 7:19 PM
>>>> Hey all.
>>>>
>>>> I've been working on https://issues.jboss.org/browse/WELD-1162 and
>>>> need your opinion.
>>>>
>>>> Say we have:
>>>>
>>>> public interface Foo<T> {
>>>>    void doSomething(T t);
>>>> }
>>>> public interface StringFoo extends Foo<String> {}
>>>> public class StringFooImpl implements StringFoo {}
>>>>
>>>> and
>>>>
>>>> @Inject StringFoo stringFoo;
>>>>
>>>> The proxy created by Weld is a subclass of StringFooImpl and
>>>> therefore has two declared methods:
>>>>
>>>> void doSomething(Object o) { doSomething((String) o); }
>>>> void doSomething(String) {...}
>>>>
>>>> However, when StringFooImpl is a session bean, with StringFoo as its
>>>> local interface, the proxy is a subclass of Object and therefore the
>>>> proxy only has the following declared method:
>>>>
>>>> void doSomething(Object o);
>>>>
>>>> In both cases, when a client invokes stringFoo.doSomething("foo"),
>>>> the method doSomething(Object) is invoked. But there's a difference
>>>> in what happens next:
>>>>
>>>>   * In the non-ejb version, the bridge method then immediately
>>>>     invokes doSomething(String) and only then is the proxy's method
>>>>     handler invoked. The handler is therefore dealing with the
>>>>     method doSomething(*String*)
>>>>   * in the EJB version, doSomething(Object) is not a bridge method,
>>>>     and so the method handler is invoked directly and it (the
>>>>     handler) is operating on doSomething(*Object*).
>>>>
>>>> In the second case, this ultimately means that Weld will check
>>>> whether doSomething(Object) is intercepted. It isn't, since
>>>> Beans.getInterceptableMethods() is ignoring bridge methods. The
>>>> interceptor will not be invoked. On the other hand, in the first
>>>> case, the interceptor _will_ be invoked, since Weld will be checking
>>>> whether doSomething(String) is intercepted.
>>>>
>>>> My initial solution was to make Beans.getInterceptableMethods() also
>>>> return bridge methods, but now I'm thinking the actual problem is in
>>>> the proxy itself. IMO, when creating a proxy based on an interface,
>>>> we should also generate bridge methods on the proxy (this should be
>>>> either done by Weld or by Javassist directly). These bridge methods
>>>> should be perfectly normal bridge methods and should not invoke the
>>>> method handler directly. They should simply invoke the non-bridge
>>>> method and the non-bridge method should then invoke the method handler.
>>>>
>>>> The java compiler can't add bridge methods directly to interfaces
>>>> which require them, so it adds them to all the classes implementing
>>>> the interface (StringFooImpl in our case). Since we are creating
>>>> StringFoo$Proxy, which is also a class implementing an interface
>>>> which requires bridge methods, we should add the bridge methods
>>>> to it - exactly as the java compiler would.
>>>>
>>>> This would solve the interceptor problem and possibly other similar
>>>> problems as well.
>>>>
>>>> What do you think?
>>>>
>>>> Marko
>>>>
>>>>
>>>> _______________________________________________
>>>> weld-dev mailing list
>>>> weld-dev at lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/weld-dev
>>
>
> _______________________________________________
> weld-dev mailing list
> weld-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/weld-dev


More information about the weld-dev mailing list