Why does Introspector
not correctly discover the properties of a dynamic proxy class in Jetty/GAE?
I ran into this curious problem while trying to use a dynamic proxy with Java EL/JSPs when deploying locally on GAE with Jetty. You can see the original question here.
Anyways, I have since simplified the code and narrowed down the problem. Here is the new code:
MyServlet.java:
package test;
// imports omitted
public class MyServlet extends HttpServlet {
public interface MyInterface {
public String getValue();
}
private static <T> T getProxy(Class<T> c) {
return (T)Proxy.newProxyInstance(
klass.getClassLoader(),
new Class<?>[]{ klass },
new InvocationHandler() {
@Override public Object invoke(Object proxy, Method m,
Object[] args) throws Throwable {
return null;
}
});
}
public static void testIntrospection() {
StringBuilder sb = new StringBuilder();
try {
MyInterface proxy = getProxy(MyInterface.class);
BeanInfo info = Introspector.getBeanInfo(proxy.getClass());
for (PropertyDescriptor d : info.getPropertyDescriptors())
sb.append(d.getName()).append(", ");
} catch (Exception e) {
throw new AssertionError("failed", e);
}
throw new AssertionError("found: " + sb.toString());
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse resp) {
testIntrospection();
}
public static void main(String... args) {
testIntrospection();
}
}
When I deploy the code above and send a GET request, I get the following:
java.lang.AssertionError: found: class,
However, I expected that both class
and value
would be discovered, as per the documentation for Proxy. But, when I just run it in main()
, I get the expected output. I also tried putting the proxied interface in a separate file/package, and it did not work. To make things weirder, I also get the expected output when I change MyInterface
to be private, protected, or default.
Why have I limited the question to GAE/Jetty? Because I was able to deploy the exact same servlet on Tomcat 7 with no problem, even when MyInterface
is public.
In case it's relevant, I am using the Google plugin in Eclipse Juno, and I am only deploying locally.
One last thing: I checked the output of proxy.getClass().getDeclaredMethods()
and it did include getValue
. However, I can't simply parse the bean properties myself, because I need it to work in EL, which relies on Introspector
.
I am really stumped by this one, so any guidance is greatly appreciated.