Spring MVC - Asynchronous Request Processing using DeferredResult

[Updated: Dec 14, 2016, Created: Jul 26, 2016]

As we saw in the last tutorial that Spring controller's handler method can process Servlet 3 based asynchronous request processing by returning an instance of Callable.

Another option is for the controller method to return an instance of org.springframework.web.context.request.async.DeferredResult.



Callable vs DeferredResult

A Callable returned from a handler method, is processed asynchronously by the Spring container. Whereas, a DeferredResult<?> (which should also be returned from a handler method as well) produces the return value from a thread of its own choice i.e. the developer is responsible for creating a new thread and doing all thread management.



Example

Let's rewrite our previous example to see how that works.


Creating the Controller

@Controller
public class MyController {
    Logger logger = Logger.getLogger(MyController.class.getSimpleName());

    @RequestMapping("test")
    public @ResponseBody DeferredResult<String> handleTestRequest () {

        logger.info("handler started");
        final DeferredResult<String> deferredResult = new DeferredResult<>();

        new Thread(() -> {
            logger.info("async task started");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            logger.info("async task finished");
            deferredResult.setResult("test async result");
        }).start();

        logger.info("handler finished");
        return deferredResult;
    }
}



The Unit test

Same as last example



Output:

.....
Jul 27, 2016 5:10:06 PM org.springframework.test.web.servlet.TestDispatcherServlet initServletBean
INFO: FrameworkServlet '': initialization completed in 16 ms
Jul 27, 2016 5:10:06 PM com.logicbig.example.MyController handleTestRequest
INFO: handler started
Jul 27, 2016 5:10:06 PM com.logicbig.example.MyController handleTestRequest
INFO: handler finished
Jul 27, 2016 5:10:06 PM com.logicbig.example.MyController lambda$handleTestRequest$0
INFO: async task started
Jul 27, 2016 5:10:08 PM com.logicbig.example.MyController lambda$handleTestRequest$0
INFO: async task finished
.....



In what scenarios we should prefer DeferredResult over Callable

DeferredResult is a better choice if we want to use an entirely decoupled code for processing, e.g. putting some information in a queue which is being polled by some other thread.

Example Project

Dependencies and Technologies Used :

  • Spring Web MVC 4.2.4.RELEASE: Spring Web MVC.
  • Java Servlet API 3.0.1
  • Spring TestContext Framework 4.2.4.RELEASE: Spring TestContext Framework.
  • JUnit 4.12: JUnit is a unit testing framework for Java, created by Erich Gamma and Kent Beck.
  • JDK 1.8
  • Maven 3.0.4

Async Callable Select All Download
  • spring-async-deferredresult-example
    • src
      • main
        • java
          • com
            • logicbig
              • example
      • test
        • java
          • com
            • logicbig
              • example

See Also