Reputation: 613
I have two spring bean. They are name is same but the class is defferent.
Here is the bean definitions.
This one is the first.
@Bean(name = "approve_sign_up_project_request|Task_1tm7e53")
public StudentTaskToResponseDataConverter perfectUserProfileVO() {
return studentTaskVO -> {
ResponseVo vo = toResponseVO(studentTaskVO);
vo.setData(new PerfectUserProfileVO());
return vo;
};
}
This one is the second
@Bean(name = "approve_sign_up_project_request|Task_1tm7e53")
public UserTaskCompleter perfectUserProfile() {
return new UserTaskCompleter() {
@Override
public void validate(Task task, CompleteUserTaskDTO dto) throws RuntimeException {
Long studentId = getStudentId(task);
UserProfileIntegrityValidatedResultDTO results = userService.
validateTheIntegrityOfUserProfile(studentId);
if (results.getComplete()) {
//nothing to do for now
}else {
LOGGER.error("Validated failed cause the student -- {} not yet perfected the profile",
studentId);
throw new UserProfileImperfectException("Missing fields are " + results.getMissingFields());
}
}
@Override
public void executeBusinessLogic(Task task, CompleteUserTaskDTO dto) {
}
@Override
public Map<String, Object> getTheVariablesForCompleterUserTask(Task task, CompleteUserTaskDTO dto) {
return null;
}
};
}
And When I use below code to get the bean the spring will throw an excetpion. But I did not understand the reason. I think the spring will give me the right bean when I use the bean name and bean class to get it. But actully I am wrong the spring did not give it.
Here is the code of to get bean
private UserTaskCompleter getBean(CompleteUserTaskDTO dto) {
String beanName = dto.getProcessDefinitionKey() + "|" + dto.getActivityId();
return applicationContext.getBean(beanName, UserTaskCompleter.class);
}
Here is the exception
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'approve_sign_up_project_request|Task_1tm7e53' is expected to be of type 'com.hikedu.backend.camunda.beanconfig.taskcompleter.UserTaskCompleter' but was actually of type 'com.hikedu.backend.camunda.beanconfig.tasktoresponsedatecoverter.signupprojectprocess.SignUpProjectProcessTaskConverterConfig$$Lambda$625/484805627'
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:384)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1091)
at com.hikedu.backend.camunda.beanconfig.taskcompleter.BaseUserTaskCompleter.getBean(BaseUserTaskCompleter.java:45)
at com.hikedu.backend.camunda.beanconfig.taskcompleter.BaseUserTaskCompleter.validate(BaseUserTaskCompleter.java:29)
at com.hikedu.backend.service.impl.camunda.signupprojectprocess.BaseSignUpProjectProcessServiceImpl.completeUserTask(BaseSignUpProjectProcessServiceImpl.java:165)
at com.hikedu.backend.controller.SignUpProjectProcessUserTaskController.completerStudentTask(SignUpProjectProcessUserTaskController.java:93)
at com.hikedu.backend.controller.SignUpProjectProcessUserTaskController$$FastClassBySpringCGLIB$$a695dddd.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
Can someone tell me how to get the right bean by name when have two same name and different calss bean.
Upvotes: 1
Views: 1099
Reputation: 188
The answer that Himly quotes, does not let Spring create beans with the same name. It actually prevents it from starting up, since building the application will fail.
If multiple beans are defined with the same name, then the one defined later will override the one defined earlier. As a result, in your case only one bean named approve_sign_up_project_request|Task_1tm7e53
will exist, unless you disable the bean definition overriding.
Upvotes: 2
Reputation: 613
I already understaned the reason.
When definitioned two same name and different type bean. The spring will choose the last one to overriding others.
In my case there are just one bean named "approve_sign_up_project_request|Task_1tm7e53" and the type is StudentTaskToResponseDataConverter.
When I use the name and the UserTaskCompleter type to get the bean form beanFactory
the spring cannot find it and then the spring will throw the excetpion.
How to allow the spring create same name bean ?
I find the answer from here
Here is the import part of the answer
You may use an initializer when building your Spring Boot app:
@SpringBootApplication public class SpringBootApp { public static void main(String... args) { new SpringApplicationBuilder(SpringBootApp.class) .initializers(new ApplicationContextInitializer<GenericApplicationContext>() { @Override public void initialize(GenericApplicationContext applicationContext) { applicationContext.setAllowBeanDefinitionOverriding(false); } }) .run(args); } }
Or with java 8:
new SpringApplicationBuilder(SpringBootApp.class) .initializers((GenericApplicationContext c) -> c.setAllowBeanDefinitionOverriding(false) ) .run(args);
Upvotes: 0