diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/EndpointDiscoverer.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/EndpointDiscoverer.java index f174650df3..d92de1d523 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/EndpointDiscoverer.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/EndpointDiscoverer.java @@ -145,17 +145,17 @@ public abstract class EndpointDiscoverer, O exten } private void addExtensionBeans(Collection endpointBeans) { - Map byType = endpointBeans.stream() - .collect(Collectors.toMap((bean) -> bean.getType(), (bean) -> bean)); + Map byId = endpointBeans.stream() + .collect(Collectors.toMap(EndpointBean::getId, (bean) -> bean)); String[] beanNames = BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors( this.applicationContext, EndpointExtension.class); for (String beanName : beanNames) { ExtensionBean extensionBean = createExtensionBean(beanName); - EndpointBean endpointBean = byType.get(extensionBean.getEndpointType()); + EndpointBean endpointBean = byId.get(extensionBean.getEndpointId()); Assert.state(endpointBean != null, () -> ("Invalid extension '" + extensionBean.getBeanName() - + "': no endpoint found with type '" - + extensionBean.getEndpointType().getName() + "'")); + + "': no endpoint found with id '" + + extensionBean.getEndpointId() + "'")); addExtensionBean(endpointBean, extensionBean); } } @@ -488,20 +488,24 @@ public abstract class EndpointDiscoverer, O exten private final Object bean; - private final Class endpointType; + private final String endpointId; private final Class filter; ExtensionBean(String beanName, Object bean) { + this.bean = bean; + this.beanName = beanName; AnnotationAttributes attributes = AnnotatedElementUtils .getMergedAnnotationAttributes(bean.getClass(), EndpointExtension.class); - this.beanName = beanName; - this.bean = bean; - this.endpointType = attributes.getClass("endpoint"); + Class endpointType = attributes.getClass("endpoint"); + AnnotationAttributes endpointAttributes = AnnotatedElementUtils + .findMergedAnnotationAttributes(endpointType, Endpoint.class, true, + true); + Assert.state(endpointAttributes != null, () -> "Extension " + + endpointType.getName() + " does not specify an endpoint"); + this.endpointId = endpointAttributes.getString("id"); this.filter = attributes.getClass("filter"); - Assert.state(!this.endpointType.equals(Void.class), () -> "Extension " - + this.endpointType.getName() + " does not specify an endpoint"); } public String getBeanName() { @@ -512,8 +516,8 @@ public abstract class EndpointDiscoverer, O exten return this.bean; } - public Class getEndpointType() { - return this.endpointType; + public String getEndpointId() { + return this.endpointId; } public Class getFilter() { diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/annotation/EndpointDiscovererTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/annotation/EndpointDiscovererTests.java index 9d99cd2fa2..b38c076ef6 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/annotation/EndpointDiscovererTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/annotation/EndpointDiscovererTests.java @@ -233,6 +233,25 @@ public class EndpointDiscovererTests { }); } + @Test + public void getEndpointShouldFindParentExtension() { + load(SubSpecializedEndpointsConfiguration.class, (context) -> { + SpecializedEndpointDiscoverer discoverer = new SpecializedEndpointDiscoverer( + context); + Map endpoints = mapEndpoints( + discoverer.getEndpoints()); + Map operations = mapOperations( + endpoints.get("specialized")); + assertThat(operations).containsKeys( + ReflectionUtils.findMethod(SpecializedTestEndpoint.class, "getAll")); + assertThat(operations).containsKeys(ReflectionUtils.findMethod( + SubSpecializedTestEndpoint.class, "getSpecialOne", String.class)); + assertThat(operations).containsKeys( + ReflectionUtils.findMethod(SpecializedExtension.class, "getSpecial")); + assertThat(operations).hasSize(3); + }); + } + @Test public void getEndpointsShouldApplyFilters() { load(SpecializedEndpointsConfiguration.class, (context) -> { @@ -371,6 +390,12 @@ public class EndpointDiscovererTests { } + @Import({ TestEndpoint.class, SubSpecializedTestEndpoint.class, + SpecializedExtension.class }) + static class SubSpecializedEndpointsConfiguration { + + } + @Endpoint(id = "test") static class TestEndpoint { @@ -449,6 +474,15 @@ public class EndpointDiscovererTests { } + static class SubSpecializedTestEndpoint extends SpecializedTestEndpoint { + + @ReadOperation + public Object getSpecialOne(@Selector String id) { + return null; + } + + } + static class TestEndpointDiscoverer extends EndpointDiscoverer { diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/jmx/annotation/JmxEndpointDiscovererTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/jmx/annotation/JmxEndpointDiscovererTests.java index 9b92b4c28e..2dec175552 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/jmx/annotation/JmxEndpointDiscovererTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/jmx/annotation/JmxEndpointDiscovererTests.java @@ -117,8 +117,7 @@ public class JmxEndpointDiscovererTests { this.thrown.expect(IllegalStateException.class); this.thrown.expectMessage( "Invalid extension 'jmxEndpointDiscovererTests.TestJmxEndpointExtension': " - + "no endpoint found with type '" - + TestEndpoint.class.getName() + "'"); + + "no endpoint found with id 'test'"); discoverer.getEndpoints(); }); } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/WebEndpointDiscovererTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/WebEndpointDiscovererTests.java index 65c8a533f4..cf31c236d8 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/WebEndpointDiscovererTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/WebEndpointDiscovererTests.java @@ -82,8 +82,8 @@ public class WebEndpointDiscovererTests { load(TestWebEndpointExtensionConfiguration.class, (discoverer) -> { this.thrown.expect(IllegalStateException.class); this.thrown.expectMessage( - "Invalid extension 'endpointExtension': no endpoint found with type '" - + TestEndpoint.class.getName() + "'"); + "Invalid extension 'endpointExtension': no endpoint found with id '" + + "test'"); discoverer.getEndpoints(); }); }