別のスレッドで実行されるSpring Integrationロジックを持つWebアプリケーションがあります。問題は、ある時点でSpring IntegrationロジックがリクエストスコープのBeanを使用しようとすると、次のエラーが発生することです:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.tenantContext': Scope 'request' 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.
Caused by: 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.
ContextLoaderListenerを設定しています:
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
私のScoped Beanにはそのように注釈が付けられています(私のBeanをプロキシすると役立つと聞いたので):
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class TenantContext implements Serializable {
私がやっていることは可能ですか?はいの場合、ここで何が欠けていますか?いいえの場合、それを達成する方法に関する他の提案はありますか?
リクエスト(およびセッション)スコープのBeanは、リクエストが実行されているWebコンテナスレッドでのみ使用できます。
スレッドがSIフローからの非同期応答を待っていると思いますか?
その場合、リクエストスコープのBeanをメッセージにバインドできます(おそらくヘッダー内、またはペイロード内のどこかに)。
public class WebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootConfiguration.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebMvcConfiguration.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
@Override
protected Filter[] getServletFilters() {
return new Filter[] { new HiddenHttpMethodFilter() };
}
**@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
servletContext.addListener(new RequestContextListener());
}**
}
プロパティthreadContextInheritableをtrueに設定してRequestContextFilterを使用します。これにより、子スレッドは要求オブジェクト自体を含む親のコンテキストを継承します。また、リクエストオブジェクトはそのリクエストに非常に固有であり、さまざまなリクエスト間で共有できないため、エグゼキュータがプール内のスレッドを再利用しないようにしてください。そのようなエグゼキューターの1つがSimpleAsyncTaskExecutorです。
詳細については、 スコープ 'session'は現在のスレッドに対してアクティブではありません; IllegalStateException:スレッドバインド要求が見つかりません を参照してください。