diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/BasicErrorController.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/BasicErrorController.java index d119addb1a..a4882d7a88 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/BasicErrorController.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/BasicErrorController.java @@ -43,6 +43,7 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver; import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver; /** @@ -65,6 +66,8 @@ public class BasicErrorController implements ErrorController { private DefaultHandlerExceptionResolver resolver = new DefaultHandlerExceptionResolver(); + private ResponseStatusExceptionResolver statuses = new ResponseStatusExceptionResolver(); + @Value("${error.path:/error}") private String errorPath; @@ -76,7 +79,9 @@ public class BasicErrorController implements ErrorController { @ExceptionHandler(Exception.class) public void handle(HttpServletRequest request, HttpServletResponse response, Exception e) throws Exception { - this.resolver.resolveException(request, response, null, e); + if (this.statuses.resolveException(request, response, null, e) == null) { + this.resolver.resolveException(request, response, null, e); + } if (response.getStatus() == HttpServletResponse.SC_OK) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/BasicErrorControllerIntegrationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/BasicErrorControllerIntegrationTests.java index ef24c20565..ab9fc2e191 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/BasicErrorControllerIntegrationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/BasicErrorControllerIntegrationTests.java @@ -36,6 +36,7 @@ import org.springframework.boot.autoconfigure.web.BasicErrorControllerIntegratio import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.test.annotation.DirtiesContext; @@ -47,6 +48,7 @@ import org.springframework.test.web.servlet.RequestBuilder; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.validation.BindException; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.View; @@ -93,6 +95,16 @@ public class BasicErrorControllerIntegrationTests { assertTrue("Wrong content: " + content, content.contains("Expected!")); } + @Test + public void testErrorWithResponseStatus() throws Exception { + MvcResult result = this.mockMvc.perform(get("/bang")) + .andExpect(status().isNotFound()).andReturn(); + MvcResult response = this.mockMvc.perform(new ErrorDispatcher(result, "/error")) + .andReturn(); + String content = response.getResponse().getContentAsString(); + assertTrue("Wrong content: " + content, content.contains("Expected!")); + } + @Test public void testBindingExceptionForMachineClient() throws Exception { // In a real container the response is carried over into the error dispatcher, but @@ -151,6 +163,11 @@ public class BasicErrorControllerIntegrationTests { throw new IllegalStateException("Expected!"); } + @RequestMapping("/bang") + public String bang() { + throw new NotFoundException("Expected!"); + } + @RequestMapping("/bind") public String bind() throws Exception { BindException error = new BindException(this, "test"); @@ -162,6 +179,15 @@ public class BasicErrorControllerIntegrationTests { } + @ResponseStatus(value = HttpStatus.NOT_FOUND) + private static class NotFoundException extends RuntimeException { + + public NotFoundException(String string) { + super(string); + } + + } + private class ErrorDispatcher implements RequestBuilder { private MvcResult result;