diff --git a/spring-context/src/main/java/org/springframework/jmx/export/MBeanExporter.java b/spring-context/src/main/java/org/springframework/jmx/export/MBeanExporter.java
index 8aef23614c..2cca9ffc78 100644
--- a/spring-context/src/main/java/org/springframework/jmx/export/MBeanExporter.java
+++ b/spring-context/src/main/java/org/springframework/jmx/export/MBeanExporter.java
@@ -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 Spring-managed bean 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.
+ *
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.
- *
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
//---------------------------------------------------------------------
diff --git a/spring-context/src/test/java/org/springframework/jmx/AbstractMBeanServerTests.java b/spring-context/src/test/java/org/springframework/jmx/AbstractMBeanServerTests.java
index ab05a3ea6e..9676a69adf 100644
--- a/spring-context/src/test/java/org/springframework/jmx/AbstractMBeanServerTests.java
+++ b/spring-context/src/test/java/org/springframework/jmx/AbstractMBeanServerTests.java
@@ -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));
}
diff --git a/spring-context/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java b/spring-context/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java
index e1bd521a1d..a249f6a315 100644
--- a/spring-context/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java
+++ b/spring-context/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java
@@ -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 {
diff --git a/spring-context/src/test/java/org/springframework/jmx/export/MBeanExporterTests.java b/spring-context/src/test/java/org/springframework/jmx/export/MBeanExporterTests.java
index 808eedba81..532034b64c 100644
--- a/spring-context/src/test/java/org/springframework/jmx/export/MBeanExporterTests.java
+++ b/spring-context/src/test/java/org/springframework/jmx/export/MBeanExporterTests.java
@@ -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 map = new HashMap();
@@ -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 beans = new HashMap();
- 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 beans = new HashMap();
+ 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 getBeanMap() {
Map map = new HashMap();
map.put(OBJECT_NAME, new JmxTestBean());
diff --git a/spring-context/src/test/java/org/springframework/jmx/export/NotificationListenerTests.java b/spring-context/src/test/java/org/springframework/jmx/export/NotificationListenerTests.java
index a6423dcee8..86edb16bf0 100644
--- a/spring-context/src/test/java/org/springframework/jmx/export/NotificationListenerTests.java
+++ b/spring-context/src/test/java/org/springframework/jmx/export/NotificationListenerTests.java
@@ -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();
diff --git a/spring-context/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerTests.java b/spring-context/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerTests.java
index 0c3ece7839..06424ac7b3 100644
--- a/spring-context/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerTests.java
+++ b/spring-context/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerTests.java
@@ -175,7 +175,7 @@ public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemble
Map beans = new HashMap();
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);
diff --git a/spring-context/src/test/java/org/springframework/jmx/export/autodetectLazyMBeans.xml b/spring-context/src/test/java/org/springframework/jmx/export/autodetectLazyMBeans.xml
index 960a57b12c..009109490d 100644
--- a/spring-context/src/test/java/org/springframework/jmx/export/autodetectLazyMBeans.xml
+++ b/spring-context/src/test/java/org/springframework/jmx/export/autodetectLazyMBeans.xml
@@ -17,10 +17,4 @@
-
-
-
-
-
-
diff --git a/spring-context/src/test/java/org/springframework/jmx/export/autodetectMBeans.xml b/spring-context/src/test/java/org/springframework/jmx/export/autodetectMBeans.xml
index d028b5274c..ccda368e1b 100644
--- a/spring-context/src/test/java/org/springframework/jmx/export/autodetectMBeans.xml
+++ b/spring-context/src/test/java/org/springframework/jmx/export/autodetectMBeans.xml
@@ -17,12 +17,6 @@
-
-
-
-
-
-
diff --git a/spring-context/src/test/resources/org/springframework/jmx/export/autodetectNoAutoStartup.xml b/spring-context/src/test/resources/org/springframework/jmx/export/autodetectNoAutoStartup.xml
new file mode 100644
index 0000000000..d385c07c48
--- /dev/null
+++ b/spring-context/src/test/resources/org/springframework/jmx/export/autodetectNoAutoStartup.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/asciidoc/index.adoc b/src/asciidoc/index.adoc
index 84eeb27e88..afcdf5eced 100644
--- a/src/asciidoc/index.adoc
+++ b/src/asciidoc/index.adoc
@@ -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 <>)
+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]]