Properly discover endpoints that are proxied

Previously to this commit, if a `@ControllerEndpoint`,
`@RestControllerEndpoint` or `@ServletEndpoint` annotated bean was
proxied, the endpoint wasn't properly detected.

This commit makes sure that annotation retrieval works on the user class
while preserving the get (vs. find) retrieval semantic

Closes gh-12441
This commit is contained in:
Stephane Nicoll
2018-04-10 20:19:28 +02:00
parent 86b96254a1
commit e8fac7d9c4
4 changed files with 79 additions and 2 deletions

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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<ExposableControllerEndpoint> 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<ExposableControllerEndpoint> 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 {

View File

@@ -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<ExposableServletEndpoint> 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<EndpointServlet> {
@Override
public EndpointServlet get() {
return new EndpointServlet(TestServlet.class);
}
}
@Endpoint(id = "test")
static class TestEndpoint {