Spring MVC - Configuring Asynchronous Request Processing

[Updated: Jan 4, 2017, Created: Jan 4, 2017]

Enabling native asynchronous support

Spring Async mechanism is built on native servlet asynchronous specification. That means 'asyncSupported' must be set to true on the Servlet level i.e. DispatcherServlet.

If you are using JavaConfig along with @EnableWebMvc or Spring boot with @SpringBootApplication then this flag is set to true by default. We have not been enabling it explicitly in our previous examples.

If you are using some other way of configuration and things don't work for you please check out spring ref here.



Using a custom TaskExecutor

In cases where Spring takes care of thread management (instead of we create threads ourselves) such as where handler method returns Callable<?> or StreamingResponseBody, Spring uses SimpleAsyncTaskExecutor by default.

To use other implementation of TaskExecutor we can extend our configuration class from WebMvcConfigurerAdapter or we can use it as bean. For example in a boot application:

@SpringBootApplication
public class AsyncConfigExample{
    @Bean
    WebMvcConfigurer configurer(){
        return new WebMvcConfigurerAdapter(){
            @Override
            public void configureAsyncSupport (AsyncSupportConfigurer configurer) {
                ThreadPoolTaskExecutor t = new ThreadPoolTaskExecutor();
                t.setCorePoolSize(10);
                t.setMaxPoolSize(100);
                t.setQueueCapacity(50);
                t.setAllowCoreThreadTimeOut(true);
                t.setKeepAliveSeconds(120);
                t.initialize();
                configurer.setTaskExecutor(t);
            }
        };
    }
    public static void main (String[] args) {
        SpringApplication.run(AsyncConfigExample.class, args);
    }
}



Wrapping Callable in WebAsyncTask

In cases where we return Callable implementation from the handler methods, We can wrap it in a WebAsyncTask which allows to set timeout and a custom task executor per callable basis:


@Controller
public class MyWebController3 {

    @RequestMapping("/test3")
    public
    @ResponseBody
    WebAsyncTask<String> handleRequest (HttpServletRequest r) {
        System.out.println("asyncSupported: " + r.isAsyncSupported());
        System.out.println(Thread.currentThread().getName());

        Callable<String> callable = () -> {
            System.out.println(Thread.currentThread().getName());
            return "WebAsyncTask test";
        };

        ConcurrentTaskExecutor t = new ConcurrentTaskExecutor(
                  Executors.newFixedThreadPool(1));
        return new WebAsyncTask<>(10000L, t, callable);
    }
}

Please check out complete examples in the project browser below.

Example Project


Dependencies and Technologies Used :
  • Spring Boot Web Starter 1.4.2.RELEASE: Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container.
    Corresponding Spring version: 4.3.4.RELEASE
  • JDK 1.8
  • Maven 3.3.9

Async Configuration Select All Download
  • spring-mvc-async-config
    • src
      • main
        • java
          • com
            • logicbig
              • example