Ensure Weblogic and Websphere JMX are covered

To ensure an MBeanServer is available when needed you have to
look in JNDI before resorting to the JDK platform factory.

I had to copy some private code from Spring, but it seems
worth it.

Fixes gh-1092
This commit is contained in:
Dave Syer 2014-06-13 11:27:41 +01:00
parent 2c691e5ae5
commit 1bf256dd58
4 changed files with 107 additions and 14 deletions

View File

@ -29,7 +29,6 @@ import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jmx.support.MBeanServerFactoryBean;
import org.springframework.util.StringUtils;
/**
@ -65,9 +64,7 @@ public class EndpointMBeanExportAutoConfiguration {
@Bean
@ConditionalOnMissingBean(MBeanServer.class)
public MBeanServerFactoryBean mbeanServer() {
MBeanServerFactoryBean factory = new MBeanServerFactoryBean();
factory.setLocateExistingServerIfPossible(true);
return factory;
public MBeanServer mbeanServer() {
return new JmxAutoConfiguration().mbeanServer();
}
}

View File

@ -29,7 +29,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.jmx.config.EnableIntegrationMBeanExport;
import org.springframework.integration.monitor.IntegrationMBeanExporter;
import org.springframework.jmx.support.MBeanServerFactoryBean;
/**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
@ -59,10 +58,8 @@ public class IntegrationAutoConfiguration {
@Bean
@ConditionalOnMissingBean(MBeanServer.class)
public MBeanServerFactoryBean mbeanServer() {
MBeanServerFactoryBean factory = new MBeanServerFactoryBean();
factory.setLocateExistingServerIfPossible(true);
return factory;
public MBeanServer mbeanServer() {
return new JmxAutoConfiguration().mbeanServer();
}
}

View File

@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.jmx;
import javax.management.MBeanServer;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@ -36,6 +37,10 @@ import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource;
import org.springframework.jmx.export.annotation.AnnotationMBeanExporter;
import org.springframework.jmx.export.naming.ObjectNamingStrategy;
import org.springframework.jmx.support.MBeanServerFactoryBean;
import org.springframework.jmx.support.WebSphereMBeanServerFactoryBean;
import org.springframework.jndi.JndiObjectFactoryBean;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* {@link EnableAutoConfiguration Auto-configuration} to enable/disable Spring's
@ -81,10 +86,8 @@ public class JmxAutoConfiguration {
@Bean
@ConditionalOnMissingBean(MBeanServer.class)
public MBeanServerFactoryBean mbeanServer() {
MBeanServerFactoryBean factory = new MBeanServerFactoryBean();
factory.setLocateExistingServerIfPossible(true);
return factory;
public MBeanServer mbeanServer() {
return SpecificPlatform.get().getMBeanServer();
}
@EnableMBeanExport(defaultDomain = "${spring.jmx.default_domain:}", server = "${spring.jmx.server:mbeanServer}")
@ -92,4 +95,65 @@ public class JmxAutoConfiguration {
}
// Copied and adapted from MBeanExportConfiguration
private static enum SpecificPlatform {
WEBLOGIC("weblogic.management.Helper") {
@Override
public FactoryBean<?> getMBeanServerFactory() {
JndiObjectFactoryBean factory = new JndiObjectFactoryBean();
factory.setJndiName("java:comp/env/jmx/runtime");
return factory;
}
},
WEBSPHERE("com.ibm.websphere.management.AdminServiceFactory") {
@Override
public FactoryBean<MBeanServer> getMBeanServerFactory() {
return new WebSphereMBeanServerFactoryBean();
}
},
GENERIC("org.springframework.jmx.support.MBeanServerFactoryBean") {
@Override
public FactoryBean<MBeanServer> getMBeanServerFactory() {
MBeanServerFactoryBean factory = new MBeanServerFactoryBean();
factory.setLocateExistingServerIfPossible(true);
factory.afterPropertiesSet();
return factory;
}
};
private final String identifyingClass;
private SpecificPlatform(String identifyingClass) {
this.identifyingClass = identifyingClass;
}
public MBeanServer getMBeanServer() {
Object server;
try {
server = getMBeanServerFactory().getObject();
Assert.isInstanceOf(MBeanServer.class, server);
return (MBeanServer) server;
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
protected abstract FactoryBean<?> getMBeanServerFactory();
public static SpecificPlatform get() {
ClassLoader classLoader = MBeanExportConfiguration.class.getClassLoader();
for (SpecificPlatform environment : values()) {
if (ClassUtils.isPresent(environment.identifyingClass, classLoader)) {
return environment;
}
}
return null;
}
}
}

View File

@ -22,10 +22,12 @@ import javax.validation.constraints.NotNull;
import org.junit.After;
import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.validation.BindException;
import org.springframework.validation.Errors;
@ -129,6 +131,16 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
equalTo(FooEnum.FOO));
}
@Test
public void testValueBindingForDefaults() throws Exception {
this.context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context, "default.value:foo");
this.context.register(PropertyWithValue.class);
this.context.refresh();
assertThat(this.context.getBean(PropertyWithValue.class).getValue(),
equalTo("foo"));
}
@Configuration
@EnableConfigurationProperties
public static class TestConfigurationWithValidatingSetter {
@ -263,4 +275,27 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
static enum FooEnum {
FOO, BAZ, BAR
}
@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "test")
public static class PropertyWithValue {
@Value("${default.value}")
private String value;
public void setValue(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
public static PropertySourcesPlaceholderConfigurer configurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
}