对于异步请求,Tomcat在与触发初始化事件的线程不同的线程中触发requestdestromed事件。
在这种情况下,使用
ThreadLocals
,不会停用请求上下文,因此不会调用bean处理方法。
请参见:
What do WELD-000225, WELD-000335 and WELD-000715 warnings mean?
Tomcat Bug 57314
我的应用程序依赖于容器生命周期事件来关闭资源和清理,因此我需要一种方法使异步请求的所有内容都能正常工作。我想出的解决办法是添加一个
WebFilter
使执行链末尾的当前请求上下文无效。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws Exception {
BeanManager beanManager = CDI.current().getBeanManager();
AlterableContext context = (AlterableContext) beanManager.getContext(RequestScoped.class);
try {
chain.doFilter(request, response);
} finally {
if (request.isAsyncStarted()) {
AbstractBoundContext<?> ctxt = (AbstractBoundContext<?>) delegate;
ctxt.invalidate();
ctxt.deactivate();
ctxt.cleanup();
}
}
}
Tomcat抱怨说:
SEVERE: The web application [cdi-weld] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@3d97cd8b]) and a value of type [org.jboss.weld.module.web.servlet.HttpContextLifecycle.Counter] (value [org.jboss.weld.module.web.servlet.HttpContextLifecycle$Counter@43a15b16]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
Nov 02, 2018 10:43:55 AM org.apache.catalina.loader.WebappClassLoaderBase checkThreadLocalMapForLeaks
SEVERE: The web application [cdi-weld] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@21d33dd8]) and a value of type [org.jboss.weld.contexts.AbstractManagedContext.ManagedState] (value [org.jboss.weld.contexts.AbstractManagedContext$ManagedState@2a336421]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
Nov 02, 2018 10:43:55 AM org.apache.catalina.loader.WebappClassLoaderBase checkThreadLocalMapForLeaks
SEVERE: The web application [cdi-weld] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@294b0f79]) and a value of type [org.jboss.weld.module.web.servlet.ConversationContextActivator$$Lambda$555/1676983761] (value [org.jboss.weld.module.web.servlet.ConversationContextActivator$$Lambda$555/1676983761@60fb88ad]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
我的理解是,每个请求的线程局部变量都会被覆盖,所以这并不完全是内存泄漏,但我仍然对这个解决方案不是100%满意。