Spring supports Servlet 3 based asynchronous request processing
We don't have to use Servlet 3 asynchronous API, instead Spring MVC abstracts away the thread management details from the controllers.
To use this support, the return value of a handler method has to be java.util.concurrent.Callable .
Spring MVC invokes the returned instance of Callable in a separate thread with the help of an underlying org.springframework.core.task.TaskExecutor
The request is dispatched back to the Servlet container to resume processing using the value returned by the Callable.
This example shows how to use this feature of Spring MVC
Creating the Controller
@Controller
public class MyController {
Logger logger = Logger.getLogger(MyController.class.getSimpleName());
@RequestMapping("test")
public @ResponseBody Callable<String> handleTestRequest () {
logger.info("handler started");
Callable<String> callable = new Callable<String>() {
@Override
public String call () throws Exception {
logger.info("async task started");
Thread.sleep(2000);
logger.info("async task finished");
return "async result";
}
};
logger.info("handler finished");
return callable;
}
}
The Unit test
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = MyWebConfig.class)
public class ControllerTest {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup () {
DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(this.wac);
this.mockMvc = builder.build();
}
@Test
public void testController () throws Exception {
MockHttpServletRequestBuilder builder =
MockMvcRequestBuilders.get("/test");
this.mockMvc.perform(builder)
.andExpect(MockMvcResultMatchers.request()
.asyncStarted())
.andExpect(MockMvcResultMatchers.request()
.asyncResult("async result"))
.andExpect(MockMvcResultMatchers.status()
.isOk());
}
}
Output:
On running the test, the following lines of logs shows that the controller method exits immediately and a new thread is spawned by Spring to free the main Servlet container thread.
Mar 18, 2016 8:48:20 PM org.springframework.test.web.servlet.TestDispatcherServlet initServletBean
INFO: FrameworkServlet '': initialization completed in 14 ms
Mar 18, 2016 8:48:20 PM com.logicbig.example.MyController handleTestRequest
INFO: handler started
Mar 18, 2016 8:48:20 PM com.logicbig.example.MyController handleTestRequest
INFO: handler finished
Mar 18, 2016 8:48:20 PM com.logicbig.example.MyController$1 call
INFO: async task started
Mar 18, 2016 8:48:22 PM com.logicbig.example.MyController$1 call
INFO: async task finished
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
|