Search code examples
springspring-bootspring-data-jpaspring-configspring-boot-configuration

Custom Auto Configuration in Spring Boot cannot find DataSource with ConditionalOnBean


I have a problem with Spring Boot version 2.0.1.RELEASE (in Spring Boot 2.0.0.RELEASE the below configuration worked nice).

Could somebody help me out please why this configuration is not working? I have this configuration and this config did not match the ConditionalOnBean condition.

The AutoConfigureOrder / Order / AutoConfigureAfter seems that doesn't have any effect.

@Configuration
@ConditionalOnClass({DataSource.class, JpaRepository.class})
@ConditionalOnBean(DataSource.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
@ConditionalOnProperty(prefix = "spring.data.jpa.repositories", name = "enabled", havingValue = "true", matchIfMissing = true)
@AutoConfigureOrder(LOWEST_PRECEDENCE)
@Order(LOWEST_PRECEDENCE)
public class MyJpaAuditAutoConfiguration {

    @ConditionalOnMissingBean
    @Bean
    public MyTransactionHelper transactionHelper() {
        return new MyTransactionHelper();
    }

}

In spring.factories I have:

     org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.example.MyJpaAuditAutoConfiguration

Application start output for this configuration:

DataSourceAutoConfiguration matched:
  - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

...

JpaAuditAutoConfiguration:
  Did not match:
     - @ConditionalOnBean (types: javax.sql.DataSource; SearchStrategy: all) did not find any beans of type javax.sql.DataSource (OnBeanCondition)
  Matched:
     - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.data.jpa.repository.JpaRepository'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
     - @ConditionalOnProperty (spring.data.jpa.repositories.enabled=true) matched (OnPropertyCondition)

In my opinion, the config class is evaluated before DataSourceAutoConfiguration and that's the reason why the bean cannot be found. Other configs like DataSourceHealthIndicatorAutoConfiguration found the bean.

DataSourceHealthIndicatorAutoConfiguration matched:
  - @ConditionalOnClass found required classes 'org.springframework.jdbc.core.JdbcTemplate', 'org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
  - @ConditionalOnEnabledHealthIndicator management.health.defaults.enabled is considered true (OnEnabledHealthIndicatorCondition)
  - @ConditionalOnBean (types: javax.sql.DataSource; SearchStrategy: all) found bean 'dataSource' (OnBeanCondition)

Solution

  • After spring boot upgrade to version 2.1.2.RELEASE it was solved automatically.

    (I renamed some classes in the answer)

    So in Spring Boot version 2.1.2.RELEASE:

    @Configuration
    @ConditionalOnBean(DataSource.class)
    @ConditionalOnClass({DataSource.class, JpaRepository.class})
    @ConditionalOnProperty(prefix = "spring.data.jpa.repositories", name = "enabled", havingValue = "true", matchIfMissing = true)
    @AutoConfigureAfter(DataSourceAutoConfiguration.class)
    public class JpaTransactionHelperAutoConfiguration {
    
        @ConditionalOnMissingBean
        @Bean
        public TransactionHelper transactionHelper() {
            return new TransactionHelper();
        }
    
    }
    

    NOTE: by removing the @AutoConfigureAfter(DataSourceAutoConfiguration.class) it won't work in Spring Boot version 2.1.2.RELEASE.

    In Spring Boot version 2.0.1.RELEASE I just removed the ConditionalOnBean annotation:

    @Configuration
    @ConditionalOnClass({DataSource.class, JpaRepository.class})
    @ConditionalOnProperty(prefix = "spring.data.jpa.repositories", name = "enabled", havingValue = "true", matchIfMissing = true)
    @AutoConfigureAfter(DataSourceAutoConfiguration.class)
    public class JpaTransactionHelperAutoConfiguration {
    
        @ConditionalOnMissingBean
        @Bean
        public TransactionHelper transactionHelper() {
            return new TransactionHelper();
        }
    
    }