From f660b6df2f07619c19e8f9149cc48c8af63963c8 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Thu, 24 Mar 2016 15:44:33 -0400 Subject: [PATCH] INT-3959: Make Certain JMX Classes Top Level JIRA: https://jira.spring.io/browse/INT-3959 Also add `LifecycleMessageHandlerMetrics.getDelegate()` and `LifecycleMessageSourceMetrics.getDelegate()` to avoid reflection on each `extractManagedBean()` --- .../LifecycleMessageHandlerMetrics.java | 4 ++ .../LifecycleMessageSourceMetrics.java | 3 + .../IntegrationJmxAttributeSource.java | 65 +++++++++++++++++ .../monitor/IntegrationMBeanExporter.java | 70 ------------------- ...IntegrationMetadataMBeanInfoAssembler.java | 64 +++++++++++++++++ .../IntegrationMetadataNamingStrategy.java | 60 ++++++++++++++++ 6 files changed, 196 insertions(+), 70 deletions(-) create mode 100644 spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationJmxAttributeSource.java create mode 100644 spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMetadataMBeanInfoAssembler.java create mode 100644 spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMetadataNamingStrategy.java diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/management/LifecycleMessageHandlerMetrics.java b/spring-integration-core/src/main/java/org/springframework/integration/support/management/LifecycleMessageHandlerMetrics.java index 4015035065..f23922e667 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/management/LifecycleMessageHandlerMetrics.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/management/LifecycleMessageHandlerMetrics.java @@ -42,6 +42,10 @@ public class LifecycleMessageHandlerMetrics implements MessageHandlerMetrics, Li this.delegate = delegate; } + public MessageHandlerMetrics getDelegate() { + return this.delegate; + } + @SuppressWarnings("unchecked") @Override public void configureMetrics(AbstractMessageHandlerMetrics metrics) { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/management/LifecycleMessageSourceMetrics.java b/spring-integration-core/src/main/java/org/springframework/integration/support/management/LifecycleMessageSourceMetrics.java index 6c45403798..df4f97d2f7 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/management/LifecycleMessageSourceMetrics.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/management/LifecycleMessageSourceMetrics.java @@ -41,6 +41,9 @@ public class LifecycleMessageSourceMetrics implements MessageSourceMetrics, Life this.delegate = delegate; } + public MessageSourceMetrics getDelegate() { + return this.delegate; + } @Override @ManagedOperation diff --git a/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationJmxAttributeSource.java b/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationJmxAttributeSource.java new file mode 100644 index 0000000000..bbd7698143 --- /dev/null +++ b/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationJmxAttributeSource.java @@ -0,0 +1,65 @@ +/* + * Copyright 2016 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.integration.monitor; + +import org.springframework.beans.annotation.AnnotationBeanUtils; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.beans.factory.config.EmbeddedValueResolver; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.integration.support.management.IntegrationManagedResource; +import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource; +import org.springframework.jmx.export.metadata.InvalidMetadataException; +import org.springframework.jmx.export.metadata.ManagedResource; +import org.springframework.util.StringValueResolver; + +/** + * The {@link AnnotationJmxAttributeSource} extension to resolve {@link ManagedResource}s + * via {@link IntegrationManagedResource} on classes. + * + * @author Gary Russell + * @author Artem Bilan + * @since 4.3 + */ +public class IntegrationJmxAttributeSource extends AnnotationJmxAttributeSource { + + private StringValueResolver valueResolver; + + public void setValueResolver(StringValueResolver valueResolver) { + this.valueResolver = valueResolver; + } + + @Override + public void setBeanFactory(BeanFactory beanFactory) { + super.setBeanFactory(beanFactory); + if (beanFactory instanceof ConfigurableBeanFactory) { + this.valueResolver = new EmbeddedValueResolver((ConfigurableBeanFactory) beanFactory); + } + } + + @Override + public ManagedResource getManagedResource(Class beanClass) throws InvalidMetadataException { + IntegrationManagedResource ann = AnnotationUtils.getAnnotation(beanClass, IntegrationManagedResource.class); + if (ann == null) { + return null; + } + ManagedResource managedResource = new ManagedResource(); + AnnotationBeanUtils.copyPropertiesToBean(ann, managedResource, this.valueResolver); + return managedResource; + } + +} diff --git a/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMBeanExporter.java b/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMBeanExporter.java index ee5fe2cb66..5643ab13dc 100644 --- a/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMBeanExporter.java +++ b/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMBeanExporter.java @@ -28,10 +28,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; -import javax.management.Descriptor; import javax.management.DynamicMBean; import javax.management.JMException; -import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import javax.management.modelmbean.ModelMBean; @@ -41,13 +39,10 @@ import org.apache.commons.logging.LogFactory; import org.springframework.aop.TargetSource; import org.springframework.aop.framework.Advised; import org.springframework.beans.BeansException; -import org.springframework.beans.DirectFieldAccessor; -import org.springframework.beans.annotation.AnnotationBeanUtils; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.EmbeddedValueResolverAware; import org.springframework.context.Lifecycle; -import org.springframework.core.annotation.AnnotationUtils; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.context.IntegrationContextUtils; import org.springframework.integration.context.OrderlyShutdownCapable; @@ -57,7 +52,6 @@ import org.springframework.integration.gateway.MessagingGatewaySupport; import org.springframework.integration.handler.AbstractMessageProducingHandler; import org.springframework.integration.history.MessageHistoryConfigurer; import org.springframework.integration.support.context.NamedComponent; -import org.springframework.integration.support.management.IntegrationManagedResource; import org.springframework.integration.support.management.IntegrationManagementConfigurer; import org.springframework.integration.support.management.LifecycleMessageHandlerMetrics; import org.springframework.integration.support.management.LifecycleMessageSourceMetrics; @@ -74,14 +68,10 @@ import org.springframework.integration.support.management.TrackableComponent; import org.springframework.integration.support.management.TrackableRouterMetrics; import org.springframework.jmx.export.MBeanExporter; import org.springframework.jmx.export.UnableToRegisterMBeanException; -import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource; import org.springframework.jmx.export.annotation.ManagedAttribute; import org.springframework.jmx.export.annotation.ManagedMetric; import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler; -import org.springframework.jmx.export.metadata.InvalidMetadataException; -import org.springframework.jmx.export.metadata.JmxAttributeSource; -import org.springframework.jmx.export.metadata.ManagedResource; import org.springframework.jmx.export.naming.MetadataNamingStrategy; import org.springframework.jmx.support.MetricType; import org.springframework.messaging.MessageChannel; @@ -1086,64 +1076,4 @@ public class IntegrationMBeanExporter extends MBeanExporter implements Applicati return ReflectionUtils.getField(field, target); } - private static Object extractManagedBean(Object managedBean) { - if (managedBean instanceof LifecycleMessageHandlerMetrics - || managedBean instanceof LifecycleMessageSourceMetrics) { - DirectFieldAccessor accessor = new DirectFieldAccessor(managedBean); - return accessor.getPropertyValue("delegate"); - } - return managedBean; - } - - private static class IntegrationJmxAttributeSource extends AnnotationJmxAttributeSource { - - private StringValueResolver valueResolver; - - void setValueResolver(StringValueResolver valueResolver) { - this.valueResolver = valueResolver; - } - - @Override - public ManagedResource getManagedResource(Class beanClass) throws InvalidMetadataException { - IntegrationManagedResource ann = AnnotationUtils.getAnnotation(beanClass, IntegrationManagedResource.class); - if (ann == null) { - return null; - } - ManagedResource managedResource = new ManagedResource(); - AnnotationBeanUtils.copyPropertiesToBean(ann, managedResource, this.valueResolver); - return managedResource; - } - } - - private static class IntegrationMetadataMBeanInfoAssembler extends MetadataMBeanInfoAssembler { - - private IntegrationMetadataMBeanInfoAssembler(JmxAttributeSource attributeSource) { - super(attributeSource); - } - - @Override - protected String getDescription(Object managedBean, String beanKey) { - return super.getDescription(extractManagedBean(managedBean), beanKey); - } - - @Override - protected void populateMBeanDescriptor(Descriptor desc, Object managedBean, String beanKey) { - super.populateMBeanDescriptor(desc, extractManagedBean(managedBean), beanKey); - } - - } - - private static class IntegrationMetadataNamingStrategy extends MetadataNamingStrategy { - - private IntegrationMetadataNamingStrategy(JmxAttributeSource attributeSource) { - super(attributeSource); - } - - @Override - public ObjectName getObjectName(Object managedBean, String beanKey) throws MalformedObjectNameException { - return super.getObjectName(extractManagedBean(managedBean), beanKey); - } - - } - } diff --git a/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMetadataMBeanInfoAssembler.java b/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMetadataMBeanInfoAssembler.java new file mode 100644 index 0000000000..6418ae5ecb --- /dev/null +++ b/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMetadataMBeanInfoAssembler.java @@ -0,0 +1,64 @@ +/* + * Copyright 2016 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.integration.monitor; + +import javax.management.Descriptor; + +import org.springframework.integration.support.management.LifecycleMessageHandlerMetrics; +import org.springframework.integration.support.management.LifecycleMessageSourceMetrics; +import org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler; +import org.springframework.jmx.export.metadata.JmxAttributeSource; + +/** + * The {@link MetadataMBeanInfoAssembler} extension to assemble metadata MBean info + * from the {@link LifecycleMessageSourceMetrics} or {@link LifecycleMessageHandlerMetrics} + * managed bean's delegate. + *

