Updating from springboot 2.0.2 to springboot 2.1.2 results in No qualifying bean of type exception

deckard cain :

I updated parent pom to use spring boot 2.1.2 release. Among other errors and deprecations that I fixed there is one that's bothering me most:

Error creating bean with name 'adminServiceImpl': Unsatisfied dependency expressed through field 'taskExecutor'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value="taskExecutor")}

My configuration class looks like this:

@EnableScheduling
@EnableAsync
@Configuration
@ConfigurationProperties("thread.pool")
public class MyAsyncConfig extends AsyncConfigurerSupport {
...
@Bean(name = "taskExecutor")
@Override
@Primary
public TaskExecutor getAsyncExecutor() {
    final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.initialize();
    return executor;
}

And the class where I'm autowiring has the executor field defined:

@Autowired
@Qualifier("taskExecutor")
private ThreadPoolTaskExecutor taskExecutor;

This used to work in springboot 2.0.2, but when I moved to 2.1.2 release, I got

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor' available.

One way I fixed this is in configuration class declaring return type of getAsyncExecutor() method to be ThreadPoolTaskExecutor. After doing that, it works. But I am wondering why wouldn't it work as it did in 2.0.2?

Stephane Nicoll :

An interesting arrangement here that works but it could very well not depending on how the ApplicationContext processes the bean definitions.

On one hand a TaskExecutor is exposed and on the other you are requesting that very specific bean with a different type. The context may not be able to honour that and if that's what you want, you must narrow down the return type of the bean definition to ThreadPoolTaskExecutor.

It'd be tempting to think the new auto-configuration support in Spring Boot is related to the change of behaviour but this breaks as well when they are both excluded.

Since you've upgraded to Spring Boot 2.1, you can reduce your configuration anyway:

@EnableScheduling
@EnableAsync
@Configuration
public class MyConfiguration {}

Please don't use @ConfigurationProperties on configuration classes, these are regular components that we use to bind the environment to.

You can still inject the async ThreadPoolTaskExecutor with that name or the more refined one that we promote, applicationTaskExecutor.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=147733&siteId=1