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
- Create a Spring Boot 3.5.4 application
- 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);
}
}
- 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));