ym_wp
ym_wp

Reputation: 145

Spring boot - A single @Configuration @import will work but multiple will not, why?

In a Spring boot project, I have a RestController that contains:

@Autowired
private ProactiveDbManager proactiveDbManager;

@Autowired
private CoreDbManager coreDbManager;

Theses 2 db managers are in another Spring boot module, so I'm importing them with a configuration class:

@Configuration
@PropertySource("classpath:application.properties")
@Import({ProactiveDbCommonsConfig.class})
public class ProactiveDbConfig {

}

and:

@Configuration
@PropertySource("classpath:application.properties")
@Import({CoreDbCommonsConfig.class})
public class CoreDbConfig {

}

ProactiveDbCommonsConfig and CoreDbCommonsConfig are also configurations. ProactiveDbCommonsConfig:

@Configuration
public class ProactiveDbCommonsConfig {
    private static final Logger LOGGER = LoggerFactory.getLogger(ProactiveDbCommonsConfig.class);

    private ProactiveDbManager proactiveDbManager;
    @Bean
    public MasterHandler masterHandler() {
        return new MasterHandler(true);
    }

    @Bean
    public ProactiveDbManager dBManager(MasterHandler masterHandler) {
        List<String> dbConnectionStrings = masterHandler.getDbConnectionStringsJsonsList(DbConsts.DEFAULT_DATA_CENTER);
        LOGGER.debug("DB manager created.");
        proactiveDbManager = new ProactiveDbManager(dbConnectionStrings);
        return proactiveDbManager;
    }


    @Override
    protected void finalize() {
        try {
            closeDbConnection();
        } catch (Exception ignored) {
        }
    }

    @PreDestroy
    public void closeDbConnection() throws Exception {
        if (this.proactiveDbManager != null) {
            this.proactiveDbManager.disconnect();
            this.proactiveDbManager = null;
        }
    }
}

My problem is that if I remove 1 of the autowired in the controller and remove its configuration (i.e ProactiveDbConfig) then it works. Both of them work alone, but not together.

The error I get is:

Field coreDbManager in x.y.z.controllers.h required a bean of type 'x.y.a.db.managers.CoreDbManager' that could not be found.

Stack trace:

15:56:14.609 [main] DEBUG o.s.b.d.LoggingFailureAnalysisReporter - Application failed to start due to an exception
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'x.y.db.managers.CoreDbManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)
    at x.y.app.MyApp.main(MyApp.java:10)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.CommandLineWrapper.main(CommandLineWrapper.java:66)
15:56:14.609 [main] ERROR o.s.b.d.LoggingFailureAnalysisReporter - 

Upvotes: 1

Views: 1191

Answers (1)

M. Deinum
M. Deinum

Reputation: 124601

When using @Configuration classes and not explicitly defining a name of the bean in @Bean(name = "<your-name-here>") the methodname will be used as the name of the bean.

If you import multiple configuration files which contain beans with the same name one will override the other. Newer versions of Spring Boot prevent this by disable overriding (which is enabled by default) which will lead to an exception upon startup.

In your case the solution, either rename the method or add an explicit name to the @Bean annotation.

Upvotes: 2

Related Questions