Search code examples
spring-bootspring-ioc

Spring boot: bean definition name duplicated


I'm getting next message when my service starts:

ConflictingBeanDefinitionException: Annotation-specified bean name 'estatRegistreServiceImpl' for bean class [cat.gencat.catsalut.hes.mpi.api.loader.service.EstatRegistreServiceImpl] conflicts with existing, non-compatible bean definition of same name and class [cat.gencat.catsalut.hes.mpi.api.admin.service.impl.EstatRegistreServiceImpl]

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'estatRegistreServiceImpl' for bean class [cat.gencat.catsalut.hes.mpi.api.loader.service.EstatRegistreServiceImpl] conflicts with existing, non-compatible bean definition of same name and class [cat.gencat.catsalut.hes.mpi.api.admin.service.impl.EstatRegistreServiceImpl]

Currently, I've created two packages containing my services:

src/main/java/cat/gencat/catsalut/hes/mpi/api/admin/service/
src/main/java/cat/gencat/catsalut/hes/mpi/api/loader/service/

src/main/java/cat/gencat/catsalut/hes/mpi/api/admin/service/

src/main/java/cat/gencat/catsalut/hes/mpi/api/admin/service/
├── EstatRegistreService.java
├── impl
    ├── EstatRegistreServiceImpl.java

And

src/main/java/cat/gencat/catsalut/hes/mpi/api/loader/service/
├── EstatRegistreService.java
├── impl
    ├── EstatRegistreServiceImpl.java

Both beans are registered using the same name: estatRegistreServiceImpl.

I know I've able to use @Service annotation setting a registration name. I don't want to mantain these string literals since I've a lot of service-like classes.

Is there any way to get it without using @Service("service1") and @Service("service2)`?

Thanks


Solution

  • Well you can create a custom bean name generator. It will add full qualifier path to when registering bean.

    Here I have implemented to ApplicationRunner interface just to illustrate the what is the bean names will be!

    @SpringBootApplication
    @ComponentScan(nameGenerator = YourMainApplication.CustomGenerator.class)
    public class YourMainApplication extends SpringBootServletInitializer implements ApplicationRunner {
    
        @Autowired
        private ApplicationContext context;
    
        public static void main(String[] args) {
            SpringApplication.run(YourMainApplication.class, args);
        }
    
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
            return application.sources(YourMainApplication.class);
        }
    
        public static class CustomGenerator extends AnnotationBeanNameGenerator {
            @Override
            public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
                return definition.getBeanClassName();
            }
        }
    
        @Override
        public void run(ApplicationArguments args) {
            String[] allServiceBeansNames = context.getBeanNamesForAnnotation(Service.class);
            for(String beanName : allServiceBeansNames) {
                System.out.println(beanName);
            }
        }
    }