Given the following code
public interface Foo<T> { T get(); } @Remote public interface Bar extends Foo<String> { } @Stateless public class BarImpl implements Bar { @Interceptors(ExceptionInterceptor.class) public String get() { throw new RuntimeException("not implemented"); } } public class ExceptionInterceptor { @AroundInvoke public Object convertExceptionForExternalSystem(InvocationContext ctx) throws RuntimeException, Error { try { return ctx.proceed(); } catch (Throwable e) { if (e instanceof Error) throw new Error("Changed"); throw new RuntimeException("Changed"); } } }
When we call the method on the remote control,
Bar bar = context.lookup(Bar.class.getName()); bar.get();
or
Foo foo = context.lookup(Bar.class.getName()); foo.get();
the interceptor is not called (using Glassfish 3.0.1).
The problem seems to be due to the compiled class file for the interface
javap Foo Compiled from "Foo.java" public interface Foo{ public abstract java.lang.Object get(); }
whereas for BarImpl it
javap BarImpl Compiled from "BarImpl.java" public class BarImpl extends java.lang.Object implements Bar{ public BarImpl(); public java.lang.String get(); public java.lang.Object get(); }
So, when we call
Bar bar = ...; bar.get();
Internally method
public java.lang.Object get();
which will delegate
public java.lang.String get();
Interceptors seem to be called only on the first call. When I change the interface panel to
@Remote public interface Bar extends Foo<String> { @Override String get(); }
The interceptor is called in the first call (bar.get ()), but not in the second call (foo.get ()). Defining interceptors at the class level can solve the problem, but in our case this is not an option.
Are we doing something wrong, or is this a common java-ee-6 problem, or is it a bug in glass fish? Is there a workaround? Or should we completely abandon the use of generics in our Services?