Hi,
I have two beans, whose implementation is session scoped. One of them gets the other autowired via its interface, and registers itself as a listener for a particular event. When it is disposed (@PreDestroy), the bean removes the listener to avoid memory leaks.

The problem: When the session expires, and Spring disposes all session scoped beans, the session is not bound to the current thread (there is no request running).

Code:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.eventBus': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:342) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
	at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:33) ~[spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
	at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.getTarget(Cglib2AopProxy.java:654) ~[spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
	at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:605) ~[spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
	at com.google.common.eventbus.EventBus$$EnhancerByCGLIB$$fd92a9c4.unregister(<generated>) ~[cglib-nodep-2.2.jar:na]
	at com.siemens.goos.sikmobile.manager.navigation.NextStepManagerImpl.dispose(NextStepManagerImpl.java:190) ~[NextStepManagerImpl.class:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.6.0_29]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[na:1.6.0_29]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_29]
	at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_29]
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:346) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeDestroyMethods(InitDestroyAnnotationBeanPostProcessor.java:311) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeDestruction(InitDestroyAnnotationBeanPostProcessor.java:150) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
	at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:193) [spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
	at org.springframework.beans.factory.support.DisposableBeanAdapter.run(DisposableBeanAdapter.java:187) [spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
	at org.springframework.web.context.request.DestructionCallbackBindingListener.valueUnbound(DestructionCallbackBindingListener.java:51) [spring-web-3.1.2.RELEASE.jar:3.1.2.RELEASE]
	at org.apache.catalina.session.StandardSession.removeAttributeInternal(StandardSession.java:1800) [catalina.jar:7.0.27.A]
	at org.apache.catalina.session.StandardSession.expire(StandardSession.java:865) [catalina.jar:7.0.27.A]
	at org.apache.catalina.session.StandardSession.isValid(StandardSession.java:658) [catalina.jar:7.0.27.A]
	at org.apache.catalina.session.ManagerBase.processExpires(ManagerBase.java:534) [catalina.jar:7.0.27.A]
	at org.apache.catalina.session.ManagerBase.backgroundProcess(ManagerBase.java:519) [catalina.jar:7.0.27.A]
	at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1357) [catalina.jar:7.0.27.A]
	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1537) [catalina.jar:7.0.27.A]
	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1547) [catalina.jar:7.0.27.A]
	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1547) [catalina.jar:7.0.27.A]
	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1526) [catalina.jar:7.0.27.A]
	at java.lang.Thread.run(Thread.java:662) [na:1.6.0_29]
I did not find a solution so far. I'm sure that Spring should handle this, so I have created a Jira issue https://jira.springsource.org/browse/SPR-9672

My current work-around is not removing the listener, and adding a comment that it is not required, as the event source is also session scoped. Of course, this is dirty, as the interface of the bean does not give any clue about the scope, and I do assumptions which may be wrong when implementations change.

I'm wondering if anyone else has encountered this scenario. A Google search has not revealed a clean work-around.

Regards, Sebastian Paul