polishing
Reorganized class structure to match our code style (setter for properties at the top of the class, public method before private implementation). Removed DisposableBean as it the lifecycle is already taking care of removing MBeans on stop. Cleaned test suite Issue: SPR-8045
This commit is contained in:
parent
2ede219e66
commit
c7b106577f
|
|
@ -46,7 +46,6 @@ import org.springframework.beans.factory.BeanClassLoaderAware;
|
|||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.CannotLoadBeanClassException;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
|
|
@ -68,7 +67,6 @@ import org.springframework.util.ClassUtils;
|
|||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
|
||||
/**
|
||||
* JMX exporter that allows for exposing any <i>Spring-managed bean</i> to a
|
||||
* JMX {@link javax.management.MBeanServer}, without the need to define any
|
||||
|
|
@ -91,6 +89,8 @@ import org.springframework.util.ObjectUtils;
|
|||
* @author Juergen Hoeller
|
||||
* @author Rick Evans
|
||||
* @author Mark Fisher
|
||||
* @author Marten Deinum
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.2
|
||||
* @see #setBeans
|
||||
* @see #setAutodetect
|
||||
|
|
@ -100,7 +100,7 @@ import org.springframework.util.ObjectUtils;
|
|||
* @see MBeanExporterListener
|
||||
*/
|
||||
public class MBeanExporter extends MBeanRegistrationSupport
|
||||
implements MBeanExportOperations, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean, SmartLifecycle {
|
||||
implements MBeanExportOperations, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, SmartLifecycle {
|
||||
|
||||
/**
|
||||
* Autodetection mode indicating that no autodetection should be used.
|
||||
|
|
@ -405,16 +405,31 @@ public class MBeanExporter extends MBeanRegistrationSupport
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the phase in which the MBeans should be exported to the
|
||||
* JMX domain. The startup order proceeds from lowest to highest, and
|
||||
* the shutdown order is the reverse of that. By default this value
|
||||
* is {@code Integer.MAX_VALUE} meaning that MBeans are exported
|
||||
* as late as possible and removed from the domain as soon as possible.
|
||||
*/
|
||||
public void setPhase(int phase) {
|
||||
this.phase = phase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to automatically export MBeans after initialization.
|
||||
* <p>Default is "true"; set this to "false" to allow for manual startup
|
||||
* through the {@link #start()} method.
|
||||
*/
|
||||
public void setAutoStartup(boolean autoStartup) {
|
||||
this.autoStartup = autoStartup;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Lifecycle in bean factory: automatically register/unregister beans
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Start bean registration automatically when deployed in an
|
||||
* {@code ApplicationContext}.
|
||||
* @see #registerBeans()
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
// If no server was provided then try to find one. This is useful in an environment
|
||||
|
|
@ -424,15 +439,56 @@ public class MBeanExporter extends MBeanRegistrationSupport
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters all beans that this exported has exposed via JMX
|
||||
* when the enclosing {@code ApplicationContext} is destroyed.
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
logger.info("Unregistering JMX-exposed beans on shutdown");
|
||||
unregisterNotificationListeners();
|
||||
unregisterBeans();
|
||||
public void start() {
|
||||
logger.info("Registering beans for JMX exposure");
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
try {
|
||||
registerBeans();
|
||||
registerNotificationListeners();
|
||||
} catch (RuntimeException ex) {
|
||||
// Unregister beans already registered by this exporter.
|
||||
unregisterNotificationListeners();
|
||||
unregisterBeans();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
running = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
logger.info("Unregistering JMX-exposed beans on stop");
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
unregisterNotificationListeners();
|
||||
unregisterBeans();
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(Runnable callback) {
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
stop();
|
||||
callback.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
return this.running;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutoStartup() {
|
||||
return this.autoStartup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPhase() {
|
||||
return this.phase;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1053,79 +1109,6 @@ public class MBeanExporter extends MBeanRegistrationSupport
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to automatically start the container after initialization.
|
||||
* <p>Default is "true"; set this to "false" to allow for manual startup
|
||||
* through the {@link #start()} method.
|
||||
*/
|
||||
public void setAutoStartup(boolean autoStartup) {
|
||||
this.autoStartup = autoStartup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutoStartup() {
|
||||
return this.autoStartup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(Runnable callback) {
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
stop();
|
||||
callback.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
logger.info("Registering beans for JMX exposure");
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
try {
|
||||
registerBeans();
|
||||
registerNotificationListeners();
|
||||
} catch (RuntimeException ex) {
|
||||
// Unregister beans already registered by this exporter.
|
||||
unregisterNotificationListeners();
|
||||
unregisterBeans();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
running = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
logger.info("Unregistering JMX-exposed beans on stop");
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
unregisterNotificationListeners();
|
||||
unregisterBeans();
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
return this.running;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the phase in which this container should be started and
|
||||
* stopped. The startup order proceeds from lowest to highest, and
|
||||
* the shutdown order is the reverse of that. By default this value
|
||||
* is Integer.MAX_VALUE meaning that this container starts as late
|
||||
* as possible and stops as soon as possible.
|
||||
*/
|
||||
public void setPhase(int phase) {
|
||||
this.phase = phase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPhase() {
|
||||
return this.phase;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Inner classes for internal use
|
||||
//---------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import org.junit.Before;
|
|||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.jmx.export.MBeanExporter;
|
||||
import org.springframework.tests.TestGroup;
|
||||
import org.springframework.util.MBeanTestUtils;
|
||||
|
||||
|
|
@ -91,6 +92,17 @@ public abstract class AbstractMBeanServerTests {
|
|||
return this.server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the specified {@link MBeanExporter}.
|
||||
*
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
* @see org.springframework.context.Lifecycle#start()
|
||||
*/
|
||||
protected void start(MBeanExporter exporter) {
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
}
|
||||
|
||||
protected void assertIsRegistered(String message, ObjectName objectName) {
|
||||
assertTrue(message, getServer().isRegistered(objectName));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests {
|
|||
adapter.setServer(getServer());
|
||||
adapter.setBeans(beans);
|
||||
adapter.setAssembler(new ProxyTestAssembler());
|
||||
adapter.afterPropertiesSet();
|
||||
start(adapter);
|
||||
}
|
||||
|
||||
protected MBeanServerConnection getServerConnection() throws Exception {
|
||||
|
|
|
|||
|
|
@ -33,11 +33,16 @@ import javax.management.ObjectInstance;
|
|||
import javax.management.ObjectName;
|
||||
import javax.management.modelmbean.ModelMBeanInfo;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.jmx.AbstractMBeanServerTests;
|
||||
|
|
@ -63,10 +68,14 @@ import static org.junit.Assert.*;
|
|||
* @author Mark Fisher
|
||||
* @author Chris Beams
|
||||
* @author Sam Brannen
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private static final String OBJECT_NAME = "spring:test=jmxMBeanAdaptor";
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
|
|
@ -76,12 +85,9 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
// put a non-NotificationListener instance in as a value...
|
||||
listeners.put("*", this);
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
try {
|
||||
exporter.setNotificationListenerMappings(listeners);
|
||||
fail("Must have thrown a ClassCastException when registering a non-NotificationListener instance as a NotificationListener.");
|
||||
}
|
||||
catch (ClassCastException expected) {
|
||||
}
|
||||
|
||||
thrown.expect(ClassCastException.class);
|
||||
exporter.setNotificationListenerMappings(listeners);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
|
|
@ -91,12 +97,9 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
// put null in as a value...
|
||||
listeners.put("*", null);
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
try {
|
||||
exporter.setNotificationListenerMappings(listeners);
|
||||
fail("Must have thrown an IllegalArgumentException when registering a null instance as a NotificationListener.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
exporter.setNotificationListenerMappings(listeners);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
|
|
@ -116,9 +119,9 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
exporter.setServer(server);
|
||||
exporter.setNotificationListenerMappings(listeners);
|
||||
try {
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
fail("Must have thrown an MBeanExportException when registering a NotificationListener on a non-existent MBean.");
|
||||
start(exporter);
|
||||
fail("Must have thrown an MBeanExportException when registering a " +
|
||||
"NotificationListener on a non-existent MBean.");
|
||||
}
|
||||
catch (MBeanExportException expected) {
|
||||
assertTrue(expected.contains(InstanceNotFoundException.class));
|
||||
|
|
@ -130,23 +133,16 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setBeans(getBeanMap());
|
||||
exporter.setServer(server);
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
assertIsRegistered("The bean was not registered with the MBeanServer",
|
||||
ObjectNameManager.getInstance(OBJECT_NAME));
|
||||
try {
|
||||
start(exporter);
|
||||
assertIsRegistered("The bean was not registered with the MBeanServer",
|
||||
ObjectNameManager.getInstance(OBJECT_NAME));
|
||||
}
|
||||
finally {
|
||||
exporter.stop();
|
||||
}
|
||||
}
|
||||
|
||||
/** Fails if JVM platform MBean server has been started already
|
||||
@Test
|
||||
public void testWithLocatedMBeanServer() throws Exception {
|
||||
MBeanExporter adaptor = new MBeanExporter();
|
||||
adaptor.setBeans(getBeanMap());
|
||||
adaptor.afterPropertiesSet();
|
||||
assertIsRegistered("The bean was not registered with the MBeanServer", ObjectNameManager.getInstance(OBJECT_NAME));
|
||||
server.unregisterMBean(new ObjectName(OBJECT_NAME));
|
||||
}
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testUserCreatedMBeanRegWithDynamicMBean() throws Exception {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
|
|
@ -158,22 +154,24 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
exporter.setServer(server);
|
||||
exporter.setBeans(map);
|
||||
exporter.setAssembler(asm);
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
|
||||
Object name = server.getAttribute(ObjectNameManager.getInstance("spring:name=dynBean"), "Name");
|
||||
assertEquals("The name attribute is incorrect", "Rob Harrop", name);
|
||||
assertFalse("Assembler should not have been invoked", asm.invoked);
|
||||
try {
|
||||
start(exporter);
|
||||
Object name = server.getAttribute(ObjectNameManager.getInstance("spring:name=dynBean"), "Name");
|
||||
assertEquals("The name attribute is incorrect", "Rob Harrop", name);
|
||||
assertFalse("Assembler should not have been invoked", asm.invoked);
|
||||
}
|
||||
finally {
|
||||
exporter.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutodetectMBeans() throws Exception {
|
||||
GenericApplicationContext ctx = new GenericApplicationContext();
|
||||
new XmlBeanDefinitionReader(ctx).loadBeanDefinitions(new ClassPathResource("autodetectMBeans.xml", getClass()));
|
||||
ctx.refresh();
|
||||
ConfigurableApplicationContext ctx = load("autodetectMBeans.xml");
|
||||
try {
|
||||
ctx.getBean("exporter");
|
||||
MBeanServer server = (MBeanServer) ctx.getBean("server");
|
||||
MBeanServer server = ctx.getBean("server", MBeanServer.class);
|
||||
ObjectInstance instance = server.getObjectInstance(ObjectNameManager.getInstance("spring:mbean=true"));
|
||||
assertNotNull(instance);
|
||||
instance = server.getObjectInstance(ObjectNameManager.getInstance("spring:mbean2=true"));
|
||||
|
|
@ -181,39 +179,32 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
instance = server.getObjectInstance(ObjectNameManager.getInstance("spring:mbean3=true"));
|
||||
assertNotNull(instance);
|
||||
} finally {
|
||||
ctx.destroy();
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutodetectWithExclude() throws Exception {
|
||||
GenericApplicationContext ctx = new GenericApplicationContext();
|
||||
new XmlBeanDefinitionReader(ctx).loadBeanDefinitions(new ClassPathResource("autodetectMBeans.xml", getClass()));
|
||||
ctx.refresh();
|
||||
ConfigurableApplicationContext ctx = load("autodetectMBeans.xml");
|
||||
try {
|
||||
ctx.getBean("exporter");
|
||||
MBeanServer server = (MBeanServer) ctx.getBean("server");
|
||||
MBeanServer server = ctx.getBean("server", MBeanServer.class);
|
||||
ObjectInstance instance = server.getObjectInstance(ObjectNameManager.getInstance("spring:mbean=true"));
|
||||
assertNotNull(instance);
|
||||
|
||||
try {
|
||||
server.getObjectInstance(ObjectNameManager.getInstance("spring:mbean=false"));
|
||||
fail("MBean with name spring:mbean=false should have been excluded");
|
||||
} catch (InstanceNotFoundException expected) {
|
||||
}
|
||||
thrown.expect(InstanceNotFoundException.class);
|
||||
server.getObjectInstance(ObjectNameManager.getInstance("spring:mbean=false"));
|
||||
} finally {
|
||||
ctx.destroy();
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutodetectLazyMBeans() throws Exception {
|
||||
GenericApplicationContext ctx = new GenericApplicationContext();
|
||||
new XmlBeanDefinitionReader(ctx).loadBeanDefinitions(new ClassPathResource("autodetectLazyMBeans.xml", getClass()));
|
||||
ctx.refresh();
|
||||
ConfigurableApplicationContext ctx = load("autodetectLazyMBeans.xml");
|
||||
try {
|
||||
ctx.getBean("exporter");
|
||||
MBeanServer server = (MBeanServer) ctx.getBean("server");
|
||||
MBeanServer server = ctx.getBean("server", MBeanServer.class);
|
||||
|
||||
ObjectName oname = ObjectNameManager.getInstance("spring:mbean=true");
|
||||
assertNotNull(server.getObjectInstance(oname));
|
||||
|
|
@ -225,19 +216,41 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
name = (String) server.getAttribute(oname, "Name");
|
||||
assertEquals("Invalid name returned", "Juergen Hoeller", name);
|
||||
} finally {
|
||||
ctx.destroy();
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutodetectNoMBeans() throws Exception {
|
||||
GenericApplicationContext ctx = new GenericApplicationContext();
|
||||
new XmlBeanDefinitionReader(ctx).loadBeanDefinitions(new ClassPathResource("autodetectNoMBeans.xml", getClass()));
|
||||
ctx.refresh();
|
||||
ConfigurableApplicationContext ctx = load("autodetectNoMBeans.xml");
|
||||
try {
|
||||
ctx.getBean("exporter");
|
||||
} finally {
|
||||
ctx.destroy();
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutoStartupToFalse() throws Exception {
|
||||
ConfigurableApplicationContext ctx = load("autodetectNoAutoStartup.xml");
|
||||
try {
|
||||
MBeanExporter exporter = ctx.getBean("exporter", MBeanExporter.class);
|
||||
MBeanServer server = ctx.getBean("server", MBeanServer.class);
|
||||
|
||||
ObjectName on = ObjectNameManager.getInstance("spring:mbean=true");
|
||||
try {
|
||||
server.getObjectInstance(on);
|
||||
fail("MBeans should not have been exported with autoStartup set to false");
|
||||
}
|
||||
catch (InstanceNotFoundException e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
// Export manually
|
||||
exporter.start();
|
||||
assertNotNull(server.getObjectInstance(on)); // Should be exposed now.
|
||||
} finally {
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -250,14 +263,14 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
exporter.setBeans(getBeanMap());
|
||||
exporter.setServer(server);
|
||||
exporter.setListeners(new MBeanExporterListener[] { listener1, listener2 });
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
exporter.destroy();
|
||||
start(exporter);
|
||||
exporter.stop();
|
||||
|
||||
assertListener(listener1);
|
||||
assertListener(listener2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testExportJdkProxy() throws Exception {
|
||||
JmxTestBean bean = new JmxTestBean();
|
||||
|
|
@ -297,8 +310,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
exporter.setServer(server);
|
||||
exporter.setBeans(beans);
|
||||
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
start(exporter);
|
||||
|
||||
ObjectInstance instance = server.getObjectInstance(objectName);
|
||||
assertNotNull(instance);
|
||||
|
|
@ -327,8 +339,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
exporter.setBeans(beans);
|
||||
exporter.setRegistrationBehavior(MBeanExporter.REGISTRATION_IGNORE_EXISTING);
|
||||
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
start(exporter);
|
||||
|
||||
ObjectInstance instance = server.getObjectInstance(objectName);
|
||||
assertNotNull(instance);
|
||||
|
|
@ -359,8 +370,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
exporter.setBeans(beans);
|
||||
exporter.setRegistrationPolicy(RegistrationPolicy.REPLACE_EXISTING);
|
||||
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
start(exporter);
|
||||
|
||||
ObjectInstance instance = server.getObjectInstance(objectName);
|
||||
assertNotNull(instance);
|
||||
|
|
@ -385,13 +395,12 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
exporter.setServer(getServer());
|
||||
exporter.setBeans(beans);
|
||||
exporter.setExposeManagedResourceClassLoader(true);
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
start(exporter);
|
||||
|
||||
assertIsRegistered("Bean instance not registered", objectName);
|
||||
|
||||
Object result = server.invoke(objectName, "add", new Object[] { new Integer(2), new Integer(3) }, new String[] {
|
||||
int.class.getName(), int.class.getName() });
|
||||
Object result = server.invoke(objectName, "add", new Object[] {new Integer(2), new Integer(3)}, new String[] {
|
||||
int.class.getName(), int.class.getName()});
|
||||
|
||||
assertEquals("Incorrect result return from add", result, new Integer(5));
|
||||
assertEquals("Incorrect attribute value", name, server.getAttribute(objectName, "Name"));
|
||||
|
|
@ -416,8 +425,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
exporter.setBeanFactory(factory);
|
||||
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_NONE);
|
||||
// MBean has a bad ObjectName, so if said MBean is autodetected, an exception will be thrown...
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
start(exporter);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -434,8 +442,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
exporter.setAssembler(new NamedBeanAutodetectCapableMBeanInfoAssemblerStub(exportedBeanName));
|
||||
exporter.setBeanFactory(factory);
|
||||
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_MBEAN);
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
start(exporter);
|
||||
|
||||
assertIsRegistered("Bona fide MBean not autodetected in AUTODETECT_MBEAN mode",
|
||||
ObjectNameManager.getInstance(OBJECT_NAME));
|
||||
|
|
@ -458,8 +465,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
exporter.setAssembler(new NamedBeanAutodetectCapableMBeanInfoAssemblerStub(exportedBeanName));
|
||||
exporter.setBeanFactory(factory);
|
||||
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ALL);
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
start(exporter);
|
||||
assertIsRegistered("Bona fide MBean not autodetected in (AUTODETECT_ALL) mode",
|
||||
ObjectNameManager.getInstance(OBJECT_NAME));
|
||||
assertIsRegistered("Bean not autodetected in (AUTODETECT_ALL) mode",
|
||||
|
|
@ -481,8 +487,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
exporter.setAssembler(new NamedBeanAutodetectCapableMBeanInfoAssemblerStub(exportedBeanName));
|
||||
exporter.setBeanFactory(factory);
|
||||
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ASSEMBLER);
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
start(exporter);
|
||||
assertIsNotRegistered("Bona fide MBean was autodetected in AUTODETECT_ASSEMBLER mode - must not have been",
|
||||
ObjectNameManager.getInstance(OBJECT_NAME));
|
||||
assertIsRegistered("Bean not autodetected in AUTODETECT_ASSEMBLER mode",
|
||||
|
|
@ -506,104 +511,69 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
exporter.setAssembler(new NamedBeanAutodetectCapableMBeanInfoAssemblerStub(OBJECT_NAME));
|
||||
exporter.setBeanFactory(factory);
|
||||
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ASSEMBLER);
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
start(exporter);
|
||||
assertIsRegistered("Explicitly exported bona fide MBean obviously not exported.",
|
||||
ObjectNameManager.getInstance(OBJECT_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAutodetectModeToOutOfRangeNegativeValue() throws Exception {
|
||||
try {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setAutodetectMode(-1);
|
||||
fail("Must have failed when supplying an invalid negative out-of-range autodetect mode");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
public void testSetAutodetectModeToOutOfRangeNegativeValue() {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
exporter.setAutodetectMode(-1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAutodetectModeToOutOfRangePositiveValue() throws Exception {
|
||||
try {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setAutodetectMode(5);
|
||||
fail("Must have failed when supplying an invalid positive out-of-range autodetect mode");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
public void testSetAutodetectModeToOutOfRangePositiveValue() {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
exporter.setAutodetectMode(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAutodetectModeNameToNull() throws Exception {
|
||||
try {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setAutodetectModeName(null);
|
||||
fail("Must have failed when supplying a null autodetect mode name");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
public void testSetAutodetectModeNameToNull() {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
exporter.setAutodetectModeName(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAutodetectModeNameToAnEmptyString() throws Exception {
|
||||
try {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setAutodetectModeName("");
|
||||
fail("Must have failed when supplying an empty autodetect mode name");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
public void testSetAutodetectModeNameToAnEmptyString() {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
exporter.setAutodetectModeName("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAutodetectModeNameToAWhitespacedString() throws Exception {
|
||||
try {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setAutodetectModeName(" \t");
|
||||
fail("Must have failed when supplying a whitespace-only autodetect mode name");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
public void testSetAutodetectModeNameToAWhitespacedString() {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
exporter.setAutodetectModeName(" \t");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAutodetectModeNameToARubbishValue() throws Exception {
|
||||
try {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setAutodetectModeName("That Hansel is... *sssooo* hot right now!");
|
||||
fail("Must have failed when supplying a whitespace-only autodetect mode name");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
public void testSetAutodetectModeNameToARubbishValue() {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
exporter.setAutodetectModeName("That Hansel is... *sssooo* hot right now!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotRunningInBeanFactoryAndPassedBeanNameToExport() throws Exception {
|
||||
try {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
Map<String, Object> beans = new HashMap<String, Object>();
|
||||
beans.put(OBJECT_NAME, "beanName");
|
||||
exporter.setBeans(beans);
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
fail("Expecting exception because MBeanExporter is not running in a BeanFactory and was passed bean name to (lookup and then) export");
|
||||
}
|
||||
catch (MBeanExportException expected) {
|
||||
}
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
Map<String, Object> beans = new HashMap<String, Object>();
|
||||
beans.put(OBJECT_NAME, "beanName");
|
||||
exporter.setBeans(beans);
|
||||
thrown.expect(MBeanExportException.class);
|
||||
start(exporter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotRunningInBeanFactoryAndAutodetectionIsOn() throws Exception {
|
||||
try {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ALL);
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
fail("Expecting exception because MBeanExporter is not running in a BeanFactory and was configured to autodetect beans");
|
||||
}
|
||||
catch (MBeanExportException expected) {
|
||||
}
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ALL);
|
||||
thrown.expect(MBeanExportException.class);
|
||||
start(exporter);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -616,13 +586,12 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
exporter.setServer(this.server);
|
||||
MockMBeanExporterListener listener = new MockMBeanExporterListener();
|
||||
exporter.setListeners(new MBeanExporterListener[] { listener });
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
start(exporter);
|
||||
assertIsRegistered("The bean was not registered with the MBeanServer",
|
||||
ObjectNameManager.getInstance(OBJECT_NAME));
|
||||
|
||||
this.server.unregisterMBean(new ObjectName(OBJECT_NAME));
|
||||
exporter.destroy();
|
||||
exporter.stop();
|
||||
assertEquals("Listener should not have been invoked (MBean previously unregistered by external agent)", 0,
|
||||
listener.getUnregistered().size());
|
||||
}
|
||||
|
|
@ -649,7 +618,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
StubNotificationListener listener = new StubNotificationListener();
|
||||
exporter.setNotificationListenerMappings(Collections.singletonMap(beanName, listener));
|
||||
|
||||
exporter.afterPropertiesSet();
|
||||
start(exporter);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -671,7 +640,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
StubNotificationListener listener = new StubNotificationListener();
|
||||
exporter.setNotificationListenerMappings(Collections.singletonMap("*", listener));
|
||||
|
||||
exporter.afterPropertiesSet();
|
||||
start(exporter);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -699,8 +668,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
exporter.setBeanFactory(factory);
|
||||
|
||||
try {
|
||||
exporter.afterPropertiesSet();
|
||||
exporter.start();
|
||||
start(exporter);
|
||||
fail("Must have failed during creation of RuntimeExceptionThrowingConstructorBean");
|
||||
}
|
||||
catch (RuntimeException expected) {
|
||||
|
|
@ -712,6 +680,10 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
|||
ObjectNameManager.getInstance(objectName2));
|
||||
}
|
||||
|
||||
private ConfigurableApplicationContext load(String context) {
|
||||
return new ClassPathXmlApplicationContext(context, getClass());
|
||||
}
|
||||
|
||||
private Map<String, Object> getBeanMap() {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put(OBJECT_NAME, new JmxTestBean());
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
|||
exporter.setServer(server);
|
||||
exporter.setBeans(beans);
|
||||
exporter.setNotificationListenerMappings(notificationListeners);
|
||||
exporter.afterPropertiesSet();
|
||||
start(exporter);
|
||||
|
||||
// update the attribute
|
||||
String attributeName = "Name";
|
||||
|
|
@ -87,7 +87,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
|||
exporter.setServer(server);
|
||||
exporter.setBeans(beans);
|
||||
exporter.setNotificationListenerMappings(notificationListeners);
|
||||
exporter.afterPropertiesSet();
|
||||
start(exporter);
|
||||
|
||||
// update the attribute
|
||||
String attributeName = "Name";
|
||||
|
|
@ -115,7 +115,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
|||
exporter.setServer(server);
|
||||
exporter.setBeans(beans);
|
||||
exporter.setNotificationListeners(new NotificationListenerBean[] { listenerBean });
|
||||
exporter.afterPropertiesSet();
|
||||
start(exporter);
|
||||
|
||||
// update the attribute
|
||||
String attributeName = "Name";
|
||||
|
|
@ -143,7 +143,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
|||
exporter.setServer(server);
|
||||
exporter.setBeans(beans);
|
||||
exporter.setNotificationListeners(new NotificationListenerBean[] { listenerBean });
|
||||
exporter.afterPropertiesSet();
|
||||
start(exporter);
|
||||
|
||||
// update the attribute
|
||||
String attributeName = "Name";
|
||||
|
|
@ -181,7 +181,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
|||
exporter.setServer(server);
|
||||
exporter.setBeans(beans);
|
||||
exporter.setNotificationListeners(new NotificationListenerBean[] { listenerBean });
|
||||
exporter.afterPropertiesSet();
|
||||
start(exporter);
|
||||
|
||||
// update the attributes
|
||||
String nameAttribute = "Name";
|
||||
|
|
@ -227,7 +227,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
|||
exporter.setBeans(beans);
|
||||
exporter.setNotificationListenerMappings(listenerMappings);
|
||||
exporter.setBeanFactory(factory);
|
||||
exporter.afterPropertiesSet();
|
||||
start(exporter);
|
||||
assertIsRegistered("Should have registered MBean", objectName);
|
||||
|
||||
server.setAttribute(objectName, new Attribute("Age", new Integer(77)));
|
||||
|
|
@ -258,7 +258,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
|||
exporter.setBeans(beans);
|
||||
exporter.setNotificationListenerMappings(listenerMappings);
|
||||
exporter.setBeanFactory(factory);
|
||||
exporter.afterPropertiesSet();
|
||||
start(exporter);
|
||||
assertIsRegistered("Should have registered MBean", objectName);
|
||||
|
||||
server.setAttribute(objectName, new Attribute("Age", new Integer(77)));
|
||||
|
|
@ -290,7 +290,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
|||
exporter.setBeans(beans);
|
||||
exporter.setNotificationListenerMappings(listenerMappings);
|
||||
exporter.setBeanFactory(factory);
|
||||
exporter.afterPropertiesSet();
|
||||
start(exporter);
|
||||
assertIsRegistered("Should have registered MBean", objectName);
|
||||
|
||||
server.setAttribute(objectName, new Attribute("Age", new Integer(77)));
|
||||
|
|
@ -322,7 +322,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
|||
exporter.setBeans(beans);
|
||||
exporter.setNotificationListenerMappings(listenerMappings);
|
||||
exporter.setBeanFactory(factory);
|
||||
exporter.afterPropertiesSet();
|
||||
start(exporter);
|
||||
assertIsRegistered("Should have registered MBean", objectName);
|
||||
|
||||
server.setAttribute(objectName, new Attribute("Age", new Integer(77)));
|
||||
|
|
@ -362,7 +362,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
|||
exporter.setBeans(beans);
|
||||
exporter.setNotificationListenerMappings(listenerMappings);
|
||||
exporter.setBeanFactory(factory);
|
||||
exporter.afterPropertiesSet();
|
||||
start(exporter);
|
||||
assertIsRegistered("Should have registered MBean", objectName1);
|
||||
assertIsRegistered("Should have registered MBean", objectName2);
|
||||
|
||||
|
|
@ -384,7 +384,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
|||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setServer(server);
|
||||
exporter.setBeans(beans);
|
||||
exporter.afterPropertiesSet();
|
||||
start(exporter);
|
||||
|
||||
CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
|
||||
|
||||
|
|
@ -420,7 +420,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
|||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setServer(server);
|
||||
exporter.setBeans(beans);
|
||||
exporter.afterPropertiesSet();
|
||||
start(exporter);
|
||||
|
||||
CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
|
||||
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemble
|
|||
Map<String, Object> beans = new HashMap<String, Object>();
|
||||
beans.put(objectName, proxy);
|
||||
exporter.setBeans(beans);
|
||||
exporter.afterPropertiesSet();
|
||||
start(exporter);
|
||||
|
||||
MBeanInfo inf = getServer().getMBeanInfo(ObjectNameManager.getInstance(objectName));
|
||||
assertEquals("Incorrect number of operations", getExpectedOperationCount(), inf.getOperations().length);
|
||||
|
|
|
|||
|
|
@ -17,10 +17,4 @@
|
|||
<property name="name" value="Juergen Hoeller"/>
|
||||
</bean>
|
||||
|
||||
<bean id="connector" class="org.springframework.jmx.support.ConnectorServerFactoryBean">
|
||||
<property name="server">
|
||||
<ref local="server"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
|
|
|||
|
|
@ -17,12 +17,6 @@
|
|||
|
||||
<bean name="spring:mbean3=true" class="org.springframework.jmx.export.TestDynamicMBean"/>
|
||||
|
||||
<bean id="connector" class="org.springframework.jmx.support.ConnectorServerFactoryBean">
|
||||
<property name="server">
|
||||
<ref local="server"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="toBeIgnored" class="javax.management.DynamicMBean" abstract="true"/>
|
||||
|
||||
<bean id="toBeIgnoredToo" class="javax.management.DynamicMBean" abstract="true" lazy-init="true"/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="server" class="org.springframework.jmx.support.MBeanServerFactoryBean"/>
|
||||
|
||||
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
|
||||
<property name="server" ref="server"/>
|
||||
<property name="autodetect" value="true"/>
|
||||
<property name="autoStartup" value="false"/>
|
||||
</bean>
|
||||
|
||||
<bean name="spring:mbean=true" class="org.springframework.jmx.export.TestDynamicMBean"/>
|
||||
|
||||
|
||||
</beans>
|
||||
|
|
@ -41809,6 +41809,13 @@ With this configuration the `testBean` bean is exposed as an MBean under the
|
|||
are exposed as attributes and all __public__ methods (bar those inherited from the
|
||||
`Object` class) are exposed as operations.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
`MBeanExporter` is a `Lifecycle` bean (see <<beans-factory-lifecycle-processor>>)
|
||||
and MBeans are exported as late as possible during the application lifecycle by default. It
|
||||
is possible to configure the `phase` at which the export happens or disable automatic
|
||||
registration by setting the `autoStartup` flag.
|
||||
====
|
||||
|
||||
|
||||
[[jmx-exporting-mbeanserver]]
|
||||
|
|
|
|||
Loading…
Reference in New Issue