Introduce @EnableMBeanExport
Add support for @EnableMBeanExport annotation allowing @Configuration classes to easily export all MBeans and @ManagedResources from the Spring application context. The annotation is functionally equivalent to the XML <context:mbean-export/> element. Issue: SPR-8943
This commit is contained in:
committed by
Chris Beams
parent
6179261d58
commit
cae08db6a9
@@ -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;
|
||||
|
||||
/**
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>This annotation is modeled after and functionally equivalent to Spring XML's
|
||||
* {@code <context:mbean-export/>} 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;
|
||||
}
|
||||
@@ -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.
|
||||
*
|
||||
* <p>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<String, Object> 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<MBeanServer> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
*
|
||||
* <p>By setting the {@link #setRegistrationBehaviorName(String) registrationBehaviorName}
|
||||
* property to <code>REGISTRATION_IGNORE_EXISTING</code> the registration process
|
||||
* <p>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}.
|
||||
*
|
||||
* <p>Setting {@link #setRegistrationBehaviorName(String) registrationBehaviorName} property
|
||||
* to <code>REGISTRATION_REPLACE_EXISTING</code> will cause existing MBeans to be replaced
|
||||
* <p>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.
|
||||
* <p>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<ObjectName> registeredBeans = new LinkedHashSet<ObjectName>();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <p>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 + "]");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user