You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomee.apache.org by Quintin Beukes <qu...@last.za.net> on 2009/10/21 16:06:53 UTC

Bug in @Startup annotations found - anyone have a possible solution?

Hey,

I found why @Startup causes a deadlock for Singleton beans.

When a bean is annotated with @Startup, at the end of
SingletonContainer.deploy(DeploymentInfo) the following block is
executed:
        if (deploymentInfo.isLoadOnStartup()){
            try {
                ThreadContext callContext = new
ThreadContext(deploymentInfo, null);
                ThreadContext old = ThreadContext.enter(callContext);
                try {
                    instanceManager.getInstance(callContext);
                } finally{
                    ThreadContext.exit(old);
                }
            } catch (OpenEJBException e) {
                throw new OpenEJBException("Singleton startup failed:
"+deploymentInfo.getDeploymentID(), e);
            }
        }

Now, threadContext.enter() calls all
ThreadContextListener.contextEntered() methods, which is only
GeronimoThreadContextListener. This class has a the following:
         synchronized (deploymentInfo) {
                if (deploymentInfo.get(EjbDeployment.class) == null) {
                    if (!deploymentInfo.isDestroyed()) {
                        try {
                            deploymentInfo.wait();
                        } catch (InterruptedException e) {
                        log.warn("Wait on deploymentInfo interrupted
unexpectedly");
                        }
                    }
                }
            }
        }

At this point deploymentInfo.get(EjbDeployment.class) returns null,
because it only gets set AFTER the bean has been deployed
(Container.deploy()) returns. Since it's null, and it's not
"destroyed", it goes into a wait() on deploymentInfo, which never
finished and thus holds up thread. From the point onwards OpenEJB's
deployer is held up, and you can continue/deploy/undeploy.

Anyone have a suggestion for how to fix this?

It could be possible to NOT do the isLoadOnStartup() code inside the
SingletonContainer.deploy() method, and execute it at some later time?
Or since a .notifyAll() is called when EjbDeployment.class is set on
the DeploymentInfo object, one could perhaps fork the
isLoadOnStartup() code to an alternative thread? This seems ugly
though.


Alternatively one could execute the isLoadOnStartup() code at a later
time (only after the EjbDeployment.class has been set). Though at
first glance I could find a place to put this code which would leave
OpenEJB's code independent as well as provide the facility to
Geronimo.

Any ideas would be appreciated.

Quintin Beukes