SPR-8700 REFINE ORDER OF ARGUMENT RESOLUTION AND RETURN VALUE HANDLING.
1. Consider single-purpose return value types like HttpEntity, Model, View, and ModelAndView ahead of annotations like @ResponseBody and @ModelAttribute. And reversely consider multi-purpose return value types like Map, String, and void only after annotations like @RB and @MA. 2. Order custom argument resolvers and return value handlers after the built-in ones also clarifying the fact they cannot be used to override the built-in ones in Javadoc throughout. 3. Provide hooks in RequestMappingHandlerAdapter that subclasses can use to programmatically modify the list of argument resolvers and return value handlers, also adding new getters so subclasses can get access to what they need for the override. 4. Make SessionStatus available through ModelAndViewContainer and provide an argument resolver for it. 5. Init test and javadoc improvements.
This commit is contained in:
@@ -41,8 +41,6 @@ import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.SessionAttributes;
|
||||
import org.springframework.web.bind.support.DefaultSessionAttributeStore;
|
||||
import org.springframework.web.bind.support.SessionAttributeStore;
|
||||
import org.springframework.web.bind.support.SessionStatus;
|
||||
import org.springframework.web.bind.support.SimpleSessionStatus;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
@@ -161,7 +159,7 @@ public class ModelFactoryTests {
|
||||
replay(binderFactory);
|
||||
|
||||
ModelFactory modelFactory = new ModelFactory(null, binderFactory, sessionAttrsHandler);
|
||||
modelFactory.updateModel(webRequest, mavContainer, new SimpleSessionStatus());
|
||||
modelFactory.updateModel(webRequest, mavContainer);
|
||||
|
||||
assertEquals(attrValue, mavContainer.getModel().remove(attrName));
|
||||
assertSame(dataBinder.getBindingResult(), mavContainer.getModel().remove(bindingResultKey(attrName)));
|
||||
@@ -177,6 +175,7 @@ public class ModelFactoryTests {
|
||||
|
||||
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
|
||||
mavContainer.addAttribute(attrName, attrValue);
|
||||
mavContainer.getSessionStatus().setComplete();
|
||||
sessionAttributeStore.storeAttribute(webRequest, attrName, attrValue);
|
||||
|
||||
// Resolve successfully handler session attribute once
|
||||
@@ -187,11 +186,8 @@ public class ModelFactoryTests {
|
||||
expect(binderFactory.createBinder(webRequest, attrValue, attrName)).andReturn(dataBinder);
|
||||
replay(binderFactory);
|
||||
|
||||
SessionStatus sessionStatus = new SimpleSessionStatus();
|
||||
sessionStatus.setComplete();
|
||||
|
||||
ModelFactory modelFactory = new ModelFactory(null, binderFactory, sessionAttrsHandler);
|
||||
modelFactory.updateModel(webRequest, mavContainer, sessionStatus);
|
||||
modelFactory.updateModel(webRequest, mavContainer);
|
||||
|
||||
assertEquals(attrValue, mavContainer.getModel().get(attrName));
|
||||
assertNull(sessionAttributeStore.retrieveAttribute(webRequest, attrName));
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.method.annotation.support;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
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.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
|
||||
/**
|
||||
* Test fixture with {@link MapMethodProcessor}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class MapMethodProcessorTests {
|
||||
|
||||
private MapMethodProcessor processor;
|
||||
|
||||
private ModelAndViewContainer mavContainer;
|
||||
|
||||
private MethodParameter paramMap;
|
||||
|
||||
private MethodParameter returnParamMap;
|
||||
|
||||
private NativeWebRequest webRequest;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
processor = new MapMethodProcessor();
|
||||
mavContainer = new ModelAndViewContainer();
|
||||
|
||||
Method method = getClass().getDeclaredMethod("map", Map.class);
|
||||
paramMap = new MethodParameter(method, 0);
|
||||
returnParamMap = new MethodParameter(method, 0);
|
||||
|
||||
webRequest = new ServletWebRequest(new MockHttpServletRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsParameter() {
|
||||
assertTrue(processor.supportsParameter(paramMap));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsReturnType() {
|
||||
assertTrue(processor.supportsReturnType(returnParamMap));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveArgumentValue() throws Exception {
|
||||
assertSame(mavContainer.getModel(), processor.resolveArgument(paramMap, mavContainer, webRequest, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleMapReturnValue() throws Exception {
|
||||
mavContainer.addAttribute("attr1", "value1");
|
||||
Map<String, Object> returnValue = new ModelMap("attr2", "value2");
|
||||
|
||||
processor.handleReturnValue(returnValue , returnParamMap, mavContainer, webRequest);
|
||||
|
||||
assertEquals("value1", mavContainer.getModel().get("attr1"));
|
||||
assertEquals("value2", mavContainer.getModel().get("attr2"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private Map<String, Object> map(Map<String, Object> map) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,14 +21,13 @@ import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.ui.ExtendedModelMap;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
@@ -48,10 +47,6 @@ public class ModelMethodProcessorTests {
|
||||
|
||||
private MethodParameter returnParamModel;
|
||||
|
||||
private MethodParameter paramMap;
|
||||
|
||||
private MethodParameter returnParamMap;
|
||||
|
||||
private NativeWebRequest webRequest;
|
||||
|
||||
@Before
|
||||
@@ -63,64 +58,39 @@ public class ModelMethodProcessorTests {
|
||||
paramModel = new MethodParameter(method, 0);
|
||||
returnParamModel = new MethodParameter(method, -1);
|
||||
|
||||
method = getClass().getDeclaredMethod("map", Map.class);
|
||||
paramMap = new MethodParameter(method, 0);
|
||||
returnParamMap = new MethodParameter(method, 0);
|
||||
|
||||
webRequest = new ServletWebRequest(new MockHttpServletRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsParameter() {
|
||||
assertTrue(processor.supportsParameter(paramModel));
|
||||
assertTrue(processor.supportsParameter(paramMap));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsReturnType() {
|
||||
assertTrue(processor.supportsReturnType(returnParamModel));
|
||||
assertTrue(processor.supportsReturnType(returnParamMap));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveArgumentValue() throws Exception {
|
||||
Object result = processor.resolveArgument(paramModel, mavContainer, webRequest, null);
|
||||
assertSame(mavContainer.getModel(), result);
|
||||
|
||||
result = processor.resolveArgument(paramMap, mavContainer, webRequest, null);
|
||||
assertSame(mavContainer.getModel(), result);
|
||||
assertSame(mavContainer.getModel(), processor.resolveArgument(paramModel, mavContainer, webRequest, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleModelReturnValue() throws Exception {
|
||||
mavContainer.addAttribute("attr1", "value1");
|
||||
ModelMap returnValue = new ModelMap("attr2", "value2");
|
||||
Model returnValue = new ExtendedModelMap();
|
||||
returnValue.addAttribute("attr2", "value2");
|
||||
|
||||
processor.handleReturnValue(returnValue , returnParamModel, mavContainer, webRequest);
|
||||
|
||||
assertEquals("value1", mavContainer.getModel().get("attr1"));
|
||||
assertEquals("value2", mavContainer.getModel().get("attr2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleMapReturnValue() throws Exception {
|
||||
mavContainer.addAttribute("attr1", "value1");
|
||||
Map<String, Object> returnValue = new ModelMap("attr2", "value2");
|
||||
|
||||
processor.handleReturnValue(returnValue , returnParamMap, mavContainer, webRequest);
|
||||
|
||||
assertEquals("value1", mavContainer.getModel().get("attr1"));
|
||||
assertEquals("value2", mavContainer.getModel().get("attr2"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private Model model(Model model) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private Map<String, Object> map(Map<String, Object> map) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -52,7 +52,7 @@ public class ModelAndViewContainerTests {
|
||||
assertEquals("Default model should be used if not in redirect scenario",
|
||||
"value", this.mavContainer.getModel().get("name"));
|
||||
|
||||
this.mavContainer.setUseRedirectModel(true);
|
||||
this.mavContainer.setRedirectModelScenario(true);
|
||||
|
||||
assertEquals("Redirect model should be used in redirect scenario",
|
||||
"redirectValue", this.mavContainer.getModel().get("name"));
|
||||
@@ -61,7 +61,7 @@ public class ModelAndViewContainerTests {
|
||||
@Test
|
||||
public void getModelIgnoreDefaultModelOnRedirect() {
|
||||
this.mavContainer.addAttribute("name", "value");
|
||||
this.mavContainer.setUseRedirectModel(true);
|
||||
this.mavContainer.setRedirectModelScenario(true);
|
||||
|
||||
assertEquals("Default model should be used since no redirect model was provided",
|
||||
1, this.mavContainer.getModel().size());
|
||||
|
||||
Reference in New Issue
Block a user