Fix injection point with proxied DataSource
Prior to this commit, the `ApplicationContext` couldn't start with a JDK-proxied `HikariDataSource` as the JMX auto-configuration was attempting to inject a (too narrowed) `HikariDataSource`. This commit rather injects a regular `DataSource` and attempt to unwrap it as a `HikariDataSource`. Closes gh-12271
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@@ -48,23 +48,33 @@ class DataSourceJmxConfiguration {
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(HikariDataSource.class)
|
||||
@ConditionalOnSingleCandidate(HikariDataSource.class)
|
||||
@ConditionalOnSingleCandidate(DataSource.class)
|
||||
static class Hikari {
|
||||
|
||||
private final HikariDataSource dataSource;
|
||||
private final DataSource dataSource;
|
||||
|
||||
private final ObjectProvider<MBeanExporter> mBeanExporter;
|
||||
|
||||
Hikari(HikariDataSource dataSource, ObjectProvider<MBeanExporter> mBeanExporter) {
|
||||
Hikari(DataSource dataSource, ObjectProvider<MBeanExporter> mBeanExporter) {
|
||||
this.dataSource = dataSource;
|
||||
this.mBeanExporter = mBeanExporter;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void validateMBeans() {
|
||||
MBeanExporter exporter = this.mBeanExporter.getIfUnique();
|
||||
if (exporter != null && this.dataSource.isRegisterMbeans()) {
|
||||
exporter.addExcludedBean("dataSource");
|
||||
HikariDataSource hikariDataSource = unwrapHikariDataSource();
|
||||
if (hikariDataSource != null && hikariDataSource.isRegisterMbeans()) {
|
||||
this.mBeanExporter.ifUnique((exporter) ->
|
||||
exporter.addExcludedBean("dataSource"));
|
||||
}
|
||||
}
|
||||
|
||||
private HikariDataSource unwrapHikariDataSource() {
|
||||
try {
|
||||
return this.dataSource.unwrap(HikariDataSource.class);
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,9 +31,13 @@ import org.apache.tomcat.jdbc.pool.DataSourceProxy;
|
||||
import org.apache.tomcat.jdbc.pool.jmx.ConnectionPool;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -101,6 +105,24 @@ public class DataSourceJmxConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hikariProxiedCanUseRegisterMBeans() {
|
||||
String poolName = UUID.randomUUID().toString();
|
||||
this.contextRunner.withUserConfiguration(DataSourceProxyConfiguration.class)
|
||||
.withPropertyValues(
|
||||
"spring.datasource.type=" + HikariDataSource.class.getName(),
|
||||
"spring.datasource.name=" + poolName,
|
||||
"spring.datasource.hikari.register-mbeans=true")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(javax.sql.DataSource.class);
|
||||
HikariDataSource hikariDataSource = context.getBean(
|
||||
javax.sql.DataSource.class).unwrap(HikariDataSource.class);
|
||||
assertThat(hikariDataSource.isRegisterMbeans()).isTrue();
|
||||
MBeanServer mBeanServer = context.getBean(MBeanServer.class);
|
||||
validateHikariMBeansRegistration(mBeanServer, poolName, true);
|
||||
});
|
||||
}
|
||||
|
||||
private void validateHikariMBeansRegistration(MBeanServer mBeanServer,
|
||||
String poolName, boolean expected) throws MalformedObjectNameException {
|
||||
assertThat(mBeanServer.isRegistered(
|
||||
@@ -130,4 +152,31 @@ public class DataSourceJmxConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class DataSourceProxyConfiguration {
|
||||
|
||||
@Bean
|
||||
public static DataSourceBeanPostProcessor dataSourceBeanPostProcessor() {
|
||||
return new DataSourceBeanPostProcessor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static class DataSourceBeanPostProcessor implements BeanPostProcessor {
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||
if (bean instanceof javax.sql.DataSource) {
|
||||
return wrap((javax.sql.DataSource) bean);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
private static javax.sql.DataSource wrap(javax.sql.DataSource dataSource) {
|
||||
return (javax.sql.DataSource) new ProxyFactory(dataSource).getProxy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user