Skip to content

Actuator throws an exception when using prototype scoped DataSource bean #44706

Closed
@BbIKTOP

Description

@BbIKTOP

Spring Boot 3.4.3:

    <properties>
        <java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.4.3</version>
        <relativePath/>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>2.5.0</version>
        </dependency>

Test configuration:


@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;
    }
}


Exception (org/springframework/boot/actuate/autoconfigure/metrics/jdbc/DataSourcePoolMetricsAutoConfiguration$DataSourcePoolMetadataMetricsConfiguration.class):

2025-03-13T11:15:30.078+02:00 DEBUG 57764 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Autowiring by type from bean name 'org.springframework.boot.actuate.autoconfigure.metrics.data.RepositoryMetricsAutoConfiguration' via constructor to bean named 'management.metrics-org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties'
2025-03-13T11:15:30.079+02:00 DEBUG 57764 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'repositoryTagsProvider'
2025-03-13T11:15:30.079+02:00 DEBUG 57764 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'metricsRepositoryMethodInvocationListener'
2025-03-13T11:15:30.080+02:00 DEBUG 57764 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Autowiring by type from bean name 'metricsRepositoryMethodInvocationListener' via factory method to bean named 'repositoryTagsProvider'
2025-03-13T11:15:30.081+02:00 DEBUG 57764 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.integration.IntegrationMetricsAutoConfiguration'
2025-03-13T11:15:30.082+02:00 DEBUG 57764 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration$HikariDataSourceMetricsConfiguration'
2025-03-13T11:15:30.082+02:00 DEBUG 57764 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'hikariDataSourceMeterBinder'
2025-03-13T11:15:30.083+02:00 DEBUG 57764 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration$DataSourcePoolMetadataMetricsConfiguration'
2025-03-13T11:15:30.083+02:00 DEBUG 57764 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'dataSourcePoolMetadataMeterBinder'
2025-03-13T11:15:30.083+02:00 DEBUG 57764 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Autowiring by type from bean name 'dataSourcePoolMetadataMeterBinder' via factory method to bean named 'org.springframework.beans.factory.support.DefaultListableBeanFactory@6a988392'

2025-03-13T11:15:30.084+02:00  WARN 57764 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourcePoolMetadataMeterBinder' defined in class path resource [org/springframework/boot/actuate/autoconfigure/metrics/jdbc/DataSourcePoolMetricsAutoConfiguration$DataSourcePoolMetadataMetricsConfiguration.class]: Failed to instantiate [org.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 [st/notexi/springtest/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-13T11:15:30.085+02:00 DEBUG 57764 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown
2025-03-13T11:15:30.086+02:00  INFO 57764 --- [           main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2025-03-13T11:15:30.086+02:00 DEBUG 57764 --- [           main] o.hibernate.internal.SessionFactoryImpl  : HHH000031: Closing
2025-03-13T11:15:30.086+02:00 DEBUG 57764 --- [           main] o.h.type.spi.TypeConfiguration$Scope     : Un-scoping TypeConfiguration [org.hibernate.type.spi.TypeConfiguration$Scope@1444e35f] from SessionFactory [org.hibernate.internal.SessionFactoryImpl@1b83fac3]
2025-03-13T11:15:30.086+02:00 DEBUG 57764 --- [           main] o.h.s.i.AbstractServiceRegistryImpl      : Implicitly destroying ServiceRegistry on de-registration of all child ServiceRegistries
2025-03-13T11:15:30.087+02:00 DEBUG 57764 --- [           main] o.h.b.r.i.BootstrapServiceRegistryImpl   : Implicitly destroying Boot-strap registry on de-registration of all child ServiceRegistries
2025-03-13T11:15:30.087+02:00  INFO 57764 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2025-03-13T11:15:30.087+02:00 DEBUG 57764 --- [           main] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Before shutdown stats (total=10, active=0, idle=10, waiting=0)
2025-03-13T11:15:30.087+02:00 DEBUG 57764 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase          : HikariPool-1 - Closing connection org.postgresql.jdbc.PgConnection@69ce14e6: (connection evicted)
2025-03-13T11:15:30.089+02:00 DEBUG 57764 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase          : HikariPool-1 - Closing connection org.postgresql.jdbc.PgConnection@79479b8c: (connection evicted)
2025-03-13T11:15:30.089+02:00 DEBUG 57764 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase          : HikariPool-1 - Closing connection org.postgresql.jdbc.PgConnection@36bd60ef: (connection evicted)
2025-03-13T11:15:30.089+02:00 DEBUG 57764 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase          : HikariPool-1 - Closing connection org.postgresql.jdbc.PgConnection@b753c39: (connection evicted)
2025-03-13T11:15:30.089+02:00 DEBUG 57764 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase          : HikariPool-1 - Closing connection org.postgresql.jdbc.PgConnection@56929fa0: (connection evicted)
2025-03-13T11:15:30.089+02:00 DEBUG 57764 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase          : HikariPool-1 - Closing connection org.postgresql.jdbc.PgConnection@3da82a53: (connection evicted)
2025-03-13T11:15:30.089+02:00 DEBUG 57764 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase          : HikariPool-1 - Closing connection org.postgresql.jdbc.PgConnection@32472127: (connection evicted)
2025-03-13T11:15:30.089+02:00 DEBUG 57764 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase          : HikariPool-1 - Closing connection org.postgresql.jdbc.PgConnection@107157a2: (connection evicted)
2025-03-13T11:15:30.089+02:00 DEBUG 57764 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase          : HikariPool-1 - Closing connection org.postgresql.jdbc.PgConnection@52dca593: (connection evicted)
2025-03-13T11:15:30.089+02:00 DEBUG 57764 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase          : HikariPool-1 - Closing connection org.postgresql.jdbc.PgConnection@2edaf729: (connection evicted)
2025-03-13T11:15:30.089+02:00 DEBUG 57764 --- [           main] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - After shutdown stats (total=0, active=0, idle=0, waiting=0)
2025-03-13T11:15:30.089+02:00  INFO 57764 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
2025-03-13T11:15:30.090+02:00 DEBUG 57764 --- [           main] o.s.b.f.support.DisposableBeanAdapter    : Custom destroy method 'close' on bean with name 'simpleMeterRegistry' completed
2025-03-13T11:15:30.091+02:00  INFO 57764 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]

App properties:

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

Problem:
Spring Boot Actuator is trying to instantiate a parametrized prototype bean ignoring properties.

Fix:
No need to retrieve beans with scopes other than singleton because it leads to the new bin creation. And there's no scenario exists to monitor beans created by the actuator, not by the app.

Usage example in the app:

@Data
public class CredsSource
{
    private String dbUrl;
    private String dbUser;
    private String dbPassword;
}

@Service
public class SomeServiceClass
{
    public void someMethod(@Qualifier("sourceDataSource") ObjectProvider<DataSource> srcDataSourceProvider,
                           CredsSource credsSource)
    {
        DataSource srcDataSource = srcDataSourceProvider.getObject(credsSource.getDbUrl(),
                credsSource.getDbUser(), credsSource.getDbPassword());
    }
}

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions