Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StreamingResponseBodyReturnValueHandler does not use applicationTaskExecutor

I have Spring Data REST custom controller that returns ResponseEntity<StreamingResponseBody>

In my application.yaml file, I have defined a custom task executor to be used for the StreamingResponseBody.

spring:
  task:
    execution:
      pool:
        max-size: 16
        queue-capacity: 100

However, mvc is still using the SimpleAsyncTaskExecutor, instead of the one defined above.

An Executor is required to handle java.util.concurrent.Callable return values.
Please, configure a TaskExecutor in the MVC config under "async support".
The SimpleAsyncTaskExecutor currently in use is not suitable under load.

After a little debugging, I found out that the StreamingResponseBodyReturnValueHandler does not set the applicationTaskExecutor on the WebAsyncTask type i.e. StreamingResponseBodyTask and as a result the SimpleAsyncTaskExecutor is used.

Callable<Void> callable = new StreamingResponseBodyTask(outputMessage.getBody(), streamingBody);
WebAsyncUtils.getAsyncManager(webRequest).startCallableProcessing(callable, mavContainer);

The WebMvcAutoConfiguration is picking up the applicationTaskExecutor and setting it correctly, when I debugged this method in WebMvcAutoConfiguration

@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
    if (this.beanFactory.containsBean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME)) {
        Object taskExecutor = this.beanFactory
            .getBean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME);
        if (taskExecutor instanceof AsyncTaskExecutor) {
            configurer.setTaskExecutor(((AsyncTaskExecutor) taskExecutor));
        }
    }
    Duration timeout = this.mvcProperties.getAsync().getRequestTimeout();
    if (timeout != null) {
        configurer.setDefaultTimeout(timeout.toMillis());
    }
}

Am I missing anything? How can I apply the ThreadPoolTaskExecutor for a StreamingResponseBody?

like image 508
Nikhil Avatar asked Feb 19 '26 03:02

Nikhil


1 Answers

spring-data-rest Custom Repositories (@RepositoryRestResource or @BasePathAwareController) Ignore AsyncSupportConfigurer see RepositoryRestMvcConfiguration#repositoryExporterHandlerAdapter here.
But spring-webmvc applies AsyncSupportConfigurer see WebMvcConfigurationSupport#requestMappingHandlerAdapter here

    AsyncSupportConfigurer configurer = getAsyncSupportConfigurer();
    if (configurer.getTaskExecutor() != null) {
        adapter.setTaskExecutor(configurer.getTaskExecutor());
    }
    if (configurer.getTimeout() != null) {
        adapter.setAsyncRequestTimeout(configurer.getTimeout());
    }
    adapter.setCallableInterceptors(configurer.getCallableInterceptors());
    adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors());

If it's possible, use a simple @RestController or @Controller, If not, you can create an issue here to add support for that

like image 172
Hadi Mansouri Avatar answered Feb 21 '26 15:02

Hadi Mansouri