Note that there are some explanatory texts on larger screens.

plurals
  1. POHow can I create a dynamic proxy in java that retains parameter annotations on methods?
    text
    copied!<p>I currently am trying to proxy some existing JAX/RS resources, in order to allow me to use the Hibernate Validator's method validation support. However, when I proxy my class (currently using cglib 2.2), the FormParam annotation is not present on parameters in the proxy class, and so the JAX/RS runtime (apache wink) is not populating parameters. Here's some test code that shows this:</p> <pre><code>import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.*; import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import javassist.util.proxy.ProxyFactory; public class ProxyTester { @Target( { PARAMETER }) @Retention(RUNTIME) public static @interface TestAnnotation { } public static interface IProxyMe { void aMethod(@TestAnnotation int param); } public static class ProxyMe implements IProxyMe { public void aMethod(@TestAnnotation int param) { } } static void dumpAnnotations(String type, Object proxy, Object forObject, String forMethod) { String className = forObject.getClass().getName(); System.err.println(type + " proxy for Class: " + className); for (Method method : proxy.getClass().getMethods()) { if (method.getName().equals(forMethod)) { final int paramCount = method.getParameterTypes().length; System.err.println(" Method: " + method.getName() + " has " + paramCount + " parameters"); int i = 0; for (Annotation[] paramAnnotations : method .getParameterAnnotations()) { System.err.println(" Param " + (i++) + " has " + paramAnnotations.length + " annotations"); for (Annotation annotation : paramAnnotations) { System.err.println(" Annotation " + annotation.toString()); } } } } } static Object javassistProxy(IProxyMe in) throws Exception { ProxyFactory pf = new ProxyFactory(); pf.setSuperclass(in.getClass()); Class c = pf.createClass(); return c.newInstance(); } static Object cglibProxy(IProxyMe in) throws Exception { Object p2 = Enhancer.create(in.getClass(), in.getClass() .getInterfaces(), new MethodInterceptor() { public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { return arg3.invokeSuper(arg0, arg2); } }); return p2; } static Object jdkProxy(final IProxyMe in) throws Exception { return java.lang.reflect.Proxy.newProxyInstance(in.getClass() .getClassLoader(), in.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(in, args); } }); } public static void main(String[] args) throws Exception { IProxyMe proxyMe = new ProxyMe(); dumpAnnotations("no", proxyMe, proxyMe, "aMethod"); dumpAnnotations("javassist", javassistProxy(proxyMe), proxyMe, "aMethod"); dumpAnnotations("cglib", cglibProxy(proxyMe), proxyMe, "aMethod"); dumpAnnotations("jdk", jdkProxy(proxyMe), proxyMe, "aMethod"); } } </code></pre> <p>This gives me the following output:</p> <pre> no proxy for Class: ProxyTester$ProxyMe Method: aMethod has 1 parameters Param 0 has 1 annotations Annotation @ProxyTester.TestAnnotation() javassist proxy for Class: ProxyTester$ProxyMe Method: aMethod has 1 parameters Param 0 has 0 annotations cglib proxy for Class: ProxyTester$ProxyMe Method: aMethod has 1 parameters Param 0 has 0 annotations jdk proxy for Class: ProxyTester$ProxyMe Method: aMethod has 1 parameters Param 0 has 0 annotations </pre> <p>Are there any other alternatives?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload