Merge branch '1.1.x'

Conflicts:
	spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.java
	spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/ParentAwareNamingStrategy.java
	spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jmx/JmxAutoConfigurationTests.java
pull/1991/head
Phillip Webb 10 years ago
commit 6333d4c617

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 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,30 +18,28 @@ package org.springframework.boot.autoconfigure.jmx;
import javax.management.MBeanServer; import javax.management.MBeanServer;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
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;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.SearchStrategy; import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.EnvironmentAware;
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.EnableMBeanExport; import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.context.annotation.MBeanExportConfiguration; import org.springframework.context.annotation.MBeanExportConfiguration.SpecificPlatform;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.core.type.StandardAnnotationMetadata;
import org.springframework.jmx.export.MBeanExporter; import org.springframework.jmx.export.MBeanExporter;
import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource; import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource;
import org.springframework.jmx.export.annotation.AnnotationMBeanExporter; import org.springframework.jmx.export.annotation.AnnotationMBeanExporter;
import org.springframework.jmx.export.naming.ObjectNamingStrategy; import org.springframework.jmx.export.naming.ObjectNamingStrategy;
import org.springframework.jmx.support.MBeanServerFactoryBean; import org.springframework.jmx.support.MBeanServerFactoryBean;
import org.springframework.jmx.support.WebSphereMBeanServerFactoryBean; import org.springframework.jmx.support.RegistrationPolicy;
import org.springframework.jndi.JndiObjectFactoryBean; import org.springframework.util.StringUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} to enable/disable Spring's * {@link EnableAutoConfiguration Auto-configuration} to enable/disable Spring's
@ -54,35 +52,45 @@ import org.springframework.util.ClassUtils;
@Configuration @Configuration
@ConditionalOnClass({ MBeanExporter.class }) @ConditionalOnClass({ MBeanExporter.class })
@ConditionalOnProperty(prefix = "spring.jmx", name = "enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnProperty(prefix = "spring.jmx", name = "enabled", havingValue = "true", matchIfMissing = true)
public class JmxAutoConfiguration { public class JmxAutoConfiguration implements EnvironmentAware, BeanFactoryAware {
@Autowired private RelaxedPropertyResolver propertyResolver;
private Environment environment;
@Autowired
private BeanFactory beanFactory; private BeanFactory beanFactory;
@Autowired @Override
private ObjectNamingStrategy namingStrategy; public void setEnvironment(Environment environment) {
this.propertyResolver = new RelaxedPropertyResolver(environment, "spring.jmx.");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Bean @Bean
@ConditionalOnMissingBean(value = MBeanExporter.class, search = SearchStrategy.CURRENT) @ConditionalOnMissingBean(value = MBeanExporter.class, search = SearchStrategy.CURRENT)
public AnnotationMBeanExporter mbeanExporter() { public AnnotationMBeanExporter mbeanExporter(ObjectNamingStrategy namingStrategy) {
// Re-use the @EnableMBeanExport configuration AnnotationMBeanExporter exporter = new AnnotationMBeanExporter();
MBeanExportConfiguration config = new MBeanExportConfiguration(); exporter.setRegistrationPolicy(RegistrationPolicy.FAIL_ON_EXISTING);
config.setEnvironment(this.environment); exporter.setNamingStrategy(namingStrategy);
config.setBeanFactory(this.beanFactory); String server = this.propertyResolver.getProperty("server", "mbeanServer");
config.setImportMetadata(new StandardAnnotationMetadata(Empty.class)); if (StringUtils.hasLength(server)) {
// But add a custom naming strategy exporter.setServer(this.beanFactory.getBean(server, MBeanServer.class));
AnnotationMBeanExporter exporter = config.mbeanExporter(); }
exporter.setNamingStrategy(this.namingStrategy);
return exporter; return exporter;
} }
@Bean @Bean
@ConditionalOnMissingBean(ObjectNamingStrategy.class) @ConditionalOnMissingBean(value = ObjectNamingStrategy.class, search = SearchStrategy.CURRENT)
public ParentAwareNamingStrategy objectNamingStrategy() { public ParentAwareNamingStrategy objectNamingStrategy() {
return new ParentAwareNamingStrategy(new AnnotationJmxAttributeSource()); ParentAwareNamingStrategy namingStrategy = new ParentAwareNamingStrategy(
new AnnotationJmxAttributeSource());
String defaultDomain = this.propertyResolver.getProperty("default-domain");
if (StringUtils.hasLength(defaultDomain)) {
namingStrategy.setDefaultDomain(defaultDomain);
}
return namingStrategy;
} }
@Bean @Bean
@ -99,63 +107,4 @@ public class JmxAutoConfiguration {
} }
@EnableMBeanExport(defaultDomain = "${spring.jmx.default_domain:}", server = "${spring.jmx.server:mbeanServer}")
private static class Empty {
}
// 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();
}
};
private final String identifyingClass;
private SpecificPlatform(String identifyingClass) {
this.identifyingClass = identifyingClass;
}
public MBeanServer getMBeanServer() {
try {
FactoryBean<?> factory = getMBeanServerFactory();
if (factory instanceof InitializingBean) {
((InitializingBean) factory).afterPropertiesSet();
}
Object server = factory.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;
}
}
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2015 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.
@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.jmx; package org.springframework.boot.autoconfigure.jmx;
import java.util.Hashtable;
import javax.management.MalformedObjectNameException; import javax.management.MalformedObjectNameException;
import javax.management.ObjectName; import javax.management.ObjectName;
@ -24,11 +26,11 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
import org.springframework.jmx.export.metadata.JmxAttributeSource; import org.springframework.jmx.export.metadata.JmxAttributeSource;
import org.springframework.jmx.export.naming.MetadataNamingStrategy; import org.springframework.jmx.export.naming.MetadataNamingStrategy;
import org.springframework.jmx.export.naming.ObjectNamingStrategy; import org.springframework.jmx.support.ObjectNameManager;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
/** /**
* JMX {@link ObjectNamingStrategy} that takes into consideration the parent * Extension of {@link MetadataNamingStrategy} that supports a parent
* {@link ApplicationContext}. * {@link ApplicationContext}.
* *
* @author Dave Syer * @author Dave Syer
@ -39,7 +41,7 @@ public class ParentAwareNamingStrategy extends MetadataNamingStrategy implements
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
private boolean ensureUniqueRuntimeObjectNames = false; private boolean ensureUniqueRuntimeObjectNames;
public ParentAwareNamingStrategy(JmxAttributeSource attributeSource) { public ParentAwareNamingStrategy(JmxAttributeSource attributeSource) {
super(attributeSource); super(attributeSource);
@ -55,16 +57,17 @@ public class ParentAwareNamingStrategy extends MetadataNamingStrategy implements
@Override @Override
public ObjectName getObjectName(Object managedBean, String beanKey) public ObjectName getObjectName(Object managedBean, String beanKey)
throws MalformedObjectNameException { throws MalformedObjectNameException {
StringBuilder builder = new StringBuilder(beanKey); ObjectName name = super.getObjectName(managedBean, beanKey);
if (parentContextContainsSameBean(this.applicationContext, beanKey)) { Hashtable<String, String> properties = new Hashtable<String, String>();
builder.append(",context=" properties.putAll(name.getKeyPropertyList());
+ ObjectUtils.getIdentityHexString(this.applicationContext));
}
if (this.ensureUniqueRuntimeObjectNames) { if (this.ensureUniqueRuntimeObjectNames) {
builder.append(",identity=" + ObjectUtils.getIdentityHexString(managedBean)); properties.put("identity", ObjectUtils.getIdentityHexString(managedBean));
} }
ObjectName name = super.getObjectName(managedBean, beanKey); else if (parentContextContainsSameBean(this.applicationContext, beanKey)) {
return name; properties.put("context",
ObjectUtils.getIdentityHexString(this.applicationContext));
}
return ObjectNameManager.getInstance(name.getDomain(), properties);
} }
@Override @Override
@ -73,19 +76,18 @@ public class ParentAwareNamingStrategy extends MetadataNamingStrategy implements
this.applicationContext = applicationContext; this.applicationContext = applicationContext;
} }
private boolean parentContextContainsSameBean(ApplicationContext applicationContext, private boolean parentContextContainsSameBean(ApplicationContext context,
String beanKey) { String beanKey) {
if (applicationContext.getParent() != null) { if (context.getParent() == null) {
return false;
}
try { try {
this.applicationContext.getParent().getBean(beanKey); this.applicationContext.getParent().getBean(beanKey);
return true; return true;
} }
catch (BeansException ex) { catch (BeansException ex) {
return parentContextContainsSameBean(applicationContext.getParent(), return parentContextContainsSameBean(context.getParent(), beanKey);
beanKey);
} }
} }
return false;
}
} }

@ -78,7 +78,6 @@ public class JmxAutoConfigurationTests {
this.context.setEnvironment(env); this.context.setEnvironment(env);
this.context.register(JmxAutoConfiguration.class); this.context.register(JmxAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
assertNotNull(this.context.getBean(MBeanExporter.class)); assertNotNull(this.context.getBean(MBeanExporter.class));
} }
@ -90,7 +89,6 @@ public class JmxAutoConfigurationTests {
this.context.setEnvironment(env); this.context.setEnvironment(env);
this.context.register(TestConfiguration.class, JmxAutoConfiguration.class); this.context.register(TestConfiguration.class, JmxAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
this.context.getBean(MBeanExporter.class); this.context.getBean(MBeanExporter.class);
} }
@ -103,17 +101,16 @@ public class JmxAutoConfigurationTests {
this.context.setEnvironment(env); this.context.setEnvironment(env);
this.context.register(TestConfiguration.class, JmxAutoConfiguration.class); this.context.register(TestConfiguration.class, JmxAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
MBeanExporter mBeanExporter = this.context.getBean(MBeanExporter.class); MBeanExporter mBeanExporter = this.context.getBean(MBeanExporter.class);
assertNotNull(mBeanExporter); assertNotNull(mBeanExporter);
MetadataNamingStrategy naming = (MetadataNamingStrategy) ReflectionTestUtils MetadataNamingStrategy naming = (MetadataNamingStrategy) ReflectionTestUtils
.getField(mBeanExporter, "metadataNamingStrategy"); .getField(mBeanExporter, "namingStrategy");
assertEquals("my-test-domain", assertEquals("my-test-domain",
ReflectionTestUtils.getField(naming, "defaultDomain")); ReflectionTestUtils.getField(naming, "defaultDomain"));
} }
@Test @Test
public void testParentContext() { public void testBasicParentContext() {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
this.context.register(JmxAutoConfiguration.class); this.context.register(JmxAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
@ -124,6 +121,18 @@ public class JmxAutoConfigurationTests {
this.context.refresh(); this.context.refresh();
} }
@Test
public void testParentContext() throws Exception {
this.context = new AnnotationConfigApplicationContext();
this.context.register(JmxAutoConfiguration.class, TestConfiguration.class);
this.context.refresh();
AnnotationConfigApplicationContext parent = this.context;
this.context = new AnnotationConfigApplicationContext();
this.context.setParent(parent);
this.context.register(JmxAutoConfiguration.class, TestConfiguration.class);
this.context.refresh();
}
@Test @Test
public void customJmxDomain() { public void customJmxDomain() {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();

Loading…
Cancel
Save