Search code examples
javaspringconfigurationspring-jdbcspring-bean

Spring autowire custom @ConfigurationProperties object by prefix


I would like to achieve not-trivial bean injection implementation.

I have a custom properties file:

@Getter
@Setter
@ConfigurationProperties
public class DatabaseProperties {
  private String url;
  private String username;
  private String password;
}

I Here is the configuration file:

@Configuration
@EnableConfigurationProperties(DatabaseProperties.class)
public class DBConfig {

  @Bean
  @ConfigurationProperties(prefix = "datasource.database1")
  public JdbcTemplate jdbcTemplateDatabase1(DatabaseProperties databaseProperties) {
    DataSource dataSource = new DriverManagerDataSource(
            databaseProperties.getUrl(),
            databaseProperties.getUsername(),
            databaseProperties.getPassword());
    return new JdbcTemplate(dataSource);
  }

  @Bean
  @ConfigurationProperties(prefix = "datasource.database2")
  public JdbcTemplate jdbcTemplateDatabase2(DatabaseProperties databaseProperties) {
    DataSource dataSource = new DriverManagerDataSource(
            databaseProperties.getUrl(),
            databaseProperties.getUsername(),
            databaseProperties.getPassword());
    return new JdbcTemplate(dataSource);
  }
}

The goal I want to achieve is to instantiate a new DatabaseProperties instance based on prefix.

There are two possible solutions:

  • create two beans of type DatabaseProperties using corresponding prefixes and two JdbcTemplate beans where parameter is qualified DatabaseProperties bean accordingly.
  • in each JdbcTemplate bean provide 3 parameters (String url, String username, String password) and inject them through @Value

BUT Is it possible to get rid of creating DatabaseProperties beans for each JdbcTemplate or using @Value ?


Solution

  • You don't need create a DatabaseProperties. Spring already does this for us on datasources and proprierties variable

    
    @Configuration
    public class ConfigDataSource {
    
    
        @Bean("datasource-1")  // this name will qualify on @autowired
        @ConfigurationProperties(prefix="spring.datasource.yourname-datasource-1") // this is the name for the prefix for datasource on .properties settings
        public DataSource dataSourcePostgres() {
            return DataSourceBuilder.create().build();
        }
        
        
        @Bean("datasource-2")  // this name will qualify on @autowired
        @ConfigurationProperties(prefix="spring.datasource.yourname-datasource-2") // this is the name for the prefix for datasource on .properties settings
        public DataSource dataSourceMySql() {
            return DataSourceBuilder.create().build();
        }
        
    }
    

    .properties

    # Its required use the same name declared in bean
    spring.datasource.yourname-datasource-1.url=...
    spring.datasource.yourname-datasource-1.jdbcUrl=${spring.datasource.yourname-datasource-1}
    spring.datasource.yourname-datasource-1.username=user
    spring.datasource.yourname-datasource-1.password=pass
    spring.datasource.yourname-datasource-1.driver-class-name=your.driver
    
    spring.datasource.yourname-datasource-2.url=...
    spring.datasource.yourname-datasource-2.jdbcUrl=${spring.datasource.yourname-datasource-2}
    spring.datasource.yourname-datasource-2.username=user
    spring.datasource.yourname-datasource-2.password=pass
    spring.datasource.yourname-datasource-2.driver-class-name=your.driver
    

    using on services

    
    @Awtowired
    @Qualifier("datasource-1")
    private DataSource dataSource1;
    
    @Awtowired
    @Qualifier("datasource-2")
    private DataSource dataSource2;
    
    public testJdbcTemplate(){
         // You can qualifier JdbcTemplate below on bean and not necessary need instance on service
         JdbcTemplate jdbcTemplateDatasource1 = new JdbcTemplate(dataSource1);
         JdbcTemplate jdbcTemplateDatasource2 = new JdbcTemplate(dataSource2);
    }