diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfiguration.java index 1119d094aa..c21f7ef406 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfiguration.java @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.admin; +import java.util.List; + import javax.management.MalformedObjectNameException; import org.springframework.beans.factory.ObjectProvider; @@ -55,13 +57,13 @@ public class SpringApplicationAdminJmxAutoConfiguration { */ private static final String DEFAULT_JMX_NAME = "org.springframework.boot:type=Admin,name=SpringApplication"; - private final MBeanExporter mbeanExporter; + private final List mbeanExporters; private final Environment environment; public SpringApplicationAdminJmxAutoConfiguration( - ObjectProvider mbeanExporter, Environment environment) { - this.mbeanExporter = mbeanExporter.getIfAvailable(); + ObjectProvider> mbeanExporters, Environment environment) { + this.mbeanExporters = mbeanExporters.getIfAvailable(); this.environment = environment; } @@ -71,8 +73,10 @@ public class SpringApplicationAdminJmxAutoConfiguration { throws MalformedObjectNameException { String jmxName = this.environment.getProperty(JMX_NAME_PROPERTY, DEFAULT_JMX_NAME); - if (this.mbeanExporter != null) { // Make sure to not register that MBean twice - this.mbeanExporter.addExcludedBean(jmxName); + if (this.mbeanExporters != null) { // Make sure to not register that MBean twice + for (MBeanExporter mbeanExporter : this.mbeanExporters) { + mbeanExporter.addExcludedBean(jmxName); + } } return new SpringApplicationAdminMXBeanRegistrar(jmxName); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/JndiDataSourceAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/JndiDataSourceAutoConfiguration.java index b94d34c2be..dcfd3a9a28 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/JndiDataSourceAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/JndiDataSourceAutoConfiguration.java @@ -18,7 +18,6 @@ package org.springframework.boot.autoconfigure.jdbc; import javax.sql.DataSource; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -65,15 +64,12 @@ public class JndiDataSourceAutoConfiguration { } private void excludeMBeanIfNecessary(Object candidate, String beanName) { - try { - MBeanExporter mbeanExporter = this.context.getBean(MBeanExporter.class); + for (MBeanExporter mbeanExporter : this.context + .getBeansOfType(MBeanExporter.class).values()) { if (JmxUtils.isMBean(candidate.getClass())) { mbeanExporter.addExcludedBean(beanName); } } - catch (NoSuchBeanDefinitionException ex) { - // No exporter. Exclusion is unnecessary - } } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfigurationTests.java index 1f2e44cd86..de3a00a6fd 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfigurationTests.java @@ -33,13 +33,15 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.boot.WebApplicationType; import org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jmx.export.MBeanExporter; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; @@ -62,8 +64,9 @@ public class SpringApplicationAdminJmxAutoConfigurationTests { private final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class, - SpringApplicationAdminJmxAutoConfiguration.class)); + .withConfiguration( + AutoConfigurations.of(MultipleMBeanExportersConfiguration.class, + SpringApplicationAdminJmxAutoConfiguration.class)); @Test public void notRegisteredByDefault() @@ -108,7 +111,7 @@ public class SpringApplicationAdminJmxAutoConfigurationTests { try (ConfigurableApplicationContext context = new SpringApplicationBuilder() .sources(ServletWebServerFactoryAutoConfiguration.class, DispatcherServletAutoConfiguration.class, - JmxAutoConfiguration.class, + MultipleMBeanExportersConfiguration.class, SpringApplicationAdminJmxAutoConfiguration.class) .run("--" + ENABLE_ADMIN_PROP, "--server.port=0")) { assertThat(context).isInstanceOf(ServletWebServerApplicationContext.class); @@ -124,10 +127,11 @@ public class SpringApplicationAdminJmxAutoConfigurationTests { @Test public void onlyRegisteredOnceWhenThereIsAChildContext() throws Exception { SpringApplicationBuilder parentBuilder = new SpringApplicationBuilder() - .web(WebApplicationType.NONE).sources(JmxAutoConfiguration.class, + .web(WebApplicationType.NONE) + .sources(MultipleMBeanExportersConfiguration.class, SpringApplicationAdminJmxAutoConfiguration.class); SpringApplicationBuilder childBuilder = parentBuilder - .child(JmxAutoConfiguration.class, + .child(MultipleMBeanExportersConfiguration.class, SpringApplicationAdminJmxAutoConfiguration.class) .web(WebApplicationType.NONE); try (ConfigurableApplicationContext parent = parentBuilder @@ -160,4 +164,19 @@ public class SpringApplicationAdminJmxAutoConfigurationTests { new Object[] { key }, new String[] { String.class.getName() }); } + @Configuration + static class MultipleMBeanExportersConfiguration { + + @Bean + public MBeanExporter firstMBeanExporter() { + return new MBeanExporter(); + } + + @Bean + public MBeanExporter secondMBeanExporter() { + return new MBeanExporter(); + } + + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/JndiDataSourceAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/JndiDataSourceAutoConfigurationTests.java index 100243e3c6..d2df13de6f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/JndiDataSourceAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/JndiDataSourceAutoConfigurationTests.java @@ -115,6 +115,29 @@ public class JndiDataSourceAutoConfigurationTests { assertThat(excludedBeans).containsExactly("dataSource"); } + @SuppressWarnings("unchecked") + @Test + public void mbeanDataSourceIsExcludedFromExportByAllExporters() + throws IllegalStateException, NamingException { + DataSource dataSource = new BasicDataSource(); + configureJndi("foo", dataSource); + + this.context = new AnnotationConfigApplicationContext(); + TestPropertyValues.of("spring.datasource.jndi-name:foo").applyTo(this.context); + this.context.register(JndiDataSourceAutoConfiguration.class, + MBeanExporterConfiguration.class, + AnotherMBeanExporterConfiguration.class); + this.context.refresh(); + + assertThat(this.context.getBean(DataSource.class)).isEqualTo(dataSource); + for (MBeanExporter exporter : this.context.getBeansOfType(MBeanExporter.class) + .values()) { + Set excludedBeans = (Set) new DirectFieldAccessor(exporter) + .getPropertyValue("excludedBeans"); + assertThat(excludedBeans).containsExactly("dataSource"); + } + } + @SuppressWarnings("unchecked") @Test public void standardDataSourceIsNotExcludedFromExport() @@ -149,4 +172,13 @@ public class JndiDataSourceAutoConfigurationTests { } + private static class AnotherMBeanExporterConfiguration { + + @Bean + MBeanExporter anotherMbeanExporter() { + return new MBeanExporter(); + } + + } + }