Append context id to objectName of Endpoint MBeans if name already exists in MBeanServer

This commit is contained in:
Christian Dupuis 2014-01-29 21:06:14 +01:00
parent 9758ca5535
commit 5cf2387e58
2 changed files with 69 additions and 4 deletions

View File

@ -28,11 +28,14 @@ import javax.management.ObjectName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.actuate.endpoint.ShutdownEndpoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.SmartLifecycle;
import org.springframework.jmx.export.MBeanExportException;
@ -52,7 +55,7 @@ import org.springframework.util.ObjectUtils;
* @author Christian Dupuis
*/
public class EndpointMBeanExporter extends MBeanExporter implements SmartLifecycle,
BeanFactoryAware {
BeanFactoryAware, ApplicationContextAware {
public static final String DEFAULT_DOMAIN = "org.springframework.boot";
@ -76,6 +79,8 @@ public class EndpointMBeanExporter extends MBeanExporter implements SmartLifecyc
private final ReentrantLock lifecycleLock = new ReentrantLock();
private ApplicationContext applicationContext;
private ListableBeanFactory beanFactory;
private String domain = DEFAULT_DOMAIN;
@ -91,6 +96,12 @@ public class EndpointMBeanExporter extends MBeanExporter implements SmartLifecyc
setAssembler(this.assembler);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
@ -159,6 +170,10 @@ public class EndpointMBeanExporter extends MBeanExporter implements SmartLifecyc
StringBuilder builder = new StringBuilder();
builder.append(this.domain);
builder.append(":type=Endpoint");
if (parentContextContainsSameBean(this.applicationContext, beanKey)) {
builder.append(",context="
+ ObjectUtils.getIdentityHexString(this.applicationContext));
}
builder.append(",name=" + beanKey);
if (this.ensureUniqueRuntimeObjectNames) {
builder.append(",identity="
@ -172,6 +187,21 @@ public class EndpointMBeanExporter extends MBeanExporter implements SmartLifecyc
return this.defaultNamingStrategy.getObjectName(bean, beanKey);
}
private boolean parentContextContainsSameBean(ApplicationContext applicationContext,
String beanKey) {
if (applicationContext.getParent() != null) {
try {
this.applicationContext.getParent().getBean(beanKey, Endpoint.class);
return true;
}
catch (BeansException ex) {
return parentContextContainsSameBean(applicationContext.getParent(),
beanKey);
}
}
return false;
}
private String getStaticNames() {
if (this.objectNameStaticProperties.isEmpty()) {
return "";
@ -243,4 +273,5 @@ public class EndpointMBeanExporter extends MBeanExporter implements SmartLifecyc
this.lifecycleLock.unlock();
}
}
}

View File

@ -97,11 +97,45 @@ public class EndpointMBeanExportAutoConfigurationTests {
+ ",key1=value1,key2=value2")));
}
@Test
public void testEndpointMBeanExporterInParentChild() throws IntrospectionException,
InstanceNotFoundException, MalformedObjectNameException, ReflectionException {
this.context = new AnnotationConfigApplicationContext();
this.context.register(EndpointAutoConfiguration.class,
EndpointMBeanExportAutoConfiguration.class);
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();
parent.register(EndpointAutoConfiguration.class,
EndpointMBeanExportAutoConfiguration.class);
this.context.setParent(parent);
parent.refresh();
this.context.refresh();
parent.close();
System.out.println("parent " + ObjectUtils.getIdentityHexString(parent));
System.out.println("child " + ObjectUtils.getIdentityHexString(this.context));
}
private ObjectName getObjectName(String domain, String beanKey,
ApplicationContext applicationContext) throws MalformedObjectNameException {
return ObjectNameManager.getInstance(String.format(
"%s:type=Endpoint,name=%s,identity=%s", domain, beanKey,
ObjectUtils.getIdentityHexString(applicationContext.getBean(beanKey))));
if (applicationContext.getParent() != null) {
return ObjectNameManager
.getInstance(String.format(
"%s:type=Endpoint,name=%s,context=%s,identity=%s", domain,
beanKey,
ObjectUtils.getIdentityHexString(applicationContext),
ObjectUtils.getIdentityHexString(applicationContext
.getBean(beanKey))));
}
else {
return ObjectNameManager
.getInstance(String.format("%s:type=Endpoint,name=%s,identity=%s",
domain, beanKey, ObjectUtils
.getIdentityHexString(applicationContext
.getBean(beanKey))));
}
}
@Configuration