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@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(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/weld-dev