0
votes

I would like to configure asynchronous processing support for a subset of request mappings in my Spring Boot application which match /async/*. Examples:

  • localhost:8080/async/downloadLargeFile
  • localhost:8080/async/longRunningRask

Taking the first example, I have implemented my method as follows using StreamingResponseBody:

@GetMapping
public ResponseEntity<StreamingResponseBody> downloadLargeFile() throws IOException {
    long size = Files.size(path);
    InputStream inputStream = Files.newInputStream(path);
    return ResponseEntity.ok()
        .contentLength(size)
        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=large_file.txt")
        .body(inputStream::transferTo);
}

In the documentation for StreamingResponseBody, it states I should be configuring an AsyncTaskExecutor, so I have this @Configuration class which implements WebMvcConfigurer as well:

@Configuration
public class AsyncConfigurer implements WebMvcConfigurer {

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
        configurer.setDefaultTimeout(-1);
        configurer.setTaskExecutor(asyncTaskExecutor());
    }

    @Bean
    public AsyncTaskExecutor asyncTaskExecutor() {
        return new SimpleAsyncTaskExecutor("async");
    }
}

However, I cannot find a way to use this task executor only with requests that match a given pattern.

As a more general question - how do I restrict the WebMvcConfigurer to apply only to a subset of requests matching a pattern?

If this is not possible or not recommended, what is the proper way to accomplish the same behaviour?

1
Do you have more parts that use async in your application? This executor will only be used for the async part of the web application. Also you might not want to use the SimpleAsyncTaskExecutor but rather a threadpool based one. - M. Deinum
Hi @M.Deinum, what do you mean by "the async part of the web application"? How is that defined exactly? Yes, I would like to use an AsyncTaskExecutor for other requests as well, but limiting it to working for just one would already be of assistance. Are you suggesting that I may want to use a pooled one if I have several async requests? - Paul Benn
You want to limit the number of threads created, this one creates threads on the fly. The normal requests are handled by your servlet container, the async onces (like you have here) are passed on to the TaskExecutor you define, so that the regular request handling threads are free to handle other incoming requests again. - M. Deinum
But how does the context know which requests are async and which ones are not - i.e. how does it know which task executor to route things to? - Paul Benn
There is just 1 task executor for async task, other request are handled by the servlet container. The async stuff depends on the return type of your controller. Things like Future, Flux, or a StreamingResponseBody are handled async (check the spring documentation for that). - M. Deinum

1 Answers

1
votes

The TaskExecutor when configured for/with the WebMvcConfigurer on the AsyncSupportConfigurer will solely be used for async processing of web requests. All other requests are handled by the default request handling threads as available on your servlet container.

The async nature is defined by the return type of your method. The async types are described in the MVC Async part of the Spring Reference guide.