I was reading the JayWay article about Async support on Servlet with Spring.
The interesting part is:
If your service is expected to receive large request or response bodies, especially if the clients write or read slowly, you would benefit from using the non-blocking IO feature introduced in Servlet 3.1, as mentioned earlier. On the ServletInputStream there is the method setReadListener where you can set a ReadListener.
I saw that you can do something with DeferredResult
in terms of starting the servlet asynchronously but I cannot find information about anything related about ReadListener
and WriteListener
.
Or at least, I expected something on that side because it's kind on the border of my application, I just need to get the request and send a result.
Yes, it is possible to use ReadListeners with Spring's DeferredResult, I'll outline the process below. I imagine the process for WriteListeners is similar.
Starting Async Processing
When Spring sees a DeferredResult as a return type the WebAsyncManager will call request.startAsync() after your method executes. This starts the request processing in async mode. It is important that you do not start async processing manually in your controller method, Spring cannot cope with async processing already being started and exceptions will be thrown.
Attaching your ReadListener
This will vary by container. Jetty will allow you to attach the readListener to the ServletInputStream in your controller method, before async processing has begun as follows:
Tomcat, and perhaps other containers too, do not permit this. Their interpretation of the Servlet Spec is that asynchronous processing must be started before it is permissible to attach the ReadListener. Therefore, if you want your application to be container agnostic, I suggest the below technique.
Create a DeferredResultProcessingInterceptor
Spring provides a mechanism for intercepting asynchronous request processing with DeferredResultProcessingInterceptors. Create your interceptor as follows:
The preProcess method will be executed immediately after Spring has started async processing, but before anything else occurs, which is exactly what we want.
The DeferredResultProcessingInterceptor can be attached to your request in your controller method as follows: