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 ProjectDependencies 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
|