In the PR below, WebSocketMessagingAutoConfiguration has been modified to use a virtual thread executor
https://github.com/spring-projects/spring-boot/pull/39611
public class WebSocketMessagingAutoConfiguration {
// ...
WebSocketMessageConverterConfiguration(ObjectMapper objectMapper,
Map<String, AsyncTaskExecutor> taskExecutors) {
this.objectMapper = objectMapper;
this.executor = determineAsyncTaskExecutor(taskExecutors);
}
private static AsyncTaskExecutor determineAsyncTaskExecutor(Map<String, AsyncTaskExecutor> taskExecutors) {
if (taskExecutors.size() == 1) {
return taskExecutors.values().iterator().next();
}
return taskExecutors.get(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME);
}
// ...
}
Upon checking the taskExecutors being injected, it is taskScheduler.
When used with spring-integration, the following Bean is being configured first.
Is it possible to modify it to allow for auto-configuration?
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(TaskSchedulerBuilder.class)
@ConditionalOnMissingBean(name = IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME)
@SuppressWarnings("removal")
public class IntegrationAutoConfiguration {
// ..
protected static class IntegrationTaskSchedulerConfiguration {
@Bean(name = IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME)
public ThreadPoolTaskScheduler taskScheduler(TaskSchedulerBuilder taskSchedulerBuilder,
ObjectProvider<ThreadPoolTaskSchedulerBuilder> threadPoolTaskSchedulerBuilderProvider) {
// ...
}
}
// ..
}
Below is the configuration added without using auto-configuration.
@Configuration
class ExecutorConfig {
@Bean(
name = [
TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME,
AsyncAnnotationBeanPostProcessor.DEFAULT_TASK_EXECUTOR_BEAN_NAME
]
)
fun applicationTaskExecutorVirtualThreads(builder: SimpleAsyncTaskExecutorBuilder): SimpleAsyncTaskExecutor {
return builder.build()
}
}
Of course, the bottom properties are also set.
spring:
threads:
virtual:
enabled: true
Comment From: mhalbritter
Ah, hm, IntegrationAutoConfiguration.IntegrationTaskSchedulerConfiguration#taskScheduler is executed if there's no taskScheduler bean. TaskSchedulingConfigurations.TaskSchedulerConfiguration#taskSchedulerVirtualThreads creates such a bean, but only if @EnableScheduling has been used on the main class.
So I guess we should make IntegrationTaskSchedulerConfiguration virtual threads aware.
The workaround for now is to add @EnableScheduling on the main class (or any other @Configuration class).
Comment From: csh0034
@mhalbritter
I understand that IntegrationTaskSchedulerConfiguration needs to recognize virtual threads.
However, even when adding the following configuration, IntegrationTaskSchedulerConfiguration is called before TaskSchedulerConfiguration, and TaskSchedulingConfigurations.TaskSchedulerConfiguration#taskSchedulerVirtualThreads is not called.
@Configuration
@EnableScheduling
class ScheduleConfig
Is there a priority issue?
Additionally, as mentioned in the initial question, the executor assigned to WebSocketMessageConverterConfigurationshould be TaskSchedulerConfiguration.TaskSchedulerConfiguration#taskSchedulerVirtualThreads, but this method is not called at all.
WebSocketMessageConverterConfiguration.determineAsyncTaskExecutor only has the taskScheduler created in IntegrationAutoConfiguration.IntegrationTaskSchedulerConfiguration#taskScheduler
https://github.com/spring-projects/spring-boot/pull/39611/commits/e9bf2b32cf019a7c0f4854334d2f1a12e0f8d4a8
Should I provide a sample for verification?
Comment From: mhalbritter
Should I provide a sample for verification?
Yes, please.
Comment From: csh0034
p.s. Even though I'm not using SockJS, I noticed that defaultSockJsSchedulerContainer is added in WebSocketMessageConverterConfiguration.determineAsyncTaskExecutor
It wasn't there in version 3.3.0, but it appears in version 3.3.1. I don't understand the reason for this change.
Comment From: csh0034
It seems that the reason TaskSchedulingConfigurations.TaskSchedulerConfiguration#taskSchedulerVirtualThreads is not being called is due to AbstractMessageBrokerConfiguration#messageBrokerTaskScheduler.
TaskSchedulingConfigurations.TaskSchedulerConfiguration:
Did not match:
- @ConditionalOnMissingBean (types: org.springframework.scheduling.TaskScheduler,java.util.concurrent.ScheduledExecutorService; SearchStrategy: all) found beans of type 'org.springframework.scheduling.TaskScheduler' messageBrokerTaskScheduler (OnBeanCondition)
Comment From: csh0034
The AbstractMessageBrokerConfiguration in Spring has been modified to use the executor registered in ChannelRegistration, and WebSocketMessagingAutoConfiguration in Spring Boot has been changed to inject the auto-configured executor into ChannelRegistration.
However, due to the various Beans declared in Spring's AbstractMessageBrokerConfiguration, TaskExecutorConfigurations.TaskExecutorConfiguration in Spring Boot is not called.
TaskExecutorConfigurations.TaskExecutorConfiguration:
Did not match:
- @ConditionalOnMissingBean (types: java.util.concurrent.Executor; SearchStrategy: all) found beans of type 'java.util.concurrent.Executor' clientInboundChannelExecutor, clientOutboundChannelExecutor, brokerChannelExecutor (OnBeanCondition)
I'm adding this comment here because I'm unsure where to raise this issue.
Comment From: facewise
@mhalbritter Hello. Can I pick up this issue?
Comment From: mhalbritter
Sure. I'll assign you to the issue.
Comment From: mhalbritter
Superseded by https://github.com/spring-projects/spring-boot/pull/41695. Thanks @facewise !
Comment From: csh0034
@mhalbritter Should I create a separate issue for this comment?
https://github.com/spring-projects/spring-boot/issues/41188#issuecomment-2185464365
Comment From: mhalbritter
I haven't looked at https://github.com/spring-projects/spring-boot/pull/41695 in detail - if that PR doesn't solve that issue, then yes, please create a separate issue.
Comment From: facewise
@csh0034
TaskSchedulingAutoConfiguration just checks if the TaskScheduler bean exists (plus, if you enabled @EnableScheduling), otherwise instantiates a fallback. And IMO it's intended and fits well to the purpose of autoconfiguration.
However if you add @EnableWebSocketMessageBroker in your configuration, imported DelegatingWebSocketMessageBrokerConfiguration creates a TaskScheduler bean for the message broker, which means it's not necessary to auto-configure a TaskScheduler bean.
But this issue is related to IntegrationAutoConfiguration as @mhalbritter said, since it is not aware of virtual threads.
I see you intended the virtual threads TaskExecutor to be injected in WebSocketAutoConfiguration, then #41695 can resolve it.