+ * All other managed beans are left as is. + * + * @author Gary Russell + * @author Artem Bilan + * + * @since 4.3 + */ +public class IntegrationMetadataMBeanInfoAssembler extends MetadataMBeanInfoAssembler { + + public IntegrationMetadataMBeanInfoAssembler(JmxAttributeSource attributeSource) { + super(attributeSource); + } + + @Override + protected String getDescription(Object managedBean, String beanKey) { + return super.getDescription(extractManagedBean(managedBean), beanKey); + } + + @Override + protected void populateMBeanDescriptor(Descriptor desc, Object managedBean, String beanKey) { + super.populateMBeanDescriptor(desc, extractManagedBean(managedBean), beanKey); + } + + private Object extractManagedBean(Object managedBean) { + if (managedBean instanceof LifecycleMessageSourceMetrics) { + return ((LifecycleMessageSourceMetrics) managedBean).getDelegate(); + } + else if (managedBean instanceof LifecycleMessageHandlerMetrics) { + return ((LifecycleMessageHandlerMetrics) managedBean).getDelegate(); + } + return managedBean; + } + +} diff --git a/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMetadataNamingStrategy.java b/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMetadataNamingStrategy.java new file mode 100644 index 0000000000..192959421f --- /dev/null +++ b/spring-integration-jmx/src/main/java/org/springframework/integration/monitor/IntegrationMetadataNamingStrategy.java @@ -0,0 +1,60 @@ +/* + * Copyright 2016 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.integration.monitor; + +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; + +import org.springframework.integration.support.management.LifecycleMessageHandlerMetrics; +import org.springframework.integration.support.management.LifecycleMessageSourceMetrics; +import org.springframework.jmx.export.metadata.JmxAttributeSource; +import org.springframework.jmx.export.naming.MetadataNamingStrategy; + +/** + * The {@link MetadataNamingStrategy} naming extension to extract an {@link ObjectName} + * from the {@link LifecycleMessageSourceMetrics} or {@link LifecycleMessageHandlerMetrics} + * managed bean's delegate. + *

+ * Otherwise delegate to the {@link MetadataNamingStrategy#getObjectName} as is. + * + * @author Gary Russell + * @author Artem Bilan + * + * @since 4.3 + */ +public class IntegrationMetadataNamingStrategy extends MetadataNamingStrategy { + + public IntegrationMetadataNamingStrategy(JmxAttributeSource attributeSource) { + super(attributeSource); + } + + @Override + public ObjectName getObjectName(Object managedBean, String beanKey) throws MalformedObjectNameException { + return super.getObjectName(extractManagedBean(managedBean), beanKey); + } + + private Object extractManagedBean(Object managedBean) { + if (managedBean instanceof LifecycleMessageSourceMetrics) { + return ((LifecycleMessageSourceMetrics) managedBean).getDelegate(); + } + else if (managedBean instanceof LifecycleMessageHandlerMetrics) { + return ((LifecycleMessageHandlerMetrics) managedBean).getDelegate(); + } + return managedBean; + } + +}