diff --git a/spring-context/src/main/java/org/springframework/context/config/MBeanExportBeanDefinitionParser.java b/spring-context/src/main/java/org/springframework/context/config/MBeanExportBeanDefinitionParser.java index 779894122ce..51291a4236e 100644 --- a/spring-context/src/main/java/org/springframework/context/config/MBeanExportBeanDefinitionParser.java +++ b/spring-context/src/main/java/org/springframework/context/config/MBeanExportBeanDefinitionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.jmx.export.annotation.AnnotationMBeanExporter; -import org.springframework.jmx.support.MBeanRegistrationSupport; +import org.springframework.jmx.support.RegistrationPolicy; import org.springframework.util.StringUtils; /** @@ -62,11 +62,11 @@ class MBeanExportBeanDefinitionParser extends AbstractBeanDefinitionParser { @Override protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(AnnotationMBeanExporter.class); - + // Mark as infrastructure bean and attach source location. builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); builder.getRawBeanDefinition().setSource(parserContext.extractSource(element)); - + String defaultDomain = element.getAttribute(DEFAULT_DOMAIN_ATTRIBUTE); if (StringUtils.hasText(defaultDomain)) { builder.addPropertyValue("defaultDomain", defaultDomain); @@ -84,14 +84,14 @@ class MBeanExportBeanDefinitionParser extends AbstractBeanDefinitionParser { } String registration = element.getAttribute(REGISTRATION_ATTRIBUTE); - int registrationBehavior = MBeanRegistrationSupport.REGISTRATION_FAIL_ON_EXISTING; + RegistrationPolicy registrationPolicy = RegistrationPolicy.FAIL_ON_EXISTING; if (REGISTRATION_IGNORE_EXISTING.equals(registration)) { - registrationBehavior = MBeanRegistrationSupport.REGISTRATION_IGNORE_EXISTING; + registrationPolicy = RegistrationPolicy.IGNORE_EXISTING; } else if (REGISTRATION_REPLACE_EXISTING.equals(registration)) { - registrationBehavior = MBeanRegistrationSupport.REGISTRATION_REPLACE_EXISTING; + registrationPolicy = RegistrationPolicy.REPLACE_EXISTING; } - builder.addPropertyValue("registrationBehavior", registrationBehavior); + builder.addPropertyValue("registrationPolicy", registrationPolicy); return builder.getBeanDefinition(); } diff --git a/spring-context/src/main/java/org/springframework/jmx/export/annotation/EnableMBeanExport.java b/spring-context/src/main/java/org/springframework/jmx/export/annotation/EnableMBeanExport.java new file mode 100644 index 00000000000..98dbca72dae --- /dev/null +++ b/spring-context/src/main/java/org/springframework/jmx/export/annotation/EnableMBeanExport.java @@ -0,0 +1,66 @@ +/* + * Copyright 2002-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jmx.export.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.context.annotation.Import; +import org.springframework.jmx.support.RegistrationPolicy; + +/** + * Enables default exporting of all standard {@code MBean}s from the Spring context, as + * well as well all {@code @ManagedResource} annotated beans. + * + *

The resulting {@link org.springframework.jmx.export.MBeanExporter MBeanExporter} + * bean is defined under the name "mbeanExporter". Alternatively, consider defining a + * custom {@link AnnotationMBeanExporter} bean explicitly. + * + *

This annotation is modeled after and functionally equivalent to Spring XML's + * {@code } element. + * + * @author Phillip Webb + * @since 3.2 + * @see MBeanExportConfiguration + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Import(MBeanExportConfiguration.class) +public @interface EnableMBeanExport { + + /** + * The default domain to use when generating JMX ObjectNames. + */ + String defaultDomain() default ""; + + /** + * The bean name of the MBeanServer to which MBeans should be exported. Default is to + * use the platform's default MBeanServer. + */ + String server() default ""; + + /** + * The policy to use when attempting to register an MBean under an + * {@link javax.management.ObjectName} that already exists. Defaults to + * {@link RegistrationPolicy#FAIL_ON_EXISTING}. + */ + RegistrationPolicy registration() default RegistrationPolicy.FAIL_ON_EXISTING; +} diff --git a/spring-context/src/main/java/org/springframework/jmx/export/annotation/MBeanExportConfiguration.java b/spring-context/src/main/java/org/springframework/jmx/export/annotation/MBeanExportConfiguration.java new file mode 100644 index 00000000000..4b4993c0fea --- /dev/null +++ b/spring-context/src/main/java/org/springframework/jmx/export/annotation/MBeanExportConfiguration.java @@ -0,0 +1,156 @@ +/* + * Copyright 2002-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jmx.export.annotation; + +import java.util.Map; + +import javax.management.MBeanServer; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportAware; +import org.springframework.context.annotation.Role; +import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.jmx.support.RegistrationPolicy; +import org.springframework.jmx.support.WebSphereMBeanServerFactoryBean; +import org.springframework.jndi.JndiObjectFactoryBean; +import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; + +/** + * {@code @Configuration} class that registers a {@link AnnotationMBeanExporter} bean. + * + *

This configuration class is automatically imported when using the @{@link + * EnableMBeanExport} annotation. See its Javadoc for complete usage details. + * + * @author Phillip Webb + * @author Chris Beams + * @since 3.2 + * @see EnableMBeanExport + */ +@Configuration +public class MBeanExportConfiguration implements ImportAware, BeanFactoryAware { + + private static final String MBEAN_EXPORTER_BEAN_NAME = "mbeanExporter"; + + private AnnotationAttributes attributes; + + private BeanFactory beanFactory; + + + public void setImportMetadata(AnnotationMetadata importMetadata) { + Map map = importMetadata.getAnnotationAttributes(EnableMBeanExport.class.getName()); + this.attributes = AnnotationAttributes.fromMap(map); + Assert.notNull(this.attributes, "@EnableMBeanExport is not present on " + + "importing class " + importMetadata.getClassName()); + } + + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = beanFactory; + } + + @Bean(name=MBEAN_EXPORTER_BEAN_NAME) + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) + public AnnotationMBeanExporter mbeanExporter() { + AnnotationMBeanExporter exporter = new AnnotationMBeanExporter(); + setupDomain(exporter); + setupServer(exporter); + setupRegistrationPolicy(exporter); + return exporter; + } + + private void setupDomain(AnnotationMBeanExporter exporter) { + String defaultDomain = this.attributes.getString("defaultDomain"); + if (StringUtils.hasText(defaultDomain)) { + exporter.setDefaultDomain(defaultDomain); + } + } + + private void setupServer(AnnotationMBeanExporter exporter) { + String server = this.attributes.getString("server"); + if (StringUtils.hasText(server)) { + exporter.setServer(this.beanFactory.getBean(server, MBeanServer.class)); + } + else { + SpecificPlatform specificPlatform = SpecificPlatform.get(); + if(specificPlatform != null) { + exporter.setServer(specificPlatform.getMBeanServer()); + } + } + } + + private void setupRegistrationPolicy(AnnotationMBeanExporter exporter) { + RegistrationPolicy registrationPolicy = this.attributes.getEnum("registration"); + exporter.setRegistrationPolicy(registrationPolicy); + } + + + private static enum SpecificPlatform { + + WEBLOGIC("weblogic.management.Helper") { + @Override + public FactoryBean getMBeanServerFactory() { + JndiObjectFactoryBean factory = new JndiObjectFactoryBean(); + factory.setJndiName("java:comp/env/jmx/runtime"); + return factory; + } + }, + + WEBSPHERE("com.ibm.websphere.management.AdminServiceFactory") { + @Override + public FactoryBean getMBeanServerFactory() { + return new WebSphereMBeanServerFactoryBean(); + } + }; + + private final String identifyingClass; + + private SpecificPlatform(String identifyingClass) { + this.identifyingClass = identifyingClass; + } + + public MBeanServer getMBeanServer() { + Object server; + try { + server = getMBeanServerFactory().getObject(); + Assert.isInstanceOf(MBeanServer.class, server); + return (MBeanServer) server; + } catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + + protected abstract FactoryBean getMBeanServerFactory(); + + public static SpecificPlatform get() { + ClassLoader classLoader = MBeanExportConfiguration.class.getClassLoader(); + for (SpecificPlatform environment : values()) { + if(ClassUtils.isPresent(environment.identifyingClass, classLoader)) { + return environment; + } + } + return null; + } + } +} diff --git a/spring-context/src/main/java/org/springframework/jmx/support/MBeanRegistrationSupport.java b/spring-context/src/main/java/org/springframework/jmx/support/MBeanRegistrationSupport.java index 71d824b09e3..f8ac78b9f17 100644 --- a/spring-context/src/main/java/org/springframework/jmx/support/MBeanRegistrationSupport.java +++ b/spring-context/src/main/java/org/springframework/jmx/support/MBeanRegistrationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.Constants; +import org.springframework.util.Assert; /** * Provides supporting infrastructure for registering MBeans with an @@ -47,21 +48,22 @@ import org.springframework.core.Constants; * register an MBean using a {@link javax.management.ObjectName} that is * already used. * - *

By setting the {@link #setRegistrationBehaviorName(String) registrationBehaviorName} - * property to REGISTRATION_IGNORE_EXISTING the registration process + *

By setting the {@link #setRegistrationPolicy(RegistrationPolicy) registrationPolicy} + * property to {@link RegistrationPolicy#IGNORE_EXISTING} the registration process * will simply ignore existing MBeans leaving them registered. This is useful in settings * where multiple applications want to share a common MBean in a shared {@link MBeanServer}. * - *

Setting {@link #setRegistrationBehaviorName(String) registrationBehaviorName} property - * to REGISTRATION_REPLACE_EXISTING will cause existing MBeans to be replaced + *

Setting {@link #setRegistrationPolicy(RegistrationPolicy) registrationPolicy} property + * to {@link RegistrationPolicy#REPLACE_EXISTING} will cause existing MBeans to be replaced * during registration if necessary. This is useful in situations where you can't guarantee * the state of your {@link MBeanServer}. * * @author Rob Harrop * @author Juergen Hoeller + * @author Phillip Webb * @since 2.0 * @see #setServer - * @see #setRegistrationBehaviorName + * @see #setRegistrationPolicy * @see org.springframework.jmx.export.MBeanExporter */ public class MBeanRegistrationSupport { @@ -70,19 +72,25 @@ public class MBeanRegistrationSupport { * Constant indicating that registration should fail when * attempting to register an MBean under a name that already exists. *

This is the default registration behavior. + * @deprecated since Spring 3.2, in favor of {@link RegistrationPolicy#FAIL_ON_EXISTING} */ + @Deprecated public static final int REGISTRATION_FAIL_ON_EXISTING = 0; /** * Constant indicating that registration should ignore the affected MBean * when attempting to register an MBean under a name that already exists. + * @deprecated since Spring 3.2, in favor of {@link RegistrationPolicy#IGNORE_EXISTING} */ + @Deprecated public static final int REGISTRATION_IGNORE_EXISTING = 1; /** * Constant indicating that registration should replace the affected MBean * when attempting to register an MBean under a name that already exists. + * @deprecated since Spring 3.2, in favor of {@link RegistrationPolicy#REPLACE_EXISTING} */ + @Deprecated public static final int REGISTRATION_REPLACE_EXISTING = 2; @@ -107,10 +115,10 @@ public class MBeanRegistrationSupport { protected final Set registeredBeans = new LinkedHashSet(); /** - * The action take when registering an MBean and finding that it already exists. + * The policy used when registering an MBean and finding that it already exists. * By default an exception is raised. */ - private int registrationBehavior = REGISTRATION_FAIL_ON_EXISTING; + private RegistrationPolicy registrationPolicy = RegistrationPolicy.FAIL_ON_EXISTING; /** @@ -136,22 +144,37 @@ public class MBeanRegistrationSupport { * @see #REGISTRATION_FAIL_ON_EXISTING * @see #REGISTRATION_IGNORE_EXISTING * @see #REGISTRATION_REPLACE_EXISTING + * @deprecated since Spring 3.2, in favor of {@link #setRegistrationPolicy(RegistrationPolicy)} */ + @Deprecated public void setRegistrationBehaviorName(String registrationBehavior) { setRegistrationBehavior(constants.asNumber(registrationBehavior).intValue()); } /** - * Specify what action should be taken when attempting to register an MBean + * Specify what action should be taken when attempting to register an MBean * under an {@link javax.management.ObjectName} that already exists. *

Default is REGISTRATION_FAIL_ON_EXISTING. * @see #setRegistrationBehaviorName(String) * @see #REGISTRATION_FAIL_ON_EXISTING * @see #REGISTRATION_IGNORE_EXISTING * @see #REGISTRATION_REPLACE_EXISTING + * @deprecated since Spring 3.2, in favor of {@link #setRegistrationPolicy(RegistrationPolicy)} */ + @Deprecated public void setRegistrationBehavior(int registrationBehavior) { - this.registrationBehavior = registrationBehavior; + setRegistrationPolicy(RegistrationPolicy.valueOf(registrationBehavior)); + } + + /** + * The policy to use when attempting to register an MBean + * under an {@link javax.management.ObjectName} that already exists. + * @param registrationPolicy the policy to use + * @since 3.2 + */ + public void setRegistrationPolicy(RegistrationPolicy registrationPolicy) { + Assert.notNull(registrationPolicy, "RegistrationPolicy must not be null"); + this.registrationPolicy = registrationPolicy; } @@ -169,12 +192,12 @@ public class MBeanRegistrationSupport { registeredBean = this.server.registerMBean(mbean, objectName); } catch (InstanceAlreadyExistsException ex) { - if (this.registrationBehavior == REGISTRATION_IGNORE_EXISTING) { + if (this.registrationPolicy == RegistrationPolicy.IGNORE_EXISTING) { if (logger.isDebugEnabled()) { logger.debug("Ignoring existing MBean at [" + objectName + "]"); } } - else if (this.registrationBehavior == REGISTRATION_REPLACE_EXISTING) { + else if (this.registrationPolicy == RegistrationPolicy.REPLACE_EXISTING) { try { if (logger.isDebugEnabled()) { logger.debug("Replacing existing MBean at [" + objectName + "]"); diff --git a/spring-context/src/main/java/org/springframework/jmx/support/RegistrationPolicy.java b/spring-context/src/main/java/org/springframework/jmx/support/RegistrationPolicy.java new file mode 100644 index 00000000000..8109a247d92 --- /dev/null +++ b/spring-context/src/main/java/org/springframework/jmx/support/RegistrationPolicy.java @@ -0,0 +1,67 @@ +/* + * Copyright 2002-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jmx.support; + +/** + * Indicates registration behavior when attempting to register an MBean that already + * exists. + * + * @author Phillip Webb + * @author Chris Beams + * @since 3.2 + */ +public enum RegistrationPolicy { + + /** + * Registration should fail when attempting to register an MBean under a name that + * already exists. + */ + FAIL_ON_EXISTING, + + /** + * Registration should ignore the affected MBean when attempting to register an MBean + * under a name that already exists. + */ + IGNORE_EXISTING, + + /** + * Registration should replace the affected MBean when attempting to register an MBean + * under a name that already exists. + */ + REPLACE_EXISTING; + + /** + * Translate from an {@link MBeanRegistrationSupport} registration behavior constant + * to a {@link RegistrationPolicy} enum value. + * @param registrationBehavior one of the now-deprecated REGISTRATION_* constants + * available in {@link MBeanRegistrationSupport}. + */ + @SuppressWarnings("deprecation") + public static RegistrationPolicy valueOf(int registrationBehavior) { + switch (registrationBehavior) { + case MBeanRegistrationSupport.REGISTRATION_IGNORE_EXISTING: + return RegistrationPolicy.IGNORE_EXISTING; + case MBeanRegistrationSupport.REGISTRATION_REPLACE_EXISTING: + return RegistrationPolicy.REPLACE_EXISTING; + case MBeanRegistrationSupport.REGISTRATION_FAIL_ON_EXISTING: + return RegistrationPolicy.FAIL_ON_EXISTING; + } + throw new IllegalArgumentException( + "Unknown MBean registration behavior: " + registrationBehavior); + } + +} 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 5d060ccb964..95c610e11fb 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,6 @@ import javax.management.ObjectInstance; import javax.management.ObjectName; import javax.management.modelmbean.ModelMBeanInfo; -import org.junit.Ignore; import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.TestBean; import org.springframework.beans.factory.support.BeanDefinitionBuilder; @@ -48,12 +47,13 @@ import org.springframework.jmx.export.assembler.MBeanInfoAssembler; import org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler; import org.springframework.jmx.export.naming.SelfNaming; import org.springframework.jmx.support.ObjectNameManager; +import org.springframework.jmx.support.RegistrationPolicy; import test.interceptor.NopInterceptor; /** * Integration tests for the {@link MBeanExporter} class. - * + * * @author Rob Harrop * @author Juergen Hoeller * @author Rick Evans @@ -324,7 +324,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests { MBeanExporter exporter = new MBeanExporter(); exporter.setServer(server); exporter.setBeans(beans); - exporter.setRegistrationBehavior(MBeanExporter.REGISTRATION_REPLACE_EXISTING); + exporter.setRegistrationPolicy(RegistrationPolicy.REPLACE_EXISTING); exporter.afterPropertiesSet(); diff --git a/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBeanFactory.java b/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBeanFactory.java index c94cb07e06c..3e47e82bfd3 100644 --- a/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBeanFactory.java +++ b/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ import org.springframework.jmx.IJmxTestBean; /** * @author Juergen Hoeller */ -public class AnnotationTestBeanFactory implements FactoryBean { +public class AnnotationTestBeanFactory implements FactoryBean { private final FactoryCreatedAnnotationTestBean instance = new FactoryCreatedAnnotationTestBean(); @@ -30,7 +30,7 @@ public class AnnotationTestBeanFactory implements FactoryBean { this.instance.setName("FACTORY"); } - public IJmxTestBean getObject() throws Exception { + public FactoryCreatedAnnotationTestBean getObject() throws Exception { return this.instance; } diff --git a/spring-context/src/test/java/org/springframework/jmx/export/annotation/EnableMBeanExportConfigurationTests.java b/spring-context/src/test/java/org/springframework/jmx/export/annotation/EnableMBeanExportConfigurationTests.java new file mode 100644 index 00000000000..3c53e2a5b13 --- /dev/null +++ b/spring-context/src/test/java/org/springframework/jmx/export/annotation/EnableMBeanExportConfigurationTests.java @@ -0,0 +1,182 @@ +/* + * Copyright 2002-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jmx.export.annotation; + +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import org.junit.Test; + +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; +import org.springframework.jmx.export.MBeanExporterTests; +import org.springframework.jmx.export.TestDynamicMBean; +import org.springframework.jmx.support.MBeanServerFactoryBean; +import org.springframework.jmx.support.ObjectNameManager; +import org.springframework.jmx.support.RegistrationPolicy; + +import static org.junit.Assert.*; + +/** + * Tests for {@link EnableMBeanExport} and {@link MBeanExportConfiguration}. + * + * @author Phillip Webb + * @see AnnotationLazyInitMBeanTests + */ +public class EnableMBeanExportConfigurationTests { + + @Test + public void testLazyNaming() throws Exception { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext( + LazyNamingConfiguration.class); + try { + MBeanServer server = (MBeanServer) ctx.getBean("server"); + ObjectName oname = ObjectNameManager.getInstance("bean:name=testBean4"); + assertNotNull(server.getObjectInstance(oname)); + String name = (String) server.getAttribute(oname, "Name"); + assertEquals("Invalid name returned", "TEST", name); + } + finally { + ctx.close(); + } + } + + @Test + public void testLazyAssembling() throws Exception { + AnnotationConfigApplicationContext ctx = + new AnnotationConfigApplicationContext(LazyAssemblingConfiguration.class); + try { + MBeanServer server = (MBeanServer) ctx.getBean("server"); + + ObjectName oname = ObjectNameManager.getInstance("bean:name=testBean4"); + assertNotNull(server.getObjectInstance(oname)); + String name = (String) server.getAttribute(oname, "Name"); + assertEquals("Invalid name returned", "TEST", name); + + oname = ObjectNameManager.getInstance("bean:name=testBean5"); + assertNotNull(server.getObjectInstance(oname)); + name = (String) server.getAttribute(oname, "Name"); + assertEquals("Invalid name returned", "FACTORY", name); + + oname = ObjectNameManager.getInstance("spring:mbean=true"); + assertNotNull(server.getObjectInstance(oname)); + name = (String) server.getAttribute(oname, "Name"); + assertEquals("Invalid name returned", "Rob Harrop", name); + + oname = ObjectNameManager.getInstance("spring:mbean=another"); + assertNotNull(server.getObjectInstance(oname)); + name = (String) server.getAttribute(oname, "Name"); + assertEquals("Invalid name returned", "Juergen Hoeller", name); + } + finally { + ctx.close(); + } + } + + @Test + public void testComponentScan() throws Exception { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext( + ComponentScanConfiguration.class); + try { + MBeanServer server = (MBeanServer) ctx.getBean("server"); + ObjectName oname = ObjectNameManager.getInstance("bean:name=testBean4"); + assertNotNull(server.getObjectInstance(oname)); + String name = (String) server.getAttribute(oname, "Name"); + assertNull(name); + } finally { + ctx.close(); + } + } + + @Configuration + @EnableMBeanExport(server = "server") + static class LazyNamingConfiguration { + + @Bean + public MBeanServerFactoryBean server() throws Exception { + return new MBeanServerFactoryBean(); + } + + @Bean + @Lazy + public AnnotationTestBean testBean() { + AnnotationTestBean bean = new AnnotationTestBean(); + bean.setName("TEST"); + bean.setAge(100); + return bean; + } + } + + @Configuration + @EnableMBeanExport(server="server", registration=RegistrationPolicy.REPLACE_EXISTING) + static class LazyAssemblingConfiguration { + + @Bean + public MBeanServerFactoryBean server() throws Exception { + return new MBeanServerFactoryBean(); + } + + @Bean(name="bean:name=testBean4") + @Lazy + public AnnotationTestBean testBean4() { + AnnotationTestBean bean = new AnnotationTestBean(); + bean.setName("TEST"); + bean.setAge(100); + return bean; + } + + @Bean(name="bean:name=testBean5") + public AnnotationTestBeanFactory testBean5() throws Exception { + return new AnnotationTestBeanFactory(); + } + + @Bean(name="spring:mbean=true") + @Lazy + public TestDynamicMBean dynamic() { + return new TestDynamicMBean(); + } + + @Bean(name="spring:mbean=another") + @Lazy + public MBeanExporterTests.Person person() { + MBeanExporterTests.Person person = new MBeanExporterTests.Person(); + person.setName("Juergen Hoeller"); + return person; + } + + @Bean + @Lazy + public Object notLoadable() throws Exception { + return Class.forName("does.not.exist").newInstance(); + } + } + + @Configuration + @ComponentScan(excludeFilters = @ComponentScan.Filter(value=Configuration.class)) + @EnableMBeanExport(server = "server") + static class ComponentScanConfiguration { + + @Bean + public MBeanServerFactoryBean server() throws Exception { + return new MBeanServerFactoryBean(); + } + } + +} diff --git a/spring-context/src/test/java/org/springframework/jmx/export/annotation/componentScan.xml b/spring-context/src/test/java/org/springframework/jmx/export/annotation/componentScan.xml index 91cb4bdae2b..c4161779fa7 100644 --- a/spring-context/src/test/java/org/springframework/jmx/export/annotation/componentScan.xml +++ b/spring-context/src/test/java/org/springframework/jmx/export/annotation/componentScan.xml @@ -1,14 +1,15 @@ - + - + - + + + diff --git a/spring-context/src/test/java/org/springframework/jmx/export/annotation/lazyAssembling.xml b/spring-context/src/test/java/org/springframework/jmx/export/annotation/lazyAssembling.xml index c1d7afdab64..f06f02b354b 100644 --- a/spring-context/src/test/java/org/springframework/jmx/export/annotation/lazyAssembling.xml +++ b/spring-context/src/test/java/org/springframework/jmx/export/annotation/lazyAssembling.xml @@ -7,8 +7,6 @@ - - diff --git a/spring-context/src/test/java/org/springframework/jmx/support/RegistrationPolicyTests.java b/spring-context/src/test/java/org/springframework/jmx/support/RegistrationPolicyTests.java new file mode 100644 index 00000000000..c99d7edec75 --- /dev/null +++ b/spring-context/src/test/java/org/springframework/jmx/support/RegistrationPolicyTests.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jmx.support; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +/** + * Unit tests for {@link RegistrationPolicy}. + * + * @author Chris Beams + */ +public class RegistrationPolicyTests { + + @Test + @SuppressWarnings("deprecation") + public void convertRegistrationBehaviorToRegistrationPolicy() { + assertThat( + RegistrationPolicy.valueOf(MBeanRegistrationSupport.REGISTRATION_FAIL_ON_EXISTING), + equalTo(RegistrationPolicy.FAIL_ON_EXISTING)); + assertThat( + RegistrationPolicy.valueOf(MBeanRegistrationSupport.REGISTRATION_IGNORE_EXISTING), + equalTo(RegistrationPolicy.IGNORE_EXISTING)); + assertThat( + RegistrationPolicy.valueOf(MBeanRegistrationSupport.REGISTRATION_REPLACE_EXISTING), + equalTo(RegistrationPolicy.REPLACE_EXISTING)); + + try { + RegistrationPolicy.valueOf(Integer.MAX_VALUE); + fail("Expected IllegalArgumentException"); + } + catch (IllegalArgumentException ex) { + assertTrue(ex.getMessage().startsWith("Unknown MBean registration behavior")); + } + } + +}