diff --git a/core/spring-boot/src/main/java/org/springframework/boot/web/servlet/support/ErrorPageFilterConfiguration.java b/core/spring-boot/src/main/java/org/springframework/boot/web/servlet/support/ErrorPageFilterConfiguration.java index d980979368d..c478dbfc646 100644 --- a/core/spring-boot/src/main/java/org/springframework/boot/web/servlet/support/ErrorPageFilterConfiguration.java +++ b/core/spring-boot/src/main/java/org/springframework/boot/web/servlet/support/ErrorPageFilterConfiguration.java @@ -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(); + } + } diff --git a/core/spring-boot/src/test/java/org/springframework/boot/web/servlet/support/SpringBootServletInitializerTests.java b/core/spring-boot/src/test/java/org/springframework/boot/web/servlet/support/SpringBootServletInitializerTests.java index 5c86176f922..cdb4904908f 100644 --- a/core/spring-boot/src/test/java/org/springframework/boot/web/servlet/support/SpringBootServletInitializerTests.java +++ b/core/spring-boot/src/test/java/org/springframework/boot/web/servlet/support/SpringBootServletInitializerTests.java @@ -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 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 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 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 { diff --git a/system-test/spring-boot-deployment-system-tests/src/systemTest/java/org/springframework/boot/deployment/AbstractDeploymentTests.java b/system-test/spring-boot-deployment-system-tests/src/systemTest/java/org/springframework/boot/deployment/AbstractDeploymentTests.java index 51a7477f10e..4d6677f388e 100644 --- a/system-test/spring-boot-deployment-system-tests/src/systemTest/java/org/springframework/boot/deployment/AbstractDeploymentTests.java +++ b/system-test/spring-boot-deployment-system-tests/src/systemTest/java/org/springframework/boot/deployment/AbstractDeploymentTests.java @@ -56,6 +56,14 @@ abstract class AbstractDeploymentTests { }); } + @Test + void errorPage() { + getDeployedApplication().test((rest) -> { + ResponseEntity response = rest.getForEntity("/does-not-exist", String.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); + }); + } + @Test void health() { getDeployedApplication().test((rest) -> {