Merge branch '2.0.x'

pull/12825/head
Stephane Nicoll 7 years ago
commit 55ea9f796f

@ -29,6 +29,7 @@ import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/** /**
* {@link EndpointDiscoverer} for {@link ExposableControllerEndpoint controller * {@link EndpointDiscoverer} for {@link ExposableControllerEndpoint controller
@ -60,7 +61,7 @@ public class ControllerEndpointDiscoverer
@Override @Override
protected boolean isEndpointExposed(Object endpointBean) { protected boolean isEndpointExposed(Object endpointBean) {
Class<?> type = endpointBean.getClass(); Class<?> type = ClassUtils.getUserClass(endpointBean.getClass());
return AnnotatedElementUtils.isAnnotated(type, ControllerEndpoint.class) return AnnotatedElementUtils.isAnnotated(type, ControllerEndpoint.class)
|| AnnotatedElementUtils.isAnnotated(type, RestControllerEndpoint.class); || AnnotatedElementUtils.isAnnotated(type, RestControllerEndpoint.class);
} }

@ -30,6 +30,7 @@ import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/** /**
* {@link EndpointDiscoverer} for {@link ExposableServletEndpoint servlet endpoints}. * {@link EndpointDiscoverer} for {@link ExposableServletEndpoint servlet endpoints}.
@ -60,7 +61,7 @@ public class ServletEndpointDiscoverer
@Override @Override
protected boolean isEndpointExposed(Object endpointBean) { protected boolean isEndpointExposed(Object endpointBean) {
Class<?> type = endpointBean.getClass(); Class<?> type = ClassUtils.getUserClass(endpointBean.getClass());
return AnnotatedElementUtils.isAnnotated(type, ServletEndpoint.class); return AnnotatedElementUtils.isAnnotated(type, ServletEndpoint.class);
} }

@ -31,9 +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.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.web.PathMapper; import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; 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.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.validation.annotation.Validated;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -41,21 +46,26 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link ControllerEndpointDiscoverer}. * Tests for {@link ControllerEndpointDiscoverer}.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Stephane Nicoll
*/ */
public class ControllerEndpointDiscovererTests { public class ControllerEndpointDiscovererTests {
@Rule @Rule
public final ExpectedException thrown = ExpectedException.none(); public final ExpectedException thrown = ExpectedException.none();
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();
@Test @Test
public void getEndpointsWhenNoEndpointBeansShouldReturnEmptyCollection() { public void getEndpointsWhenNoEndpointBeansShouldReturnEmptyCollection() {
load(EmptyConfiguration.class, this.contextRunner.withUserConfiguration(EmptyConfiguration.class).run(
(discoverer) -> assertThat(discoverer.getEndpoints()).isEmpty()); assertDiscoverer((discoverer) ->
assertThat(discoverer.getEndpoints()).isEmpty()));
} }
@Test @Test
public void getEndpointsShouldIncludeControllerEndpoints() { public void getEndpointsShouldIncludeControllerEndpoints() {
load(TestControllerEndpoint.class, (discoverer) -> { this.contextRunner.withUserConfiguration(TestControllerEndpoint.class)
.run(assertDiscoverer((discoverer) -> {
Collection<ExposableControllerEndpoint> endpoints = discoverer.getEndpoints(); Collection<ExposableControllerEndpoint> endpoints = discoverer.getEndpoints();
assertThat(endpoints).hasSize(1); assertThat(endpoints).hasSize(1);
ExposableControllerEndpoint endpoint = endpoints.iterator().next(); ExposableControllerEndpoint endpoint = endpoints.iterator().next();
@ -63,52 +73,82 @@ public class ControllerEndpointDiscovererTests {
assertThat(endpoint.getController()) assertThat(endpoint.getController())
.isInstanceOf(TestControllerEndpoint.class); .isInstanceOf(TestControllerEndpoint.class);
assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class); assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class);
}); }));
}
@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 @Test
public void getEndpointsShouldIncludeRestControllerEndpoints() { public void getEndpointsShouldIncludeRestControllerEndpoints() {
load(TestRestControllerEndpoint.class, (discoverer) -> { this.contextRunner.withUserConfiguration(TestRestControllerEndpoint.class)
.run(assertDiscoverer((discoverer) -> {
Collection<ExposableControllerEndpoint> endpoints = discoverer.getEndpoints(); Collection<ExposableControllerEndpoint> endpoints = discoverer.getEndpoints();
assertThat(endpoints).hasSize(1); assertThat(endpoints).hasSize(1);
ExposableControllerEndpoint endpoint = endpoints.iterator().next(); ExposableControllerEndpoint endpoint = endpoints.iterator().next();
assertThat(endpoint.getId()).isEqualTo("testrestcontroller"); assertThat(endpoint.getId()).isEqualTo("testrestcontroller");
assertThat(endpoint.getController()) assertThat(endpoint.getController())
.isInstanceOf(TestRestControllerEndpoint.class); .isInstanceOf(TestRestControllerEndpoint.class);
}); }));
}
@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 @Test
public void getEndpointsShouldNotDiscoverRegularEndpoints() { public void getEndpointsShouldNotDiscoverRegularEndpoints() {
load(WithRegularEndpointConfiguration.class, (discoverer) -> { this.contextRunner.withUserConfiguration(WithRegularEndpointConfiguration.class)
.run(assertDiscoverer((discoverer) -> {
Collection<ExposableControllerEndpoint> endpoints = discoverer.getEndpoints(); Collection<ExposableControllerEndpoint> endpoints = discoverer.getEndpoints();
List<String> ids = endpoints.stream().map(ExposableEndpoint::getId) List<String> ids = endpoints.stream().map(ExposableEndpoint::getId)
.collect(Collectors.toList()); .collect(Collectors.toList());
assertThat(ids).containsOnly("testcontroller", "testrestcontroller"); assertThat(ids).containsOnly("testcontroller", "testrestcontroller");
}); }));
} }
@Test @Test
public void getEndpointWhenEndpointHasOperationsShouldThrowException() { public void getEndpointWhenEndpointHasOperationsShouldThrowException() {
load(TestControllerWithOperation.class, (discoverer) -> { this.contextRunner.withUserConfiguration(TestControllerWithOperation.class)
.run(assertDiscoverer((discoverer) -> {
this.thrown.expect(IllegalStateException.class); this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage("ControllerEndpoints must not declare operations"); this.thrown.expectMessage("ControllerEndpoints must not declare operations");
discoverer.getEndpoints(); discoverer.getEndpoints();
}); }));
} }
private void load(Class<?> configuration, private ContextConsumer<AssertableApplicationContext> assertDiscoverer(
Consumer<ControllerEndpointDiscoverer> consumer) { Consumer<ControllerEndpointDiscoverer> consumer) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( return (context) -> {
configuration);
try {
ControllerEndpointDiscoverer discoverer = new ControllerEndpointDiscoverer( ControllerEndpointDiscoverer discoverer = new ControllerEndpointDiscoverer(
context, PathMapper.useEndpointId(), Collections.emptyList()); context, PathMapper.useEndpointId(), Collections.emptyList());
consumer.accept(discoverer); consumer.accept(discoverer);
} };
finally {
context.close();
}
} }
@Configuration @Configuration
@ -128,11 +168,23 @@ public class ControllerEndpointDiscovererTests {
} }
@ControllerEndpoint(id = "testcontroller")
@Validated
static class TestProxyControllerEndpoint {
}
@RestControllerEndpoint(id = "testrestcontroller") @RestControllerEndpoint(id = "testrestcontroller")
static class TestRestControllerEndpoint { static class TestRestControllerEndpoint {
} }
@RestControllerEndpoint(id = "testrestcontroller")
@Validated
static class TestProxyRestControllerEndpoint {
}
@Endpoint(id = "test") @Endpoint(id = "test")
static class TestEndpoint { static class TestEndpoint {

@ -40,9 +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.EndpointServlet;
import org.springframework.boot.actuate.endpoint.web.ExposableServletEndpoint; import org.springframework.boot.actuate.endpoint.web.ExposableServletEndpoint;
import org.springframework.boot.actuate.endpoint.web.PathMapper; import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; 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.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.validation.annotation.Validated;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -50,88 +55,108 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link ServletEndpointDiscoverer}. * Tests for {@link ServletEndpointDiscoverer}.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Stephane Nicoll
*/ */
public class ServletEndpointDiscovererTests { public class ServletEndpointDiscovererTests {
@Rule @Rule
public final ExpectedException thrown = ExpectedException.none(); public final ExpectedException thrown = ExpectedException.none();
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();
@Test @Test
public void getEndpointsWhenNoEndpointBeansShouldReturnEmptyCollection() { public void getEndpointsWhenNoEndpointBeansShouldReturnEmptyCollection() {
load(EmptyConfiguration.class, this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
(discoverer) -> assertThat(discoverer.getEndpoints()).isEmpty()); .run(assertDiscoverer((discoverer)
-> assertThat(discoverer.getEndpoints()).isEmpty()));
} }
@Test @Test
public void getEndpointsShouldIncludeServletEndpoints() { public void getEndpointsShouldIncludeServletEndpoints() {
load(TestServletEndpoint.class, (discoverer) -> { this.contextRunner.withUserConfiguration(TestServletEndpoint.class)
.run(assertDiscoverer((discoverer) -> {
Collection<ExposableServletEndpoint> endpoints = discoverer.getEndpoints(); Collection<ExposableServletEndpoint> endpoints = discoverer.getEndpoints();
assertThat(endpoints).hasSize(1); assertThat(endpoints).hasSize(1);
ExposableServletEndpoint endpoint = endpoints.iterator().next(); ExposableServletEndpoint endpoint = endpoints.iterator().next();
assertThat(endpoint.getId()).isEqualTo("testservlet"); assertThat(endpoint.getId()).isEqualTo("testservlet");
assertThat(endpoint.getEndpointServlet()).isNotNull(); assertThat(endpoint.getEndpointServlet()).isNotNull();
assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class); assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class);
}); }));
}
@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 @Test
public void getEndpointsShouldNotDiscoverRegularEndpoints() { public void getEndpointsShouldNotDiscoverRegularEndpoints() {
load(WithRegularEndpointConfiguration.class, (discoverer) -> { this.contextRunner.withUserConfiguration(WithRegularEndpointConfiguration.class)
.run(assertDiscoverer((discoverer) -> {
Collection<ExposableServletEndpoint> endpoints = discoverer.getEndpoints(); Collection<ExposableServletEndpoint> endpoints = discoverer.getEndpoints();
List<String> ids = endpoints.stream().map(ExposableEndpoint::getId) List<String> ids = endpoints.stream().map(ExposableEndpoint::getId)
.collect(Collectors.toList()); .collect(Collectors.toList());
assertThat(ids).containsOnly("testservlet"); assertThat(ids).containsOnly("testservlet");
}); }));
} }
@Test @Test
public void getEndpointWhenEndpointHasOperationsShouldThrowException() { public void getEndpointWhenEndpointHasOperationsShouldThrowException() {
load(TestServletEndpointWithOperation.class, (discoverer) -> { this.contextRunner.withUserConfiguration(TestServletEndpointWithOperation.class)
.run(assertDiscoverer((discoverer) -> {
this.thrown.expect(IllegalStateException.class); this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage("ServletEndpoints must not declare operations"); this.thrown.expectMessage("ServletEndpoints must not declare operations");
discoverer.getEndpoints(); discoverer.getEndpoints();
}); }));
} }
@Test @Test
public void getEndpointWhenEndpointNotASupplierShouldThrowException() { public void getEndpointWhenEndpointNotASupplierShouldThrowException() {
load(TestServletEndpointNotASupplier.class, (discoverer) -> { this.contextRunner.withUserConfiguration(TestServletEndpointNotASupplier.class)
.run(assertDiscoverer((discoverer) -> {
this.thrown.expect(IllegalStateException.class); this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage("must be a supplier"); this.thrown.expectMessage("must be a supplier");
discoverer.getEndpoints(); discoverer.getEndpoints();
}); }));
} }
@Test @Test
public void getEndpointWhenEndpointSuppliesWrongTypeShouldThrowException() { public void getEndpointWhenEndpointSuppliesWrongTypeShouldThrowException() {
load(TestServletEndpointSupplierOfWrongType.class, (discoverer) -> { this.contextRunner
.withUserConfiguration(TestServletEndpointSupplierOfWrongType.class)
.run(assertDiscoverer((discoverer) -> {
this.thrown.expect(IllegalStateException.class); this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage("must supply an EndpointServlet"); this.thrown.expectMessage("must supply an EndpointServlet");
discoverer.getEndpoints(); discoverer.getEndpoints();
}); }));
} }
@Test @Test
public void getEndpointWhenEndpointSuppliesNullShouldThrowException() { public void getEndpointWhenEndpointSuppliesNullShouldThrowException() {
load(TestServletEndpointSupplierOfNull.class, (discoverer) -> { this.contextRunner.withUserConfiguration(TestServletEndpointSupplierOfNull.class)
.run(assertDiscoverer((discoverer) -> {
this.thrown.expect(IllegalStateException.class); this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage("must not supply null"); this.thrown.expectMessage("must not supply null");
discoverer.getEndpoints(); discoverer.getEndpoints();
}); }));
} }
private void load(Class<?> configuration, private ContextConsumer<AssertableApplicationContext> assertDiscoverer(
Consumer<ServletEndpointDiscoverer> consumer) { Consumer<ServletEndpointDiscoverer> consumer) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( return (context) -> {
configuration);
try {
ServletEndpointDiscoverer discoverer = new ServletEndpointDiscoverer(context, ServletEndpointDiscoverer discoverer = new ServletEndpointDiscoverer(context,
PathMapper.useEndpointId(), Collections.emptyList()); PathMapper.useEndpointId(), Collections.emptyList());
consumer.accept(discoverer); consumer.accept(discoverer);
} };
finally {
context.close();
}
} }
@Configuration @Configuration
@ -155,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") @Endpoint(id = "test")
static class TestEndpoint { static class TestEndpoint {

Loading…
Cancel
Save