diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/ParentAwareNamingStrategy.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/ParentAwareNamingStrategy.java index da8781f7a23b..288552fe1b96 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/ParentAwareNamingStrategy.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/ParentAwareNamingStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -26,6 +26,7 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.jmx.export.metadata.JmxAttributeSource; import org.springframework.jmx.export.naming.MetadataNamingStrategy; +import org.springframework.jmx.support.JmxUtils; import org.springframework.jmx.support.ObjectNameManager; import org.springframework.util.ObjectUtils; @@ -55,22 +56,21 @@ public void setEnsureUniqueRuntimeObjectNames(boolean ensureUniqueRuntimeObjectN this.ensureUniqueRuntimeObjectNames = ensureUniqueRuntimeObjectNames; } + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + @Override public ObjectName getObjectName(Object managedBean, String beanKey) throws MalformedObjectNameException { ObjectName name = super.getObjectName(managedBean, beanKey); - Hashtable properties = new Hashtable<>(name.getKeyPropertyList()); if (this.ensureUniqueRuntimeObjectNames) { - properties.put("identity", ObjectUtils.getIdentityHexString(managedBean)); + return JmxUtils.appendIdentityToObjectName(name, managedBean); } - else if (parentContextContainsSameBean(this.applicationContext, beanKey)) { - properties.put("context", ObjectUtils.getIdentityHexString(this.applicationContext)); + if (parentContextContainsSameBean(this.applicationContext, beanKey)) { + return appendToObjectName(name, "context", ObjectUtils.getIdentityHexString(this.applicationContext)); } - return ObjectNameManager.getInstance(name.getDomain(), properties); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; + return name; } private boolean parentContextContainsSameBean(ApplicationContext context, String beanKey) { @@ -86,4 +86,11 @@ private boolean parentContextContainsSameBean(ApplicationContext context, String } } + private ObjectName appendToObjectName(ObjectName name, String key, String value) + throws MalformedObjectNameException { + Hashtable keyProperties = name.getKeyPropertyList(); + keyProperties.put(key, value); + return ObjectNameManager.getInstance(name.getDomain(), keyProperties); + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jmx/ParentAwareNamingStrategyTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jmx/ParentAwareNamingStrategyTests.java new file mode 100644 index 000000000000..5f0531971b2b --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jmx/ParentAwareNamingStrategyTests.java @@ -0,0 +1,100 @@ +/* + * Copyright 2012-2022 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 + * + * https://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.boot.autoconfigure.jmx; + +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource; +import org.springframework.jmx.export.annotation.ManagedResource; +import org.springframework.util.ObjectUtils; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link ParentAwareNamingStrategy}. + * + * @author Andy Wilkinson + */ +class ParentAwareNamingStrategyTests { + + private ApplicationContextRunner contextRunner = new ApplicationContextRunner(); + + @Test + void objectNameMatchesManagedResourceByDefault() throws MalformedObjectNameException { + this.contextRunner.withBean("testManagedResource", TestManagedResource.class).run((context) -> { + ParentAwareNamingStrategy strategy = new ParentAwareNamingStrategy(new AnnotationJmxAttributeSource()); + strategy.setApplicationContext(context); + assertThat(strategy.getObjectName(context.getBean("testManagedResource"), "testManagedResource") + .getKeyPropertyListString()).isEqualTo("type=something,name1=def,name2=ghi"); + }); + } + + @Test + void uniqueObjectNameAddsIdentityProperty() throws MalformedObjectNameException { + this.contextRunner.withBean("testManagedResource", TestManagedResource.class).run((context) -> { + ParentAwareNamingStrategy strategy = new ParentAwareNamingStrategy(new AnnotationJmxAttributeSource()); + strategy.setApplicationContext(context); + strategy.setEnsureUniqueRuntimeObjectNames(true); + Object resource = context.getBean("testManagedResource"); + ObjectName objectName = strategy.getObjectName(resource, "testManagedResource"); + assertThat(objectName.getDomain()).isEqualTo("ABC"); + assertThat(objectName.getCanonicalKeyPropertyListString()).isEqualTo( + "identity=" + ObjectUtils.getIdentityHexString(resource) + ",name1=def,name2=ghi,type=something"); + }); + } + + @Test + void sameBeanInParentContextAddsContextProperty() throws MalformedObjectNameException { + this.contextRunner.withBean("testManagedResource", TestManagedResource.class).run((parent) -> this.contextRunner + .withBean("testManagedResource", TestManagedResource.class).withParent(parent).run((context) -> { + ParentAwareNamingStrategy strategy = new ParentAwareNamingStrategy( + new AnnotationJmxAttributeSource()); + strategy.setApplicationContext(context); + Object resource = context.getBean("testManagedResource"); + ObjectName objectName = strategy.getObjectName(resource, "testManagedResource"); + assertThat(objectName.getDomain()).isEqualTo("ABC"); + assertThat(objectName.getCanonicalKeyPropertyListString()).isEqualTo("context=" + + ObjectUtils.getIdentityHexString(context) + ",name1=def,name2=ghi,type=something"); + })); + } + + @Test + void uniqueObjectNameAndSameBeanInParentContextOnlyAddsIdentityProperty() throws MalformedObjectNameException { + this.contextRunner.withBean("testManagedResource", TestManagedResource.class).run((parent) -> this.contextRunner + .withBean("testManagedResource", TestManagedResource.class).withParent(parent).run((context) -> { + ParentAwareNamingStrategy strategy = new ParentAwareNamingStrategy( + new AnnotationJmxAttributeSource()); + strategy.setApplicationContext(context); + strategy.setEnsureUniqueRuntimeObjectNames(true); + Object resource = context.getBean("testManagedResource"); + ObjectName objectName = strategy.getObjectName(resource, "testManagedResource"); + assertThat(objectName.getDomain()).isEqualTo("ABC"); + assertThat(objectName.getCanonicalKeyPropertyListString()).isEqualTo("identity=" + + ObjectUtils.getIdentityHexString(resource) + ",name1=def,name2=ghi,type=something"); + })); + } + + @ManagedResource(objectName = "ABC:type=something,name1=def,name2=ghi") + public static class TestManagedResource { + + } + +}