I see a couple of similar questions here but nothing works in my case. So, although it looks like a "duplicate", I hope it is not.
Problem: I have an app with multiple (actually 3) datasources. The primary is used by the Spring JPA, other two by the pure JDBC API. One of these DataSources (sourceDataSource) is defined as a parametrized prototype scoped bean and instantiated with different parameters via ObjectProvider.
The @Configuration class looks like that:
@Configuration
public class DbConfig
{
@Bean
@ConfigurationProperties("spring.datasource")
public DataSourceProperties primaryDataSourceProperties()
{
return new DataSourceProperties();
}
@Bean(name = "cfgDataSource")
@Primary
@ConfigurationProperties("spring.datasource.hikari")
public DataSource primaryDataSource()
{
return primaryDataSourceProperties()
.initializeDataSourceBuilder()
.type(HikariDataSource.class)
.build();
}
@Bean
@ConfigurationProperties("app.destination-datasource")
public DataSourceProperties destinationDataSourceProperties()
{
return new DataSourceProperties();
}
@Bean(name = "destinationDataSource")
@ConfigurationProperties("app.destination-datasource.hikari")
public DataSource destinationDataSource()
{
HikariDataSource dataSource = destinationDataSourceProperties()
.initializeDataSourceBuilder()
.type(HikariDataSource.class)
.build();
return dataSource;
}
@Bean
@ConfigurationProperties("app.source-datasource")
public DataSourceProperties sourceDataSourceProperties()
{
return new DataSourceProperties();
}
@Bean(name = "sourceDataSource")
@Scope("prototype")
@ConfigurationProperties("app.source-datasource.hikari")
@Lazy
public DataSource sourceDataSource(String url, String user, String password)
{
DataSourceProperties srcProps = sourceDataSourceProperties();
srcProps.setUrl(url);
srcProps.setUsername(user);
srcProps.setPassword(password);
DataSource ds = srcProps
.initializeDataSourceBuilder()
.build();
return ds;
}
}
Everything works fine, JPA is working, DataSources creation too, but just till I try to add actuator. After adding actuator, I am getting the following exception:
2025-03-13T01:33:28.175+02:00 WARN 39155 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt:
.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourcePoolMetadataMeterBinder' defined in class path resource [/springframework/boot/actuate/autoconfigure/metrics/jdbc/DataSourcePoolMetricsAutoConfiguration$DataSourcePoolMetadataMetricsConfiguration.class]:
Failed to instantiate [.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration$DataSourcePoolMetadataMetricsConfiguration$DataSourcePoolMetadataMeterBinder]:
Factory method 'dataSourcePoolMetadataMeterBinder' threw exception with message:
Error creating bean with name 'sourceDataSource' defined in class path resource [app/config/DbConfig.class]:
Unsatisfied dependency expressed through method 'sourceDataSource' parameter 0:
No qualifying bean of type 'java.lang.String' available:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
2025-03-13T01:33:28.177+02:00 INFO 39155 --- [ main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2025-03-13T01:33:28.183+02:00 INFO 39155 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2025-03-13T01:33:28.195+02:00 INFO 39155 --- [ main] .s.b.a.l.ConditionEvaluationReportLogger :
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2025-03-13T01:33:28.215+02:00 ERROR 39155 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method sourceDataSource in com.freewayfleet.dbreplicator.config.DbConfig required a bean of type 'java.lang.String' that could not be found.
Action:
Consider defining a bean of type 'java.lang.String' in your configuration.
My question is, why does actuator try to instantiate a prototype scoped bean and how to fix that? I think I could make some decorator for this particular parametrized DataSource, but it will require to refactor a lot of code and current approach is "cleaner", I suppose.
I tried these solutions (in different combinations and all together):
management:
health:
db:
enabled: false
endpoint:
health:
group:
readiness:
include: db
exclude: db/sourceDataSource
default:
include: "*"
exclude: "sourceDataSource"
server:
port: 9091
endpoints:
web:
base-path: /actuator
path-mapping:
health: /health
exposure:
include: metrics,health,env
but with the same results. I am definitely doing something wrong. Please help.
Spring Boot 3.4.3