Cleanup problem with Ejb3Registrar and proxy factories
brian.stansberry Aug 21, 2008 10:36 PMThis post is specifically about code in the proxy module, but I think it might point to a general issue with Ejb3McRegistrar. Cutting to the chase, it looks like Ejb3McRegistrar leaves no way to back out a failed bind() call.
I had a test with a misnamed deployment descriptor, which led to a failure in proxy factory registration:
2008-08-21 18:50:39,196 ERROR [org.jboss.kernel.plugins.dependency.AbstractKernelController] (RMI TCP Connection(18)-192.168.1.146) Error installing to Start: name=ProxyFactory/ClusteredStatefulRemote state=Create java.lang.IllegalStateException: Partition Ejb3IsLocalTestPartition not found at org.jboss.ha.framework.server.HAPartitionLocator.getHAPartition(HAPartitionLocator.java:124) at org.jboss.ejb3.proxy.clustered.registry.ProxyClusteringRegistry.registerClusteredBean(ProxyClusteringRegistry.java:114) at org.jboss.ejb3.proxy.clustered.factory.session.stateful.StatefulSessionClusteredProxyFactory.start(StatefulSessionClusteredProxyFactory.java:111) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ..... at org.jboss.kernel.plugins.dependency.AbstractKernelController.install(AbstractKernelController.java:106) at org.jboss.ejb3.common.registrar.plugin.mc.Ejb3McRegistrar.install(Ejb3McRegistrar.java:309) at org.jboss.ejb3.common.registrar.plugin.mc.Ejb3McRegistrar.bind(Ejb3McRegistrar.java:163) at org.jboss.ejb3.proxy.jndiregistrar.JndiSessionRegistrarBase.registerProxyFactory(JndiSessionRegistrarBase.java:906) .....
That's fine; it was a bad deployment. But the problem is the undeploy didn't properly clean up:
2008-08-21 18:50:39,264 DEBUG [org.jboss.ejb3.stateful.StatefulContainer] (RMI TCP Connection(18)-192.168.1.146) Failed to cleanup after start() failure org.jboss.ejb3.common.registrar.spi.NotBoundException: Requested value bound at name "ProxyFactory/ClusteredStatefulRemote" is not bound. at org.jboss.ejb3.common.registrar.plugin.mc.Ejb3McRegistrar.lookup(Ejb3McRegistrar.java:91) at org.jboss.ejb3.proxy.jndiregistrar.JndiSessionRegistrarBase.deregisterProxyFactory(JndiSessionRegistrarBase.java:934) at org.jboss.ejb3.proxy.jndiregistrar.JndiSessionRegistrarBase.unbindEjb(JndiSessionRegistrarBase.java:477) at org.jboss.ejb3.session.SessionSpecContainer.lockedStop(SessionSpecContainer.java:732) at org.jboss.ejb3.stateful.StatefulContainer.lockedStop(StatefulContainer.java:324) at org.jboss.ejb3.stateful.StatefulContainer.lockedStart(StatefulContainer.java:308) at org.jboss.ejb3.EJBContainer.start(EJBContainer.java:855)
The effect of this is the "ProxyFactory/ClusteredStatefulRemote" bean was left registered in the MC, but not in an installed state. When later tests would deploy the same jar, they would all fail with "java.lang.IllegalStateException: ProxyFactory/ClusteredStatelessRemote is already installed". AFAICT, the only way to clean this up is to reboot the server.
There's a couple levels of issues here:
1) JndiSessionRegistrarBase.deregisterProxyFactory is doing a Ejb3Registrar.lookup before doing an unbind. It does this so it can make some assertions. Problem is Ejb3McRegistrar implements lookup by calling KernelController.getInstalledContext(). That will return null in this case, because "ProxyFactory/ClusteredStatefulRemote" never made it to ControllerState.INSTALLED. As a result, lookup() throws an exception.
2) If Ejb3McRegistrar.lookup() somehow was changed to get past that problem and find the ControllerContext, I believe it would still fail, because it checks ControllerContext.getError() and throws an exception if it finds one.
3) Even if the JndiSessionRegistrarBase.deregisterProxyFactory's call to Ejb3Registrar.lookup() were eliminated and the method went directly to Ejb3Registrar.unbind(), it would still fail because the first thing Ejb3McRegistrar.unbind() does is call lookup(). :-)
Bottom line, it looks like Ejb3McRegistrar leaves no way to back out a failed bind() call.