From 9849e2087d3c29b4bce60ae78c4097d8bb738e4c Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Fri, 1 Nov 2013 16:46:08 +0200 Subject: [PATCH] INT-2628 Add ObjectNamingStrategy to IMBE Allow customization of the generated ObjectName for the Integration components. JIRA: https://jira.springsource.org/browse/INT-2628 INT-2628 Polishing - Address PR comments - Rename `naming-strategy` to `object-naming-strategy` for consistency with `object-name-static-properties` --- .../jmx/config/MBeanExporterParser.java | 15 ++-- .../monitor/IntegrationMBeanExporter.java | 6 +- .../jmx/config/spring-integration-jmx-3.0.xsd | 13 ++++ .../MBeanExporterParserTests-context.xml | 5 +- .../jmx/config/MBeanExporterParserTests.java | 2 + ...nRegistrationCustomNamingTests-context.xml | 35 +++++++++ .../MBeanRegistrationCustomNamingTests.java | 72 +++++++++++++++++++ src/reference/docbook/jmx.xml | 40 +++++++++++ src/reference/docbook/whats-new.xml | 23 ++++-- 9 files changed, 194 insertions(+), 17 deletions(-) create mode 100644 spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/MBeanRegistrationCustomNamingTests-context.xml create mode 100644 spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/MBeanRegistrationCustomNamingTests.java diff --git a/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/MBeanExporterParser.java b/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/MBeanExporterParser.java index c03d788bf3..e41560c10f 100644 --- a/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/MBeanExporterParser.java +++ b/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/MBeanExporterParser.java @@ -1,11 +1,11 @@ /* - * Copyright 2002-2012 the original author or authors. - * + * Copyright 2002-2013 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. @@ -33,7 +33,7 @@ import org.springframework.util.StringUtils; /** * Parser for the 'mbean-export' element of the integration JMX namespace. - * + * * @author Mark Fisher * @author Gary Russell * @since 2.0 @@ -61,7 +61,8 @@ public class MBeanExporterParser extends AbstractSingleBeanDefinitionParser { IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "object-name-static-properties"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "managed-components", "componentNamePatterns"); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "shutdown-executor"); - + IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "object-naming-strategy", "namingStrategy"); + builder.addPropertyValue("server", mbeanServer); this.registerMBeanExporterHelper(parserContext.getRegistry()); } @@ -70,7 +71,7 @@ public class MBeanExporterParser extends AbstractSingleBeanDefinitionParser { BeanDefinitionBuilder mBeanExporterHelperBuilder = BeanDefinitionBuilder.rootBeanDefinition(MBeanExporterHelper.class); BeanDefinitionReaderUtils.registerWithGeneratedName(mBeanExporterHelperBuilder.getBeanDefinition(), registry); } - + private Object getMBeanServer(Element element, ParserContext parserContext) { String mbeanServer = element.getAttribute("server"); if (StringUtils.hasText(mbeanServer)) { 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 634aeede57..5374236dca 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 @@ -167,7 +167,7 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP private final MetadataMBeanInfoAssembler assembler = new MetadataMBeanInfoAssembler(attributeSource); - private final MetadataNamingStrategy namingStrategy = new MetadataNamingStrategy(attributeSource); + private final MetadataNamingStrategy defaultNamingStrategy = new MetadataNamingStrategy(attributeSource); private String[] componentNamePatterns = { "*" }; @@ -183,7 +183,7 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP super(); // Shouldn't be necessary, but to be on the safe side... setAutodetect(false); - setNamingStrategy(namingStrategy); + setNamingStrategy(defaultNamingStrategy); setAssembler(assembler); } @@ -210,7 +210,7 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP */ public void setDefaultDomain(String domain) { this.domain = domain; - this.namingStrategy.setDefaultDomain(domain); + this.defaultNamingStrategy.setDefaultDomain(domain); } public void setComponentNamePatterns(String[] componentNamePatterns) { diff --git a/spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-3.0.xsd b/spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-3.0.xsd index 04f8b34b2c..28dc8ecf52 100644 --- a/spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-3.0.xsd +++ b/spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-3.0.xsd @@ -204,6 +204,19 @@ + + + + + + + + + An ObjectNamingStrategy to generate the MBean's ObjectName. See the reference documentation + for details of the default ObjectName. Also see 'object-name-static-properties'. + + + diff --git a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/MBeanExporterParserTests-context.xml b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/MBeanExporterParserTests-context.xml index fc496855ff..3b419513d5 100644 --- a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/MBeanExporterParserTests-context.xml +++ b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/MBeanExporterParserTests-context.xml @@ -18,11 +18,14 @@ + object-name-static-properties="appProperties" + object-naming-strategy="keyNamer"/> foo bar + + diff --git a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/MBeanExporterParserTests.java b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/MBeanExporterParserTests.java index 03c6c870f1..1565113abe 100644 --- a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/MBeanExporterParserTests.java +++ b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/MBeanExporterParserTests.java @@ -18,6 +18,7 @@ package org.springframework.integration.jmx.config; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import java.util.Properties; @@ -57,6 +58,7 @@ public class MBeanExporterParserTests { assertTrue(properties.containsKey("foo")); assertTrue(properties.containsKey("bar")); assertEquals(server, exporter.getServer()); + assertSame(context.getBean("keyNamer"), TestUtils.getPropertyValue(exporter, "namingStrategy")); exporter.destroy(); } diff --git a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/MBeanRegistrationCustomNamingTests-context.xml b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/MBeanRegistrationCustomNamingTests-context.xml new file mode 100644 index 0000000000..2e41b34f61 --- /dev/null +++ b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/MBeanRegistrationCustomNamingTests-context.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/MBeanRegistrationCustomNamingTests.java b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/MBeanRegistrationCustomNamingTests.java new file mode 100644 index 0000000000..c47cc0363d --- /dev/null +++ b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/MBeanRegistrationCustomNamingTests.java @@ -0,0 +1,72 @@ +/* + * Copyright 2013 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.jmx.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Set; + +import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jmx.export.naming.KeyNamingStrategy; +import org.springframework.jmx.export.naming.ObjectNamingStrategy; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dave Syer + * @author Gary Russell + * @since 3.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class MBeanRegistrationCustomNamingTests { + + @Autowired + private MBeanServer server; + + @Test + public void testHandlerMBeanRegistration() throws Exception { + Set names = server.queryNames(new ObjectName("test.MBeanRegistration:type=Integration,componentType=MessageHandler,*"), null); + assertEquals(6, names.size()); + assertTrue(names.contains(new ObjectName("test.MBeanRegistration:type=Integration,componentType=MessageHandler,name=chain,bean=endpoint"))); + assertTrue(names.contains(new ObjectName("test.MBeanRegistration:type=Integration,componentType=MessageHandler,name=chain$child.t1,bean=handler"))); + assertTrue(names.contains(new ObjectName("test.MBeanRegistration:type=Integration,componentType=MessageHandler,name=chain$child.f1,bean=handler"))); + } + + public static class Source { + public String get() { + return "foo"; + } + } + + public static class Namer implements ObjectNamingStrategy { + + private final ObjectNamingStrategy realNamer = new KeyNamingStrategy(); + @Override + public ObjectName getObjectName(Object managedBean, String beanKey) throws MalformedObjectNameException { + String actualBeanKey = beanKey.replace("type=", "type=Integration,componentType="); + return realNamer.getObjectName(managedBean, actualBeanKey); + } + + } + +} diff --git a/src/reference/docbook/jmx.xml b/src/reference/docbook/jmx.xml index 20ef093cc1..d39e8742d8 100644 --- a/src/reference/docbook/jmx.xml +++ b/src/reference/docbook/jmx.xml @@ -366,6 +366,46 @@ + + + Custom elements can be appended to the object name by providing a reference to a + Properties object in the object-name-static-properties attribute. + + + Also, since Spring Integration 3.0, you can use a custom + ObjectNamingStrategy + using the object-naming-strategy attribute. This permits greater control over the naming of the + MBeans. For example, to group all Integration MBeans under + an 'Integration' type. A simple custom naming strategy implementation might be: + + + + The beanKey argument is a String containing the standard object name beginning with + the default-domain and including any additional static properties. + This example simply moves the standard type part to componentType and + sets the type to 'Integration', + enabling selection of all Integration MBeans in one query: + "my.domain:type=Integration,*. This also groups the beans under one tree entry under the + domain in tools like VisualVM. + + + The default naming strategy is a + MetadataNamingStrategy. The exporter propagates the default-domain to that object to allow it + to generate a fallback object name if parsing of the bean key fails. If your custom naming strategy is a + MetadataNamingStrategy (or subclass), the exporter will not + propagate the default-domain; you will need to configure it on your strategy bean. +
diff --git a/src/reference/docbook/whats-new.xml b/src/reference/docbook/whats-new.xml index 5cb22379b3..dc68dabc5f 100644 --- a/src/reference/docbook/whats-new.xml +++ b/src/reference/docbook/whats-new.xml @@ -63,12 +63,23 @@
JMX Support - A new <int-jmx:tree-polling-channel-adapter/> is provided; this - adapter queries the JMX MBean tree and sends a message with a payload that is the - graph of objects that matches the query. By default the MBeans are mapped to - primitives and simple Objects like Map, List and arrays - permitting simple - transformation, for example, to JSON - . + + + A new <int-jmx:tree-polling-channel-adapter/> is provided; this + adapter queries the JMX MBean tree and sends a message with a payload that is the + graph of objects that matches the query. By default the MBeans are mapped to + primitives and simple Objects like Map, List and arrays - permitting simple + transformation, for example, to JSON. + + + The IntegrationMBeanExporter now allows the configuration of + a custom ObjectNamingStrategy using the naming-strategy + attribute. + + + + + For more information, see .