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?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With