Classloading problem in proxy factories
brian.stansberry Aug 21, 2008 11:08 AMI'm testing proxy-clustered and am seeing a failure that looks like a problem in the core proxy module.
Test is doing a lookup of an SLSB; call to ProxyFactory to create the proxy fails:
javax.naming.NamingException: Could not dereference object [Root exception is java.lang.RuntimeException: Could not create the EJB3 Business Proxy implementing "org.jboss.ejb3.test.clusteredsession.ClusteredStatelessRemote" for clusteredStateless] at org.jnp.interfaces.NamingContext.getObjectInstanceWrapFailure(NamingContext.java:1340) at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:765) at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:629) at javax.naming.InitialContext.lookup(InitialContext.java:351) at org.jboss.ejb3.test.clusteredsession.unit.StatelessUnitTestCase.testLoadbalance(StatelessUnitTestCase.java:72) at junit.extensions.TestDecorator.basicRun(TestDecorator.java:24) at junit.extensions.TestSetup$1.protect(TestSetup.java:23) at junit.extensions.TestSetup.run(TestSetup.java:27) Caused by: java.lang.RuntimeException: Could not create the EJB3 Business Proxy implementing "org.jboss.ejb3.test.clusteredsession.ClusteredStatelessRemote" for clusteredStateless at org.jboss.ejb3.proxy.factory.session.SessionProxyFactoryBase.createProxyBusiness(SessionProxyFactoryBase.java:234) at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:121) at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRemotingInvocationHandler.java:82) at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:908) at org.jboss.remoting.transport.socket.ServerThread.completeInvocation(ServerThread.java:742) at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:695) at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:522) at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:230) Caused by: java.lang.LinkageError: loader constraints violated when linking org/jboss/ejb3/test/clusteredsession/NodeAnswer class at java.lang.Class.getDeclaredConstructors0(Native Method) at java.lang.Class.privateGetDeclaredConstructors(Class.java:2357) at java.lang.Class.getConstructor0(Class.java:2671) at java.lang.Class.getConstructor(Class.java:1629) at org.jboss.ejb3.proxy.factory.ProxyFactoryBase.createProxyConstructor(ProxyFactoryBase.java:124) at org.jboss.ejb3.proxy.factory.session.SessionProxyFactoryBase.createProxyBusiness(SessionProxyFactoryBase.java:212) at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:121) at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRemotingInvocationHandler.java:82) at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:908) at org.jboss.remoting.transport.socket.ServerThread.completeInvocation(ServerThread.java:742) at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:695) at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:522) at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:230) at org.jboss.remoting.MicroRemoteClientInvoker.invoke(MicroRemoteClientInvoker.java:206) at org.jboss.remoting.Client.invoke(Client.java:1708) at org.jboss.remoting.Client.invoke(Client.java:612) at org.jboss.aspects.remoting.InvokeRemoteInterceptor.invoke(InvokeRemoteInterceptor.java:60) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102) at org.jboss.aspects.remoting.ClusterChooserInterceptor.invoke(ClusterChooserInterceptor.java:84) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102) at org.jboss.ejb3.proxy.remoting.IsLocalProxyFactoryInterceptor.invoke(IsLocalProxyFactoryInterceptor.java:72) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102) at org.jboss.aspects.remoting.ClusteredPojiProxy.invoke(ClusteredPojiProxy.java:79) at $Proxy2.createProxyBusiness(Unknown Source) at org.jboss.ejb3.proxy.objectfactory.session.SessionProxyObjectFactory.createProxy(SessionProxyObjectFactory.java:129) at org.jboss.ejb3.proxy.clustered.objectfactory.session.SessionClusteredProxyObjectFactory.getProxy(SessionClusteredProxyObjectFactory.java:76) at org.jboss.ejb3.proxy.objectfactory.ProxyObjectFactory.getObjectInstance(ProxyObjectFactory.java:146) at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:304) at org.jnp.interfaces.NamingContext.getObjectInstance(NamingContext.java:1315) at org.jnp.interfaces.NamingContext.getObjectInstanceWrapFailure(NamingContext.java:1332) at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:765) at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:629) at javax.naming.InitialContext.lookup(InitialContext.java:351) at org.jboss.ejb3.test.clusteredsession.unit.StatelessUnitTestCase.testLoadbalance(StatelessUnitTestCase.java:72) at junit.extensions.TestDecorator.basicRun(TestDecorator.java:24) at junit.extensions.TestSetup$1.protect(TestSetup.java:23) at junit.extensions.TestSetup.run(TestSetup.java:27)
Failure is coming in the SessionProxyFactoryBase code that attempts to replace the cached proxy constructor with one created using the TCCL:
// Obtain the correct business proxy constructor Constructor<?> constructor = this.getConstructorsProxySpecificBusinessInterface().get( businessInterfaceName.trim()); /* * In place for web injection (isolated CL) */ ClassLoader tcl = Thread.currentThread().getContextClassLoader(); try { // See if we can get at the bean class from the TCL Class<?> businessInterfaceClass = Class.forName(businessInterfaceName, false, tcl); // If so, use the TCL to generate the Proxy class, not the Container CL Set<Class<?>> businessInterfaces = new HashSet<Class<?>>(); businessInterfaces.add(businessInterfaceClass); constructor = this.createProxyConstructor(businessInterfaces, tcl); } catch (ClassNotFoundException cce) { // Ignore }
The business interface is simple:
public interface ClusteredStatelessRemote { NodeAnswer getNodeState(); }
It's odd to me that Class.forName() is able to load the ClusteredStatelessRemote class using the TCCL, and a nested call to Proxy.getProxyClass(...) passing the classloader and the interface is able to generate a proxy class, yet there is a LinkageError trying to find the constructor.