Skip to content

Commit 628c2cd

Browse files
committed
Ensure JMX endpoints are uniquely named in a context hierarchy
Closes gh-31718
1 parent 043354f commit 628c2cd

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointAutoConfiguration.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2021 the original author or authors.
2+
* Copyright 2012-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@
4343
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
4444
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
4545
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
46+
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
4647
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
4748
import org.springframework.boot.context.properties.EnableConfigurationProperties;
4849
import org.springframework.context.ApplicationContext;
@@ -86,7 +87,7 @@ public JmxEndpointDiscoverer jmxAnnotationEndpointDiscoverer(ParameterValueMappe
8687
}
8788

8889
@Bean
89-
@ConditionalOnMissingBean(EndpointObjectNameFactory.class)
90+
@ConditionalOnMissingBean(value = EndpointObjectNameFactory.class, search = SearchStrategy.CURRENT)
9091
public DefaultEndpointObjectNameFactory endpointObjectNameFactory(MBeanServer mBeanServer,
9192
Environment environment) {
9293
String contextId = ObjectUtils.getIdentityHexString(this.applicationContext);

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointAutoConfigurationTests.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure.endpoint.jmx;
1818

19+
import java.util.Arrays;
20+
import java.util.HashSet;
21+
import java.util.Set;
1922
import java.util.function.Function;
2023

2124
import javax.management.MBeanServer;
25+
import javax.management.ObjectName;
2226

2327
import org.junit.jupiter.api.Test;
2428
import org.mockito.ArgumentCaptor;
@@ -35,8 +39,11 @@
3539
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
3640

3741
import static org.assertj.core.api.Assertions.assertThat;
42+
import static org.mockito.ArgumentMatchers.any;
43+
import static org.mockito.BDDMockito.given;
3844
import static org.mockito.BDDMockito.then;
3945
import static org.mockito.Mockito.mock;
46+
import static org.mockito.Mockito.times;
4047

4148
/**
4249
* Tests for {@link JmxEndpointAutoConfiguration}.
@@ -78,6 +85,26 @@ void jmxEndpointWithCustomEndpointObjectNameFactory() {
7885
});
7986
}
8087

88+
@Test
89+
void jmxEndpointWithContextHierarchyGeneratesUniqueNamesForEachEndpoint() throws Exception {
90+
given(this.mBeanServer.queryNames(any(), any()))
91+
.willReturn(new HashSet<>(Arrays.asList(new ObjectName("test:test=test"))));
92+
ArgumentCaptor<ObjectName> objectName = ArgumentCaptor.forClass(ObjectName.class);
93+
this.contextRunner.withPropertyValues("spring.jmx.enabled=true").with(mockMBeanServer()).run((parent) -> {
94+
this.contextRunner.withPropertyValues("spring.jmx.enabled=true").withParent(parent).run((child) -> {
95+
});
96+
this.contextRunner.withPropertyValues("spring.jmx.enabled=true").withParent(parent).run((child) -> {
97+
});
98+
});
99+
then(this.mBeanServer).should(times(3)).registerMBean(any(Object.class), objectName.capture());
100+
Set<ObjectName> uniqueValues = new HashSet<>(objectName.getAllValues());
101+
assertThat(uniqueValues).hasSize(3);
102+
assertThat(uniqueValues).allMatch((name) -> name.getDomain().equals("org.springframework.boot"));
103+
assertThat(uniqueValues).allMatch((name) -> name.getKeyProperty("type").equals("Endpoint"));
104+
assertThat(uniqueValues).allMatch((name) -> name.getKeyProperty("name").equals("Test"));
105+
assertThat(uniqueValues).allMatch((name) -> name.getKeyProperty("context") != null);
106+
}
107+
81108
private Function<ApplicationContextRunner, ApplicationContextRunner> mockMBeanServer() {
82109
return (ctxRunner) -> ctxRunner.withBean("mbeanServer", MBeanServer.class, () -> this.mBeanServer);
83110
}

0 commit comments

Comments
 (0)