HikariCP 6.3.1 MicrometerMetricsTrackerFactory compatibility issue with Spring Boot 3.5.4

Description

Spring Boot 3.5.4 ships with HikariCP 6.3.1 and Micrometer dependencies that are incompatible, causing a NoSuchMethodException when trying to configure HikariCP with Micrometer metrics tracking.

Steps to Reproduce

  1. Create a Spring Boot 3.5.4 application
  2. Configure a custom HikariCP DataSource with Micrometer registry:
@Configuration
public class PostgresConfiguration {

    @Primary
    @Bean("postgresDataSource")
    public DataSource postgresDataSource(PostgresProperty property, MeterRegistry meterRegistry) {
        HikariConfig hikariConfig = new HikariConfig();
        // ... other configurations
        hikariConfig.setMetricRegistry(meterRegistry); // This line causes the issue
        return new HikariDataSource(hikariConfig);
    }
}
  1. Start the application

Expected Behavior

The application should start successfully with HikariCP metrics enabled.

Actual Behavior

Application fails to start with the following exception:

java.lang.NoSuchMethodException: com.zaxxer.hikari.metrics.micrometer.MicrometerMetricsTrackerFactory.<init>(io.micrometer.prometheusmetrics.PrometheusMeterRegistry)

Environment

  • Spring Boot Version: 3.5.4
  • HikariCP Version: 6.3.1 (managed by Spring Boot)
  • Java Version: Java 21 (based on stack trace)
  • OS: Linux (based on log timestamps)

Root Cause

The issue occurs because HikariCP 6.3.1's MicrometerMetricsTrackerFactory constructor signature is incompatible with the Micrometer PrometheusMeterRegistry type that Spring Boot 3.5.4 provides. When HikariCP tries to instantiate the metrics tracker factory, it cannot find the expected constructor.

Stack Trace

Caused by: java.lang.NoSuchMethodException: com.zaxxer.hikari.metrics.micrometer.MicrometerMetricsTrackerFactory.<init>(io.micrometer.prometheusmetrics.PrometheusMeterRegistry)
        at java.base/java.lang.Class.getConstructor0(Class.java:3761) ~[na:na]
        at java.base/java.lang.Class.getConstructor(Class.java:2442) ~[na:na]
        at com.zaxxer.hikari.util.UtilityElf.createInstance(UtilityElf.java:119) ~[HikariCP-6.3.1.jar!/:na]
        at com.zaxxer.hikari.pool.HikariPool.setMetricRegistry(HikariPool.java:292) ~[HikariCP-6.3.1.jar!/:na]
        at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:103) ~[HikariCP-6.3.1.jar!/:na]
        at com.zaxxer.hikari.HikariDataSource.<init>(HikariDataSource.java:80) ~[HikariCP-6.3.1.jar!/:na]

Workaround

Currently, users need to either: 1. Avoid using setMetricRegistry() in custom HikariCP configurations 2. Manually manage HikariCP and Micrometer dependency versions to ensure compatibility

Demo Project

I have a minimal demo project that reproduces this issue. Please let me know if you'd like me to attach it as a ZIP file.

Additional Information

This appears to be a dependency management issue where Spring Boot 3.5.4's managed dependencies include incompatible versions of HikariCP and Micrometer libraries. The issue specifically affects users who create custom DataSource beans with Micrometer metrics enabled.

Configuration Code

package com.example.demo.configuration;

import com.example.demo.configuration.property.PostgresProperty;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

@Configuration
public class PostgresConfiguration {

    @Primary
    @Bean("postgresDataSource")
    public DataSource postgresDataSource(PostgresProperty property, MeterRegistry meterRegistry) {

        HikariConfig hikariConfig = new HikariConfig();

        // Connection properties
        hikariConfig.setDriverClassName("org.postgresql.Driver");
        hikariConfig.setJdbcUrl(property.url());
        hikariConfig.setUsername(property.username());
        hikariConfig.setPassword(property.password());

        // Pool sizing
        hikariConfig.setMinimumIdle(property.connection().minimum().idle());
        hikariConfig.setMaximumPoolSize(property.connection().maximum().poolSize());

        // Timeout configurations
        hikariConfig.setConnectionTimeout(property.connection().connectionTimeout().toMillis());
        hikariConfig.setValidationTimeout(property.connection().validationTimeout().toMillis());
        hikariConfig.setMaxLifetime(property.connection().maxLifetime().toMillis());
        hikariConfig.setIdleTimeout(property.connection().idleTimeout().toMillis());

        // SQL configurations
        hikariConfig.setConnectionInitSql(property.connection().connectionInitSql());
        hikariConfig.setConnectionTestQuery(property.connection().connectionTestQuery());

        // Other configurations
        hikariConfig.setAllowPoolSuspension(property.connection().allowPoolSuspension());
        hikariConfig.setRegisterMbeans(property.connection().registerMbeans());
        hikariConfig.setMetricRegistry(meterRegistry); // This line causes the issue
        hikariConfig.setPoolName(property.connection().connectionPoolName());

        // Additional Postgres specific properties
        hikariConfig.addDataSourceProperty("defaultRowFetchSize", property.defaultRowFetchSize());
        return new HikariDataSource(hikariConfig);
    }
}

Comment From: garvit-joshi

Reproducible Project: https://github.com/garvit-joshi/spring-boot-issue-46591

Comment From: snicoll

@garvit-joshi thanks for the report but Spring Boot isn't involved in the issue, besides providing dependency management. We could downgrade, but I don't think this is a good idea as it would affect other users that are relying on recent fixes.

I'd have expected you to report that against the HikariCP project but it looks like a number of users are affected in a similar fashion, https://github.com/brettwooldridge/HikariCP/issues/2339

Flagging for team attention to see if we want to do something about this in dependency management.

Comment From: wilkinsona

Short of downgrading to 6.3.0 (and I agree that isn't a good idea), I don't think there's anything we can do in dependency management.

The problem's caused by a regression in 6.3.1. It switched to using reflection to create com.zaxxer.hikari.metrics.micrometer.MicrometerMetricsTrackerFactory and it's incorrectly looking for a constructor that takes the exact type of the passed-in MeterRegistry implementation rather than the MeterRegistry interface.

You may be able to work around the problem by configuring a MetricsTrackerFactory directly instead of the metric registry:

hikariConfig.setMetricsTrackerFactory(new MicrometerMetricsTrackerFactory(meterRegistry));