Skip to content

Commit 4c446c3

Browse files
committed
Only add management error page for Spring MVC
Move management `ErrorPage` registration from the `WebMvcEndpointChildContextConfiguration` to `WebMvcEndpointChildContextConfiguration` and only add it when the error controller is registered. Fixes gh-17938
1 parent 8a879dd commit 4c446c3

File tree

3 files changed

+113
-2
lines changed

3 files changed

+113
-2
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementWebServerFactoryCustomizer.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import org.springframework.boot.autoconfigure.web.ServerProperties;
2929
import org.springframework.boot.util.LambdaSafe;
3030
import org.springframework.boot.web.server.ConfigurableWebServerFactory;
31-
import org.springframework.boot.web.server.ErrorPage;
3231
import org.springframework.boot.web.server.Ssl;
3332
import org.springframework.boot.web.server.WebServerFactory;
3433
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
@@ -107,7 +106,6 @@ protected void customize(T factory, ManagementServerProperties managementServerP
107106
}
108107
factory.setServerHeader(serverProperties.getServerHeader());
109108
factory.setAddress(managementServerProperties.getAddress());
110-
factory.addErrorPages(new ErrorPage(serverProperties.getError().getPath()));
111109
}
112110

113111
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/WebMvcEndpointChildContextConfiguration.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,16 @@
2424
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
2525
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
2626
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
27+
import org.springframework.boot.autoconfigure.web.ServerProperties;
2728
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
2829
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
30+
import org.springframework.boot.web.server.ErrorPage;
31+
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
2932
import org.springframework.boot.web.servlet.error.ErrorAttributes;
3033
import org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter;
34+
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
3135
import org.springframework.context.annotation.Bean;
36+
import org.springframework.core.Ordered;
3237
import org.springframework.web.context.request.RequestContextListener;
3338
import org.springframework.web.filter.RequestContextFilter;
3439
import org.springframework.web.servlet.DispatcherServlet;
@@ -59,6 +64,12 @@ public ManagementErrorEndpoint errorEndpoint(ErrorAttributes errorAttributes) {
5964
return new ManagementErrorEndpoint(errorAttributes);
6065
}
6166

67+
@Bean
68+
@ConditionalOnBean(ErrorAttributes.class)
69+
public ManagementErrorPageCustomizer managementErrorPageCustomizer(ServerProperties serverProperties) {
70+
return new ManagementErrorPageCustomizer(serverProperties);
71+
}
72+
6273
@Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
6374
public DispatcherServlet dispatcherServlet() {
6475
DispatcherServlet dispatcherServlet = new DispatcherServlet();
@@ -96,4 +107,29 @@ public RequestContextFilter requestContextFilter() {
96107
return new OrderedRequestContextFilter();
97108
}
98109

110+
/**
111+
* {@link WebServerFactoryCustomizer} to add an {@link ErrorPage} so that the
112+
* {@link ManagementErrorEndpoint} can be used.
113+
*/
114+
private static class ManagementErrorPageCustomizer
115+
implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {
116+
117+
private final ServerProperties properties;
118+
119+
ManagementErrorPageCustomizer(ServerProperties properties) {
120+
this.properties = properties;
121+
}
122+
123+
@Override
124+
public void customize(ConfigurableServletWebServerFactory factory) {
125+
factory.addErrorPages(new ErrorPage(this.properties.getError().getPath()));
126+
}
127+
128+
@Override
129+
public int getOrder() {
130+
return 0;
131+
}
132+
133+
}
134+
99135
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2012-2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.web.servlet;
18+
19+
import org.junit.Test;
20+
21+
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
22+
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration;
23+
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration;
24+
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
25+
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
26+
import org.springframework.boot.autoconfigure.AutoConfigurations;
27+
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
28+
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
29+
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
30+
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
31+
import org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer;
32+
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
33+
import org.springframework.http.MediaType;
34+
import org.springframework.stereotype.Component;
35+
import org.springframework.web.reactive.function.client.ClientResponse;
36+
import org.springframework.web.reactive.function.client.WebClient;
37+
38+
import static org.assertj.core.api.Assertions.assertThat;
39+
40+
/**
41+
* Integration tests for {@link WebMvcEndpointChildContextConfiguration}.
42+
*
43+
* @author Phillip Webb
44+
*/
45+
public class WebMvcEndpointChildContextConfigurationIntegrationTests {
46+
47+
@Test // gh-17938
48+
public void errorPageAndErrorControllerAreUsed() {
49+
new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new)
50+
.withConfiguration(AutoConfigurations.of(ManagementContextAutoConfiguration.class,
51+
ServletWebServerFactoryAutoConfiguration.class, ServletManagementContextAutoConfiguration.class,
52+
WebEndpointAutoConfiguration.class, EndpointAutoConfiguration.class,
53+
DispatcherServletAutoConfiguration.class, ErrorMvcAutoConfiguration.class))
54+
.withUserConfiguration(FailingEndpoint.class)
55+
.withInitializer(new ServerPortInfoApplicationContextInitializer()).withPropertyValues("server.port=0",
56+
"management.server.port=0", "management.endpoints.web.exposure.include=*")
57+
.run((context) -> {
58+
String port = context.getEnvironment().getProperty("local.management.port");
59+
WebClient client = WebClient.create("http://localhost:" + port);
60+
ClientResponse response = client.get().uri("actuator/fail").accept(MediaType.APPLICATION_JSON)
61+
.exchange().block();
62+
assertThat(response.bodyToMono(String.class).block()).contains("message\":\"Epic Fail");
63+
});
64+
}
65+
66+
@Component
67+
@Endpoint(id = "fail")
68+
public static class FailingEndpoint {
69+
70+
@ReadOperation
71+
public String fail() {
72+
throw new IllegalStateException("Epic Fail");
73+
}
74+
75+
}
76+
77+
}

0 commit comments

Comments
 (0)