From 66df039b03347c4e01fa5965754eba90316999f7 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 9 Jan 2012 20:18:44 -0500 Subject: [PATCH] SPR-8698 Support flash attrs and a ModelAndView return value. Before this change, flash attributes could only be added if via RedirectAttributes.addFlashAttribute(..) if the method returned a view name or a View instance. With this change, the above is supported with a ModelAndView return value as well. --- .../ModelAndViewMethodReturnValueHandler.java | 28 ++++++-- ...lAndViewMethodReturnValueHandlerTests.java | 67 ++++++++++++++++--- 2 files changed, 79 insertions(+), 16 deletions(-) diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ModelAndViewMethodReturnValueHandler.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ModelAndViewMethodReturnValueHandler.java index 661e403b724..b5494f50614 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ModelAndViewMethodReturnValueHandler.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ModelAndViewMethodReturnValueHandler.java @@ -21,6 +21,8 @@ import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.SmartView; +import org.springframework.web.servlet.View; /** * Handles return values of type {@link ModelAndView} copying view and model @@ -48,17 +50,29 @@ public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturn MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { - if (returnValue != null) { - ModelAndView mav = (ModelAndView) returnValue; - mavContainer.setViewName(mav.getViewName()); - if (!mav.isReference()) { - mavContainer.setView(mav.getView()); + if (returnValue == null) { + mavContainer.setRequestHandled(true); + return; + } + + ModelAndView mav = (ModelAndView) returnValue; + if (mav.isReference()) { + String viewName = mav.getViewName(); + mavContainer.setViewName(viewName); + if (viewName != null && viewName.startsWith("redirect:")) { + mavContainer.setRedirectModelScenario(true); } - mavContainer.addAllAttributes(mav.getModel()); } else { - mavContainer.setRequestHandled(true); + View view = mav.getView(); + mavContainer.setView(view); + if (view instanceof SmartView) { + if (((SmartView) view).isRedirectView()) { + mavContainer.setRedirectModelScenario(true); + } + } } + mavContainer.addAllAttributes(mav.getModel()); } } \ No newline at end of file diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ModelAndViewMethodReturnValueHandlerTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ModelAndViewMethodReturnValueHandlerTests.java index cb99e9566b7..cfec1453542 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ModelAndViewMethodReturnValueHandlerTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ModelAndViewMethodReturnValueHandlerTests.java @@ -18,6 +18,8 @@ package org.springframework.web.servlet.mvc.method.annotation; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import java.lang.reflect.Method; @@ -26,10 +28,11 @@ import org.junit.Before; import org.junit.Test; import org.springframework.core.MethodParameter; import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.ui.ModelMap; import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.method.annotation.ModelAndViewMethodReturnValueHandler; +import org.springframework.web.servlet.mvc.support.RedirectAttributesModelMap; import org.springframework.web.servlet.view.RedirectView; /** @@ -45,44 +48,90 @@ public class ModelAndViewMethodReturnValueHandlerTests { private ServletWebRequest webRequest; + private MethodParameter returnParamModelAndView; + @Before - public void setUp() { + public void setUp() throws Exception { this.handler = new ModelAndViewMethodReturnValueHandler(); this.mavContainer = new ModelAndViewContainer(); this.webRequest = new ServletWebRequest(new MockHttpServletRequest()); + this.returnParamModelAndView = getReturnValueParam("modelAndView"); } @Test public void supportsReturnType() throws Exception { - assertTrue(handler.supportsReturnType(getReturnValueParam("modelAndView"))); + assertTrue(handler.supportsReturnType(returnParamModelAndView)); assertFalse(handler.supportsReturnType(getReturnValueParam("viewName"))); } @Test - public void handleReturnValueViewName() throws Exception { + public void handleViewReference() throws Exception { ModelAndView mav = new ModelAndView("viewName", "attrName", "attrValue"); - handler.handleReturnValue(mav, getReturnValueParam("modelAndView"), mavContainer, webRequest); + handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest); assertEquals("viewName", mavContainer.getView()); assertEquals("attrValue", mavContainer.getModel().get("attrName")); } @Test - public void handleReturnValueView() throws Exception { + public void handleViewInstance() throws Exception { ModelAndView mav = new ModelAndView(new RedirectView(), "attrName", "attrValue"); - handler.handleReturnValue(mav, getReturnValueParam("modelAndView"), mavContainer, webRequest); + handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest); assertEquals(RedirectView.class, mavContainer.getView().getClass()); assertEquals("attrValue", mavContainer.getModel().get("attrName")); } @Test - public void handleReturnValueNull() throws Exception { - handler.handleReturnValue(null, getReturnValueParam("modelAndView"), mavContainer, webRequest); + public void handleNull() throws Exception { + handler.handleReturnValue(null, returnParamModelAndView, mavContainer, webRequest); assertTrue(mavContainer.isRequestHandled()); } + @Test + public void handleRedirectAttributesWithViewReference() throws Exception { + RedirectAttributesModelMap redirectAttributes = new RedirectAttributesModelMap(); + mavContainer.setRedirectModel(redirectAttributes); + + ModelAndView mav = new ModelAndView(new RedirectView(), "attrName", "attrValue"); + handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest); + + assertEquals(RedirectView.class, mavContainer.getView().getClass()); + assertEquals("attrValue", mavContainer.getModel().get("attrName")); + assertSame("RedirectAttributes should be used if controller redirects", redirectAttributes, + mavContainer.getModel()); + } + + @Test + public void handleRedirectAttributesWithViewInstance() throws Exception { + RedirectAttributesModelMap redirectAttributes = new RedirectAttributesModelMap(); + mavContainer.setRedirectModel(redirectAttributes); + + ModelAndView mav = new ModelAndView("redirect:viewName", "attrName", "attrValue"); + handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest); + + ModelMap model = mavContainer.getModel(); + assertEquals("redirect:viewName", mavContainer.getViewName()); + assertEquals("attrValue", model.get("attrName")); + assertSame("RedirectAttributes should be used if controller redirects", redirectAttributes, model); + } + + @Test + public void handleRedirectAttributesWithoutRedirect() throws Exception { + RedirectAttributesModelMap redirectAttributes = new RedirectAttributesModelMap(); + mavContainer.setRedirectModel(redirectAttributes); + + ModelAndView mav = new ModelAndView(); + handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest); + + ModelMap model = mavContainer.getModel(); + assertEquals(null, mavContainer.getView()); + assertTrue(mavContainer.getModel().isEmpty()); + assertNotSame("RedirectAttributes should not be used if controller doesn't redirect", redirectAttributes, model); + } + + private MethodParameter getReturnValueParam(String methodName) throws Exception { Method method = getClass().getDeclaredMethod(methodName); return new MethodParameter(method, -1);