SPR-6464 Add 'setAlwaysUseRedirectAttributes' flag.

When set to 'true' the flag makes RedirectAttributes the only way to add 
attributes for a redirect thus ignoring the content of the default model 
even if RedirectAttributes is not in the list of controller method args.
This commit is contained in:
Rossen Stoyanchev
2011-09-13 07:53:17 +00:00
parent a456a1a0e3
commit 2799e710bc
8 changed files with 227 additions and 80 deletions

View File

@@ -30,6 +30,7 @@ import org.springframework.beans.DirectFieldAccessor;
import org.springframework.core.MethodParameter;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
@@ -42,19 +43,21 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite;
import org.springframework.web.method.support.InvocableHandlerMethod;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.FlashMap;
import org.springframework.web.servlet.FlashMapManager;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.annotation.support.RedirectAttributesMethodArgumentResolver;
import org.springframework.web.servlet.mvc.method.annotation.support.ServletRequestMethodArgumentResolver;
import org.springframework.web.servlet.mvc.method.annotation.support.ViewMethodReturnValueHandler;
/**
* Fine-grained {@link RequestMappingHandlerAdapter} unit tests.
*
* <p>For higher-level adapter tests see:
* <ul>
* <li>{@link ServletAnnotationControllerHandlerMethodTests}
* <li>{@link HandlerMethodAnnotationDetectionTests}
* <li>{@link RequestMappingHandlerAdapterIntegrationTests}
* </ul>
* Unit tests for {@link RequestMappingHandlerAdapter}.
*
* @author Rossen Stoyanchev
*
* @see ServletAnnotationControllerHandlerMethodTests
* @see HandlerMethodAnnotationDetectionTests
* @see RequestMappingHandlerAdapterIntegrationTests
*/
public class RequestMappingHandlerAdapterTests {
@@ -68,35 +71,56 @@ public class RequestMappingHandlerAdapterTests {
public void setup() throws Exception {
this.handlerAdapter = new RequestMappingHandlerAdapter();
this.handlerAdapter.setApplicationContext(new GenericWebApplicationContext());
this.request = new MockHttpServletRequest();
this.response = new MockHttpServletResponse();
}
@Test
public void cacheControlWithoutSessionAttributes() throws Exception {
SimpleHandler handler = new SimpleHandler();
handlerAdapter.afterPropertiesSet();
handlerAdapter.setCacheSeconds(100);
handlerAdapter.handle(request, response, handlerMethod(new SimpleHandler(), "handle"));
handlerAdapter.handle(request, response, handlerMethod(handler, "handle"));
assertTrue(response.getHeader("Cache-Control").toString().contains("max-age"));
}
@Test
public void cacheControlWithSessionAttributes() throws Exception {
SessionAttributeHandler handler = new SessionAttributeHandler();
handlerAdapter.afterPropertiesSet();
handlerAdapter.setCacheSeconds(100);
handlerAdapter.handle(request, response, handlerMethod(new SessionAttributeHandler(), "handle"));
handlerAdapter.handle(request, response, handlerMethod(handler, "handle"));
assertEquals("no-cache", response.getHeader("Cache-Control"));
}
@Test
public void setAlwaysUseRedirectAttributes() throws Exception {
HandlerMethodArgumentResolver redirectAttributesResolver = new RedirectAttributesMethodArgumentResolver();
HandlerMethodArgumentResolver modelResolver = new ModelMethodProcessor();
HandlerMethodReturnValueHandler viewHandler = new ViewMethodReturnValueHandler();
handlerAdapter.setArgumentResolvers(Arrays.asList(redirectAttributesResolver, modelResolver));
handlerAdapter.setReturnValueHandlers(Arrays.asList(viewHandler));
handlerAdapter.setAlwaysUseRedirectAttributes(true);
handlerAdapter.afterPropertiesSet();
request.setAttribute(FlashMapManager.OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
HandlerMethod handlerMethod = handlerMethod(new RedirectAttributeHandler(), "handle", Model.class);
ModelAndView mav = handlerAdapter.handle(request, response, handlerMethod);
assertTrue("No redirect attributes added, model should be empty", mav.getModel().isEmpty());
}
@Test
@SuppressWarnings("unchecked")
public void setArgumentResolvers() {
List<HandlerMethodArgumentResolver> expected = new ArrayList<HandlerMethodArgumentResolver>();
expected.add(new ServletRequestMethodArgumentResolver());
handlerAdapter.setArgumentResolvers(expected);
List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<HandlerMethodArgumentResolver>();
argumentResolvers.add(new ServletRequestMethodArgumentResolver());
handlerAdapter.setArgumentResolvers(argumentResolvers);
handlerAdapter.afterPropertiesSet();
HandlerMethodArgumentResolverComposite composite = (HandlerMethodArgumentResolverComposite)
@@ -105,15 +129,16 @@ public class RequestMappingHandlerAdapterTests {
List<HandlerMethodArgumentResolver> actual = (List<HandlerMethodArgumentResolver>)
new DirectFieldAccessor(composite).getPropertyValue("argumentResolvers");
assertEquals(expected, actual);
assertEquals(argumentResolvers, actual);
}
@Test
@SuppressWarnings("unchecked")
public void setInitBinderArgumentResolvers() {
List<HandlerMethodArgumentResolver> expected = new ArrayList<HandlerMethodArgumentResolver>();
expected.add(new ServletRequestMethodArgumentResolver());
handlerAdapter.setInitBinderArgumentResolvers(expected);
List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<HandlerMethodArgumentResolver>();
argumentResolvers.add(new ServletRequestMethodArgumentResolver());
handlerAdapter.setInitBinderArgumentResolvers(argumentResolvers);
handlerAdapter.afterPropertiesSet();
HandlerMethodArgumentResolverComposite composite = (HandlerMethodArgumentResolverComposite)
@@ -122,15 +147,16 @@ public class RequestMappingHandlerAdapterTests {
List<HandlerMethodArgumentResolver> actual = (List<HandlerMethodArgumentResolver>)
new DirectFieldAccessor(composite).getPropertyValue("argumentResolvers");
assertEquals(expected, actual);
assertEquals(argumentResolvers, actual);
}
@Test
@SuppressWarnings("unchecked")
public void setReturnValueHandlers() {
List<HandlerMethodReturnValueHandler> expected = new ArrayList<HandlerMethodReturnValueHandler>();
expected.add(new ModelMethodProcessor());
handlerAdapter.setReturnValueHandlers(expected);
HandlerMethodReturnValueHandler handler = new ModelMethodProcessor();
List<HandlerMethodReturnValueHandler> handlers = Arrays.asList(handler);
handlerAdapter.setReturnValueHandlers(handlers);
handlerAdapter.afterPropertiesSet();
HandlerMethodReturnValueHandlerComposite composite = (HandlerMethodReturnValueHandlerComposite)
@@ -139,14 +165,14 @@ public class RequestMappingHandlerAdapterTests {
List<HandlerMethodReturnValueHandler> actual = (List<HandlerMethodReturnValueHandler>)
new DirectFieldAccessor(composite).getPropertyValue("returnValueHandlers");
assertEquals(expected, actual);
assertEquals(handlers, actual);
}
@Test
@SuppressWarnings("unchecked")
public void setCustomArgumentResolvers() {
TestHanderMethodArgumentResolver resolver = new TestHanderMethodArgumentResolver();
handlerAdapter.setCustomArgumentResolvers(Arrays.<HandlerMethodArgumentResolver>asList(resolver));
HandlerMethodArgumentResolver resolver = new TestHanderMethodArgumentResolver();
handlerAdapter.setCustomArgumentResolvers(Arrays.asList(resolver));
handlerAdapter.afterPropertiesSet();
HandlerMethodArgumentResolverComposite composite = (HandlerMethodArgumentResolverComposite)
@@ -181,13 +207,14 @@ public class RequestMappingHandlerAdapterTests {
assertTrue(actual.contains(handler));
}
private HandlerMethod handlerMethod(Object handler, String methodName, Class<?>... paramTypes) throws Exception {
Method method = handler.getClass().getDeclaredMethod(methodName, paramTypes);
return new InvocableHandlerMethod(handler, method);
}
private final class TestHanderMethodArgumentResolver implements HandlerMethodArgumentResolver {
public boolean supportsParameter(MethodParameter parameter) {
return false;
}
@@ -209,19 +236,23 @@ public class RequestMappingHandlerAdapterTests {
}
}
private static class SimpleHandler {
@SuppressWarnings("unused")
static class SimpleHandler {
public void handle() {
}
}
@SessionAttributes("attr1")
private static class SessionAttributeHandler {
@SuppressWarnings("unused")
static class SessionAttributeHandler {
public void handle() {
}
}
static class RedirectAttributeHandler {
public String handle(Model model) {
model.addAttribute("someAttr", "someAttrValue");
return "redirect:/path";
}
}
}

View File

@@ -1456,8 +1456,8 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Test
public void flashAttribute() throws Exception {
initServletWithControllers(MessageController.class);
public void redirectAttribute() throws Exception {
initServletWithControllers(RedirectAttributesController.class);
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/messages");
HttpSession session = request.getSession();
@@ -2803,7 +2803,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
static class MessageController {
static class RedirectAttributesController {
@InitBinder
public void initBinder(WebDataBinder dataBinder) {
@@ -2827,8 +2827,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
}
// Test cases deleted from the original SevletAnnotationControllerTests:
// @Ignore("Controller interface => no method-level @RequestMapping annotation")

View File

@@ -119,6 +119,24 @@ public class RedirectAttributesModelMapTests {
assertEquals("33", this.redirectAttributes.get("age"));
}
@Test
public void put() {
this.redirectAttributes.put("testBean", new TestBean("Fred"));
assertEquals("Fred", this.redirectAttributes.get("testBean"));
}
@Test
public void putAll() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("person", new TestBean("Fred"));
map.put("age", 33);
this.redirectAttributes.putAll(map);
assertEquals("Fred", this.redirectAttributes.get("person"));
assertEquals("33", this.redirectAttributes.get("age"));
}
public static class TestBeanConverter implements Converter<TestBean, String> {
public String convert(TestBean source) {