Earlier I was using 2.0.9.RELEASE, i have simply upgraded to 2.1.7.RELEASE. One of the bean couldn't be found or scanned by ComponentScan.
***************************
APPLICATION FAILED TO START
***************************
Description:
Field taskExecutor in com.helper.Helper required a bean of type 'com.task.TaskExecutor' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.task.TaskExecutor' in your configuration.
In main class @ComponentScan
is present and TaskExecutor is annotated with @Component
.
I have tried moving up the main class, but didn't help still.
Comment From: rgampa
UPDATE
Looks the problem is with the class name, by changing it to TaskExecutorImpl
it worked.
Works
@Component("taskExecutorImpl")
public class TaskExecutorImpl
@Autowired
private TaskExecutorImpl taskExecutorImpl;
Doesn't work
@Component("taskExecutot")
public class TaskExecutor
@Autowired
private TaskExecutor taskExecutor;
Comment From: snicoll
@rgampa there is now a taskExecutor
bean that is provided by auto-configuration which probably overrides yours.
Earlier I was using 2.0.9.RELEASE, i have simply upgraded to 2.1.7.RELEASE
I don't think that is possible as we do fail if something is trying to override a bean by name the way I think this is happening here. If you have set this property yourself, it is more than a simple upgrade as you described it. Getting this failure and taking appropriate action is what you should do on upgrade.
If you haven't set spring.main.allow-bean-definition-overriding
then please share a sample that we can use to reproduce this behaviour.
Comment From: rgampa
@snicoll Thanks for your reply. I would have checked existing bean before posting here, but error was confusing. I haven't set spring.main.allow-bean-definition-overriding
. However by changing bean name to taskExecutorImpl
it works fine. This can be closed.
Comment From: Pinocchio2018
@snicoll Hi. I update a project to reproduce this problem. here 's the link : https://github.com/Pinocchio2018/TaskExecutorBeanProblem
A personal Java Bean named 'TaskExecutor' will cause Spring boot start problem
This problem confuse me a lot. Please help me if you know the problem reason. Thank you.
Comment From: snicoll
Thank you for sharing a sample.
This problem confuse me a lot. Please help me if you know the problem reason.
The problem is described here already. Your user-bean has the same name as a (new) well-known component in Spring Boot. The auto-configuration for task execution will unfortunately create a bean with id taskExecutor
that is going to override yours. You also have a bean named taskExecutor
. It isn't created at all and when you try to inject it, it does not exist.
In the meantime you can change the name of your bean, for instance:
@Service("myTaskExecutor")
public class TaskExecutor {
That said, I would expect your project to fail differently with a nicer exception message as we've disabled bean overriding by default. But it doesn't and I can't see why that is.
Comment From: wilkinsona
This looks like a Framework bug to me. Here's a minimal sample that reproduces some behaviour that I would not expect:
package com.example;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
public class TaskExecutorBeanProblemApplication {
public static void main(String[] args) {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)context.getBeanFactory();
beanFactory.setAllowBeanDefinitionOverriding(false);
context.register(FirstConfiguration.class, SecondConfiguration.class);
context.refresh();
System.out.println(context.getBean("taskExecutor"));
System.out.println(beanFactory.getBeanDefinition("taskExecutor"));
}
}
@Configuration
static class FirstConfiguration {
@Bean
TaskExecutor taskExecutor() {
return new TaskExecutor();
}
}
@Configuration
static class SecondConfiguration {
@Bean(name = { "applicationTaskExecutor", "taskExecutor" })
ThreadPoolTaskExecutor threadPoolTaskExecutor() {
return new ThreadPoolTaskExecutor();
}
}
static class TaskExecutor {
}
}
The getBean("taskExecutor")
call returns the following:
org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor@3d121db3
While the beanFactory.getBeanDefinition("taskExecutor")
returns a definition for a different bean:
Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=taskExecutorBeanProblemApplication.FirstConfiguration; factoryMethodName=taskExecutor; initMethodName=null; destroyMethodName=(inferred); defined in com.example.TaskExecutorBeanProblemApplication$FirstConfiguration
I would guess that this mismatched view of the state is why the override isn't detected and prevented.
Comment From: saltyx
I think this may be a bug. I check the ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod
method.
// Consider name and any aliases
List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
// Register aliases even when overridden
for (String alias : names) {
this.registry.registerAlias(beanName, alias);
}
// Has this effectively been overridden before (e.g. via XML)?
if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
......
}
It uses the first item in the name array as the beanName, therefore, when checking whether the existing bean definition can be overridden, it is actually not checked whether the alias exists
In order to verify, I changed the name of the custom bean from TaskExecutor to ApplicationTaskExecutor. After executing it again, it reminded me that the name has been used. This is different from the previous bean not found error
When verifying whether the bean can be overridden, I think both beanName and its alias should be checked
Comment From: jhoeller
This seems to be caused by a missing check for an alias overriding a bean definition of the same name in DefaultListableBeanFactory
. Adding such a check makes the scenario fail with an IllegalStateException
for me here, in case of allowBeanDefinitionOverriding=false
.
I'll make sure to get this into 5.3 M2. Backporting is tough here since some applications may rely on an accidental override.