Search code examples
javaspringspring-bootspring-boot-configuration

Cannot override Spring Bean although CondionalOnMissingBean is present


I have this class in a library project:

@ConditionalOnMissingBean(name = "myServiceActivator")
@Component(value = "myServiceActivator")
public class MyServiceActivator {

    @ServiceActivator(inputChannel = "SomeChannel")
    public void handleApplicationEvent(@Payload Object object) {
        // ...
    }

}

And in a project where I have the library as dependency I have:

@Component(value = "myServiceActivator")
public class ChildServiceActivator {

    @ServiceActivator(inputChannel = "SomeChannel")
    public void handleApplicationEvent(@Header("SomeHeader") String header, @Payload Object object) {
        // Do something else
    }
}

And I'm getting:

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'myServiceActivator' for bean class [com.company.project.domain.integration.ChildServiceActivator] conflicts with existing, non-compatible bean definition of same name and class [com.company.commons.domain.integration.MyServiceActivator]

I'd expect @ConditionalOnMissingBean to skip creation of MyServiceActivator as per here, here and actually many more. Why doesn't it and how do I only create an instance of ChildServiceActivator?


Solution

  • Removing

    @ConditionalOnMissingBean(name = "myServiceActivator")
    @Component(value = "myServiceActivator")
    

    and moving the definition of the @Bean to a @Configuration file as:

    @Configuration
    public class ServiceActivatorConfiguration{
        
        @Bean
        @ConditionalOnMissingBean(name = "myServiceActivator")
        public ServiceActivator serviceActivator() {
            return new MyServiceActivator();
        }
    }
    

    and overriding this configuration in the child project:

    @Configuration
    public class ChildServiceActivatorConfiguration{
        
        @Bean
        public ServiceActivator serviceActivator() {
            return new ChildServiceActivator();
        }
    }
    

    resolved the issue, as suggested here.