Respect ModelAndView.status in @ExceptionHandler

Issue: SPR-14006
This commit is contained in:
Rossen Stoyanchev 2016-10-24 15:59:54 +01:00
parent aea3a75018
commit efe3996cf9
3 changed files with 34 additions and 2 deletions

View File

@ -127,7 +127,8 @@ public class ModelAndView {
* @param model Map of model names (Strings) to model objects
* (Objects). Model entries may not be {@code null}, but the
* model Map may be {@code null} if there is no model data.
* @param status an alternative status code to use for the response.
* @param status an alternative status code to use for the response;
* The response status is set just prior to View rendering.
* @since 4.3
*/
public ModelAndView(String viewName, Map<String, ?> model, HttpStatus status) {
@ -240,6 +241,7 @@ public class ModelAndView {
/**
* Set the HTTP status to use for the response.
* <p>The response status is set just prior to View rendering.
* @since 4.3
*/
public void setStatus(HttpStatus status) {

View File

@ -32,11 +32,13 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.ui.ModelMap;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.ServletWebRequest;
@ -390,7 +392,9 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
return new ModelAndView();
}
else {
ModelAndView mav = new ModelAndView().addAllObjects(mavContainer.getModel());
ModelMap model = mavContainer.getModel();
HttpStatus status = mavContainer.getStatus();
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, status);
mav.setViewName(mavContainer.getViewName());
if (!mavContainer.isViewReference()) {
mav.setView((View) mavContainer.getView());

View File

@ -1742,6 +1742,18 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
assertEquals("view", response.getForwardedUrl());
}
@Test // SPR-14796
public void modelAndViewWithStatusInExceptionHandler() throws Exception {
initServletWithControllers(ModelAndViewController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/exception");
MockHttpServletResponse response = new MockHttpServletResponse();
getServlet().service(request, response);
assertEquals(422, response.getStatus());
assertEquals("view", response.getForwardedUrl());
}
@Test
public void httpHead() throws ServletException, IOException {
initServletWithControllers(ResponseEntityController.class);
@ -3302,6 +3314,20 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
public ModelAndView methodWithHttpStatus(MyEntity object) {
return new ModelAndView("view", new ModelMap(), HttpStatus.UNPROCESSABLE_ENTITY);
}
@RequestMapping("/exception")
public void raiseException() throws Exception {
throw new TestException();
}
@ExceptionHandler(TestException.class)
public ModelAndView handleException() {
return new ModelAndView("view", new ModelMap(), HttpStatus.UNPROCESSABLE_ENTITY);
}
@SuppressWarnings("serial")
private static class TestException extends Exception {
}
}
}