views:

54

answers:

0

I have a Java webapp that's using PicoContainer for dependency injection. When I shut down the app, I sometimes get the following stack trace repeated a few times in my error log:

2009-11-18 17:32:29,352 ERROR [/] - Session event listener threw exception

java.lang.IllegalStateException: Cannot stop.  Current container state was: STARTED
    at org.picocontainer.lifecycle.DefaultLifecycleState.stopping(DefaultLifecycleState.java:72)
    at org.picocontainer.web.ThreadLocalLifecycleState.stopping(ThreadLocalLifecycleState.java:19)
    at org.picocontainer.DefaultPicoContainer.stop(DefaultPicoContainer.java:691)
    at org.picocontainer.web.PicoServletContainerListener.sessionDestroyed(PicoServletContainerListener.java:249)
    at org.apache.catalina.session.StandardSession.expire(StandardSession.java:666)
    at org.apache.catalina.session.StandardSession.isValid(StandardSession.java:558)
    at org.apache.catalina.session.ManagerBase.processExpires(ManagerBase.java:654)
    at org.apache.catalina.session.ManagerBase.backgroundProcess(ManagerBase.java:639)
    at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1280)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1561)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1570)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1570)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1550)

I'm wondering if anyone has seen something like this before. The error seems paradoxical, as the line that throws the exception first specifically checks that the container has not been started:

    if (!(isStarted())) {
        throw new IllegalStateException("Cannot stop.  Current container state was: " + state);
    }

(note that isStarted() returns state == STARTED)

We suspect the problem could be related to threading, as the DefaultLifecycleState being stopped is held in a ThreadLocal variable, and the code in PicoServletContainerListener that throws the exception has just overridden the value in the ThreadLocal:

    SessionStoreHolder ssh = (SessionStoreHolder) session.getAttribute(SessionStoreHolder.class.getName());

    SessionContainerHolder sch = (SessionContainerHolder) context.getAttribute(SessionContainerHolder.class
            .getName());
    ThreadLocalLifecycleState tlLifecycleState = sch.getLifecycleStateModel();

    sessionStoring.putCacheForThread(ssh.getStoreWrapper());
    tlLifecycleState.putLifecycleStateModelForThread(ssh.getLifecycleState());

    sessionContainer.stop();
    sessionContainer.dispose();
    sessionStoring.invalidateCacheForThread();

However, we can't find any evidence online that others have had this problem, which makes us suspect that we're doing something wrong on our end. Anybody know more? I'll try to post an update if I figure anything out.