Rework EndpointMBeanExporter to prevent name clashes and to provide more flexibility in naming of endpoint MBeans
This commit is contained in:
parent
b81930fcce
commit
65d6757a10
|
@ -16,15 +16,19 @@
|
|||
|
||||
package org.springframework.boot.actuate.autoconfigure;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.jmx.EndpointMBeanExporter;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.jmx.export.MBeanExporter;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} to enable JMX export for
|
||||
|
@ -33,13 +37,41 @@ import org.springframework.jmx.export.MBeanExporter;
|
|||
* @author Christian Dupuis
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnBean({ MBeanExporter.class })
|
||||
@AutoConfigureAfter({ EndpointAutoConfiguration.class })
|
||||
@ConditionalOnExpression("${endpoints.jmx.enabled:true}")
|
||||
class EndpointMBeanExportAutoConfiguration {
|
||||
|
||||
private RelaxedPropertyResolver environment;
|
||||
|
||||
@Autowired
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = new RelaxedPropertyResolver(environment);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EndpointMBeanExporter endpointMBeanExporter() {
|
||||
return new EndpointMBeanExporter();
|
||||
EndpointMBeanExporter mbeanExporter = new EndpointMBeanExporter();
|
||||
|
||||
String domain = this.environment.getProperty("endpoints.jmx.domain");
|
||||
if (StringUtils.hasText(domain)) {
|
||||
mbeanExporter.setDomain(domain);
|
||||
}
|
||||
|
||||
Boolean ensureUnique = this.environment.getProperty("endpoints.jmx.unique_names",
|
||||
Boolean.class, Boolean.FALSE);
|
||||
mbeanExporter.setEnsureUniqueRuntimeObjectNames(ensureUnique);
|
||||
|
||||
mbeanExporter.setObjectNameStaticProperties(getObjectNameStaticProperties());
|
||||
|
||||
return mbeanExporter;
|
||||
}
|
||||
|
||||
private Properties getObjectNameStaticProperties() {
|
||||
String staticNames = this.environment.getProperty("endpoints.jmx.static_names");
|
||||
if (StringUtils.hasText(staticNames)) {
|
||||
return StringUtils.splitArrayElementsIntoProperties(
|
||||
StringUtils.commaDelimitedListToStringArray(staticNames), "=");
|
||||
}
|
||||
return new Properties();
|
||||
}
|
||||
}
|
|
@ -19,15 +19,9 @@ package org.springframework.boot.actuate.endpoint.jmx;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource;
|
||||
import org.springframework.jmx.export.annotation.ManagedAttribute;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
import org.springframework.jmx.export.naming.MetadataNamingStrategy;
|
||||
import org.springframework.jmx.export.naming.SelfNaming;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
|
@ -39,24 +33,16 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||
* @author Christian Dupuis
|
||||
*/
|
||||
@ManagedResource
|
||||
public class EndpointMBean implements SelfNaming {
|
||||
|
||||
private AnnotationJmxAttributeSource annotationSource = new AnnotationJmxAttributeSource();
|
||||
|
||||
private MetadataNamingStrategy metadataNamingStrategy = new MetadataNamingStrategy(
|
||||
this.annotationSource);
|
||||
public class EndpointMBean {
|
||||
|
||||
private Endpoint<?> endpoint;
|
||||
|
||||
private String beanName;
|
||||
|
||||
private ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
public EndpointMBean(String beanName, Endpoint<?> endpoint) {
|
||||
Assert.notNull(beanName, "BeanName must not be null");
|
||||
Assert.notNull(endpoint, "Endpoint must not be null");
|
||||
this.endpoint = endpoint;
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Returns the class of the underlying endpoint")
|
||||
|
@ -69,11 +55,6 @@ public class EndpointMBean implements SelfNaming {
|
|||
return this.endpoint.isSensitive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectName getObjectName() throws MalformedObjectNameException {
|
||||
return this.metadataNamingStrategy.getObjectName(this, this.beanName);
|
||||
}
|
||||
|
||||
public Endpoint<?> getEndpoint() {
|
||||
return this.endpoint;
|
||||
}
|
||||
|
|
|
@ -18,24 +18,31 @@ package org.springframework.boot.actuate.endpoint.jmx;
|
|||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
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.NoSuchBeanDefinitionException;
|
||||
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;
|
||||
import org.springframework.jmx.export.MBeanExporter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource;
|
||||
import org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler;
|
||||
import org.springframework.jmx.export.naming.MetadataNamingStrategy;
|
||||
import org.springframework.jmx.export.naming.SelfNaming;
|
||||
import org.springframework.jmx.support.ObjectNameManager;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* {@link ApplicationListener} that registers all known {@link Endpoint}s with an
|
||||
|
@ -44,10 +51,21 @@ import org.springframework.util.Assert;
|
|||
*
|
||||
* @author Christian Dupuis
|
||||
*/
|
||||
public class EndpointMBeanExporter implements SmartLifecycle, ApplicationContextAware {
|
||||
public class EndpointMBeanExporter extends MBeanExporter implements SmartLifecycle,
|
||||
BeanFactoryAware {
|
||||
|
||||
public static final String DEFAULT_DOMAIN = "org.springframework.boot";
|
||||
|
||||
private static Log logger = LogFactory.getLog(EndpointMBeanExporter.class);
|
||||
|
||||
private final AnnotationJmxAttributeSource attributeSource = new AnnotationJmxAttributeSource();
|
||||
|
||||
private final MetadataMBeanInfoAssembler assembler = new MetadataMBeanInfoAssembler(
|
||||
this.attributeSource);
|
||||
|
||||
private final MetadataNamingStrategy defaultNamingStrategy = new MetadataNamingStrategy(
|
||||
this.attributeSource);
|
||||
|
||||
private Set<Endpoint<?>> registeredEndpoints = new HashSet<Endpoint<?>>();
|
||||
|
||||
private volatile boolean autoStartup = true;
|
||||
|
@ -58,45 +76,65 @@ public class EndpointMBeanExporter implements SmartLifecycle, ApplicationContext
|
|||
|
||||
private final ReentrantLock lifecycleLock = new ReentrantLock();
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
private ListableBeanFactory beanFactory;
|
||||
|
||||
private String domain = DEFAULT_DOMAIN;
|
||||
|
||||
private boolean ensureUniqueRuntimeObjectNames = false;
|
||||
|
||||
private Properties objectNameStaticProperties = new Properties();
|
||||
|
||||
public EndpointMBeanExporter() {
|
||||
super();
|
||||
setAutodetect(false);
|
||||
setNamingStrategy(this.defaultNamingStrategy);
|
||||
setAssembler(this.assembler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
super.setBeanFactory(beanFactory);
|
||||
if (beanFactory instanceof ListableBeanFactory) {
|
||||
this.beanFactory = (ListableBeanFactory) beanFactory;
|
||||
}
|
||||
else {
|
||||
logger.info("EndpointMBeanExporter not running in a ListableBeanFactory: "
|
||||
+ "autodetection of Endpoints not available.");
|
||||
}
|
||||
}
|
||||
|
||||
public void setDomain(String domain) {
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnsureUniqueRuntimeObjectNames(boolean ensureUniqueRuntimeObjectNames) {
|
||||
super.setEnsureUniqueRuntimeObjectNames(ensureUniqueRuntimeObjectNames);
|
||||
this.ensureUniqueRuntimeObjectNames = ensureUniqueRuntimeObjectNames;
|
||||
}
|
||||
|
||||
public void setObjectNameStaticProperties(Properties objectNameStaticProperties) {
|
||||
this.objectNameStaticProperties = objectNameStaticProperties;
|
||||
}
|
||||
|
||||
protected void doStart() {
|
||||
try {
|
||||
MBeanExporter mbeanExporter = this.applicationContext
|
||||
.getBean(MBeanExporter.class);
|
||||
locateAndRegisterEndpoints(mbeanExporter);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException nsbde) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not obtain MBeanExporter. No Endpoint JMX export will be attemted.");
|
||||
}
|
||||
}
|
||||
locateAndRegisterEndpoints();
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
protected void locateAndRegisterEndpoints(MBeanExporter mbeanExporter) {
|
||||
Assert.notNull(mbeanExporter, "MBeanExporter must not be null");
|
||||
Map<String, Endpoint> endpoints = this.applicationContext
|
||||
.getBeansOfType(Endpoint.class);
|
||||
protected void locateAndRegisterEndpoints() {
|
||||
Map<String, Endpoint> endpoints = this.beanFactory.getBeansOfType(Endpoint.class);
|
||||
for (Map.Entry<String, Endpoint> endpointEntry : endpoints.entrySet()) {
|
||||
if (!this.registeredEndpoints.contains(endpointEntry.getValue())) {
|
||||
registerEndpoint(endpointEntry.getKey(), endpointEntry.getValue(),
|
||||
mbeanExporter);
|
||||
registerEndpoint(endpointEntry.getKey(), endpointEntry.getValue());
|
||||
this.registeredEndpoints.add(endpointEntry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerEndpoint(String beanName, Endpoint<?> endpoint,
|
||||
MBeanExporter mbeanExporter) {
|
||||
protected void registerEndpoint(String beanName, Endpoint<?> endpoint) {
|
||||
try {
|
||||
mbeanExporter.registerManagedResource(getEndpointMBean(beanName, endpoint));
|
||||
registerBeanNameOrInstance(getEndpointMBean(beanName, endpoint), beanName);
|
||||
}
|
||||
catch (MBeanExportException ex) {
|
||||
logger.error("Could not register MBean for endpoint [" + beanName + "]", ex);
|
||||
|
@ -110,6 +148,42 @@ public class EndpointMBeanExporter implements SmartLifecycle, ApplicationContext
|
|||
return new DataEndpointMBean(beanName, endpoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectName getObjectName(Object bean, String beanKey)
|
||||
throws MalformedObjectNameException {
|
||||
if (bean instanceof SelfNaming) {
|
||||
return ((SelfNaming) bean).getObjectName();
|
||||
}
|
||||
|
||||
if (bean instanceof EndpointMBean) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(this.domain);
|
||||
builder.append(":type=Endpoint");
|
||||
builder.append(",name=" + beanKey);
|
||||
if (this.ensureUniqueRuntimeObjectNames) {
|
||||
builder.append(",identity="
|
||||
+ ObjectUtils.getIdentityHexString(((EndpointMBean) bean)
|
||||
.getEndpoint()));
|
||||
}
|
||||
builder.append(getStaticNames());
|
||||
return ObjectNameManager.getInstance(builder.toString());
|
||||
}
|
||||
|
||||
return this.defaultNamingStrategy.getObjectName(bean, beanKey);
|
||||
}
|
||||
|
||||
private String getStaticNames() {
|
||||
if (this.objectNameStaticProperties.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
for (Object key : this.objectNameStaticProperties.keySet()) {
|
||||
builder.append("," + key + "=" + this.objectNameStaticProperties.get(key));
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
// SmartLifeCycle implementation
|
||||
|
||||
public final int getPhase() {
|
||||
|
|
|
@ -16,13 +16,24 @@
|
|||
|
||||
package org.springframework.boot.actuate.autoconfigure;
|
||||
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.IntrospectionException;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.ReflectionException;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.actuate.endpoint.jmx.EndpointMBeanExporter;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.EnableMBeanExport;
|
||||
import org.springframework.jmx.export.MBeanExporter;
|
||||
import org.springframework.jmx.support.ObjectNameManager;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
@ -53,7 +64,10 @@ public class EndpointMBeanExportAutoConfigurationTests {
|
|||
|
||||
@Test(expected = NoSuchBeanDefinitionException.class)
|
||||
public void testEndpointMBeanExporterIsNotInstalled() {
|
||||
MockEnvironment environment = new MockEnvironment();
|
||||
environment.setProperty("endpoints.jmx.enabled", "false");
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
this.context.setEnvironment(environment);
|
||||
this.context.register(EndpointAutoConfiguration.class,
|
||||
EndpointMBeanExportAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
|
@ -61,6 +75,35 @@ public class EndpointMBeanExportAutoConfigurationTests {
|
|||
fail();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndpointMBeanExporterWithProperties() throws IntrospectionException,
|
||||
InstanceNotFoundException, MalformedObjectNameException, ReflectionException {
|
||||
MockEnvironment environment = new MockEnvironment();
|
||||
environment.setProperty("endpoints.jmx.domain", "test-domain");
|
||||
environment.setProperty("endpoints.jmx.unique_names", "true");
|
||||
environment.setProperty("endpoints.jmx.static_names", "key1=value1, key2=value2");
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
this.context.setEnvironment(environment);
|
||||
this.context.register(EndpointAutoConfiguration.class,
|
||||
EndpointMBeanExportAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
this.context.getBean(EndpointMBeanExporter.class);
|
||||
|
||||
MBeanExporter mbeanExporter = this.context.getBean(EndpointMBeanExporter.class);
|
||||
|
||||
assertNotNull(mbeanExporter.getServer().getMBeanInfo(
|
||||
ObjectNameManager.getInstance(getObjectName("test-domain",
|
||||
"healthEndpoint", this.context).toString()
|
||||
+ ",key1=value1,key2=value2")));
|
||||
}
|
||||
|
||||
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))));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableMBeanExport
|
||||
public static class TestConfiguration {
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
package org.springframework.boot.actuate.endpoint.jmx;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.management.MBeanInfo;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
|
@ -27,10 +30,11 @@ import org.junit.Test;
|
|||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.jmx.export.MBeanExporter;
|
||||
import org.springframework.jmx.support.ObjectNameManager;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
@ -58,20 +62,15 @@ public class EndpointMBeanExporterTests {
|
|||
new RootBeanDefinition(EndpointMBeanExporter.class));
|
||||
this.context.registerBeanDefinition("endpoint1", new RootBeanDefinition(
|
||||
TestEndpoint.class));
|
||||
this.context.registerBeanDefinition(
|
||||
"mbeanExporter",
|
||||
new RootBeanDefinition(MBeanExporter.class, null,
|
||||
new MutablePropertyValues(Collections.singletonMap(
|
||||
"ensureUniqueRuntimeObjectNames", "false"))));
|
||||
this.context.refresh();
|
||||
|
||||
MBeanExporter mbeanExporter = this.context.getBean(MBeanExporter.class);
|
||||
MBeanExporter mbeanExporter = this.context.getBean(EndpointMBeanExporter.class);
|
||||
|
||||
MBeanInfo mbeanInfo = mbeanExporter.getServer().getMBeanInfo(
|
||||
getObjectName("endpoint1", this.context));
|
||||
assertNotNull(mbeanInfo);
|
||||
assertEquals(5, mbeanInfo.getOperations().length);
|
||||
assertEquals(5, mbeanInfo.getAttributes().length);
|
||||
assertEquals(3, mbeanInfo.getOperations().length);
|
||||
assertEquals(3, mbeanInfo.getAttributes().length);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -83,14 +82,9 @@ public class EndpointMBeanExporterTests {
|
|||
TestEndpoint.class));
|
||||
this.context.registerBeanDefinition("endpoint2", new RootBeanDefinition(
|
||||
TestEndpoint.class));
|
||||
this.context.registerBeanDefinition(
|
||||
"mbeanExporter",
|
||||
new RootBeanDefinition(MBeanExporter.class, null,
|
||||
new MutablePropertyValues(Collections.singletonMap(
|
||||
"ensureUniqueRuntimeObjectNames", "false"))));
|
||||
this.context.refresh();
|
||||
|
||||
MBeanExporter mbeanExporter = this.context.getBean(MBeanExporter.class);
|
||||
MBeanExporter mbeanExporter = this.context.getBean(EndpointMBeanExporter.class);
|
||||
|
||||
assertNotNull(mbeanExporter.getServer().getMBeanInfo(
|
||||
getObjectName("endpoint1", this.context)));
|
||||
|
@ -98,6 +92,69 @@ public class EndpointMBeanExporterTests {
|
|||
getObjectName("endpoint2", this.context)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegistrationWithDifferentDomain() throws Exception {
|
||||
this.context = new GenericApplicationContext();
|
||||
this.context.registerBeanDefinition(
|
||||
"endpointMbeanExporter",
|
||||
new RootBeanDefinition(EndpointMBeanExporter.class, null,
|
||||
new MutablePropertyValues(Collections.singletonMap("domain",
|
||||
"test-domain"))));
|
||||
this.context.registerBeanDefinition("endpoint1", new RootBeanDefinition(
|
||||
TestEndpoint.class));
|
||||
this.context.refresh();
|
||||
|
||||
MBeanExporter mbeanExporter = this.context.getBean(EndpointMBeanExporter.class);
|
||||
|
||||
assertNotNull(mbeanExporter.getServer().getMBeanInfo(
|
||||
getObjectName("test-domain", "endpoint1", false, this.context)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegistrationWithDifferentDomainAndIdentity() throws Exception {
|
||||
Map<String, Object> properties = new HashMap<String, Object>();
|
||||
properties.put("domain", "test-domain");
|
||||
properties.put("ensureUniqueRuntimeObjectNames", true);
|
||||
this.context = new GenericApplicationContext();
|
||||
this.context.registerBeanDefinition("endpointMbeanExporter",
|
||||
new RootBeanDefinition(EndpointMBeanExporter.class, null,
|
||||
new MutablePropertyValues(properties)));
|
||||
this.context.registerBeanDefinition("endpoint1", new RootBeanDefinition(
|
||||
TestEndpoint.class));
|
||||
this.context.refresh();
|
||||
|
||||
MBeanExporter mbeanExporter = this.context.getBean(EndpointMBeanExporter.class);
|
||||
|
||||
assertNotNull(mbeanExporter.getServer().getMBeanInfo(
|
||||
getObjectName("test-domain", "endpoint1", true, this.context)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegistrationWithDifferentDomainAndIdentityAndStaticNames()
|
||||
throws Exception {
|
||||
Map<String, Object> properties = new HashMap<String, Object>();
|
||||
properties.put("domain", "test-domain");
|
||||
properties.put("ensureUniqueRuntimeObjectNames", true);
|
||||
Properties staticNames = new Properties();
|
||||
staticNames.put("key1", "value1");
|
||||
staticNames.put("key2", "value2");
|
||||
properties.put("objectNameStaticProperties", staticNames);
|
||||
this.context = new GenericApplicationContext();
|
||||
this.context.registerBeanDefinition("endpointMbeanExporter",
|
||||
new RootBeanDefinition(EndpointMBeanExporter.class, null,
|
||||
new MutablePropertyValues(properties)));
|
||||
this.context.registerBeanDefinition("endpoint1", new RootBeanDefinition(
|
||||
TestEndpoint.class));
|
||||
this.context.refresh();
|
||||
|
||||
MBeanExporter mbeanExporter = this.context.getBean(EndpointMBeanExporter.class);
|
||||
|
||||
assertNotNull(mbeanExporter.getServer().getMBeanInfo(
|
||||
ObjectNameManager.getInstance(getObjectName("test-domain", "endpoint1",
|
||||
true, this.context).toString()
|
||||
+ ",key1=value1,key2=value2")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegistrationWithParentContext() throws Exception {
|
||||
this.context = new GenericApplicationContext();
|
||||
|
@ -105,19 +162,13 @@ public class EndpointMBeanExporterTests {
|
|||
new RootBeanDefinition(EndpointMBeanExporter.class));
|
||||
this.context.registerBeanDefinition("endpoint1", new RootBeanDefinition(
|
||||
TestEndpoint.class));
|
||||
this.context.registerBeanDefinition(
|
||||
"mbeanExporter",
|
||||
new RootBeanDefinition(MBeanExporter.class, null,
|
||||
new MutablePropertyValues(Collections.singletonMap(
|
||||
"ensureUniqueRuntimeObjectNames", "false"))));
|
||||
|
||||
GenericApplicationContext parent = new GenericApplicationContext();
|
||||
|
||||
this.context.setParent(parent);
|
||||
parent.refresh();
|
||||
this.context.refresh();
|
||||
|
||||
MBeanExporter mbeanExporter = this.context.getBean(MBeanExporter.class);
|
||||
MBeanExporter mbeanExporter = this.context.getBean(EndpointMBeanExporter.class);
|
||||
|
||||
assertNotNull(mbeanExporter.getServer().getMBeanInfo(
|
||||
getObjectName("endpoint1", this.context)));
|
||||
|
@ -125,10 +176,25 @@ public class EndpointMBeanExporterTests {
|
|||
parent.close();
|
||||
}
|
||||
|
||||
private ObjectName getObjectName(String beanKey, ApplicationContext applicationContext)
|
||||
private ObjectName getObjectName(String beanKey, GenericApplicationContext context)
|
||||
throws MalformedObjectNameException {
|
||||
return new DataEndpointMBean(beanKey,
|
||||
(Endpoint<?>) applicationContext.getBean(beanKey)).getObjectName();
|
||||
return getObjectName("org.springframework.boot", beanKey, false, context);
|
||||
}
|
||||
|
||||
private ObjectName getObjectName(String domain, String beanKey,
|
||||
boolean includeIdentity, ApplicationContext applicationContext)
|
||||
throws MalformedObjectNameException {
|
||||
if (includeIdentity) {
|
||||
return ObjectNameManager
|
||||
.getInstance(String.format("%s:type=Endpoint,name=%s,identity=%s",
|
||||
domain, beanKey, ObjectUtils
|
||||
.getIdentityHexString(applicationContext
|
||||
.getBean(beanKey))));
|
||||
}
|
||||
else {
|
||||
return ObjectNameManager.getInstance(String.format(
|
||||
"%s:type=Endpoint,name=%s", domain, beanKey));
|
||||
}
|
||||
}
|
||||
|
||||
public static class TestEndpoint extends AbstractEndpoint<String> {
|
||||
|
|
Loading…
Reference in New Issue