Home > Software engineering >  Initialize datasource bean on condition
Initialize datasource bean on condition

Time:01-27

So, I need to make an initialization of DataSource by condition. I take all the db-config data from the .env file, where there is a special variable spring_profiles_active. When this variable is equal to "p2" I need to initialize secondDataSource, otherwise not. How do I do this? My configuration:

@Configuration
public class JpaConfig {
    @Value("${jdbc.url}")
    private String jdbcUrl;
    @Value("${jdbc.username}")
    private String jdbcUsername;
    @Value("${jdbc.password}")
    private String jdbcPassword;
    @Value("${jdbc.driverClassName}")
    private String jdbcDriverClassName;

    @Value("${second.jdbc.url}")
    private String secondJdbcUrl;
    @Value("${second.jdbc.username}")
    private String secondJdbcUsername;
    @Value("${second.jdbc.password}")
    private String secondJdbcPassword;
    @Value("${second.jdbc.driverClassName}")
    private String secondJdbcDriverClassName;

    @Bean
    @Primary
    public DataSource dataSource(){
        DriverManagerDataSource dataSource = new DriverManagerDataSource();

        dataSource.setDriverClassName(jdbcDriverClassName);
        dataSource.setUrl(jdbcUrl);
        dataSource.setUsername(jdbcUsername);
        dataSource.setPassword(EncryptionUtil.decryptProperty(jdbcPassword));

        return dataSource;
    }

    @Bean
    @Qualifier("secondDataSource")
    public DataSource secondDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();

        dataSource.setDriverClassName(secondJdbcDriverClassName);
        dataSource.setUrl(secondJdbcUrl);
        dataSource.setUsername(secondJdbcUsername);
        dataSource.setPassword(EncryptionUtil.decryptProperty(secondJdbcPassword));

        return dataSource;
    }
 

    @Bean
    @Primary
    public JdbcTemplate jdbcTemplate() { return new JdbcTemplate(dataSource()); }

    @Bean
    @Qualifier("secondJdbcTemplate")
    public JdbcTemplate secondJdbcTemplate(@Qualifier("secondDataSource") DataSource secondDataSource) {
        return new JdbcTemplate(secondDataSource);
    }
}

  • update: I try to do this with @Condition annotation, but get an exception java.lang.NullPointerException: null in return activeProfile.equals("p2"). code:
    @Configuration
    @Conditional(SecondJpaConfigCondition.class)
    public class SecondJpaConfig {
    
        @Value("${second.jdbc.url}")
        private String secondJdbcUrl;
        @Value("${second.jdbc.username}")
        private String secondJdbcUsername;
        @Value("${second.jdbc.password}")
        private String secondJdbcPassword;
        @Value("${second.jdbc.driverClassName}")
        private String secondJdbcDriverClassName;
        
        @Bean
        @Qualifier("secondDataSource")
        public DataSource secondDataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
    
            dataSource.setDriverClassName(secondJdbcDriverClassName);
            dataSource.setUrl(secondJdbcUrl);
            dataSource.setUsername(secondJdbcUsername);
            dataSource.setPassword(EncryptionUtil.decryptProperty(secondJdbcPassword));
    
            return dataSource;
        }
        
        @Bean
        @Qualifier("secondJdbcTemplate")
        public JdbcTemplate secondJdbcTemplate(@Qualifier("secondDataSource") DataSource secondDataSource) {
            return new JdbcTemplate(secondDataSource);
        }
    }
@Component
public class SecondJpaConfigCondition implements Condition {

    @Value("${spring.profiles.active}")
    private String activeProfile;

    @Override
    public boolean matches(ConditionContext arg0, AnnotatedTypeMetadata arg1) {
        return activeProfile.equals("p2");
    }
}

CodePudding user response:

I recommend you to use the @ConditionalOnProperty annotation. It can be used on the class or a method with the @Bean annotation. I would separate the configuration of the two databases in two different classes (it's not mandatory, you could us the annotion over the secondDataSource and secondJdbcTemplate methods) and do something like this:

JpaConfig (First Datasource):



@Configuration
public class JpaConfig {
    
    @Value("${jdbc.url}")
    private String jdbcUrl;
    @Value("${jdbc.username}")
    private String jdbcUsername;
    @Value("${jdbc.password}")
    private String jdbcPassword;
    @Value("${jdbc.driverClassName}")
    private String jdbcDriverClassName;

    @Bean
    @Primary
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();

        dataSource.setDriverClassName(jdbcDriverClassName);
        dataSource.setUrl(jdbcUrl);
        dataSource.setUsername(jdbcUsername);
        dataSource.setPassword(EncryptionUtil.decryptProperty(jdbcPassword));

        return dataSource;
    }

    @Bean
    @Primary
    public JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource());
    }

}

JpaConditionalConfig (Second Datasource):



    @Configuration
    @ConditionalOnProperty(prefix = "cond", name = "spring_profiles_active", havingValue = "p2")
    public class JpaOptionalConfig {
    
        @Value("${second.jdbc.url}")
        private String secondJdbcUrl;
        @Value("${second.jdbc.username}")
        private String secondJdbcUsername;
        @Value("${second.jdbc.password}")
        private String secondJdbcPassword;
        @Value("${second.jdbc.driverClassName}")
        private String secondJdbcDriverClassName;
        
        @Bean
        @Qualifier("secondDataSource")
        public DataSource secondDataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
    
            dataSource.setDriverClassName(secondJdbcDriverClassName);
            dataSource.setUrl(secondJdbcUrl);
            dataSource.setUsername(secondJdbcUsername);
            dataSource.setPassword(EncryptionUtil.decryptProperty(secondJdbcPassword));
    
            return dataSource;
        }
        
        @Bean
        @Qualifier("secondJdbcTemplate")
        public JdbcTemplate secondJdbcTemplate(@Qualifier("secondDataSource") DataSource secondDataSource) {
            return new JdbcTemplate(secondDataSource);
        }
    }

Properties file where is defined the spring_profiles_active property, which will be read by Spring to know if the conditional beans should be created:



    jdbc.url=jdbc:h2:mem:mydb
    jdbc.username=sa
    jdbc.password=password
    jdbc.driverClassName=org.h2.Driver
    
    second.jdbc.url=jdbc:h2:mem:mydb
    second.jdbc.username=sa
    second.jdbc.password=password
    second.jdbc.driverClassName=org.h2.Driver
    
    #THIS IS THE PROPERTY USED IN THE CONDITIONAL BEANS
    conditional.spring_profiles_active=p2

  •  Tags:  
  • Related