Commit 86cd7275 authored by Madhura Bhave's avatar Madhura Bhave

MVC endpoints bean methods are @ConditionalOnMissingBean

Fixes gh-10105
parent beb257f4
......@@ -111,8 +111,9 @@ public class EndpointWebMvcHypermediaManagementContextConfiguration {
};
}
@ConditionalOnEnabledEndpoint("actuator")
@Bean
@ConditionalOnEnabledEndpoint("actuator")
@ConditionalOnMissingBean
public HalJsonMvcEndpoint halJsonMvcEndpoint(
ManagementServletContext managementServletContext,
ResourceProperties resources, ResourceLoader resourceLoader) {
......@@ -137,6 +138,7 @@ public class EndpointWebMvcHypermediaManagementContextConfiguration {
static class DocsMvcEndpointConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint("docs")
@ConditionalOnResource(resources = "classpath:/META-INF/resources/spring-boot-actuator/docs/index.html")
public DocsMvcEndpoint docsMvcEndpoint(
......
......@@ -143,6 +143,7 @@ public class EndpointWebMvcManagementContextConfiguration {
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(EnvironmentEndpoint.class)
@ConditionalOnEnabledEndpoint("env")
public EnvironmentMvcEndpoint environmentMvcEndpoint(EnvironmentEndpoint delegate) {
......@@ -173,6 +174,7 @@ public class EndpointWebMvcManagementContextConfiguration {
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(LoggersEndpoint.class)
@ConditionalOnEnabledEndpoint("loggers")
public LoggersMvcEndpoint loggersMvcEndpoint(LoggersEndpoint delegate) {
......@@ -180,6 +182,7 @@ public class EndpointWebMvcManagementContextConfiguration {
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(MetricsEndpoint.class)
@ConditionalOnEnabledEndpoint("metrics")
public MetricsMvcEndpoint metricsMvcEndpoint(MetricsEndpoint delegate) {
......@@ -187,6 +190,7 @@ public class EndpointWebMvcManagementContextConfiguration {
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint("logfile")
@Conditional(LogFileCondition.class)
public LogFileMvcEndpoint logfileMvcEndpoint() {
......@@ -194,6 +198,7 @@ public class EndpointWebMvcManagementContextConfiguration {
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(ShutdownEndpoint.class)
@ConditionalOnEnabledEndpoint(value = "shutdown", enabledByDefault = false)
public ShutdownMvcEndpoint shutdownMvcEndpoint(ShutdownEndpoint delegate) {
......@@ -201,6 +206,7 @@ public class EndpointWebMvcManagementContextConfiguration {
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(AuditEventRepository.class)
@ConditionalOnEnabledEndpoint("auditevents")
public AuditEventsMvcEndpoint auditEventMvcEndpoint(
......
......@@ -45,6 +45,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link EndpointWebMvcHypermediaManagementContextConfiguration}.
*
* @author Andy Wilkinson
* @author Madhura Bhave
*/
public class EndpointWebMvcHypermediaManagementContextConfigurationTests {
......@@ -112,7 +113,38 @@ public class EndpointWebMvcHypermediaManagementContextConfigurationTests {
.isEqualTo("http://localhost/docs/#spring_boot_actuator__{rel}");
}
@Test
public void halJsonMvcEndpointIsConditionalOnMissingBean() throws Exception {
createContext();
this.context.register(HalJsonConfiguration.class, TestConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
EndpointWebMvcHypermediaManagementContextConfiguration.class);
this.context.refresh();
HalJsonMvcEndpoint bean = this.context.getBean(HalJsonMvcEndpoint.class);
assertThat(bean).isInstanceOf(TestHalJsonMvcEndpoint.class);
}
@Test
public void docsMvcEndpointIsConditionalOnMissingBean() throws Exception {
createContext();
this.context.register(DocsConfiguration.class, TestConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
EndpointWebMvcHypermediaManagementContextConfiguration.class);
this.context.refresh();
DocsMvcEndpoint bean = this.context.getBean(DocsMvcEndpoint.class);
assertThat(bean).isInstanceOf(TestDocsMvcEndpoint.class);
}
private void load(String... properties) {
createContext();
EnvironmentTestUtils.addEnvironment(this.context, properties);
this.context.register(TestConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
EndpointWebMvcHypermediaManagementContextConfiguration.class);
this.context.refresh();
}
private void createContext() {
this.context = new AnnotationConfigWebApplicationContext();
this.context.setClassLoader(new ClassLoader(getClass().getClassLoader()) {
......@@ -126,11 +158,6 @@ public class EndpointWebMvcHypermediaManagementContextConfigurationTests {
}
});
EnvironmentTestUtils.addEnvironment(this.context, properties);
this.context.register(TestConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
EndpointWebMvcHypermediaManagementContextConfiguration.class);
this.context.refresh();
}
private String getCurieHref() {
......@@ -152,4 +179,40 @@ public class EndpointWebMvcHypermediaManagementContextConfigurationTests {
}
@Configuration
static class DocsConfiguration {
@Bean
public DocsMvcEndpoint testDocsMvcEndpoint(ManagementServletContext managementServletContext) {
return new TestDocsMvcEndpoint(managementServletContext);
}
}
@Configuration
static class HalJsonConfiguration {
@Bean
public HalJsonMvcEndpoint testHalJsonMvcEndpoint(ManagementServletContext managementServletContext) {
return new TestHalJsonMvcEndpoint(managementServletContext);
}
}
static class TestDocsMvcEndpoint extends DocsMvcEndpoint {
TestDocsMvcEndpoint(ManagementServletContext managementServletContext) {
super(managementServletContext);
}
}
static class TestHalJsonMvcEndpoint extends HalJsonMvcEndpoint {
TestHalJsonMvcEndpoint(ManagementServletContext managementServletContext) {
super(managementServletContext);
}
}
}
......@@ -16,21 +16,43 @@
package org.springframework.boot.actuate.autoconfigure;
import java.security.Principal;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.actuate.audit.AuditEventRepository;
import org.springframework.boot.actuate.audit.InMemoryAuditEventRepository;
import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint;
import org.springframework.boot.actuate.endpoint.HealthEndpoint;
import org.springframework.boot.actuate.endpoint.LoggersEndpoint;
import org.springframework.boot.actuate.endpoint.MetricsEndpoint;
import org.springframework.boot.actuate.endpoint.ShutdownEndpoint;
import org.springframework.boot.actuate.endpoint.mvc.AuditEventsMvcEndpoint;
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
import org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint;
import org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint;
import org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint;
import org.springframework.boot.actuate.endpoint.mvc.LogFileMvcEndpoint;
import org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint;
import org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpointSecurityInterceptor;
import org.springframework.boot.actuate.endpoint.mvc.ShutdownMvcEndpoint;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration;
import org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration;
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
......@@ -50,14 +72,6 @@ public class EndpointWebMvcManagementContextConfigurationTests {
public void setup() {
this.context = new AnnotationConfigWebApplicationContext();
this.context.setServletContext(new MockServletContext());
this.context.register(SecurityAutoConfiguration.class,
WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
EndpointAutoConfiguration.class, EndpointWebMvcAutoConfiguration.class,
ManagementServerPropertiesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
WebClientAutoConfiguration.class,
EndpointWebMvcManagementContextConfiguration.class);
}
@After
......@@ -72,6 +86,7 @@ public class EndpointWebMvcManagementContextConfigurationTests {
EnvironmentTestUtils.addEnvironment(this.context,
"management.security.enabled=false",
"management.security.roles=my-role,your-role");
this.context.register(TestEndpointConfiguration.class);
this.context.refresh();
EndpointHandlerMapping mapping = this.context.getBean("endpointHandlerMapping",
EndpointHandlerMapping.class);
......@@ -84,9 +99,237 @@ public class EndpointWebMvcManagementContextConfigurationTests {
assertThat(roles).containsExactly("my-role", "your-role");
}
@Test
public void healthMvcEndpointIsConditionalOnMissingBean() throws Exception {
this.context.register(HealthConfiguration.class, TestEndpointConfiguration.class);
this.context.refresh();
HealthMvcEndpoint mvcEndpoint = this.context.getBean(HealthMvcEndpoint.class);
assertThat(mvcEndpoint).isInstanceOf(TestHealthMvcEndpoint.class);
}
@Test
public void envMvcEndpointIsConditionalOnMissingBean() throws Exception {
this.context.register(EnvConfiguration.class, TestEndpointConfiguration.class);
this.context.refresh();
EnvironmentMvcEndpoint mvcEndpoint = this.context.getBean(EnvironmentMvcEndpoint.class);
assertThat(mvcEndpoint).isInstanceOf(TestEnvMvcEndpoint.class);
}
@Test
public void metricsMvcEndpointIsConditionalOnMissingBean() throws Exception {
this.context.register(MetricsConfiguration.class, TestEndpointConfiguration.class);
this.context.refresh();
MetricsMvcEndpoint mvcEndpoint = this.context.getBean(MetricsMvcEndpoint.class);
assertThat(mvcEndpoint).isInstanceOf(TestMetricsMvcEndpoint.class);
}
@Test
public void logFileMvcEndpointIsConditionalOnMissingBean() throws Exception {
this.context.register(LogFileConfiguration.class, TestEndpointConfiguration.class);
this.context.refresh();
LogFileMvcEndpoint mvcEndpoint = this.context.getBean(LogFileMvcEndpoint.class);
assertThat(mvcEndpoint).isInstanceOf(TestLogFileMvcEndpoint.class);
}
@Test
public void shutdownEndpointIsConditionalOnMissingBean() throws Exception {
this.context.register(ShutdownConfiguration.class, TestEndpointConfiguration.class);
this.context.refresh();
ShutdownMvcEndpoint mvcEndpoint = this.context.getBean(ShutdownMvcEndpoint.class);
assertThat(mvcEndpoint).isInstanceOf(TestShutdownMvcEndpoint.class);
}
@Test
public void auditEventsMvcEndpointIsConditionalOnMissingBean() throws Exception {
this.context.register(AuditEventsConfiguration.class, TestEndpointConfiguration.class);
this.context.refresh();
AuditEventsMvcEndpoint mvcEndpoint = this.context.getBean(AuditEventsMvcEndpoint.class);
assertThat(mvcEndpoint).isInstanceOf(TestAuditEventsMvcEndpoint.class);
}
@Test
public void loggersMvcEndpointIsConditionalOnMissingBean() throws Exception {
this.context.register(LoggersConfiguration.class, TestEndpointConfiguration.class);
this.context.refresh();
LoggersMvcEndpoint mvcEndpoint = this.context.getBean(LoggersMvcEndpoint.class);
assertThat(mvcEndpoint).isInstanceOf(TestLoggersMvcEndpoint.class);
}
@Test
public void heapdumpMvcEndpointIsConditionalOnMissingBean() throws Exception {
this.context.register(HeapdumpConfiguration.class, TestEndpointConfiguration.class);
this.context.refresh();
HeapdumpMvcEndpoint mvcEndpoint = this.context.getBean(HeapdumpMvcEndpoint.class);
assertThat(mvcEndpoint).isInstanceOf(TestHeapdumpMvcEndpoint.class);
}
@SuppressWarnings("unchecked")
private List<String> getRoles(MvcEndpointSecurityInterceptor securityInterceptor) {
return (List<String>) ReflectionTestUtils.getField(securityInterceptor, "roles");
}
@Configuration
@ImportAutoConfiguration({ SecurityAutoConfiguration.class,
WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
EndpointAutoConfiguration.class, EndpointWebMvcAutoConfiguration.class,
ManagementServerPropertiesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
WebClientAutoConfiguration.class,
EndpointWebMvcManagementContextConfiguration.class })
static class TestEndpointConfiguration {
}
@Configuration
static class HealthConfiguration {
@Bean
public HealthMvcEndpoint testHealthMvcEndpoint(HealthEndpoint endpoint) {
return new TestHealthMvcEndpoint(endpoint);
}
}
static class EnvConfiguration {
@Bean
public EnvironmentMvcEndpoint testEnvironmentMvcEndpoint(EnvironmentEndpoint endpoint) {
return new TestEnvMvcEndpoint(endpoint);
}
}
static class MetricsConfiguration {
@Bean
public MetricsMvcEndpoint testMetricsMvcEndpoint(MetricsEndpoint endpoint) {
return new TestMetricsMvcEndpoint(endpoint);
}
}
static class LoggersConfiguration {
@Bean
public LoggersMvcEndpoint testLoggersMvcEndpoint(LoggersEndpoint endpoint) {
return new TestLoggersMvcEndpoint(endpoint);
}
@Bean
LoggersEndpoint loggersEndpoint() {
return new LoggersEndpoint(new LoggingSystem() {
@Override
public void beforeInitialize() {
}
});
}
}
static class LogFileConfiguration {
@Bean
public LogFileMvcEndpoint testLogFileMvcEndpoint() {
return new TestLogFileMvcEndpoint();
}
}
static class AuditEventsConfiguration {
@Bean
public AuditEventRepository repository() {
return new TestAuditEventRepository();
}
@Bean
public AuditEventsMvcEndpoint testAuditEventsMvcEndpoint(AuditEventRepository repository) {
return new TestAuditEventsMvcEndpoint(repository);
}
}
static class TestAuditEventRepository extends InMemoryAuditEventRepository {
}
static class HeapdumpConfiguration {
@Bean
public HeapdumpMvcEndpoint testHeapdumpMvcEndpoint() {
return new TestHeapdumpMvcEndpoint();
}
}
static class ShutdownConfiguration {
@Bean
public ShutdownMvcEndpoint testShutdownMvcEndpoint(ShutdownEndpoint endpoint) {
return new TestShutdownMvcEndpoint(endpoint);
}
}
static class TestHealthMvcEndpoint extends HealthMvcEndpoint {
TestHealthMvcEndpoint(HealthEndpoint delegate) {
super(delegate);
}
@Override
protected boolean exposeHealthDetails(HttpServletRequest request,
Principal principal) {
return true;
}
}
static class TestEnvMvcEndpoint extends EnvironmentMvcEndpoint {
TestEnvMvcEndpoint(EnvironmentEndpoint delegate) {
super(delegate);
}
}
static class TestLoggersMvcEndpoint extends LoggersMvcEndpoint {
TestLoggersMvcEndpoint(LoggersEndpoint delegate) {
super(delegate);
}
}
static class TestHeapdumpMvcEndpoint extends HeapdumpMvcEndpoint {
}
static class TestLogFileMvcEndpoint extends LogFileMvcEndpoint {
}
static class TestMetricsMvcEndpoint extends MetricsMvcEndpoint {
TestMetricsMvcEndpoint(MetricsEndpoint delegate) {
super(delegate);
}
}
static class TestAuditEventsMvcEndpoint extends AuditEventsMvcEndpoint {
TestAuditEventsMvcEndpoint(AuditEventRepository auditEventRepository) {
super(auditEventRepository);
}
}
static class TestShutdownMvcEndpoint extends ShutdownMvcEndpoint {
TestShutdownMvcEndpoint(ShutdownEndpoint delegate) {
super(delegate);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment