Make Hikari's pool accessible via reflection in a native image
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Has been cancelled Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Has been cancelled Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:windows-latest name:Windows]) (push) Has been cancelled Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Has been cancelled Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:windows-latest name:Windows]) (push) Has been cancelled Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:24], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Has been cancelled Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:24], map[id:windows-latest name:Windows]) (push) Has been cancelled Details
Run CodeQL Analysis / run-analysis (push) Has been cancelled Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:false version:17]) (push) Has been cancelled Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:true version:21]) (push) Has been cancelled Details
Build and Deploy Snapshot / Trigger Docs Build (push) Has been cancelled Details
Build and Deploy Snapshot / Verify (push) Has been cancelled Details

When it's inaccessible, the jdbc.connections.active and
jdbc.connections.idle metrics are lost.

Closes gh-46214
This commit is contained in:
Andy Wilkinson 2025-06-27 15:33:00 +01:00
parent c0d66d1984
commit 5479f5c3d3
2 changed files with 70 additions and 0 deletions

View File

@ -24,6 +24,8 @@ import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbcp2.BasicDataSourceMXBean; import org.apache.commons.dbcp2.BasicDataSourceMXBean;
import org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean; import org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.jdbc.DataSourceUnwrapper; import org.springframework.boot.jdbc.DataSourceUnwrapper;
import org.springframework.boot.jdbc.metadata.CommonsDbcp2DataSourcePoolMetadata; import org.springframework.boot.jdbc.metadata.CommonsDbcp2DataSourcePoolMetadata;
@ -33,6 +35,7 @@ import org.springframework.boot.jdbc.metadata.OracleUcpDataSourcePoolMetadata;
import org.springframework.boot.jdbc.metadata.TomcatDataSourcePoolMetadata; import org.springframework.boot.jdbc.metadata.TomcatDataSourcePoolMetadata;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportRuntimeHints;
/** /**
* Register the {@link DataSourcePoolMetadataProvider} instances for the supported data * Register the {@link DataSourcePoolMetadataProvider} instances for the supported data
@ -65,6 +68,7 @@ public class DataSourcePoolMetadataProvidersConfiguration {
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnClass(HikariDataSource.class) @ConditionalOnClass(HikariDataSource.class)
@ImportRuntimeHints(HikariDataSourcePoolMetadataRuntimeHints.class)
static class HikariPoolDataSourceMetadataProviderConfiguration { static class HikariPoolDataSourceMetadataProviderConfiguration {
@Bean @Bean
@ -116,4 +120,13 @@ public class DataSourcePoolMetadataProvidersConfiguration {
} }
static class HikariDataSourcePoolMetadataRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
hints.reflection().registerType(HikariDataSource.class, (builder) -> builder.withField("pool"));
}
}
} }

View File

@ -0,0 +1,57 @@
/*
* Copyright 2012-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.jdbc.metadata;
import java.util.Optional;
import com.zaxxer.hikari.HikariDataSource;
import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvidersConfiguration.HikariDataSourcePoolMetadataRuntimeHints;
import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvidersConfiguration.HikariPoolDataSourceMetadataProviderConfiguration;
import org.springframework.context.annotation.ImportRuntimeHints;
import org.springframework.core.annotation.MergedAnnotations;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link HikariDataSourcePoolMetadataRuntimeHints}.
*
* @author Andy Wilkinson
*/
class HikariDataSourcePoolMetadataRuntimeHintsTests {
@Test
@SuppressWarnings("rawtypes")
void importsRegistrar() {
Optional<Class[]> imported = MergedAnnotations.from(HikariPoolDataSourceMetadataProviderConfiguration.class)
.get(ImportRuntimeHints.class)
.getValue("value", Class[].class);
assertThat(imported).hasValue(new Class[] { HikariDataSourcePoolMetadataRuntimeHints.class });
}
@Test
void registersHints() {
RuntimeHints runtimeHints = new RuntimeHints();
new HikariDataSourcePoolMetadataRuntimeHints().registerHints(runtimeHints, getClass().getClassLoader());
assertThat(HikariDataSource.class).hasDeclaredFields("pool");
assertThat(RuntimeHintsPredicates.reflection().onField(HikariDataSource.class, "pool")).accepts(runtimeHints);
}
}