https://issues.apache.org/bugzilla/show_bug.cgi?id=47512
Summary: Binding java.lang.reflect.Proxy to JNDI directory raises java.lang.ClassCastException Product: Tomcat 6 Version: 6.0.18 Platform: All OS/Version: All Status: NEW Severity: normal Priority: P2 Component: Catalina AssignedTo: dev@tomcat.apache.org ReportedBy: mrr...@gmail.com I've created a custom javax.naming.spi.ObjectFactory that is able to bind javax.naming.Reference(s) into the global JNDI naming directory during startup time using a org.apache.catalina.LifecycleListener. I want two separate web contexts invoke the custom ObjectFactory#getObjectInstance method indirectly, getting through the local to the global JNDI context with a ResourceLink by invoking the local InitialContext#lookup method. Since both contexts have different classloaders my intention is to create a java.lang.reflect.Proxy given the current thread classloader. For the first web context, everything goes Ok. The thread reaches the ObjectFactory, the object factory peeks the current thread classloader (always a webapp classloader), peeks the name of the interface to use for Proxy#newProxyInstance method, and the object to proxify for an internal collection and returns the proxy. The problem arises for the second web context. The InitialContext#lookup method resolves the name and, although the thread never reaches the ObjectFactory, the object is resolved. Surprisingly, the returned object is the proxy created for the first web context. This proxy implements an interface available in the first web context's classloader. This interface is present in the second context classpath, but is loaded by a different webapp classloader. Thus, a java.lang.ClassCastException is raised. Digging into the tomcat codebase, I found in org.apache.naming.NamingContext that once a reference is resolved, the resolved object is sort of rebound to the original name. Thus, when the second lookup invocation arrives, the name is associated to an object (not a reference) and the ObjectFactory is never invoked. Here's the org.apache.naming.NamingContext code, lines 791 to 799: } else if (entry.type == NamingEntry.REFERENCE) { try { Object obj = NamingManager.getObjectInstance(entry.value, name, this, env); if (obj != null) { entry.value = obj; entry.type = NamingEntry.ENTRY; } return obj; When a NamingEntry.REFERENCE arrive, the reference is resolved with the help of a javax.naming.spi.NamingManager. If the resolved object is null, the entry is converted to a NamingEntry.ENTRY instead of leaving it as a NamingEntry.REFERENCE. In my opinion, the entry should be left as a REFERENCE, so the next invocation to the method, no matter who is the invoker nor its classloader, resolves the reference again with the javax.naming.spi.NamingManager's help. This "cache" policy of references should be left to the ObjectFactory itself, which will have all the necessary information to apply such a policy. The code change would only imply the removal of the if I've shown above. Regards, Martin. -- Configure bugmail: https://issues.apache.org/bugzilla/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are the assignee for the bug. --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org