Java Config for Autowiring a DataSource with PropertyPlaceholderConfigurer
I want to use Java Config to declare my PropertyPlaceholderConfigurer bean. The bean loads its properties from a database table using CommonsConfigurationFactoryBean with a DatabaseConfiguration bean. A different DataSource bean profile is loaded depending upon the environment in which the application is deployed. The problem I am facing appears to be in the order in which my beans are loaded. The PropertyPlaceholderConfigurer bean seems to be loaded before my DataSource bean, which causes problems because I need a reference to the DataSource bean in order to load my properties. In the following code example, dataSource is null when PropertyPlaceholderConfigurer initializes. I am using Spring 3.1.1.RELEASE
Code:
@Configuration
public class DatabaseConfig {
@Autowired
private DataSource dataSource;
@Bean
public PropertyPlaceholderConfigurer propertyPlaceholderConfigurer() throws Exception {
PropertyPlaceholderConfigurer p = new PropertyPlaceholderConfigurer();
p.setProperties((Properties) commonsConfigurationFactoryBean().getObject());
return p;
}
@Bean
public CommonsConfigurationFactoryBean commonsConfigurationFactoryBean() {
return new CommonsConfigurationFactoryBean(databaseConfiguration());
}
@Bean
public DatabaseConfiguration databaseConfiguration() {
return new DatabaseConfiguration(dataSource, "TABLE", "NAME_COLUMN", "KEY_COLUMN", "VALUE_COLUMN", "NAME");
}
@Profile({ "dev" })
static class Dev {
@Bean
public DataSource dataSource() {
return new SimpleDriverDataSource(new OracleDriver(), "jdbc:oracle:thin:@dev-host:port:db", "username",
"password");
}
}
@Profile({ "prod" })
static class Prod {
@Bean
public DataSource dataSource() {
return new SimpleDriverDataSource(new OracleDriver(), "jdbc:oracle:thin:@prod-host:port:db", "username",
"password");
}
}
}
Using inheritance should work here, though I have not verified.
I removed the CommonsConfigurationFactoryBean as it is not supported in Spring 3.x and we can do fine here without it. Because the @Profile extends the abstract Base class the bean context should properly resolve. Hope this works for you!
Code:
@Configuration
public class DatabaseConfig {
static abstract class Base {
public abstract DataSource dataSource();
@Bean
public PropertyPlaceholderConfigurer propertyPlaceholderConfigurer() throws Exception {
PropertyPlaceholderConfigurer p = new PropertyPlaceholderConfigurer();
p.setProperties(ConfigurationConverter.getProperties(databaseConfiguration()));
return p;
}
@Bean
public DatabaseConfiguration databaseConfiguration() {
return new DatabaseConfiguration(dataSource(), "TABLE", "NAME_COLUMN", "KEY_COLUMN", "VALUE_COLUMN", "NAME");
}
}
@Profile({ "dev" })
static class Dev extends Base {
@Bean
public DataSource dataSource() {
return new SimpleDriverDataSource(new OracleDriver(), "jdbc:oracle:thin:@dev-host:port:db", "username",
"password");
}
}
@Profile({ "prod" })
static class Prod extends Base {
@Bean
public DataSource dataSource() {
return new SimpleDriverDataSource(new OracleDriver(), "jdbc:oracle:thin:@prod-host:port:db", "username",
"password");
}
}
}