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
This commit is contained in:
parent
e7484c66f5
commit
59a899a4da
|
|
@ -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 {
|
||||||
|
|
||||||
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 {
|
||||||
@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
|
||||||
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;
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue