0

I have to get Language of request Http Header and store in a thread context to RestController and Service can get them by using SimpleThreadScope. But I have found that, @RestController can't get the stored object, i will create a new instance. I checked that, from @RestController to @service is ok. But can't transfer object from Filter to @RestController through a bean with thread scope that installed by SimpleThreadScope.

Why Scope implemented by SimpleThreadScope can't transfer from Filter(GenericFilterBean) to a Controller (@RestController).

Jobin
  • 5,610
  • 5
  • 38
  • 53

1 Answers1

5

if you need to be able to update the state of your bean from a Filter and after that be able to read the value in @RestController or @Service and you use SimpleThreadScope then

  1. you need to register SimpleThreadScope

    @Bean
    public static BeanFactoryPostProcessor beanFactoryPostProcessor() {
        return new BeanFactoryPostProcessor() {
            @Override
            public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
                logger.info("postprocessor");
                beanFactory.registerScope("thread", new SimpleThreadScope());
            }
        };
    }
    
  2. you should annotate your bean with @Scope("thread")

    @Component
    @Scope(scopeName = "thread", proxyMode = ScopedProxyMode.TARGET_CLASS)
    public class MyBean {
    
    
    @RestController
    public class SampleController {
        private static final Logger logger = LoggerFactory.getLogger(SampleController.class);
    
        @Autowired
        private MyBean myBean;
    
        @GetMapping("/test/{somePathVar}")
        public String test(@PathVariable String somePathVar) throws InterruptedException, ExecutionException {
            logger.info("looking for bean data: {}", myBean.getData());
    
  3. In the filter you inject the bean and update it's state

    @Component
    public class MyFilter extends GenericFilterBean {
        private static final Logger logger = LoggerFactory.getLogger(MyFilter.class);
    
        @Autowired
        private MyBean myBean;
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            myBean.setData(servletRequest.getParameter("test"));
    
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }
    

Here is a useful article describing scopes in spring: http://www.baeldung.com/spring-bean-scopes. You can find details about proxyMode there.

You can see that @RequestScope might be useful for you.

Also maybe interceptors will work for your task. See the example in this article http://www.baeldung.com/spring-http-logging

Alex M981
  • 2,264
  • 14
  • 24
  • I configured similar your guide before I asked this question. Have you ever passed value from filter to rest controller with SimpleThreadScope? If you did, you will see the different you are thinking. – Anh Nguyen tuan Jan 12 '18 at 06:10
  • the bean is injected to both filter and controller. In filter you set some property of the bean, in controller you read this property. By the way you can try interceptors instead of filters – Alex M981 Jan 12 '18 at 07:09
  • Yes, Interceptor can do. I think the thread of filter and the thread of Controller are different, so that I can't pass a local thread value from Filter to Controller. – Anh Nguyen tuan Aug 01 '19 at 10:35