Commit ffdff1cd authored by Andy Wilkinson's avatar Andy Wilkinson

Consider multiple MBeanExporters when excluding beans from export

Closes gh-10632
parent 8a653d2c
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.admin; package org.springframework.boot.autoconfigure.admin;
import java.util.List;
import javax.management.MalformedObjectNameException; import javax.management.MalformedObjectNameException;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
...@@ -55,13 +57,13 @@ public class SpringApplicationAdminJmxAutoConfiguration { ...@@ -55,13 +57,13 @@ public class SpringApplicationAdminJmxAutoConfiguration {
*/ */
private static final String DEFAULT_JMX_NAME = "org.springframework.boot:type=Admin,name=SpringApplication"; private static final String DEFAULT_JMX_NAME = "org.springframework.boot:type=Admin,name=SpringApplication";
private final MBeanExporter mbeanExporter; private final List<MBeanExporter> mbeanExporters;
private final Environment environment; private final Environment environment;
public SpringApplicationAdminJmxAutoConfiguration( public SpringApplicationAdminJmxAutoConfiguration(
ObjectProvider<MBeanExporter> mbeanExporter, Environment environment) { ObjectProvider<List<MBeanExporter>> mbeanExporters, Environment environment) {
this.mbeanExporter = mbeanExporter.getIfAvailable(); this.mbeanExporters = mbeanExporters.getIfAvailable();
this.environment = environment; this.environment = environment;
} }
...@@ -71,8 +73,10 @@ public class SpringApplicationAdminJmxAutoConfiguration { ...@@ -71,8 +73,10 @@ public class SpringApplicationAdminJmxAutoConfiguration {
throws MalformedObjectNameException { throws MalformedObjectNameException {
String jmxName = this.environment.getProperty(JMX_NAME_PROPERTY, String jmxName = this.environment.getProperty(JMX_NAME_PROPERTY,
DEFAULT_JMX_NAME); DEFAULT_JMX_NAME);
if (this.mbeanExporter != null) { // Make sure to not register that MBean twice if (this.mbeanExporters != null) { // Make sure to not register that MBean twice
this.mbeanExporter.addExcludedBean(jmxName); for (MBeanExporter mbeanExporter : this.mbeanExporters) {
mbeanExporter.addExcludedBean(jmxName);
}
} }
return new SpringApplicationAdminMXBeanRegistrar(jmxName); return new SpringApplicationAdminMXBeanRegistrar(jmxName);
} }
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -18,7 +18,6 @@ package org.springframework.boot.autoconfigure.jdbc; ...@@ -18,7 +18,6 @@ package org.springframework.boot.autoconfigure.jdbc;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
...@@ -65,15 +64,12 @@ public class JndiDataSourceAutoConfiguration { ...@@ -65,15 +64,12 @@ public class JndiDataSourceAutoConfiguration {
} }
private void excludeMBeanIfNecessary(Object candidate, String beanName) { private void excludeMBeanIfNecessary(Object candidate, String beanName) {
try { for (MBeanExporter mbeanExporter : this.context
MBeanExporter mbeanExporter = this.context.getBean(MBeanExporter.class); .getBeansOfType(MBeanExporter.class).values()) {
if (JmxUtils.isMBean(candidate.getClass())) { if (JmxUtils.isMBean(candidate.getClass())) {
mbeanExporter.addExcludedBean(beanName); mbeanExporter.addExcludedBean(beanName);
} }
} }
catch (NoSuchBeanDefinitionException ex) {
// No exporter. Exclusion is unnecessary
}
} }
} }
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -42,6 +42,9 @@ import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext; ...@@ -42,6 +42,9 @@ import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext;
import org.springframework.boot.test.util.EnvironmentTestUtils; import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
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.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
...@@ -186,10 +189,25 @@ public class SpringApplicationAdminJmxAutoConfigurationTests { ...@@ -186,10 +189,25 @@ public class SpringApplicationAdminJmxAutoConfigurationTests {
private void load(String... environment) { private void load(String... environment) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(applicationContext, environment); EnvironmentTestUtils.addEnvironment(applicationContext, environment);
applicationContext.register(JmxAutoConfiguration.class, applicationContext.register(MultipleMBeanExportersConfiguration.class,
SpringApplicationAdminJmxAutoConfiguration.class); SpringApplicationAdminJmxAutoConfiguration.class);
applicationContext.refresh(); applicationContext.refresh();
this.context = applicationContext; this.context = applicationContext;
} }
@Configuration
static class MultipleMBeanExportersConfiguration {
@Bean
public MBeanExporter firstMBeanExporter() {
return new MBeanExporter();
}
@Bean
public MBeanExporter secondMBeanExporter() {
return new MBeanExporter();
}
}
} }
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -117,6 +117,30 @@ public class JndiDataSourceAutoConfigurationTests { ...@@ -117,6 +117,30 @@ public class JndiDataSourceAutoConfigurationTests {
assertThat(excludedBeans).containsExactly("dataSource"); assertThat(excludedBeans).containsExactly("dataSource");
} }
@SuppressWarnings("unchecked")
@Test
public void mbeanDataSourceIsExcludedFromExportByAllExporters()
throws IllegalStateException, NamingException {
DataSource dataSource = new BasicDataSource();
configureJndi("foo", dataSource);
this.context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context,
"spring.datasource.jndi-name:foo");
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<String> excludedBeans = (Set<String>) new DirectFieldAccessor(exporter)
.getPropertyValue("excludedBeans");
assertThat(excludedBeans).containsExactly("dataSource");
}
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Test @Test
public void standardDataSourceIsNotExcludedFromExport() public void standardDataSourceIsNotExcludedFromExport()
...@@ -152,4 +176,13 @@ public class JndiDataSourceAutoConfigurationTests { ...@@ -152,4 +176,13 @@ public class JndiDataSourceAutoConfigurationTests {
} }
private static class AnotherMBeanExporterConfiguration {
@Bean
MBeanExporter anotherMbeanExporter() {
return new MBeanExporter();
}
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment