Merge branch '4.0.x'

Closes gh-49380
This commit is contained in:
Stéphane Nicoll
2026-03-03 10:41:35 +01:00
3 changed files with 41 additions and 15 deletions
@@ -18,6 +18,7 @@ package org.springframework.boot.web.servlet.support;
import jakarta.servlet.DispatcherType;
import org.springframework.boot.web.error.ErrorPageRegistrarBeanPostProcessor;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -26,6 +27,7 @@ import org.springframework.context.annotation.Configuration;
* Configuration for {@link ErrorPageFilter}.
*
* @author Andy Wilkinson
* @author Jay Choi
*/
@Configuration(proxyBeanMethods = false)
class ErrorPageFilterConfiguration {
@@ -43,4 +45,9 @@ class ErrorPageFilterConfiguration {
return registration;
}
@Bean
static ErrorPageRegistrarBeanPostProcessor errorPageRegistrarBeanPostProcessor() {
return new ErrorPageRegistrarBeanPostProcessor();
}
}
@@ -35,12 +35,14 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.springframework.boot.DefaultApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.logging.LoggingApplicationListener;
import org.springframework.boot.testsupport.system.CapturedOutput;
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
import org.springframework.boot.web.error.ErrorPageRegistrarBeanPostProcessor;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
@@ -66,6 +68,7 @@ import static org.mockito.Mockito.mock;
*
* @author Phillip Webb
* @author Andy Wilkinson
* @author Jay Choi
*/
@ExtendWith(OutputCaptureExtension.class)
class SpringBootServletInitializerTests {
@@ -130,8 +133,21 @@ class SpringBootServletInitializerTests {
try (AbstractApplicationContext context = (AbstractApplicationContext) new WithErrorPageFilterNotRegistered()
.createRootApplicationContext(this.servletContext)) {
assertThat(context).isNotNull();
Map<String, ErrorPageFilter> errorPageFilterBeans = context.getBeansOfType(ErrorPageFilter.class);
assertThat(errorPageFilterBeans).isEmpty();
assertThat(context.getBeansOfType(ErrorPageFilter.class)).isEmpty();
assertThat(context.getBeansOfType(ErrorPageRegistrarBeanPostProcessor.class)).isEmpty();
}
}
@Test
void errorPageRegistrarBeanPostProcessorIsRegistered() {
ServletContext servletContext = mock(ServletContext.class);
given(servletContext.addFilter(any(), any(Filter.class))).willReturn(mock(Dynamic.class));
given(servletContext.getInitParameterNames()).willReturn(Collections.emptyEnumeration());
given(servletContext.getAttributeNames()).willReturn(Collections.emptyEnumeration());
try (AbstractApplicationContext context = (AbstractApplicationContext) new DefaultSpringBootServletInitializer()
.createRootApplicationContext(servletContext)) {
assertThat(context).isNotNull();
assertThat(context.getBeansOfType(ErrorPageRegistrarBeanPostProcessor.class)).hasSize(1);
}
}
@@ -142,7 +158,7 @@ class SpringBootServletInitializerTests {
given(servletContext.addFilter(any(), any(Filter.class))).willReturn(mock(Dynamic.class));
given(servletContext.getInitParameterNames()).willReturn(Collections.emptyEnumeration());
given(servletContext.getAttributeNames()).willReturn(Collections.emptyEnumeration());
try (AbstractApplicationContext context = (AbstractApplicationContext) new WithErrorPageFilter()
try (AbstractApplicationContext context = (AbstractApplicationContext) new DefaultSpringBootServletInitializer()
.createRootApplicationContext(servletContext)) {
assertThat(context).isNotNull();
Map<String, FilterRegistrationBean> registrations = context.getBeansOfType(FilterRegistrationBean.class);
@@ -160,7 +176,7 @@ class SpringBootServletInitializerTests {
given(servletContext.addFilter(any(), any(Filter.class))).willReturn(mock(Dynamic.class));
given(servletContext.getInitParameterNames()).willReturn(Collections.emptyEnumeration());
given(servletContext.getAttributeNames()).willReturn(Collections.emptyEnumeration());
try (AbstractApplicationContext context = (AbstractApplicationContext) new WithErrorPageFilter()
try (AbstractApplicationContext context = (AbstractApplicationContext) new DefaultSpringBootServletInitializer()
.createRootApplicationContext(servletContext)) {
assertThat(context).isNotNull();
Map<String, FilterRegistrationBean> registrations = context.getBeansOfType(FilterRegistrationBean.class);
@@ -173,7 +189,7 @@ class SpringBootServletInitializerTests {
@Test
void executableWarThatUsesServletInitializerDoesNotHaveErrorPageFilterConfigured() {
try (ConfigurableApplicationContext context = new SpringApplication(ExecutableWar.class).run()) {
try (ConfigurableApplicationContext context = new SpringApplication(DefaultApplicationArguments.class).run()) {
assertThat(context.getBeansOfType(ErrorPageFilter.class)).isEmpty();
}
}
@@ -322,6 +338,11 @@ class SpringBootServletInitializerTests {
}
@Configuration(proxyBeanMethods = false)
static class DefaultSpringBootServletInitializer extends SpringBootServletInitializer {
}
@Configuration(proxyBeanMethods = false)
static class WithErrorPageFilterNotRegistered extends SpringBootServletInitializer {
@@ -331,16 +352,6 @@ class SpringBootServletInitializerTests {
}
@Configuration(proxyBeanMethods = false)
static class WithErrorPageFilter extends SpringBootServletInitializer {
}
@Configuration(proxyBeanMethods = false)
static class ExecutableWar extends SpringBootServletInitializer {
}
@Configuration(proxyBeanMethods = false)
static class Config {
@@ -56,6 +56,14 @@ abstract class AbstractDeploymentTests {
});
}
@Test
void errorPage() {
getDeployedApplication().test((rest) -> {
ResponseEntity<String> response = rest.getForEntity("/does-not-exist", String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
});
}
@Test
void health() {
getDeployedApplication().test((rest) -> {