dustins
dustins

Reputation: 353

spring configuration not autowired before bean creation?

So one of my configuration classes includes both (Testing/Production)DatabaseConfig classes, and the right one gets chosen by the the active profile. But when the DatabaseConfig class runs, it's dataSource ivar is null.

I did a debug, my TestingDatabaseConfig's dataSource() method is run before DatabaseConfig's localContainerEntityManagerFactoryBean() is run.

I guess my question is, why isn't this working, should it work, and what am I doing wrong?

@Configuration
@Profile({"testing-db", "production-db"})
@Import({TestingDatabaseConfig.class, ProductionDatabaseConfig.class})
@EnableTransactionManagement
public class DatabaseConfig
{
    @Resource
    private DataSource dataSource;

    @Bean(name = "entityManager")
    public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean()
    {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();

        entityManagerFactoryBean.setDataSource(this.dataSource);

        // other config

        return entityManagerFactoryBean;
    }

    // ... other db related beans stuff ...
}

@Configuration
@Profile("testing-db")
public class TestingDatabaseConfig implements DatabaseConfigInterface
{
    @Bean(name="dataSource")
    public DataSource dataSource()
    {
        JDBCDataSource dataSource = new JDBCDataSource();
        dataSource.setDatabase("jdbc:hsqldb:mem:testing");
        dataSource.setUser("sa");

        return dataSource;
    }
}

Upvotes: 1

Views: 6384

Answers (3)

dustins
dustins

Reputation: 353

It seems that things do not just magically work! If you want configuration classes to have their ivars autowired, you have to have it configured correctly, or in this case, having another bean that does the autowiring.

You need to create the AutowiredAnnotationBeanPostProcessor bean.

@Bean
public AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor()
{
    return new AutowiredAnnotationBeanPostProcessor();
}

or

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />

Upvotes: 0

dustins
dustins

Reputation: 353

Ok, so I must have just done this wrong the first time, but the solution is to let the beans be autowired as parameters instead of trying to have them injected as an ivar. A fake diff of what I had to change to get it to work…

-    @Resource
-    private DataSource dataSource;

- public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean()
+ public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean(DataSource dataSource)

-    entityManagerFactoryBean.setDataSource(this.dataSource);
+    entityManagerFactoryBean.setDataSource(dataSource);

Ended up being cleaner than what I was trying to do anyways =)

Upvotes: 0

Gergely Szilagyi
Gergely Szilagyi

Reputation: 3903

Of course they're not injected before the call to the constructor.

Use @PostConstruct. Here's a nice example: http://www.mkyong.com/spring/spring-postconstruct-and-predestroy-example/

Upvotes: 2

Related Questions