Commit 59a899a4 authored by Dave Syer's avatar Dave Syer

Add @ResponseStatus handler to global exception handler

We might need to revisit this to allow more fine-grained
control by users, but it seems like a sensible default.
The BasicErrorController now uses both of the deafult strategies
(ResponseStatusExceptionResolver and DefaultHandlerExceptionResolver)
from Spring MVC to try and determine an appropriate response.

Fixes gh-839
parent e7484c66
...@@ -43,6 +43,7 @@ import org.springframework.web.bind.annotation.ResponseBody; ...@@ -43,6 +43,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver; import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
/** /**
...@@ -65,6 +66,8 @@ public class BasicErrorController implements ErrorController { ...@@ -65,6 +66,8 @@ public class BasicErrorController implements ErrorController {
private DefaultHandlerExceptionResolver resolver = new DefaultHandlerExceptionResolver(); private DefaultHandlerExceptionResolver resolver = new DefaultHandlerExceptionResolver();
private ResponseStatusExceptionResolver statuses = new ResponseStatusExceptionResolver();
@Value("${error.path:/error}") @Value("${error.path:/error}")
private String errorPath; private String errorPath;
...@@ -76,7 +79,9 @@ public class BasicErrorController implements ErrorController { ...@@ -76,7 +79,9 @@ public class BasicErrorController implements ErrorController {
@ExceptionHandler(Exception.class) @ExceptionHandler(Exception.class)
public void handle(HttpServletRequest request, HttpServletResponse response, public void handle(HttpServletRequest request, HttpServletResponse response,
Exception e) throws Exception { 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) { if (response.getStatus() == HttpServletResponse.SC_OK) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} }
......
...@@ -36,6 +36,7 @@ import org.springframework.boot.autoconfigure.web.BasicErrorControllerIntegratio ...@@ -36,6 +36,7 @@ import org.springframework.boot.autoconfigure.web.BasicErrorControllerIntegratio
import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext;
...@@ -47,6 +48,7 @@ import org.springframework.test.web.servlet.RequestBuilder; ...@@ -47,6 +48,7 @@ import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.validation.BindException; import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.RequestMapping; 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.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.View; import org.springframework.web.servlet.View;
...@@ -93,6 +95,16 @@ public class BasicErrorControllerIntegrationTests { ...@@ -93,6 +95,16 @@ public class BasicErrorControllerIntegrationTests {
assertTrue("Wrong content: " + content, content.contains("Expected!")); 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 @Test
public void testBindingExceptionForMachineClient() throws Exception { public void testBindingExceptionForMachineClient() throws Exception {
// In a real container the response is carried over into the error dispatcher, but // In a real container the response is carried over into the error dispatcher, but
...@@ -151,6 +163,11 @@ public class BasicErrorControllerIntegrationTests { ...@@ -151,6 +163,11 @@ public class BasicErrorControllerIntegrationTests {
throw new IllegalStateException("Expected!"); throw new IllegalStateException("Expected!");
} }
@RequestMapping("/bang")
public String bang() {
throw new NotFoundException("Expected!");
}
@RequestMapping("/bind") @RequestMapping("/bind")
public String bind() throws Exception { public String bind() throws Exception {
BindException error = new BindException(this, "test"); BindException error = new BindException(this, "test");
...@@ -162,6 +179,15 @@ public class BasicErrorControllerIntegrationTests { ...@@ -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 class ErrorDispatcher implements RequestBuilder {
private MvcResult result; private MvcResult result;
......
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