Open SebastianS90 opened 5 days ago
Thanks for the report.
Unfortunately, it's not clear to me why you believe the Executor
beans in AbstractMessageBrokerConfiguration
to be the cause. Those beans were also defined in Spring Framework 6.1 (Boot 3.2 and 3.3) albeit as a TaskExecutor
rather than an Executor
. TaskExecutor
extends Executor
so that should make no difference to the behavior of TaskExecutorConfiguration
which I don't believe has changed in Boot 3.4.
If you would like us to spend some more time investigating, and to help us to understand what's happening in your application, please spend some time providing a complete yet minimal sample that reproduces the problem. You can share it with us by pushing it to a separate repository on GitHub or by zipping it up and attaching it to this issue.
Thanks for the sample.
In terms of auto-configuration, the behavior hasn't changed. This is with Spring Boot 3.4.0:
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)
And this is from Spring Boot 3.3.6:
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)
What has changed is the type of those beans that prevents the auto-configuration of a TaskExecutor
. In Spring Boot 3.3.x, they're TaskExecutor
instances, but in 3.4.x, they're just defined as Executor
instances. This means they can't be injected and the app fails to start.
If I downgrade your sample to Spring Boot 3.3.6, it still fails to start, but for a different reason:
Parameter 0 of constructor in com.example.demo.DemoComponent required a single bean, but 3 were found:
- clientInboundChannelExecutor: defined by method 'clientInboundChannelExecutor' in org.springframework.web.socket.config.annotation.DelegatingWebSocketMessageBrokerConfiguration
- clientOutboundChannelExecutor: defined by method 'clientOutboundChannelExecutor' in org.springframework.web.socket.config.annotation.DelegatingWebSocketMessageBrokerConfiguration
- brokerChannelExecutor: defined by method 'brokerChannelExecutor' in org.springframework.web.socket.config.annotation.DelegatingWebSocketMessageBrokerConfiguration
In your real app, how were you selecting which executor to use? I'm also wondering if you really intended to be using a WebSocket-related executor for presumably more general purposes.
Thanks for the investigation.
In my real app, the code was originally written with Spring Boot 2.6.7 and the dependency was a constructor parameter AsyncListenableTaskExecutor applicationTaskExecutor
. As far as I can remember, the parameter name was important at that time to disambiguate.
With the upgrade to Spring Boot 3.0, the constructor parameter changed to AsyncTaskExecutor applicationTaskExecutor
and was not touched ever since.
Further investigation showed that you are right that it is not the upgrade to Spring Boot 3.4 that causes the issue: I have another bean with a org.springframework.scheduling.TaskScheduler taskScheduler
dependency that I got rid of during the upgrade. While the other bean has that dependency, the AsyncTaskExecutor applicationTaskExecutor
dependency gets provided with an instance of org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
. When I remove the TaskScheduler
dependency from the other bean, then I end up with required a bean of type 'org.springframework.core.task.AsyncTaskExecutor' that could not be found
, even in Spring Boot 3.3.6. Sorry for the confusion there, I really thought that it must have been the update causing it.
However, I am unable to reproduce this in a minimal environment. It might depend on the order that classes are discovered by component scanning.
So to wrap things up, the question is whether TaskExecutionAutoConfiguration
should create its Executor even when there are special instances already present. If you decide against it and keep the @ConditionalOnMissingBean(Executor.class)
annotation, then the workaround is to copy these lines into a custom @Configuration
class:
https://github.com/spring-projects/spring-boot/blob/8964203688c111e11604bc4454743998bc387993/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations.java#L52-L65
After upgrading to Spring Boot 3.4, the application does not start:
The reason why this bean is missing and not created by
org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations
:Auto configuration is here: https://github.com/spring-projects/spring-boot/blob/8964203688c111e11604bc4454743998bc387993/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations.java#L46-L50
One of the existing beans is created here.