diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/annotation/ControllerEndpointDiscoverer.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/annotation/ControllerEndpointDiscoverer.java index 112a509224..7df0d22e42 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/annotation/ControllerEndpointDiscoverer.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/annotation/ControllerEndpointDiscoverer.java @@ -29,6 +29,7 @@ import org.springframework.boot.actuate.endpoint.web.PathMapper; import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; /** * {@link EndpointDiscoverer} for {@link ExposableControllerEndpoint controller @@ -60,7 +61,7 @@ public class ControllerEndpointDiscoverer @Override protected boolean isEndpointExposed(Object endpointBean) { - Class type = endpointBean.getClass(); + Class type = ClassUtils.getUserClass(endpointBean.getClass()); return AnnotatedElementUtils.isAnnotated(type, ControllerEndpoint.class) || AnnotatedElementUtils.isAnnotated(type, RestControllerEndpoint.class); } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/annotation/ServletEndpointDiscoverer.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/annotation/ServletEndpointDiscoverer.java index 0b9b5ccf96..f00857c2db 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/annotation/ServletEndpointDiscoverer.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/annotation/ServletEndpointDiscoverer.java @@ -30,6 +30,7 @@ import org.springframework.boot.actuate.endpoint.web.PathMapper; import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; /** * {@link EndpointDiscoverer} for {@link ExposableServletEndpoint servlet endpoints}. @@ -60,7 +61,7 @@ public class ServletEndpointDiscoverer @Override protected boolean isEndpointExposed(Object endpointBean) { - Class type = endpointBean.getClass(); + Class type = ClassUtils.getUserClass(endpointBean.getClass()); return AnnotatedElementUtils.isAnnotated(type, ServletEndpoint.class); } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/ControllerEndpointDiscovererTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/ControllerEndpointDiscovererTests.java index af79cdcfb5..b1ea4acc06 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/ControllerEndpointDiscovererTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/ControllerEndpointDiscovererTests.java @@ -31,11 +31,14 @@ import org.springframework.boot.actuate.endpoint.annotation.DiscoveredEndpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.actuate.endpoint.web.PathMapper; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration; import org.springframework.boot.test.context.assertj.AssertableApplicationContext; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.validation.annotation.Validated; import static org.assertj.core.api.Assertions.assertThat; @@ -73,6 +76,22 @@ public class ControllerEndpointDiscovererTests { })); } + @Test + public void getEndpointsShouldDiscoverProxyControllerEndpoints() { + this.contextRunner.withUserConfiguration(TestProxyControllerEndpoint.class) + .withConfiguration(AutoConfigurations.of( + ValidationAutoConfiguration.class)) + .run(assertDiscoverer((discoverer) -> { + Collection endpoints = discoverer.getEndpoints(); + assertThat(endpoints).hasSize(1); + ExposableControllerEndpoint endpoint = endpoints.iterator().next(); + assertThat(endpoint.getId()).isEqualTo("testcontroller"); + assertThat(endpoint.getController()) + .isInstanceOf(TestProxyControllerEndpoint.class); + assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class); + })); + } + @Test public void getEndpointsShouldIncludeRestControllerEndpoints() { this.contextRunner.withUserConfiguration(TestRestControllerEndpoint.class) @@ -86,6 +105,22 @@ public class ControllerEndpointDiscovererTests { })); } + @Test + public void getEndpointsShouldDiscoverProxyRestControllerEndpoints() { + this.contextRunner.withUserConfiguration(TestProxyRestControllerEndpoint.class) + .withConfiguration(AutoConfigurations.of( + ValidationAutoConfiguration.class)) + .run(assertDiscoverer((discoverer) -> { + Collection endpoints = discoverer.getEndpoints(); + assertThat(endpoints).hasSize(1); + ExposableControllerEndpoint endpoint = endpoints.iterator().next(); + assertThat(endpoint.getId()).isEqualTo("testrestcontroller"); + assertThat(endpoint.getController()) + .isInstanceOf(TestProxyRestControllerEndpoint.class); + assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class); + })); + } + @Test public void getEndpointsShouldNotDiscoverRegularEndpoints() { this.contextRunner.withUserConfiguration(WithRegularEndpointConfiguration.class) @@ -133,11 +168,23 @@ public class ControllerEndpointDiscovererTests { } + @ControllerEndpoint(id = "testcontroller") + @Validated + static class TestProxyControllerEndpoint { + + } + @RestControllerEndpoint(id = "testrestcontroller") static class TestRestControllerEndpoint { } + @RestControllerEndpoint(id = "testrestcontroller") + @Validated + static class TestProxyRestControllerEndpoint { + + } + @Endpoint(id = "test") static class TestEndpoint { diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/ServletEndpointDiscovererTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/ServletEndpointDiscovererTests.java index 2a17c5070a..f2b0a48c8b 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/ServletEndpointDiscovererTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/ServletEndpointDiscovererTests.java @@ -40,11 +40,14 @@ import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.actuate.endpoint.web.EndpointServlet; import org.springframework.boot.actuate.endpoint.web.ExposableServletEndpoint; import org.springframework.boot.actuate.endpoint.web.PathMapper; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration; import org.springframework.boot.test.context.assertj.AssertableApplicationContext; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.validation.annotation.Validated; import static org.assertj.core.api.Assertions.assertThat; @@ -81,6 +84,20 @@ public class ServletEndpointDiscovererTests { })); } + @Test + public void getEndpointsShouldDiscoverProxyServletEndpoints() { + this.contextRunner.withUserConfiguration(TestProxyServletEndpoint.class) + .withConfiguration(AutoConfigurations.of(ValidationAutoConfiguration.class)) + .run(assertDiscoverer((discoverer) -> { + Collection endpoints = discoverer.getEndpoints(); + assertThat(endpoints).hasSize(1); + ExposableServletEndpoint endpoint = endpoints.iterator().next(); + assertThat(endpoint.getId()).isEqualTo("testservlet"); + assertThat(endpoint.getEndpointServlet()).isNotNull(); + assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class); + })); + } + @Test public void getEndpointsShouldNotDiscoverRegularEndpoints() { this.contextRunner.withUserConfiguration(WithRegularEndpointConfiguration.class) @@ -163,6 +180,17 @@ public class ServletEndpointDiscovererTests { } + @ServletEndpoint(id = "testservlet") + @Validated + static class TestProxyServletEndpoint implements Supplier { + + @Override + public EndpointServlet get() { + return new EndpointServlet(TestServlet.class); + } + + } + @Endpoint(id = "test") static class TestEndpoint {