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 theNonRefreshableDsDemoApplicationTests
)
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.