I have a problem with Spring Boot configuration. I got exception on some mobile devices which should use sockets:
java.lang.IllegalArgumentException: 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. Also you must use a Servlet 3.0+ container
at org.springframework.util.Assert.isTrue(Assert.java:65)
at org.springframework.http.server.ServletServerHttpAsyncRequestControl.<init>(ServletServerHttpAsyncRequestControl.java:59)
at org.springframework.http.server.ServletServerHttpRequest.getAsyncRequestControl(ServletServerHttpRequest.java:202)
at org.springframework.web.socket.sockjs.transport.session.AbstractHttpSockJsSession.handleInitialRequest(AbstractHttpSockJsSession.java:202)
at org.springframework.web.socket.sockjs.transport.handler.AbstractHttpSendingTransportHandler.handleRequestInternal(AbstractHttpSendingTransportHandler.java:66)
at org.springframework.web.socket.sockjs.transport.handler.AbstractHttpSendingTransportHandler.handleRequest(AbstractHttpSendingTransportHandler.java:58)
at org.springframework.web.socket.sockjs.transport.TransportHandlingSockJsService.handleTransportRequest(TransportHandlingSockJsService.java:254)
at org.springframework.web.socket.sockjs.support.AbstractSockJsService.handleRequest(AbstractSockJsService.java:322)
at org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler.handleRequest(SockJsHttpRequestHandler.java:88)
at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:51)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
...
As I see from the exception, I have to enable async processing by adding true into the web.xml file. But this is the problem because I don't have it - our project uses Spring Boot.
Is there any way to provide the same functionality in Spring Boot like does?
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
.
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:
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);
}
}
@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);
}
}
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.