Spring Boot enable like in web.xml

后端 未结 3 2126
猫巷女王i
猫巷女王i 2020-12-09 22:52

I have a problem with Spring Boot configuration. I got exception on some mobile devices which should use sockets:

java.lang.IllegalArgumentException: Async s         


        
相关标签:
3条回答
  • 2020-12-09 23:30

    You just need to define dispatcherServlet @Bean:

    @Bean
    public ServletRegistrationBean dispatcherServlet() {
        ServletRegistrationBean registration = new ServletRegistrationBean(
                new DispatcherServlet(), "/");
        registration.setAsyncSupported(true);
        return registration;
    }
    

    It overrides that default one from DispatcherServletAutoConfiguration.

    0 讨论(0)
  • 2020-12-09 23:47

    Even though I am late to the party I am posting my working solution for posterity.

    I had faced the same issue and tried the solution suggested by @Artem Bilan. But after debugging the code, I came to know that the servletRegistrationBean.isAsyncSupported() is by default true.

    .

    The actual error is being generated by the code block is from the method org.springframework.web.context.request.async.StandardServletAsyncWebRequest.startAsync() and we are getting this error when getRequest().isAsyncSupported() is false. Despite the ServletRegistrationBean#asyncSupported value is true, HttpServletRequest#isAsyncSupported() method value is always set to false for all API requests.

    The Exerpt of the code block Code Reference

    Assert.state(getRequest().isAsyncSupported(),
                    "Async support must be enabled on a servlet and for all filters involved " +
                    "in async request processing. This is done in Java code using the Servlet API " +
                    "or by adding \"<async-supported>true</async-supported>\" to servlet and " +
                    "filter declarations in web.xml.");
    
    

    When analyzing further, I came to know that requestAttributes -> Globals.ASYNC_SUPPORTED_ATTR decides whether the request has to be processed in an Async way or not.

    During the normal scenario, the requests do not have Globals.ASYNC_SUPPORTED_ATTR requestAttribute, hence request.asyncSupported will be false, if we manually add that requestAttribute ASYNC_SUPPORTED_ATTR value as true for all the requests using something like filters then request#asyncSupported value will be set to true as per the below code block Code Reference

    specialAttributes.put(Globals.ASYNC_SUPPORTED_ATTR,
                    new SpecialAttributeAdapter() {
                        @Override
                        public Object get(Request request, String name) {
                            return request.asyncSupported;
                        }
    
                        @Override
                        public void set(Request request, String name, Object value) {
                            Boolean oldValue = request.asyncSupported;
                            request.asyncSupported = (Boolean)value;
                            request.notifyAttributeAssigned(name, value, oldValue);
                        }
                    });
    
    

    Though there is no explicit answer, I have implemented a workaround for this issue. To Summarize all the required changes are listed below:

    1. Add a filter to set the request attribute as request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, true)
    
    @Component
    public class AsyncSupportFilter extends OncePerRequestFilter {
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
            request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, true);
            chain.doFilter(request, response);
        }
    }
    
    
    1. Add filter to into your filter chain, in my case I have registered my filter into the spring context as below.
    
    @Component
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
       @Autowired
       private AsyncSupportFilter asyncSupportFilter = null;
       @Override
       public void configure(HttpSecurity httpSecurity) {
    
           httpSecurity.addFilter(asyncSupportFilter);
           // we can add the filter before any filter like as httpSecurity.addFilterBefore(asyncSupportFilter , BasicAuthenticationFilter.class);
       }
    }
    
    0 讨论(0)
  • 2020-12-09 23:52

    Maybe it worth to mention that Spring Boot has async-support enabled by default for dispatcher servlet and all filters

    Quotation from github:

    We automatically set async-supported to true because the DispatcherServlet knows how to work with such requests and it's basically up to individual controller methods to return something like a DeferredResult. Furthermore, we also set async-supported for any filter (provided via getServletFilters) along with setting the DispatcherType for each filter to include ASYNC.

    At least my practice supports this statement

    0 讨论(0)
提交回复
热议问题