Implemented an experimental feature in the spirit of the @Proxy concept where
an interface can be given along with an InvocationHandler implementation.
When the bean is created we'd create the InvocationHandler, create a proxy
using the interface, then use the proxy as the bean instance.
Took this idea a bit further to allow for abstract classes to get the same perk
and more. If the bean class is abstract and implements
java.lang.reflect.InvocationHandler, then the abstract methods will delegate to
the bean's java.lang.reflect.InvocationHandler.invoke(..) method.
This allows for sort of a hybrid approach where some methods can be abstract
and handled in a reflection-like manner, while others can be implemented
regularly.
An interesting difference is the code takes extreme care to implement all the
constructors of the parent class as well as the annotations of the parent class
and any method annotations and method param annotations of abstract methods.
This should allow the dynamically created class to replace the parent class in
every way, including usage in annotation heavy APIs like JAX-RS, JAX-WS or CDI.
I tested JAX-RS and it seems to work perfectly.
For example see this RESTful service:
@Stateless
@Path("/ejb")
public abstract class RESTIsVeryCool implements InvocationHandler {
@EJB
private SimpleEJB simpleEJB;
@javax.ws.rs.core.Context
Request request;
@Path("/normal")
@GET
public abstract String normal();
@Path("/rest")
@GET
public abstract String rest();
@Path("/param")
@GET
public String param(@QueryParam("arg") @DefaultValue("true") String p) {
return p;
}
@Path("/field")
@GET
public boolean field() {
return "GET".equals(request.getMethod());
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable {
return simpleEJB.ok();
}
}
This is of course an experiment. All sorts of feedback welcome! We can go
anywhere or nowhere with this :)
-David