diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java index c8f7a15974..26434dc83e 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java @@ -55,6 +55,8 @@ import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.View; import org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import org.springframework.web.servlet.support.RequestContextUtils; /** * An {@link AbstractHandlerMethodExceptionResolver} that resolves exceptions @@ -303,6 +305,7 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce // Type-based argument resolution resolvers.add(new ServletRequestMethodArgumentResolver()); resolvers.add(new ServletResponseMethodArgumentResolver()); + resolvers.add(new RedirectAttributesMethodArgumentResolver()); resolvers.add(new ModelMethodProcessor()); // Custom arguments @@ -401,6 +404,11 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce if (!mavContainer.isViewReference()) { mav.setView((View) mavContainer.getView()); } + if (model instanceof RedirectAttributes) { + Map flashAttributes = ((RedirectAttributes) model).getFlashAttributes(); + request = webRequest.getNativeRequest(HttpServletRequest.class); + RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes); + } return mav; } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RedirectAttributesMethodArgumentResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RedirectAttributesMethodArgumentResolver.java index a4126f5e39..af19698ff0 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RedirectAttributesMethodArgumentResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RedirectAttributesMethodArgumentResolver.java @@ -53,8 +53,14 @@ public class RedirectAttributesMethodArgumentResolver implements HandlerMethodAr public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { - DataBinder dataBinder = binderFactory.createBinder(webRequest, null, null); - ModelMap redirectAttributes = new RedirectAttributesModelMap(dataBinder); + ModelMap redirectAttributes; + if(binderFactory != null) { + DataBinder dataBinder = binderFactory.createBinder(webRequest, null, null); + redirectAttributes = new RedirectAttributesModelMap(dataBinder); + } + else { + redirectAttributes = new RedirectAttributesModelMap(); + } mavContainer.setRedirectModel(redirectAttributes); return redirectAttributes; } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java index f633f73b01..34355dac16 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java @@ -42,7 +42,10 @@ import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.annotation.ModelMethodProcessor; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; +import org.springframework.web.servlet.DispatcherServlet; +import org.springframework.web.servlet.FlashMap; import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.web.util.NestedServletException; import static org.junit.Assert.*; @@ -53,6 +56,7 @@ import static org.junit.Assert.*; * @author Rossen Stoyanchev * @author Arjen Poutsma * @author Kazuki Shimizu + * @author Brian Clozel * @since 3.1 */ @SuppressWarnings("unused") @@ -82,6 +86,7 @@ public class ExceptionHandlerExceptionResolverTests { this.resolver = new ExceptionHandlerExceptionResolver(); this.resolver.setWarnLogCategory(this.resolver.getClass().getName()); this.request = new MockHttpServletRequest("GET", "/"); + this.request.setAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); this.response = new MockHttpServletResponse(); } @@ -192,6 +197,20 @@ public class ExceptionHandlerExceptionResolverTests { assertEquals("IllegalArgumentException", mav.getModelMap().get("exceptionClassName")); } + @Test // SPR-14651 + public void resolveRedirectAttributesAtArgument() throws Exception { + IllegalArgumentException ex = new IllegalArgumentException(); + HandlerMethod handlerMethod = new HandlerMethod(new RedirectAttributesController(), "handle"); + this.resolver.afterPropertiesSet(); + ModelAndView mav = this.resolver.resolveException(this.request, this.response, handlerMethod, ex); + + assertNotNull(mav); + assertEquals("redirect:/", mav.getViewName()); + FlashMap flashMap = (FlashMap) this.request.getAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE); + assertNotNull("output FlashMap should exist", flashMap); + assertEquals("IllegalArgumentException", flashMap.get("exceptionClassName")); + } + @Test public void resolveExceptionGlobalHandler() throws Exception { AnnotationConfigApplicationContext cxt = new AnnotationConfigApplicationContext(MyConfig.class); @@ -364,6 +383,18 @@ public class ExceptionHandlerExceptionResolverTests { } } + @Controller + static class RedirectAttributesController { + + public void handle() {} + + @ExceptionHandler + public String handleException(Exception ex, RedirectAttributes redirectAttributes) { + redirectAttributes.addFlashAttribute("exceptionClassName", ClassUtils.getShortName(ex.getClass())); + return "redirect:/"; + } + } + @RestControllerAdvice @Order(1)