I have the following configuration:
@org.springframework.context.annotation.Configuration
@EnableJpaRepositories
@EnableAsync
@EnableScheduling
public class MyConfiguration {
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(50);
return executor;
}
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(10);
return scheduler;
}
}
Then I have a class listening for ContextRefreshEvents, like:
@Component
public class ScreenerScheduler implements ApplicationListener<ContextRefreshedEvent> {
@Inject
private TaskScheduler scheduler;
@Inject
private ApplicationContext context;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
}
When I run the application (web) I get:
Error creating bean with name 'screenerJobExecutor':
Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field:
private org.springframework.core.task.TaskExecutor example.workflow.ScreenerJobExecutor.executor;
nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [org.springframework.core.task.TaskExecutor] is defined:
expected single matching bean but found 2: taskExecutor,taskScheduler
Anyone could help figuring out why spring see two possible types for a TaskScheuler?
This @Bean method
@Bean
public TaskScheduler taskScheduler() {
returns an object of type ThreadPoolTaskScheduler which is
public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
implements TaskScheduler, SchedulingTaskExecutor {
so it fits both interfaces, TaskScheduler and TaskExecutor (super type of SchedulingTaskExecutor).
If you try to inject a field of type TaskExecutor like your stack trace says
Could not autowire field: private org.springframework.core.task.TaskExecutor...
Spring won't be able to choose which one.
This will only happen if the ApplicationContext from where you are trying to pull the beans has already initialized the beans, for example, in a Web application where your root context would register MyConfiguration and where the servlet context would declare your screenerJobExecutor bean that needs to be injected with a bean of type TaskExecutor.
You can indeed use
@Qualifier(value = "taskExecutor")
to fix this particular situation as Spring will use the bean name and not the bean type to satisfy the injection target.
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