When the DataSource is refresh scope(provided by spring-cloud), I cannot inject the JdbcTemplate to my component. Probably, JdbcTemplateConfiguration(auto-configure) not work.

  • Configuration class
  @Bean
  @RefreshScope
  DataSource dataSource(DataSourceProperties properties) {
    HikariDataSource dataSource = properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
    if (StringUtils.hasText(properties.getName())) {
      dataSource.setPoolName(properties.getName());
    }
    return dataSource;
  }
  • My component (controller)
  @RestController
  static class SettingsController {
    private final JdbcOperations operations;

    SettingsController(JdbcOperations operations) {
      this.operations = operations;
    }

    @GetMapping("/settings")
    public List<Map<String, Object>> getSettings() {
      return operations.queryForList("select * from settings order by key");
    }
  }
  • log
...
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-06-20 19:23:27.503 ERROR 35308 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in com.example.demo.RefreshableDsDemoApplication$SettingsController required a bean of type 'org.springframework.jdbc.core.JdbcOperations' that could not be found.
...

Reproduce project

  • https://github.com/kazuki43zoo/refreshable-ds-demo

How to reproduce

Please run the RefreshableDsDemoApplicationTests.

NOTE:

When the DataSource is singleton scope, it work fine. (Please run the NonRefreshableDsDemoApplicationTests)

Comment From: wilkinsona

Thanks for the sample. The problem is that using @RefreshScope results in two DataSource beans in the context, dataSource and scopedTarget.dataSource. This causes the @ConditionalOnSingleCandidate auto-configuration of JdbcTemplate to back off:

  JdbcTemplateAutoConfiguration:
      Did not match:
         - @ConditionalOnSingleCandidate (types: javax.sql.DataSource; SearchStrategy: all) did not find a primary bean from beans 'scopedTarget.dataSource', 'dataSource' (OnBeanCondition)

I think we need to ignore scoped targets when searching for a single candidate.