TaskExecutor and TaskScheduler being picked up by Spring as same type

java, spring

Solution

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.

Problem

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?

Original source