복붙노트

[SPRING] 실제 웹 요청 이외의 요청 범위 Bean 사용

SPRING

실제 웹 요청 이외의 요청 범위 Bean 사용

분리 된 스레드에서 스프링 통합 로직을 실행하는 웹 애플리케이션이 있습니다. 문제는 어떤 시점에서 Spring 통합 로직이 요청 범위 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>

My Scoped Bean은 다음과 같이 주석을 달았습니다. (콩이 proxing하면 도움이된다고 들었습니다.)

@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)  
public class TenantContext  implements Serializable {

내가 할 수있는 일이 가능한거야? 그렇다면 여기에 무엇을 놓치고 있습니까? 그렇지 않다면 어떻게 달성 할 수 있는지에 대한 다른 제안이 있습니까?

해결법

  1. ==============================

    1.요청이 실행중인 웹 컨테이너 스레드에서만 요청 (및 세션) 범위의 빈을 사용할 수 있습니다.

    요청이 실행중인 웹 컨테이너 스레드에서만 요청 (및 세션) 범위의 빈을 사용할 수 있습니다.

    스레드가 SI 흐름에서 비동기 회신을 기다리고 있다고 가정합니까?

    그렇다면 요청 범위의 Bean을 메시지 (헤더 또는 페이로드의 어딘가에)에 바인딩 할 수 있습니다.

  2. ==============================

    2.

    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());
        }**
    }
    
  3. ==============================

    3.threadContextInheritable 속성이 true로 설정된 상태로 RequestContextFilter를 사용합니다. 이렇게하면 자식 스레드가 요청 객체 자체를 포함하는 부모의 컨텍스트를 상속합니다. 또한 요청 개체는 요청에 매우 특정하며 다양한 요청에서 공유 할 수 없기 때문에 실행 프로그램이 풀의 스레드를 다시 사용하지 않도록해야합니다. 그러한 Executor 중 하나가 SimpleAsyncTaskExecutor입니다.

    threadContextInheritable 속성이 true로 설정된 상태로 RequestContextFilter를 사용합니다. 이렇게하면 자식 스레드가 요청 객체 자체를 포함하는 부모의 컨텍스트를 상속합니다. 또한 요청 개체는 요청에 매우 특정하며 다양한 요청에서 공유 할 수 없기 때문에 실행 프로그램이 풀의 스레드를 다시 사용하지 않도록해야합니다. 그러한 Executor 중 하나가 SimpleAsyncTaskExecutor입니다.

    더 자세한 정보는 Scope 'session'이 현재 스레드에 대해 참조되지 않습니다. IllegalStateException : 스레드 바인딩 요청을 찾을 수 없습니다.

  4. from https://stackoverflow.com/questions/17424739/using-a-request-scoped-bean-outside-of-an-actual-web-request by cc-by-sa and MIT license