diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodExceptionResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodExceptionResolver.java
index a561a6992da..edf5a770f19 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodExceptionResolver.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodExceptionResolver.java
@@ -24,7 +24,7 @@ import org.springframework.web.servlet.ModelAndView;
/**
* Abstract base class for {@link org.springframework.web.servlet.HandlerExceptionResolver HandlerExceptionResolver}
- * implementations that support {@link HandlerMethod HandlerMethod}s.
+ * implementations that support handling exceptions from {@link HandlerMethod}s rather than handlers.
*
* @author Rossen Stoyanchev
* @since 3.1
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/AbstractHandlerMethodAdapter.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/AbstractHandlerMethodAdapter.java
index f4f64d01e9a..3246388be4a 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/AbstractHandlerMethodAdapter.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/AbstractHandlerMethodAdapter.java
@@ -26,10 +26,11 @@ import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.support.WebContentGenerator;
/**
- * Abstract base class for {@link HandlerAdapter} implementations that support {@link HandlerMethod}s.
- * Contains template methods for handling these handler method.
+ * Abstract base class for {@link HandlerAdapter} implementations that support the handling of requests through
+ * the execution of {@link HandlerMethod}s rather than handlers.
*
* @author Arjen Poutsma
+ * @since 3.1
*/
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodAdapter.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodAdapter.java
index 230bfec9f2e..363d0a5e4e8 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodAdapter.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodAdapter.java
@@ -374,7 +374,7 @@ public class RequestMappingHandlerMethodAdapter extends AbstractHandlerMethodAda
resolvers.add(new RequestParamMethodArgumentResolver(beanFactory, false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
- resolvers.add(new PathVariableMethodArgumentResolver(beanFactory));
+ resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(messageConverters));
resolvers.add(new RequestHeaderMethodArgumentResolver(beanFactory));
@@ -404,7 +404,7 @@ public class RequestMappingHandlerMethodAdapter extends AbstractHandlerMethodAda
// Annotation-based resolvers
resolvers.add(new RequestParamMethodArgumentResolver(beanFactory, false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
- resolvers.add(new PathVariableMethodArgumentResolver(beanFactory));
+ resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new ExpressionValueMethodArgumentResolver(beanFactory));
// Type-based resolvers
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInitBinderMethodDataBinderFactory.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInitBinderMethodDataBinderFactory.java
index 8dcc54515c8..8f96204952b 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInitBinderMethodDataBinderFactory.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInitBinderMethodDataBinderFactory.java
@@ -25,7 +25,7 @@ import org.springframework.web.method.annotation.InitBinderMethodDataBinderFacto
import org.springframework.web.method.support.InvocableHandlerMethod;
/**
- * An {@link InitBinderMethodDataBinderFactory} for Servlet environments.
+ * An {@link InitBinderMethodDataBinderFactory} that creates a {@link ServletRequestDataBinder}.
*
* @author Rossen Stoyanchev
* @since 3.1
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java
index d7b204a8b46..fc920b9c4cb 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java
@@ -30,16 +30,19 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandlerCom
import org.springframework.web.method.support.InvocableHandlerMethod;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.View;
+import org.springframework.web.servlet.mvc.method.annotation.support.ServletResponseMethodArgumentResolver;
/**
- * Extends {@link InvocableHandlerMethod} with the ability to handle the return value through registered
- * {@link HandlerMethodArgumentResolver}s.
+ * Extends {@link InvocableHandlerMethod} with the ability to handle the value returned from the method through
+ * a registered {@link HandlerMethodArgumentResolver} that supports the given return value type.
+ * Return value handling may include writing to the response or updating the {@link ModelAndViewContainer} structure.
*
- *
The {@link ModelAndViewContainer} for the request contains the results from the handling of the return value.
- * It can be used to access model attributes and view selection and to check if view resolution is needed.
+ *
If the underlying method has a {@link ResponseStatus} instruction, the status on the response is set
+ * accordingly after the method is invoked but before the return value is handled.
*
* @author Rossen Stoyanchev
* @since 3.1
+ * @see #invokeAndHandle(NativeWebRequest, ModelAndViewContainer, Object...)
*/
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
@@ -65,25 +68,23 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
if (annotation != null) {
this.responseStatus = annotation.value();
this.responseReason = annotation.reason();
-
}
}
/**
- * Invokes the method and handles the return value through registered {@link HandlerMethodReturnValueHandler}s.
- * If the handler method is annotated with {@link ResponseStatus}, the status on the response is set accordingly
- * after method invocation but before return value handling.
- *
Return value handling may be skipped entirely if the handler method returns a {@code null} (or is a
- * {@code void} method) and one of the following other conditions is true:
+ * Invokes the method and handles the return value through a registered {@link HandlerMethodReturnValueHandler}.
+ *
Return value handling may be skipped entirely when the method returns {@code null} (also possibly due
+ * to a {@code void} return type) and one of the following additional conditions is true:
*
- * One of the {@link HandlerMethodArgumentResolver}s set the {@link ModelAndViewContainer#setResolveView(boolean)}
- * flag to {@code false}. This is the case when a method argument allows the handler method access to the response.
- * The request qualifies as being not modified according to {@link ServletWebRequest#isNotModified()}.
- * This is used in conjunction with a "Last-Modified" header or ETag.
- * The status on the response was set as a result of a {@link ResponseStatus} annotation
+ * A {@link HandlerMethodArgumentResolver} has set the {@link ModelAndViewContainer#setResolveView(boolean)}
+ * flag to {@code false} -- e.g. method arguments providing access to the response.
+ * The request qualifies as "not modified" as defined in {@link ServletWebRequest#checkNotModified(long)}
+ * and {@link ServletWebRequest#checkNotModified(String)}. In this case a response with "not modified" response
+ * headers will be automatically generated without the need for return value handling.
+ * The status on the response is set due to a @{@link ResponseStatus} instruction.
*
- * After the call, use the {@link ModelAndViewContainer} parameter to access model attributes and view selection
- * and to determine if view resolution is needed.
+ *
After the return value is handled, callers of this method can use the {@link ModelAndViewContainer}
+ * to gain access to model attributes, view selection choices, and to check if view resolution is even needed.
*
* @param request the current request
* @param mavContainer the {@link ModelAndViewContainer} for the current request
@@ -131,17 +132,18 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
}
/**
- * Does the request qualify as not modified?
+ * Does the given request qualify as "not modified"?
+ * @see ServletWebRequest#checkNotModified(long)
+ * @see ServletWebRequest#checkNotModified(String)
*/
private boolean isRequestNotModified(NativeWebRequest request) {
return ((ServletWebRequest) request).isNotModified();
}
/**
- * Does the method set the response status?
+ * Does this method have the response status instruction?
*/
private boolean hasResponseStatus() {
return responseStatus != null;
}
-
}
\ No newline at end of file
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/AbstractMessageConverterMethodProcessor.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/AbstractMessageConverterMethodProcessor.java
index 8714b45f9f5..3cfd9c0f099 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/AbstractMessageConverterMethodProcessor.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/AbstractMessageConverterMethodProcessor.java
@@ -37,6 +37,10 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
/**
+ * A base class for resolving method argument values by reading from the body of a request with
+ * {@link HttpMessageConverter}s and for handling method return values by writing to the response with
+ * {@link HttpMessageConverter}s.
+ *
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @since 3.1
@@ -143,4 +147,4 @@ public abstract class AbstractMessageConverterMethodProcessor
return acceptedMediaTypes;
}
-}
+}
\ No newline at end of file
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/DefaultMethodReturnValueHandler.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/DefaultMethodReturnValueHandler.java
index b42a1c56303..304126364d1 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/DefaultMethodReturnValueHandler.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/DefaultMethodReturnValueHandler.java
@@ -31,12 +31,21 @@ import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.annotation.ModelAndViewResolver;
/**
- * A catch-all {@link HandlerMethodReturnValueHandler} to handle return values not handled by any other return
- * value handler.
- *
- *
This handler should always be last in the order as {@link #supportsReturnType(MethodParameter)} always returns
- * {@code true}. An attempt is made to handle the return value through a custom {@link ModelAndViewResolver}s or
- * otherwise by treating it as a single model attribute.
+ * Attempts to handle return value types not recognized by any other {@link HandlerMethodReturnValueHandler}.
+ * Intended to be used as the last of a list of registered handlers as {@link #supportsReturnType(MethodParameter)}
+ * always returns {@code true}.
+ *
Handling takes place in the following order:
+ *
+ * Iterate over the list of {@link ModelAndViewResolver}s provided to the constructor of this class looking
+ * for a return value that isn't {@link ModelAndViewResolver#UNRESOLVED}.
+ * If the return value is not a simple type it is treated as a single model attribute to be added to the model
+ * with a name derived from its type.
+ *
+ * Note that {@link ModelAndViewResolver} is supported for backwards compatibility. Since the only way to check
+ * if it supports a return value type is to try to resolve the return value, a {@link ModelAndViewResolver} can
+ * only be invoked from here after no other {@link HandlerMethodReturnValueHandler} has recognized the return
+ * value. To avoid this limitation change the {@link ModelAndViewResolver} to implement
+ * {@link HandlerMethodReturnValueHandler} instead.
*
* @author Rossen Stoyanchev
* @since 3.1
@@ -65,10 +74,6 @@ public class DefaultMethodReturnValueHandler implements HandlerMethodReturnValue
return true;
}
- public boolean usesResponseArgument(MethodParameter parameter) {
- return false;
- }
-
public void handleReturnValue(Object returnValue,
MethodParameter returnType,
ModelAndViewContainer mavContainer,
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/HttpEntityMethodProcessor.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/HttpEntityMethodProcessor.java
index cfa7a3eb4b4..f719f2db61b 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/HttpEntityMethodProcessor.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/HttpEntityMethodProcessor.java
@@ -40,13 +40,11 @@ import org.springframework.util.Assert;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
-import org.springframework.web.method.support.HandlerMethodArgumentResolver;
-import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
- * Implementation of {@link HandlerMethodArgumentResolver} and {@link HandlerMethodReturnValueHandler}
- * that supports {@link HttpEntity} and {@link ResponseEntity}.
+ * Resolves {@link HttpEntity} method argument values.
+ * Handles {@link HttpEntity} and {@link ResponseEntity} return values.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
@@ -68,27 +66,16 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
return HttpEntity.class.equals(parameterType) || ResponseEntity.class.equals(parameterType);
}
- public boolean usesResponseArgument(MethodParameter parameterOrReturnType) {
- // only when HttpEntity or ResponseEntity is used as a return type
- return parameterOrReturnType.getParameterIndex() == -1;
- }
-
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory)
throws IOException, HttpMediaTypeNotSupportedException {
+ HttpInputMessage inputMessage = createInputMessage(webRequest);
Class> paramType = getHttpEntityType(parameter);
Object body = readWithMessageConverters(webRequest, parameter, paramType);
- HttpInputMessage inputMessage = createInputMessage(webRequest);
return new HttpEntity(body, inputMessage.getHeaders());
}
-
- @Override
- protected HttpInputMessage createInputMessage(NativeWebRequest webRequest) {
- HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
- return new ServletServerHttpRequest(servletRequest);
- }
private Class> getHttpEntityType(MethodParameter methodParam) {
Assert.isAssignable(HttpEntity.class, methodParam.getParameterType());
@@ -109,7 +96,12 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
}
throw new IllegalArgumentException(
"HttpEntity parameter (" + methodParam.getParameterName() + ") is not parameterized");
-
+ }
+
+ @Override
+ protected HttpInputMessage createInputMessage(NativeWebRequest webRequest) {
+ HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
+ return new ServletServerHttpRequest(servletRequest);
}
public void handleReturnValue(Object returnValue,
@@ -150,4 +142,5 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
HttpServletResponse servletResponse = (HttpServletResponse) webRequest.getNativeResponse();
return new ServletServerHttpResponse(servletResponse);
}
-}
+
+}
\ No newline at end of file
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ModelAndViewMethodReturnValueHandler.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ModelAndViewMethodReturnValueHandler.java
index 3166c21dfc6..d99efd844f7 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ModelAndViewMethodReturnValueHandler.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ModelAndViewMethodReturnValueHandler.java
@@ -23,7 +23,9 @@ import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.ModelAndView;
/**
- * Handles {@link ModelAndView} return values.
+ * Handles return values of type {@link ModelAndView} transferring their content to the {@link ModelAndViewContainer}.
+ * If the return value is {@code null}, the {@link ModelAndViewContainer#setResolveView(boolean)} flag is set to
+ * {@code false} to indicate view resolution is not needed.
*
* @author Rossen Stoyanchev
* @since 3.1
@@ -34,10 +36,6 @@ public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturn
return ModelAndView.class.isAssignableFrom(returnType.getParameterType());
}
- public boolean usesResponseArgument(MethodParameter parameter) {
- return false;
- }
-
public void handleReturnValue(Object returnValue,
MethodParameter returnType,
ModelAndViewContainer mavContainer,
@@ -53,4 +51,4 @@ public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturn
}
}
-}
+}
\ No newline at end of file
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolver.java
index 518a1248d17..00799c6e63b 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolver.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolver.java
@@ -20,28 +20,33 @@ import java.util.Map;
import javax.servlet.ServletException;
-import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
+import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ValueConstants;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.annotation.support.AbstractNamedValueMethodArgumentResolver;
-import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.HandlerMapping;
/**
- * Implementation of {@link HandlerMethodArgumentResolver} that supports arguments annotated with
- * {@link PathVariable @PathVariable}.
+ * Resolves method arguments annotated with an @{@link PathVariable}.
*
+ * An @{@link PathVariable} is a named value that gets resolved from a URI template variable. It is always
+ * required and does not have a default value to fall back on. See the base class
+ * {@link AbstractNamedValueMethodArgumentResolver} for more information on how named values are processed.
+ *
+ *
A {@link WebDataBinder} is invoked to apply type conversion to resolved path variable values that
+ * don't yet match the method parameter type.
+ *
* @author Rossen Stoyanchev
* @author Arjen Poutsma
* @since 3.1
*/
public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
- public PathVariableMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
- super(beanFactory);
+ public PathVariableMethodArgumentResolver() {
+ super(null);
}
public boolean supportsParameter(MethodParameter parameter) {
@@ -56,16 +61,16 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethod
@Override
@SuppressWarnings("unchecked")
- protected Object resolveNamedValueArgument(NativeWebRequest webRequest, MethodParameter parameter, String name)
- throws Exception {
- Map uriTemplateVariables = (Map) webRequest.getAttribute(
- HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
- return (uriTemplateVariables != null) ? uriTemplateVariables.get(name) : null;
+ protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
+ String key = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
+ int scope = RequestAttributes.SCOPE_REQUEST;
+ Map uriTemplateVars = (Map) request.getAttribute(key, scope);
+ return (uriTemplateVars != null) ? uriTemplateVars.get(name) : null;
}
@Override
protected void handleMissingValue(String name, MethodParameter parameter) throws ServletException {
- throw new IllegalStateException("Could not find @PathVariable [" + name + "] in @RequestMapping");
+ throw new IllegalStateException("Could not find the URL template variable [" + name + "]");
}
private static class PathVariableNamedValueInfo extends NamedValueInfo {
@@ -74,6 +79,4 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethod
super(annotation.value(), true, ValueConstants.DEFAULT_NONE);
}
}
-
-
-}
+}
\ No newline at end of file
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessor.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessor.java
index dc8795d6e68..90658a1e1b0 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessor.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessor.java
@@ -34,13 +34,11 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
-import org.springframework.web.method.support.HandlerMethodArgumentResolver;
-import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
- * Implementation of {@link HandlerMethodArgumentResolver} and {@link HandlerMethodReturnValueHandler} that supports
- * parameters annotated with {@link RequestBody} and return values annotated with {@link ResponseBody}.
+ * Resolves method arguments annotated with @{@link RequestBody}.
+ * Handles return values from methods annotated with @{@link ResponseBody}.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
@@ -60,11 +58,6 @@ public class RequestResponseBodyMethodProcessor extends AbstractMessageConverter
return returnType.getMethodAnnotation(ResponseBody.class) != null;
}
- public boolean usesResponseArgument(MethodParameter parameterOrReturnType) {
- return parameterOrReturnType.getParameterIndex() == -1 &&
- parameterOrReturnType.getMethodAnnotation(ResponseBody.class) != null;
- }
-
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletCookieValueMethodArgumentResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletCookieValueMethodArgumentResolver.java
index f49fea83209..b505c69ca81 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletCookieValueMethodArgumentResolver.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletCookieValueMethodArgumentResolver.java
@@ -22,35 +22,41 @@ import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
import org.springframework.web.context.request.NativeWebRequest;
-import org.springframework.web.method.annotation.support.CookieValueMethodArgumentResolver;
+import org.springframework.web.method.annotation.support.AbstractCookieValueMethodArgumentResolver;
+import org.springframework.web.util.UrlPathHelper;
import org.springframework.web.util.WebUtils;
/**
- * A {@link CookieValueMethodArgumentResolver} for Servlet environments.
+ * A {@link AbstractCookieValueMethodArgumentResolver} that resolves the cookie value through the {@link HttpServletRequest}.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
-public class ServletCookieValueMethodArgumentResolver extends CookieValueMethodArgumentResolver {
+public class ServletCookieValueMethodArgumentResolver extends AbstractCookieValueMethodArgumentResolver {
+
+ private UrlPathHelper urlPathHelper = new UrlPathHelper();
public ServletCookieValueMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
super(beanFactory);
}
+ public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
+ this.urlPathHelper = urlPathHelper;
+ }
+
@Override
- protected Object resolveNamedValueArgument(NativeWebRequest webRequest,
- MethodParameter parameter,
- String cookieName) throws Exception {
+ protected Object resolveName(String cookieName, MethodParameter parameter, NativeWebRequest webRequest)
+ throws Exception {
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
Cookie cookieValue = WebUtils.getCookie(servletRequest, cookieName);
if (Cookie.class.isAssignableFrom(parameter.getParameterType())) {
return cookieValue;
}
else if (cookieValue != null) {
- return getUrlPathHelper().decodeRequestString(servletRequest, cookieValue.getValue());
+ return this.urlPathHelper.decodeRequestString(servletRequest, cookieValue.getValue());
}
else {
return null;
}
}
-}
+}
\ No newline at end of file
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletModelAttributeMethodProcessor.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletModelAttributeMethodProcessor.java
index 8a44189da3a..92ce76483c4 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletModelAttributeMethodProcessor.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletModelAttributeMethodProcessor.java
@@ -21,11 +21,13 @@ import javax.servlet.ServletRequest;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.annotation.support.ModelAttributeMethodProcessor;
/**
- * A {@link ModelAttributeMethodProcessor} for Servlet environments.
+ * A Servlet-specific {@link ModelAttributeMethodProcessor} variant that casts the {@link WebDataBinder}
+ * instance to {@link ServletRequestDataBinder} prior to invoking data binding.
*
* @author Rossen Stoyanchev
* @since 3.1
@@ -33,13 +35,12 @@ import org.springframework.web.method.annotation.support.ModelAttributeMethodPro
public class ServletModelAttributeMethodProcessor extends ModelAttributeMethodProcessor {
/**
- * Creates a {@link ServletModelAttributeMethodProcessor} instance.
- * @param resolveWithoutAnnotations enable default resolution mode in which parameters without
- * annotations that aren't simple types (see {@link BeanUtils#isSimpleProperty(Class)})
- * are also treated as model attributes with a default name based on the model attribute type.
+ * @param useDefaultResolution in default resolution mode a method argument that isn't a simple type, as
+ * defined in {@link BeanUtils#isSimpleProperty(Class)}, is treated as a model attribute even if it doesn't
+ * have an @{@link ModelAttribute} annotation with its name derived from the model attribute type.
*/
- public ServletModelAttributeMethodProcessor(boolean resolveWithoutAnnotations) {
- super(resolveWithoutAnnotations);
+ public ServletModelAttributeMethodProcessor(boolean useDefaultResolution) {
+ super(useDefaultResolution);
}
/**
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletRequestMethodArgumentResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletRequestMethodArgumentResolver.java
index 27b8b57b17d..38aa461122f 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletRequestMethodArgumentResolver.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletRequestMethodArgumentResolver.java
@@ -36,61 +36,74 @@ import org.springframework.web.multipart.MultipartRequest;
import org.springframework.web.servlet.support.RequestContextUtils;
/**
- * Implementation of {@link HandlerMethodArgumentResolver} that supports {@link ServletRequest} and related arguments.
+ * Resolves request-related method argument values of the following types:
+ *
+ * {@link WebRequest}
+ * {@link ServletRequest}
+ * {@link MultipartRequest}
+ * {@link HttpSession}
+ * {@link Principal}
+ * {@link Locale}
+ * {@link InputStream}
+ * {@link Reader}
+ *
*
* @author Arjen Poutsma
+ * @author Rossen Stoyanchev
+ * @since 3.1
*/
public class ServletRequestMethodArgumentResolver implements HandlerMethodArgumentResolver {
public boolean supportsParameter(MethodParameter parameter) {
- Class> parameterType = parameter.getParameterType();
- return WebRequest.class.isAssignableFrom(parameterType) ||
- ServletRequest.class.isAssignableFrom(parameterType) ||
- MultipartRequest.class.isAssignableFrom(parameterType) ||
- HttpSession.class.isAssignableFrom(parameterType) || Principal.class.isAssignableFrom(parameterType) ||
- Locale.class.equals(parameterType) || InputStream.class.isAssignableFrom(parameterType) ||
- Reader.class.isAssignableFrom(parameterType);
- }
-
- public boolean usesResponseArgument(MethodParameter parameter) {
- return false;
+ Class> paramType = parameter.getParameterType();
+ return WebRequest.class.isAssignableFrom(paramType) ||
+ ServletRequest.class.isAssignableFrom(paramType) ||
+ MultipartRequest.class.isAssignableFrom(paramType) ||
+ HttpSession.class.isAssignableFrom(paramType) ||
+ Principal.class.isAssignableFrom(paramType) ||
+ Locale.class.equals(paramType) ||
+ InputStream.class.isAssignableFrom(paramType) ||
+ Reader.class.isAssignableFrom(paramType);
}
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws IOException {
- HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
- Class> parameterType = parameter.getParameterType();
-
- if (WebRequest.class.isAssignableFrom(parameterType)) {
+
+ Class> paramType = parameter.getParameterType();
+ if (WebRequest.class.isAssignableFrom(paramType)) {
return webRequest;
}
- if (ServletRequest.class.isAssignableFrom(parameterType) ||
- MultipartRequest.class.isAssignableFrom(parameterType)) {
- Object nativeRequest = webRequest.getNativeRequest(parameterType);
+
+ HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
+ if (ServletRequest.class.isAssignableFrom(paramType) || MultipartRequest.class.isAssignableFrom(paramType)) {
+ Object nativeRequest = webRequest.getNativeRequest(paramType);
if (nativeRequest == null) {
throw new IllegalStateException(
- "Current request is not of type [" + parameterType.getName() + "]: " + request);
+ "Current request is not of type [" + paramType.getName() + "]: " + request);
}
return nativeRequest;
}
- else if (HttpSession.class.isAssignableFrom(parameterType)) {
+ else if (HttpSession.class.isAssignableFrom(paramType)) {
return request.getSession();
}
- else if (Principal.class.isAssignableFrom(parameterType)) {
+ else if (Principal.class.isAssignableFrom(paramType)) {
return request.getUserPrincipal();
}
- else if (Locale.class.equals(parameterType)) {
+ else if (Locale.class.equals(paramType)) {
return RequestContextUtils.getLocale(request);
}
- else if (InputStream.class.isAssignableFrom(parameterType)) {
+ else if (InputStream.class.isAssignableFrom(paramType)) {
return request.getInputStream();
}
- else if (Reader.class.isAssignableFrom(parameterType)) {
+ else if (Reader.class.isAssignableFrom(paramType)) {
return request.getReader();
}
- // should not happen
- throw new UnsupportedOperationException();
+ else {
+ // should not happen
+ throw new UnsupportedOperationException();
+ }
}
-}
+
+}
\ No newline at end of file
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletResponseMethodArgumentResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletResponseMethodArgumentResolver.java
index 6193abe0cee..e971415fc4c 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletResponseMethodArgumentResolver.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletResponseMethodArgumentResolver.java
@@ -28,33 +28,46 @@ import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
+import org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod;
/**
- * Implementation of {@link HandlerMethodArgumentResolver} that supports {@link ServletResponse} and related arguments.
+ * Resolves response-related method argument values of types:
+ *
+ * {@link ServletResponse}
+ * {@link OutputStream}
+ * {@link Writer}
+ *
*
* @author Arjen Poutsma
+ * @author Rossen Stoyanchev
+ * @since 3.1
*/
public class ServletResponseMethodArgumentResolver implements HandlerMethodArgumentResolver {
public boolean supportsParameter(MethodParameter parameter) {
- Class> parameterType = parameter.getParameterType();
- return ServletResponse.class.isAssignableFrom(parameterType) ||
- OutputStream.class.isAssignableFrom(parameterType) || Writer.class.isAssignableFrom(parameterType);
- }
-
- public boolean usesResponseArgument(MethodParameter parameter) {
- return true;
+ Class> paramType = parameter.getParameterType();
+ return ServletResponse.class.isAssignableFrom(paramType)
+ || OutputStream.class.isAssignableFrom(paramType)
+ || Writer.class.isAssignableFrom(paramType);
}
+ /**
+ * {@inheritDoc}
+ * Sets the {@link ModelAndViewContainer#setResolveView(boolean)} flag to {@code false} to indicate
+ * that the method signature provides access to the response. If subsequently the underlying method
+ * returns {@code null}, view resolution will be bypassed.
+ * @see ServletInvocableHandlerMethod#invokeAndHandle(NativeWebRequest, ModelAndViewContainer, Object...)
+ */
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws IOException {
+
+ mavContainer.setResolveView(false);
+
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
Class> parameterType = parameter.getParameterType();
- mavContainer.setResolveView(false);
-
if (ServletResponse.class.isAssignableFrom(parameterType)) {
Object nativeResponse = webRequest.getNativeResponse(parameterType);
if (nativeResponse == null) {
@@ -74,4 +87,5 @@ public class ServletResponseMethodArgumentResolver implements HandlerMethodArgum
throw new UnsupportedOperationException();
}
}
+
}
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletWebArgumentResolverAdapter.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletWebArgumentResolverAdapter.java
index fdf69b2e3c6..b1787ae5706 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletWebArgumentResolverAdapter.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletWebArgumentResolverAdapter.java
@@ -22,15 +22,16 @@ import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.request.ServletWebRequest;
-import org.springframework.web.method.annotation.support.WebArgumentResolverAdapter;
+import org.springframework.web.method.annotation.support.AbstractWebArgumentResolverAdapter;
/**
- * A Servlet-specific {@link WebArgumentResolverAdapter} that provides access to a {@link NativeWebRequest}.
+ * A Servlet-specific {@link AbstractWebArgumentResolverAdapter} that creates a {@link NativeWebRequest}
+ * from {@link ServletRequestAttributes}.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
-public class ServletWebArgumentResolverAdapter extends WebArgumentResolverAdapter {
+public class ServletWebArgumentResolverAdapter extends AbstractWebArgumentResolverAdapter {
public ServletWebArgumentResolverAdapter(WebArgumentResolver adaptee) {
super(adaptee);
@@ -45,5 +46,4 @@ public class ServletWebArgumentResolverAdapter extends WebArgumentResolverAdapte
}
return null;
}
-
-}
+}
\ No newline at end of file
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandler.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandler.java
index 67347bb0f6e..2db1978c1bd 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandler.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandler.java
@@ -18,12 +18,16 @@ package org.springframework.web.servlet.mvc.method.annotation.support;
import org.springframework.core.MethodParameter;
import org.springframework.web.context.request.NativeWebRequest;
+import org.springframework.web.method.annotation.support.ModelAttributeMethodProcessor;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.View;
/**
- * Handles {@link View} and view name return values.
+ * Handles return values that are of type {@link View} or {@link String} (i.e. a logical view name).
+ *
Since {@link String} return value can be interpeted in multiple ways, this resolver should be ordered
+ * after return value handlers that recognize annotated return values such as the
+ * {@link ModelAttributeMethodProcessor} and the {@link RequestResponseBodyMethodProcessor}.
*
* @author Rossen Stoyanchev
* @since 3.1
@@ -35,10 +39,6 @@ public class ViewMethodReturnValueHandler implements HandlerMethodReturnValueHan
return (View.class.isAssignableFrom(paramType) || (String.class.equals(paramType)));
}
- public boolean usesResponseArgument(MethodParameter parameter) {
- return false;
- }
-
public void handleReturnValue(Object returnValue,
MethodParameter returnType,
ModelAndViewContainer mavContainer,
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/HttpEntityMethodProcessorTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/HttpEntityMethodProcessorTests.java
index 3b3a424a0c5..cdfb90c8a7f 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/HttpEntityMethodProcessorTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/HttpEntityMethodProcessorTests.java
@@ -122,15 +122,6 @@ public class HttpEntityMethodProcessorTests {
assertFalse("non-ResponseBody return type supported", processor.supportsReturnType(intReturnValue));
}
- @Test
- public void usesResponseArgument() {
- assertFalse("HttpEntity parameter uses response argument", processor.usesResponseArgument(httpEntityParam));
- assertTrue("ResponseBody return type does not use response argument",
- processor.usesResponseArgument(responseEntityReturnValue));
- assertTrue("HttpEntity return type does not use response argument",
- processor.usesResponseArgument(httpEntityReturnValue));
- }
-
@Test
@SuppressWarnings("unchecked")
public void resolveArgument() throws Exception {
@@ -146,8 +137,9 @@ public class HttpEntityMethodProcessorTests {
replay(messageConverter);
HttpEntity> result = (HttpEntity) processor.resolveArgument(httpEntityParam, mavContainer, request, null);
- assertEquals("Invalid argument", expected, result.getBody());
+ assertTrue("The ResolveView flag shouldn't change", mavContainer.isResolveView());
+ assertEquals("Invalid argument", expected, result.getBody());
verify(messageConverter);
}
@@ -164,6 +156,7 @@ public class HttpEntityMethodProcessorTests {
processor.resolveArgument(httpEntityParam, mavContainer, request, null);
+ assertTrue("The ResolveView flag shouldn't change", mavContainer.isResolveView());
verify(messageConverter);
}
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolverTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolverTests.java
index 45440b5ac55..bf6a06d3731 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolverTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/PathVariableMethodArgumentResolverTests.java
@@ -52,7 +52,7 @@ public class PathVariableMethodArgumentResolverTests {
@Before
public void setUp() throws Exception {
- resolver = new PathVariableMethodArgumentResolver(null);
+ resolver = new PathVariableMethodArgumentResolver();
Method method = getClass().getMethod("handle", String.class, String.class);
pathVarParam = new MethodParameter(method, 0);
stringParam = new MethodParameter(method, 1);
@@ -62,11 +62,6 @@ public class PathVariableMethodArgumentResolverTests {
webRequest = new ServletWebRequest(servletRequest, servletResponse);
}
- @Test
- public void usesResponseArgument() {
- assertFalse(resolver.usesResponseArgument(null));
- }
-
@Test
public void supportsParameter() {
assertTrue("Parameter with @PathVariable annotation", resolver.supportsParameter(pathVarParam));
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessorTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessorTests.java
index 016a222f2ed..4c770f6539e 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessorTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessorTests.java
@@ -106,13 +106,6 @@ public class RequestResponseBodyMethodProcessorTests {
assertFalse("non-ResponseBody return type supported", processor.supportsReturnType(intReturnValue));
}
- @Test
- public void usesResponseArgument() {
- assertFalse("RequestBody parameter uses response argument", processor.usesResponseArgument(stringParameter));
- assertTrue("ResponseBody return type does not use response argument",
- processor.usesResponseArgument(stringReturnValue));
- }
-
@Test
public void resolveArgument() throws Exception {
MediaType contentType = MediaType.TEXT_PLAIN;
@@ -127,8 +120,9 @@ public class RequestResponseBodyMethodProcessorTests {
replay(messageConverter);
Object result = processor.resolveArgument(stringParameter, mavContainer, webRequest, null);
- assertEquals("Invalid argument", expected, result);
+ assertEquals("Invalid argument", expected, result);
+ assertTrue("The ResolveView flag shouldn't change", mavContainer.isResolveView());
verify(messageConverter);
}
@@ -146,6 +140,7 @@ public class RequestResponseBodyMethodProcessorTests {
processor.resolveArgument(stringParameter, mavContainer, webRequest, null);
+ assertTrue("The ResolveView flag shouldn't change", mavContainer.isResolveView());
verify(messageConverter);
}
@@ -168,7 +163,7 @@ public class RequestResponseBodyMethodProcessorTests {
processor.handleReturnValue(returnValue, stringReturnValue, mavContainer, webRequest);
- assertFalse(mavContainer.isResolveView());
+ assertFalse("The ResolveView flag wasn't turned off", mavContainer.isResolveView());
verify(messageConverter);
}
@@ -186,7 +181,7 @@ public class RequestResponseBodyMethodProcessorTests {
processor.handleReturnValue(returnValue, stringReturnValue, mavContainer, webRequest);
- assertFalse(mavContainer.isResolveView());
+ assertFalse("The ResolveView flag wasn't turned off", mavContainer.isResolveView());
verify(messageConverter);
}
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletCookieValueMethodArgumentResolverTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletCookieValueMethodArgumentResolverTests.java
index f9badf04c33..9a07b80ff0a 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletCookieValueMethodArgumentResolverTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletCookieValueMethodArgumentResolverTests.java
@@ -31,7 +31,7 @@ import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.context.request.ServletWebRequest;
-import org.springframework.web.method.annotation.support.CookieValueMethodArgumentResolver;
+import org.springframework.web.method.annotation.support.AbstractCookieValueMethodArgumentResolver;
import org.springframework.web.servlet.mvc.method.annotation.support.ServletCookieValueMethodArgumentResolver;
/**
@@ -39,7 +39,7 @@ import org.springframework.web.servlet.mvc.method.annotation.support.ServletCook
*/
public class ServletCookieValueMethodArgumentResolverTests {
- private CookieValueMethodArgumentResolver resolver;
+ private ServletCookieValueMethodArgumentResolver resolver;
private MethodParameter cookieParameter;
@@ -65,11 +65,6 @@ public class ServletCookieValueMethodArgumentResolverTests {
}
- @Test
- public void usesResponseArgument() throws NoSuchMethodException {
- assertFalse("resolver uses response argument", resolver.usesResponseArgument(null));
- }
-
@Test
public void supportsParameter() {
assertTrue("Cookie parameter not supported", resolver.supportsParameter(cookieParameter));
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletRequestMethodArgumentResolverTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletRequestMethodArgumentResolverTests.java
index 5748cf7a6b5..ebdadb211e8 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletRequestMethodArgumentResolverTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletRequestMethodArgumentResolverTests.java
@@ -33,6 +33,7 @@ import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;
+import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.multipart.MultipartRequest;
import org.springframework.web.servlet.mvc.method.annotation.support.ServletRequestMethodArgumentResolver;
@@ -47,6 +48,8 @@ public class ServletRequestMethodArgumentResolverTests {
private Method supportedParams;
+ private ModelAndViewContainer mavContainer;
+
private ServletWebRequest webRequest;
private MockHttpServletRequest servletRequest;
@@ -57,23 +60,21 @@ public class ServletRequestMethodArgumentResolverTests {
supportedParams = getClass()
.getMethod("supportedParams", ServletRequest.class, MultipartRequest.class, HttpSession.class,
Principal.class, Locale.class, InputStream.class, Reader.class, WebRequest.class);
+ mavContainer = new ModelAndViewContainer();
servletRequest = new MockHttpServletRequest();
webRequest = new ServletWebRequest(servletRequest, new MockHttpServletResponse());
}
- @Test
- public void usesResponseArgument() {
- assertFalse("resolver uses response argument", resolver.usesResponseArgument(null));
- }
-
@Test
public void servletRequest() throws Exception {
MethodParameter servletRequestParameter = new MethodParameter(supportedParams, 0);
-
- assertTrue("ServletRequest not supported", resolver.supportsParameter(servletRequestParameter));
-
- Object result = resolver.resolveArgument(servletRequestParameter, null, webRequest, null);
+
+ boolean isSupported = resolver.supportsParameter(servletRequestParameter);
+ Object result = resolver.resolveArgument(servletRequestParameter, mavContainer, webRequest, null);
+
+ assertTrue("ServletRequest not supported", isSupported);
assertSame("Invalid result", servletRequest, result);
+ assertTrue("The ResolveView flag shouldn't change", mavContainer.isResolveView());
}
@Test
@@ -82,10 +83,12 @@ public class ServletRequestMethodArgumentResolverTests {
servletRequest.setSession(session);
MethodParameter sessionParameter = new MethodParameter(supportedParams, 2);
- assertTrue("Session not supported", resolver.supportsParameter(sessionParameter));
+ boolean isSupported = resolver.supportsParameter(sessionParameter);
+ Object result = resolver.resolveArgument(sessionParameter, mavContainer, webRequest, null);
- Object result = resolver.resolveArgument(sessionParameter, null, webRequest, null);
+ assertTrue("Session not supported", isSupported);
assertSame("Invalid result", session, result);
+ assertTrue("The ResolveView flag shouldn't change", mavContainer.isResolveView());
}
@Test
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletResponseMethodArgumentResolverTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletResponseMethodArgumentResolverTests.java
index 7f32054e815..059f6d68331 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletResponseMethodArgumentResolverTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ServletResponseMethodArgumentResolverTests.java
@@ -57,11 +57,6 @@ public class ServletResponseMethodArgumentResolverTests {
webRequest = new ServletWebRequest(new MockHttpServletRequest(), servletResponse);
}
- @Test
- public void usesResponseArgument() {
- assertTrue("resolver uses response argument", resolver.usesResponseArgument(null));
- }
-
@Test
public void servletResponse() throws Exception {
MethodParameter servletResponseParameter = new MethodParameter(supportedParams, 0);
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/CookieValueMethodArgumentResolver.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/AbstractCookieValueMethodArgumentResolver.java
similarity index 55%
rename from org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/CookieValueMethodArgumentResolver.java
rename to org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/AbstractCookieValueMethodArgumentResolver.java
index 8cdd58d2a83..6906eb695e1 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/CookieValueMethodArgumentResolver.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/AbstractCookieValueMethodArgumentResolver.java
@@ -18,33 +18,34 @@ package org.springframework.web.method.annotation.support;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
+import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.CookieValue;
-import org.springframework.web.context.request.NativeWebRequest;
-import org.springframework.web.method.support.HandlerMethodArgumentResolver;
-import org.springframework.web.util.UrlPathHelper;
/**
- * Implementation of {@link HandlerMethodArgumentResolver} that supports arguments annotated with
- * {@link CookieValue @CookieValue}.
- *
+ * A base abstract class to resolve method arguments annotated with @{@link CookieValue}. Subclasses must define how
+ * to extract the cookie value from the request.
+ *
+ * An @{@link CookieValue} is a named value that is resolved from a cookie. It has a required flag and a
+ * default value to fall back on when the cookie does not exist. See the base class
+ * {@link AbstractNamedValueMethodArgumentResolver} for more information on how named values are processed.
+ *
+ *
A {@link WebDataBinder} is invoked to apply type conversion to resolved cookie values that don't yet match
+ * the method parameter type.
+ *
* @author Arjen Poutsma
+ * @author Rossen Stoyanchev
+ * @since 3.1
*/
-public class CookieValueMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
+public abstract class AbstractCookieValueMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
- private UrlPathHelper urlPathHelper = new UrlPathHelper();
-
- public CookieValueMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
+ /**
+ * @param beanFactory a bean factory to use for resolving ${...} placeholder and #{...} SpEL expressions
+ * in default values, or {@code null} if default values are not expected to contain expressions
+ */
+ public AbstractCookieValueMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
super(beanFactory);
}
- public UrlPathHelper getUrlPathHelper() {
- return urlPathHelper;
- }
-
- public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
- this.urlPathHelper = urlPathHelper;
- }
-
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(CookieValue.class);
}
@@ -55,18 +56,11 @@ public class CookieValueMethodArgumentResolver extends AbstractNamedValueMethodA
return new CookieValueNamedValueInfo(annotation);
}
- @Override
- protected Object resolveNamedValueArgument(NativeWebRequest webRequest,
- MethodParameter parameter,
- String cookieName) throws Exception {
-
- throw new UnsupportedOperationException("@CookieValue not supported");
- }
-
@Override
protected void handleMissingValue(String cookieName, MethodParameter parameter) {
+ String paramTypeName = parameter.getParameterType().getName();
throw new IllegalStateException(
- "Missing cookie value '" + cookieName + "' of type [" + parameter.getParameterType().getName() + "]");
+ "Missing cookie named '" + cookieName + "' for method parameter type [" + paramTypeName + "]");
}
private static class CookieValueNamedValueInfo extends NamedValueInfo {
@@ -75,4 +69,4 @@ public class CookieValueMethodArgumentResolver extends AbstractNamedValueMethodA
super(annotation.value(), annotation.required(), annotation.defaultValue());
}
}
-}
+}
\ No newline at end of file
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/AbstractNamedValueMethodArgumentResolver.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/AbstractNamedValueMethodArgumentResolver.java
index a783f3761d4..584829d0dac 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/AbstractNamedValueMethodArgumentResolver.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/AbstractNamedValueMethodArgumentResolver.java
@@ -25,6 +25,7 @@ import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanExpressionResolver;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
+import org.springframework.util.Assert;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ValueConstants;
import org.springframework.web.bind.support.WebDataBinderFactory;
@@ -34,8 +35,19 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
- * Abstract base class for argument resolvers that resolve named values.
- *
+ * Abstract base class for resolving method arguments from a named value. Request parameters, request headers, and
+ * path variables are examples of named values. Each may have a name, a required flag, and a default value.
+ *
Subclasses define how to do the following:
+ *
+ * Obtain named value information for a method parameter
+ * Resolve names into argument values
+ * Handle missing argument values when argument values are required
+ *
+ * A default value string can contain ${...} placeholders and Spring Expression Language #{...} expressions.
+ * For this to work a {@link ConfigurableBeanFactory} must be supplied to the class constructor.
+ *
A {@link WebDataBinder} is created to apply type conversion to the resolved argument value if it doesn't
+ * match the method parameter type.
+ *
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @since 3.1
@@ -49,15 +61,15 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
private Map namedValueInfoCache =
new ConcurrentHashMap();
+ /**
+ * @param beanFactory a bean factory to use for resolving ${...} placeholder and #{...} SpEL expressions
+ * in default values, or {@code null} if default values are not expected to contain expressions
+ */
public AbstractNamedValueMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
this.expressionContext = (beanFactory != null) ? new BeanExpressionContext(beanFactory, new RequestScope()) : null;
}
- public boolean usesResponseArgument(MethodParameter parameter) {
- return false;
- }
-
public final Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
@@ -66,7 +78,7 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
- Object arg = resolveNamedValueArgument(webRequest, parameter, namedValueInfo.name);
+ Object arg = resolveName(namedValueInfo.name, parameter, webRequest);
if (arg == null) {
if (namedValueInfo.defaultValue != null) {
@@ -87,74 +99,73 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
}
}
+ /**
+ * Obtain the named value for the given method parameter.
+ */
private NamedValueInfo getNamedValueInfo(MethodParameter parameter) {
- NamedValueInfo result = namedValueInfoCache.get(parameter);
- if (result == null) {
- NamedValueInfo info = createNamedValueInfo(parameter);
- String name = info.name;
- if (name.length() == 0) {
- name = parameter.getParameterName();
- if (name == null) {
- throw new IllegalStateException("No parameter name specified for argument of type [" +
- parameter.getParameterType().getName() +
- "], and no parameter name information found in class file either.");
- }
- }
- boolean required = info.required;
- String defaultValue = (ValueConstants.DEFAULT_NONE.equals(info.defaultValue) ? null : info.defaultValue);
-
- result = new NamedValueInfo(name, required, defaultValue);
- namedValueInfoCache.put(parameter, result);
+ NamedValueInfo namedValueInfo = namedValueInfoCache.get(parameter);
+ if (namedValueInfo == null) {
+ namedValueInfo = createNamedValueInfo(parameter);
+ namedValueInfo = updateNamedValueInfo(parameter, namedValueInfo);
+ namedValueInfoCache.put(parameter, namedValueInfo);
}
- return result;
+ return namedValueInfo;
}
/**
- * Creates a new {@link NamedValueInfo} object for the given method parameter.
- *
- * Implementations typically retrieve the method annotation by means of {@link
- * MethodParameter#getParameterAnnotation(Class)}.
- *
+ * Create the {@link NamedValueInfo} object for the given method parameter. Implementations typically
+ * retrieve the method annotation by means of {@link MethodParameter#getParameterAnnotation(Class)}.
+ *
* @param parameter the method parameter
* @return the named value information
*/
protected abstract NamedValueInfo createNamedValueInfo(MethodParameter parameter);
/**
- * Resolves the given parameter into a method argument.
+ * Create a new NamedValueInfo based on the given NamedValueInfo with sanitized values.
+ */
+ private NamedValueInfo updateNamedValueInfo(MethodParameter parameter, NamedValueInfo info) {
+ String name = info.name;
+ if (info.name.length() == 0) {
+ name = parameter.getParameterName();
+ Assert.notNull(name, "Name for argument type [" + parameter.getParameterType().getName()
+ + "] not available, and parameter name information not found in class file either.");
+ }
+ String defaultValue = (ValueConstants.DEFAULT_NONE.equals(info.defaultValue) ? null : info.defaultValue);
+ return new NamedValueInfo(name, info.required, defaultValue);
+ }
+
+ /**
+ * Resolves the given parameter type and value name into an argument value.
+ * @param name the name of the value being resolved
+ * @param parameter the method parameter to resolve to an argument value
+ * @param request the current request
*
- * @param webRequest the current web request, allowing access to the native request as well
- * @param parameter the parameter to resolve to an argument. This parameter must have previously been passed to the
- * {@link #supportsParameter(org.springframework.core.MethodParameter)} method of this interface, which must have
- * returned {@code true}.
- * @param name the name
- * @return the resolved argument. May be {@code null}.
+ * @return the resolved argument. May be {@code null}
* @throws Exception in case of errors
*/
- protected abstract Object resolveNamedValueArgument(NativeWebRequest webRequest,
- MethodParameter parameter,
- String name) throws Exception;
+ protected abstract Object resolveName(String name, MethodParameter parameter, NativeWebRequest request)
+ throws Exception;
- private Object resolveDefaultValue(String value) {
+ /**
+ * Resolves the given default value into an argument value.
+ */
+ private Object resolveDefaultValue(String defaultValue) {
if (beanFactory == null) {
- return value;
+ return defaultValue;
}
- String placeholdersResolved = beanFactory.resolveEmbeddedValue(value);
+ String placeholdersResolved = beanFactory.resolveEmbeddedValue(defaultValue);
BeanExpressionResolver exprResolver = beanFactory.getBeanExpressionResolver();
if (exprResolver == null) {
- return value;
+ return defaultValue;
}
return exprResolver.evaluate(placeholdersResolved, expressionContext);
}
/**
- * Invoked when a named value is required, but
- * {@link #resolveNamedValueArgument(NativeWebRequest, MethodParameter, String)} returned {@code null}
- * and there is no default value set.
- *
- *
Concrete subclasses typically throw an exception in this scenario.
- *
- * @param name the name
+ * Invoked when a named value is required, but {@link #resolveName(String, MethodParameter, NativeWebRequest)}
+ * returned {@code null} and there is no default value. Subclasses typically throw an exception in this case.
+ * @param name the name for the value
* @param parameter the method parameter
*/
protected abstract void handleMissingValue(String name, MethodParameter parameter) throws ServletException;
@@ -189,7 +200,5 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
this.required = required;
this.defaultValue = defaultValue;
}
-
}
-
-}
+}
\ No newline at end of file
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/WebArgumentResolverAdapter.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/AbstractWebArgumentResolverAdapter.java
similarity index 59%
rename from org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/WebArgumentResolverAdapter.java
rename to org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/AbstractWebArgumentResolverAdapter.java
index fd2f30d2090..36a883332c2 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/WebArgumentResolverAdapter.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/AbstractWebArgumentResolverAdapter.java
@@ -21,32 +21,48 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.core.MethodParameter;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
+import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.support.WebArgumentResolver;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
-import org.springframework.web.context.request.RequestAttributes;
-import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
- * Adapts a {@link WebArgumentResolver} into the {@link HandlerMethodArgumentResolver} contract.
+ * An abstract base class adapting a {@link WebArgumentResolver} into the {@link HandlerMethodArgumentResolver}
+ * contract. Provided for backwards compatibility, some important considerations are listed below.
+ *
+ *
The method {@link #supportsParameter(MethodParameter)} is implemented by trying to resolve the value through
+ * the {@link WebArgumentResolver} and verifying the resulting value is not {@link WebArgumentResolver#UNRESOLVED}.
+ * Exceptions resulting from that are absorbed and ignored since the adapter can't be sure if this is the resolver
+ * that supports the method parameter or not. To avoid this limitation change the {@link WebArgumentResolver} to
+ * implement the {@link HandlerMethodArgumentResolver} contract instead.
+ *
+ *
Another potentially useful advantage of {@link HandlerMethodArgumentResolver} is that it provides access to
+ * model attributes through the {@link ModelAndViewContainer} as well as access to a {@link WebDataBinderFactory}
+ * for when type conversion through a {@link WebDataBinder} is needed.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @since 3.1
*/
-public class WebArgumentResolverAdapter implements HandlerMethodArgumentResolver {
+public abstract class AbstractWebArgumentResolverAdapter implements HandlerMethodArgumentResolver {
private final Log logger = LogFactory.getLog(this.getClass());
private final WebArgumentResolver adaptee;
- public WebArgumentResolverAdapter(WebArgumentResolver adaptee) {
+ /**
+ * Create a {@link AbstractWebArgumentResolverAdapter} with the {@link WebArgumentResolver} instance to delegate to.
+ */
+ public AbstractWebArgumentResolverAdapter(WebArgumentResolver adaptee) {
Assert.notNull(adaptee, "'adaptee' must not be null");
this.adaptee = adaptee;
}
+ /**
+ * See the class-level documentation for an important consideration about exceptions arising in this method.
+ */
public boolean supportsParameter(MethodParameter parameter) {
try {
NativeWebRequest webRequest = getWebRequest();
@@ -64,16 +80,17 @@ public class WebArgumentResolverAdapter implements HandlerMethodArgumentResolver
return false;
}
}
-
- protected NativeWebRequest getWebRequest() {
- RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
- return (requestAttributes instanceof NativeWebRequest) ? (NativeWebRequest) requestAttributes : null;
- }
- public boolean usesResponseArgument(MethodParameter parameter) {
- return false;
- }
+ /**
+ * Provide access to a {@link NativeWebRequest}.
+ */
+ protected abstract NativeWebRequest getWebRequest();
+ /**
+ * Resolves the argument value by delegating to the {@link WebArgumentResolver} instance.
+ * @exception IllegalStateException if the resolved value is {@link WebArgumentResolver#UNRESOLVED} or if the
+ * return value type cannot be assigned to the method parameter type.
+ */
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
@@ -88,4 +105,4 @@ public class WebArgumentResolverAdapter implements HandlerMethodArgumentResolver
}
return result;
}
-}
+}
\ No newline at end of file
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ErrorsMethodArgumentResolver.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ErrorsMethodArgumentResolver.java
index d5e2ff2515e..b6bb298ca3e 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ErrorsMethodArgumentResolver.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ErrorsMethodArgumentResolver.java
@@ -23,18 +23,19 @@ import org.springframework.core.MethodParameter;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
- * An implementation of {@link HandlerMethodArgumentResolver} that resolves {@link Errors} method parameters.
- * Such parameters must be preceded by {@link ModelAttribute} parameters as described in {@link RequestMapping}.
+ * Resolves method arguments of type {@link Errors} and {@link BindingResult}.
+ *
+ *
This argument should appear after a model attribute argument in the signature of the handler method.
+ * It is resolved by accessing the last attribute in the model expecting that to be a {@link BindingResult}.
*
* @author Rossen Stoyanchev
+ * @since 3.1
*/
public class ErrorsMethodArgumentResolver implements HandlerMethodArgumentResolver {
@@ -43,10 +44,6 @@ public class ErrorsMethodArgumentResolver implements HandlerMethodArgumentResolv
return Errors.class.isAssignableFrom(paramType);
}
- public boolean usesResponseArgument(MethodParameter parameter) {
- return false;
- }
-
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
@@ -67,5 +64,4 @@ public class ErrorsMethodArgumentResolver implements HandlerMethodArgumentResolv
private boolean isBindingResultKey(String key) {
return key.startsWith(BindingResult.MODEL_KEY_PREFIX);
}
-
-}
+}
\ No newline at end of file
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ExpressionValueMethodArgumentResolver.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ExpressionValueMethodArgumentResolver.java
index 2602e785681..0a826dc3b36 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ExpressionValueMethodArgumentResolver.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ExpressionValueMethodArgumentResolver.java
@@ -21,18 +21,28 @@ import javax.servlet.ServletException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
+import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.context.request.NativeWebRequest;
-import org.springframework.web.method.support.HandlerMethodArgumentResolver;
/**
- * Implementation of {@link HandlerMethodArgumentResolver} that supports arguments annotated
- * with {@link Value @Value}.
+ * Resolves method arguments annotated with @{@link Value}.
+ *
+ *
An @{@link Value} is a named value that does not have a name but gets resolved from a default value string
+ * that may contain ${...} placeholder or Spring Expression Language #{...} expressions. See the base class
+ * {@link AbstractNamedValueMethodArgumentResolver} for more information on how named values are processed.
+ *
+ *
A {@link WebDataBinder} is invoked to apply type conversion to resolved argument values that don't yet match
+ * the method parameter type.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
public class ExpressionValueMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
+ /**
+ * @param beanFactory a bean factory to use for resolving ${...} placeholder and #{...} SpEL expressions
+ * in default values, or {@code null} if default values are not expected to contain expressions
+ */
public ExpressionValueMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
super(beanFactory);
}
@@ -48,16 +58,15 @@ public class ExpressionValueMethodArgumentResolver extends AbstractNamedValueMet
}
@Override
- protected Object resolveNamedValueArgument(NativeWebRequest webRequest, MethodParameter parameter, String name)
+ protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest webRequest)
throws Exception {
- // Only interested in default value resolution
+ // There is no name to be resolved
return null;
}
@Override
protected void handleMissingValue(String name, MethodParameter parameter) throws ServletException {
- // Should not happen
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Did not expect to handle a missing value: an @Value is never required");
}
private static class ExpressionValueNamedValueInfo extends NamedValueInfo {
@@ -65,6 +74,5 @@ public class ExpressionValueMethodArgumentResolver extends AbstractNamedValueMet
private ExpressionValueNamedValueInfo(Value annotation) {
super("@Value", false, annotation.value());
}
- }
-
-}
+ }
+}
\ No newline at end of file
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ModelAttributeMethodProcessor.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ModelAttributeMethodProcessor.java
index 683753e9bde..46e756a0fce 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ModelAttributeMethodProcessor.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ModelAttributeMethodProcessor.java
@@ -21,6 +21,7 @@ import java.lang.annotation.Annotation;
import org.springframework.beans.BeanUtils;
import org.springframework.core.MethodParameter;
import org.springframework.validation.BindException;
+import org.springframework.validation.BindingResult;
import org.springframework.validation.DataBinder;
import org.springframework.validation.Errors;
import org.springframework.web.bind.WebDataBinder;
@@ -34,24 +35,30 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
- * Resolves model attribute method parameters.
+ * Resolves method arguments annotated with @{@link ModelAttribute}. Or if created in default resolution mode,
+ * resolves any non-simple type argument even without an @{@link ModelAttribute}. See the constructor for details.
+ *
+ *
A model attribute argument value is obtained from the model or is created using its default constructor.
+ * Data binding and optionally validation is then applied through a {@link WebDataBinder} instance. Validation is
+ * invoked optionally when the argument is annotated with an {@code @Valid}.
+ *
+ *
Also handles return values from methods annotated with an @{@link ModelAttribute}. The return value is
+ * added to the {@link ModelAndViewContainer}.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
-public class ModelAttributeMethodProcessor
- implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler {
+public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler {
- private final boolean resolveArgumentsWithoutAnnotations;
+ private final boolean useDefaultResolution;
/**
- * Creates a {@link ModelAttributeMethodProcessor} instance.
- * @param resolveArgumentsWithoutAnnotations enable default resolution mode in which arguments without
- * annotations that aren't simple types (see {@link BeanUtils#isSimpleProperty(Class)})
- * are also treated as model attributes with a default name based on the model attribute type.
+ * @param useDefaultResolution in default resolution mode a method argument that isn't a simple type, as
+ * defined in {@link BeanUtils#isSimpleProperty(Class)}, is treated as a model attribute even if it doesn't
+ * have an @{@link ModelAttribute} annotation with its name derived from the model attribute type.
*/
- public ModelAttributeMethodProcessor(boolean resolveArgumentsWithoutAnnotations) {
- this.resolveArgumentsWithoutAnnotations = resolveArgumentsWithoutAnnotations;
+ public ModelAttributeMethodProcessor(boolean useDefaultResolution) {
+ this.useDefaultResolution = useDefaultResolution;
}
/**
@@ -62,7 +69,7 @@ public class ModelAttributeMethodProcessor
if (parameter.hasParameterAnnotation(ModelAttribute.class)) {
return true;
}
- else if (this.resolveArgumentsWithoutAnnotations) {
+ else if (this.useDefaultResolution) {
return !BeanUtils.isSimpleProperty(parameter.getParameterType());
}
else {
@@ -70,15 +77,13 @@ public class ModelAttributeMethodProcessor
}
}
- public boolean usesResponseArgument(MethodParameter parameter) {
- return false;
- }
-
/**
- * Resolves the argument to a model attribute creating a {@link WebDataBinder} and invoking data binding on it.
- * The model attribute is obtained from the model first or otherwise created via direct instantiation.
- * @throws Exception if data binder initialization fails or if data binding results in errors and the next
- * method parameter is not of type {@link Errors}.
+ * Resolves the argument to a model attribute looking up the attribute in the model or instantiating it using its
+ * default constructor. Data binding and optionally validation is then applied through a {@link WebDataBinder}
+ * instance. Validation is invoked optionally when the method parameter is annotated with an {@code @Valid}.
+ *
+ * @throws Exception if a {@link WebDataBinder} could not be created or if data binding and validation result in
+ * an error and the next method parameter is not of type {@link Errors} or {@link BindingResult}.
*/
public final Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
@@ -164,5 +169,4 @@ public class ModelAttributeMethodProcessor
mavContainer.addAttribute(name, returnValue);
}
}
-
}
\ No newline at end of file
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ModelMethodProcessor.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ModelMethodProcessor.java
index a135b02e6ef..e53d4592d16 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ModelMethodProcessor.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ModelMethodProcessor.java
@@ -28,7 +28,12 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
- * Resolves {@link Model} and {@link Map} method parameters.
+ * Resolves {@link Map} and {@link Model} method arguments.
+ *
+ *
Handles {@link Model} return values adding their attributes to the {@link ModelAndViewContainer}.
+ * Handles {@link Map} return values in the same way as long as the method does not have an @{@link ModelAttribute}.
+ * If the method does have an @{@link ModelAttribute}, it is assumed the returned {@link Map} is a model attribute
+ * and not a model.
*
* @author Rossen Stoyanchev
* @since 3.1
@@ -40,10 +45,6 @@ public class ModelMethodProcessor implements HandlerMethodArgumentResolver, Hand
return Model.class.isAssignableFrom(paramType) || Map.class.isAssignableFrom(paramType);
}
- public boolean usesResponseArgument(MethodParameter parameter) {
- return false;
- }
-
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
@@ -78,5 +79,4 @@ public class ModelMethodProcessor implements HandlerMethodArgumentResolver, Hand
throw new UnsupportedOperationException();
}
}
-
-}
+}
\ No newline at end of file
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/RequestHeaderMapMethodArgumentResolver.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/RequestHeaderMapMethodArgumentResolver.java
index a55dee18b76..e9f9643f519 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/RequestHeaderMapMethodArgumentResolver.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/RequestHeaderMapMethodArgumentResolver.java
@@ -31,10 +31,17 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
- * Implementation of {@link HandlerMethodArgumentResolver} that supports {@link Map} arguments annotated with
- * {@link RequestHeader @RequestHeader}.
+ * Resolves {@link Map} method arguments annotated with an @{@link RequestHeader}.
+ * See {@link RequestHeaderMethodArgumentResolver} for individual header values with an @{@link RequestHeader}.
+ *
+ *
The created {@link Map} contains all request header name/value pairs. If the method parameter type
+ * is {@link MultiValueMap} instead, the created map contains all request headers and all their values in case
+ * request headers have multiple values.
*
* @author Arjen Poutsma
+ * @author Rossen Stoyanchev
+ * @since 3.1
+ * @see RequestHeaderMethodArgumentResolver
*/
public class RequestHeaderMapMethodArgumentResolver implements HandlerMethodArgumentResolver {
@@ -43,10 +50,6 @@ public class RequestHeaderMapMethodArgumentResolver implements HandlerMethodArgu
&& Map.class.isAssignableFrom(parameter.getParameterType());
}
- public boolean usesResponseArgument(MethodParameter parameter) {
- return false;
- }
-
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
@@ -79,4 +82,4 @@ public class RequestHeaderMapMethodArgumentResolver implements HandlerMethodArgu
return result;
}
}
-}
+}
\ No newline at end of file
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/RequestHeaderMethodArgumentResolver.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/RequestHeaderMethodArgumentResolver.java
index 1ff704499be..b03e48dca51 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/RequestHeaderMethodArgumentResolver.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/RequestHeaderMethodArgumentResolver.java
@@ -20,18 +20,31 @@ import java.util.Map;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
+import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.context.request.NativeWebRequest;
-import org.springframework.web.method.support.HandlerMethodArgumentResolver;
/**
- * Implementation of {@link HandlerMethodArgumentResolver} that supports arguments annotated with
- * {@link RequestHeader @RequestHeader}.
+ * Resolves method arguments annotated with @{@link RequestHeader} with the exception of {@link Map} arguments.
+ * See {@link RequestHeaderMapMethodArgumentResolver} for {@link Map} arguments annotated with @{@link RequestHeader}.
+ *
+ *
An @{@link RequestHeader} is a named value that gets resolved from a request header. It has a required flag
+ * and a default value to fall back on when the request header does not exist. See the base class
+ * {@link AbstractNamedValueMethodArgumentResolver} for more information on how named values are processed.
*
+ *
A {@link WebDataBinder} is invoked to apply type conversion to resolved request header values that
+ * don't yet match the method parameter type.
+ *
* @author Arjen Poutsma
+ * @author Rossen Stoyanchev
+ * @since 3.1
*/
public class RequestHeaderMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
+ /**
+ * @param beanFactory a bean factory to use for resolving ${...} placeholder and #{...} SpEL expressions
+ * in default values, or {@code null} if default values are not expected to contain expressions
+ */
public RequestHeaderMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
super(beanFactory);
}
@@ -48,10 +61,8 @@ public class RequestHeaderMethodArgumentResolver extends AbstractNamedValueMetho
}
@Override
- protected Object resolveNamedValueArgument(NativeWebRequest webRequest,
- MethodParameter parameter,
- String headerName) throws Exception {
- String[] headerValues = webRequest.getHeaderValues(headerName);
+ protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
+ String[] headerValues = request.getHeaderValues(name);
if (headerValues != null) {
return (headerValues.length == 1 ? headerValues[0] : headerValues);
}
@@ -62,8 +73,9 @@ public class RequestHeaderMethodArgumentResolver extends AbstractNamedValueMetho
@Override
protected void handleMissingValue(String headerName, MethodParameter parameter) {
+ String paramTypeName = parameter.getParameterType().getName();
throw new IllegalStateException(
- "Missing header '" + headerName + "' of type [" + parameter.getParameterType().getName() + "]");
+ "Missing header '" + headerName + "' for method parameter type [" + paramTypeName + "]");
}
private static class RequestHeaderNamedValueInfo extends NamedValueInfo {
@@ -72,5 +84,4 @@ public class RequestHeaderMethodArgumentResolver extends AbstractNamedValueMetho
super(annotation.value(), annotation.required(), annotation.defaultValue());
}
}
-
-}
+}
\ No newline at end of file
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/RequestParamMapMethodArgumentResolver.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/RequestParamMapMethodArgumentResolver.java
index ffffe22c1e5..6d89e0e0512 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/RequestParamMapMethodArgumentResolver.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/RequestParamMapMethodArgumentResolver.java
@@ -30,10 +30,18 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
- * Implementation of {@link HandlerMethodArgumentResolver} that supports {@link Map} arguments annotated with
- * {@link RequestParam @RequestParam}.
+ * Resolves {@link Map} method arguments annotated with an @{@link RequestParam} where the annotation does not
+ * specify a request parameter name. See {@link RequestParamMethodArgumentResolver} for resolving {@link Map}
+ * method arguments with a request parameter name.
+ *
+ *
The created {@link Map} contains all request parameter name/value pairs. If the method parameter type
+ * is {@link MultiValueMap} instead, the created map contains all request parameters and all there values for
+ * cases where request parameters have multiple values.
*
* @author Arjen Poutsma
+ * @author Rossen Stoyanchev
+ * @since 3.1
+ * @see RequestParamMethodArgumentResolver
*/
public class RequestParamMapMethodArgumentResolver implements HandlerMethodArgumentResolver {
@@ -47,10 +55,6 @@ public class RequestParamMapMethodArgumentResolver implements HandlerMethodArgum
return false;
}
- public boolean usesResponseArgument(MethodParameter parameter) {
- return false;
- }
-
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
@@ -77,4 +81,4 @@ public class RequestParamMapMethodArgumentResolver implements HandlerMethodArgum
return result;
}
}
-}
+}
\ No newline at end of file
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/RequestParamMethodArgumentResolver.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/RequestParamMethodArgumentResolver.java
index 41889d0c604..792d002ba9c 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/RequestParamMethodArgumentResolver.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/RequestParamMethodArgumentResolver.java
@@ -16,6 +16,7 @@
package org.springframework.web.method.annotation.support;
+import java.beans.PropertyEditor;
import java.util.List;
import java.util.Map;
@@ -24,38 +25,51 @@ import javax.servlet.ServletException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
+import org.springframework.core.convert.converter.Converter;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.MissingServletRequestParameterException;
+import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ValueConstants;
import org.springframework.web.context.request.NativeWebRequest;
-import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;
/**
- * Implementation of {@link HandlerMethodArgumentResolver} that supports arguments annotated with
- * {@link RequestParam @RequestParam}.
- *
+ * Resolves method arguments annotated with @{@link RequestParam}.
+ *
+ *
If the method parameter type is {@link Map}, the request parameter name is resolved and then converted
+ * to a {@link Map} via type conversion assuming a suitable {@link PropertyEditor} or {@link Converter} is
+ * registered. Alternatively, see {@link RequestParamMapMethodArgumentResolver} for access to all request
+ * parameters in a {@link Map}.
+ *
+ *
If this class is created with default resolution mode on, simple types not annotated
+ * with @{@link RequestParam} are also treated as request parameters with the parameter name based
+ * on the method argument name. See the class constructor for more details.
+ *
+ *
A {@link WebDataBinder} is invoked to apply type conversion to resolved request header values that
+ * don't yet match the method parameter type.
+ *
* @author Arjen Poutsma
* @author Rossen Stoyanchev
+ * @since 3.1
+ * @see RequestParamMapMethodArgumentResolver
*/
public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
- private final boolean resolveParamsWithoutAnnotations;
+ private final boolean useDefaultResolution;
/**
- * Creates a {@link RequestParamMethodArgumentResolver} instance.
- *
- * @param beanFactory the bean factory to use for resolving default value expressions
- * @param resolveParamsWithoutAnnotations enable default resolution mode in which parameters without
- * annotations that are simple types (see {@link BeanUtils#isSimpleProperty(Class)})
- * are also treated as model attributes with a default name based on the method argument name.
+ * @param beanFactory a bean factory to use for resolving ${...} placeholder and #{...} SpEL expressions
+ * in default values, or {@code null} if default values are not expected to contain expressions
+ * @param useDefaultResolution in default resolution mode a method argument that is a simple type, as
+ * defined in {@link BeanUtils#isSimpleProperty(Class)}, is treated as a request parameter even if it doesn't have
+ * an @{@link RequestParam} annotation, the request parameter name is derived from the method parameter name.
*/
public RequestParamMethodArgumentResolver(ConfigurableBeanFactory beanFactory,
- boolean resolveParamsWithoutAnnotations) {
+ boolean useDefaultResolution) {
super(beanFactory);
- this.resolveParamsWithoutAnnotations = resolveParamsWithoutAnnotations;
+ this.useDefaultResolution = useDefaultResolution;
}
public boolean supportsParameter(MethodParameter parameter) {
@@ -67,7 +81,7 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethod
}
return true;
}
- else if (this.resolveParamsWithoutAnnotations && !parameter.hasParameterAnnotations()) {
+ else if (this.useDefaultResolution) {
return BeanUtils.isSimpleProperty(paramType);
}
else {
@@ -84,18 +98,16 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethod
}
@Override
- protected Object resolveNamedValueArgument(NativeWebRequest webRequest,
- MethodParameter parameter,
- String paramName) throws Exception {
+ protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest webRequest) throws Exception {
MultipartRequest multipartRequest = webRequest.getNativeRequest(MultipartRequest.class);
if (multipartRequest != null) {
- List files = multipartRequest.getFiles(paramName);
+ List files = multipartRequest.getFiles(name);
if (!files.isEmpty()) {
return (files.size() == 1 ? files.get(0) : files);
}
}
- String[] paramValues = webRequest.getParameterValues(paramName);
+ String[] paramValues = webRequest.getParameterValues(name);
if (paramValues != null) {
return paramValues.length == 1 ? paramValues[0] : paramValues;
}
@@ -119,5 +131,4 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethod
super(annotation.value(), annotation.required(), annotation.defaultValue());
}
}
-
-}
+}
\ No newline at end of file
diff --git a/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/ModelMethodProcessorTests.java b/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/ModelMethodProcessorTests.java
index d316ab6377d..d904c528fa1 100644
--- a/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/ModelMethodProcessorTests.java
+++ b/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/ModelMethodProcessorTests.java
@@ -17,7 +17,6 @@
package org.springframework.web.method.annotation.support;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
@@ -69,11 +68,6 @@ public class ModelMethodProcessorTests {
this.webRequest = new ServletWebRequest(new MockHttpServletRequest());
}
- @Test
- public void usesResponseArgument() {
- assertFalse(resolver.usesResponseArgument(null));
- }
-
@Test
public void supportsParameter() {
assertTrue(resolver.supportsParameter(modelParameter));
diff --git a/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/RequestHeaderMapMethodArgumentResolverTests.java b/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/RequestHeaderMapMethodArgumentResolverTests.java
index 3c61fcbee31..48fd3e7784a 100644
--- a/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/RequestHeaderMapMethodArgumentResolverTests.java
+++ b/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/RequestHeaderMapMethodArgumentResolverTests.java
@@ -35,7 +35,6 @@ import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
-import org.springframework.web.method.annotation.support.RequestHeaderMapMethodArgumentResolver;
/**
* @author Arjen Poutsma
@@ -72,11 +71,6 @@ public class RequestHeaderMapMethodArgumentResolverTests {
}
- @Test
- public void usesResponseArgument() throws NoSuchMethodException {
- assertFalse("resolver uses response argument", resolver.usesResponseArgument(null));
- }
-
@Test
public void supportsParameter() {
assertTrue("Map parameter not supported", resolver.supportsParameter(mapParameter));
diff --git a/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/RequestHeaderMethodArgumentResolverTests.java b/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/RequestHeaderMethodArgumentResolverTests.java
index d72a9f4e825..23ec0101cc0 100644
--- a/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/RequestHeaderMethodArgumentResolverTests.java
+++ b/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/RequestHeaderMethodArgumentResolverTests.java
@@ -35,7 +35,6 @@ import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.support.GenericWebApplicationContext;
-import org.springframework.web.method.annotation.support.RequestHeaderMethodArgumentResolver;
/**
* @author Arjen Poutsma
@@ -85,11 +84,6 @@ public class RequestHeaderMethodArgumentResolverTests {
RequestContextHolder.resetRequestAttributes();
}
- @Test
- public void usesResponseArgument() throws NoSuchMethodException {
- assertFalse("resolver uses response argument", resolver.usesResponseArgument(null));
- }
-
@Test
public void supportsParameter() {
assertTrue("String parameter not supported", resolver.supportsParameter(stringParameter));
diff --git a/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/RequestParamMapMethodArgumentResolverTests.java b/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/RequestParamMapMethodArgumentResolverTests.java
index a726603b99d..c77f532244c 100644
--- a/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/RequestParamMapMethodArgumentResolverTests.java
+++ b/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/RequestParamMapMethodArgumentResolverTests.java
@@ -34,7 +34,6 @@ import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
-import org.springframework.web.method.annotation.support.RequestParamMapMethodArgumentResolver;
/**
* @author Arjen Poutsma
@@ -68,11 +67,6 @@ public class RequestParamMapMethodArgumentResolverTests {
}
- @Test
- public void usesResponseArgument() throws NoSuchMethodException {
- assertFalse("resolver uses response argument", resolver.usesResponseArgument(null));
- }
-
@Test
public void supportsParameter() {
assertTrue("Map parameter not supported", resolver.supportsParameter(mapParameter));
diff --git a/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/RequestParamMethodArgumentResolverTests.java b/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/RequestParamMethodArgumentResolverTests.java
index 43df1086adb..cd0bd5b7038 100644
--- a/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/RequestParamMethodArgumentResolverTests.java
+++ b/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/RequestParamMethodArgumentResolverTests.java
@@ -36,7 +36,6 @@ import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
-import org.springframework.web.method.annotation.support.RequestParamMethodArgumentResolver;
import org.springframework.web.multipart.MultipartFile;
/**
@@ -82,11 +81,6 @@ public class RequestParamMethodArgumentResolverTests {
}
- @Test
- public void usesResponseArgument() throws NoSuchMethodException {
- assertFalse("resolver uses response argument", resolver.usesResponseArgument(null));
- }
-
@Test
public void supportsParameter() {
assertTrue("String parameter not supported", resolver.supportsParameter(stringParameter));
@@ -154,8 +148,6 @@ public class RequestParamMethodArgumentResolverTests {
@RequestParam(value = "file") MultipartFile file,
@RequestParam Map, ?> unsupported,
String plainParam) {
-
}
-
}
diff --git a/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/WebArgumentResolverAdapterTests.java b/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/WebArgumentResolverAdapterTests.java
index 182a4d89225..ec90e88beff 100644
--- a/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/WebArgumentResolverAdapterTests.java
+++ b/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/WebArgumentResolverAdapterTests.java
@@ -33,7 +33,6 @@ import org.springframework.web.bind.support.WebArgumentResolver;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletWebRequest;
-import org.springframework.web.method.annotation.support.WebArgumentResolverAdapter;
/**
* @author Arjen Poutsma
@@ -42,7 +41,7 @@ public class WebArgumentResolverAdapterTests {
private WebArgumentResolver adaptee;
- private WebArgumentResolverAdapter adapter;
+ private TestWebArgumentResolverAdapter adapter;
private MethodParameter parameter;
@@ -51,7 +50,7 @@ public class WebArgumentResolverAdapterTests {
@Before
public void setUp() throws Exception {
adaptee = createMock(WebArgumentResolver.class);
- adapter = new WebArgumentResolverAdapter(adaptee);
+ adapter = new TestWebArgumentResolverAdapter(adaptee);
parameter = new MethodParameter(getClass().getMethod("handle", Integer.TYPE), 0);
@@ -162,4 +161,17 @@ public class WebArgumentResolverAdapterTests {
public void handle(int param) {
}
+
+ private class TestWebArgumentResolverAdapter extends AbstractWebArgumentResolverAdapter {
+
+ public TestWebArgumentResolverAdapter(WebArgumentResolver adaptee) {
+ super(adaptee);
+ }
+
+ @Override
+ protected NativeWebRequest getWebRequest() {
+ return WebArgumentResolverAdapterTests.this.webRequest;
+ }
+ }
+
}