diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java index fff6b623587..8139a275d64 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java @@ -33,11 +33,10 @@ import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.xml.SourceHttpMessageConverter; import org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter; import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.support.WebArgumentResolver; import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.annotation.ExceptionHandlerMethodResolver; +import org.springframework.web.method.annotation.support.MapMethodProcessor; import org.springframework.web.method.annotation.support.ModelAttributeMethodProcessor; import org.springframework.web.method.annotation.support.ModelMethodProcessor; import org.springframework.web.method.support.HandlerMethodArgumentResolver; @@ -48,29 +47,23 @@ import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.View; import org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver; -import org.springframework.web.servlet.mvc.method.annotation.support.DefaultMethodReturnValueHandler; import org.springframework.web.servlet.mvc.method.annotation.support.HttpEntityMethodProcessor; import org.springframework.web.servlet.mvc.method.annotation.support.ModelAndViewMethodReturnValueHandler; import org.springframework.web.servlet.mvc.method.annotation.support.RequestResponseBodyMethodProcessor; import org.springframework.web.servlet.mvc.method.annotation.support.ServletRequestMethodArgumentResolver; import org.springframework.web.servlet.mvc.method.annotation.support.ServletResponseMethodArgumentResolver; -import org.springframework.web.servlet.mvc.method.annotation.support.ServletWebArgumentResolverAdapter; import org.springframework.web.servlet.mvc.method.annotation.support.ViewMethodReturnValueHandler; +import org.springframework.web.servlet.mvc.method.annotation.support.ViewNameMethodReturnValueHandler; /** - * An {@link AbstractHandlerMethodExceptionResolver} that supports using {@link ExceptionHandler}-annotated methods - * to resolve exceptions. - * - *
{@link ExceptionHandlerMethodResolver} is a key contributing class that stores method-to-exception mappings extracted - * from {@link ExceptionHandler} annotations or from the list of method arguments on the exception-handling method. - * {@link ExceptionHandlerMethodResolver} assists with actually locating a method for a thrown exception. - * - *
Once located the invocation of the exception-handling method is done using much of the same classes - * used for {@link RequestMapping} methods, which is described under {@link RequestMappingHandlerAdapter}. - * - *
See {@link ExceptionHandler} for information on supported method arguments and return values for - * exception-handling methods. + * An {@link AbstractHandlerMethodExceptionResolver} that resolves exceptions + * through {@code @ExceptionHandler} methods. * + *
Support for custom argument and return value types can be added via
+ * {@link #setCustomArgumentResolvers} and {@link #setCustomReturnValueHandlers}.
+ * Or alternatively to re-configure all argument and return value types use
+ * {@link #setArgumentResolvers} and {@link #setReturnValueHandlers(List)}.
+ *
* @author Rossen Stoyanchev
* @since 3.1
*/
@@ -91,66 +84,96 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
/**
- * Creates an instance of {@link ExceptionHandlerExceptionResolver}.
+ * Default constructor.
*/
public ExceptionHandlerExceptionResolver() {
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false); // See SPR-7316
- messageConverters = new ArrayList An existing {@link WebArgumentResolver} can either adapted with {@link ServletWebArgumentResolverAdapter}
- * or preferably converted to a {@link HandlerMethodArgumentResolver} instead.
+ * Provide resolvers for custom argument types. Custom resolvers are ordered
+ * after built-in ones. To override the built-in support for argument
+ * resolution use {@link #setArgumentResolvers} instead.
*/
public void setCustomArgumentResolvers(List These converters are used to convert from and to HTTP requests and responses.
@@ -158,44 +181,72 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
public void setMessageConverters(List Note: This method is available for backwards
+ * compatibility only. However, it is recommended to re-write a
+ * {@code ModelAndViewResolver} as {@link HandlerMethodReturnValueHandler}.
+ * An adapter between the two interfaces is not possible since the
+ * {@link HandlerMethodReturnValueHandler#supportsReturnType} method
+ * cannot be implemented. Hence {@code ModelAndViewResolver}s are limited
+ * to always being invoked at the end after all other return value
+ * handlers have been given a chance.
+ * A {@code HandlerMethodReturnValueHandler} provides better access to
+ * the return type and controller method information and can be ordered
+ * freely relative to other return value handlers.
*/
public void setModelAndViewResolvers(List Handling takes place in the following order:
- * 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
- */
-public class DefaultMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
-
- private final List The return value is handled either with a {@link ModelAndViewResolver}
+ * or otherwise by regarding it as a model attribute if it is a non-simple
+ * type. If neither of these succeeds (essentially simple type other than
+ * String), {@link UnsupportedOperationException} is raised.
+ *
+ * Note: This class is primarily needed to support
+ * {@link ModelAndViewResolver}, which unfortunately cannot be properly
+ * adapted to the {@link HandlerMethodReturnValueHandler} contract since the
+ * {@link HandlerMethodReturnValueHandler#supportsReturnType} method
+ * cannot be implemented. Hence {@code ModelAndViewResolver}s are limited
+ * to always being invoked at the end after all other return value
+ * handlers have been given a chance. It is recommended to re-implement
+ * a {@code ModelAndViewResolver} as {@code HandlerMethodReturnValueHandler},
+ * which also provides better access to the return type and method information.
+ *
+ * @author Rossen Stoyanchev
+ * @since 3.1
+ */
+public class ModelAndViewResolverMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
+
+ private final List This resolver must be listed before the {@link ModelMethodProcessor},
- * which resolves {@link Map} and {@link Model} arguments.
+ * This resolver must be listed ahead of {@link ModelMethodProcessor} and
+ * {@link MapMethodProcessor}, which support {@link Map} and {@link Model}
+ * arguments both of which are "super" types of {@code RedirectAttributes}
+ * and would also attempt to resolve a {@code RedirectAttributes} argument.
*
* @author Rossen Stoyanchev
* @since 3.1
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestPartMethodArgumentResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestPartMethodArgumentResolver.java
index 8bdde212d4a..bd03b9d3c19 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestPartMethodArgumentResolver.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestPartMethodArgumentResolver.java
@@ -48,26 +48,26 @@ import org.springframework.web.util.WebUtils;
/**
* Resolves the following method arguments:
* When a parameter is annotated with @{@link RequestPart} the content of the
+ * When a parameter is annotated with {@code @RequestPart} the content of the
* part is passed through an {@link HttpMessageConverter} to resolve the method
* argument with the 'Content-Type' of the request part in mind. This is
* analogous to what @{@link RequestBody} does to resolve an argument based on
- * the content of a non-multipart request.
+ * the content of a regular request.
*
* When a parameter is not annotated or the name of the part is not specified,
* it is derived from the name of the method argument.
*
- * Automatic validation can be applied to a @{@link RequestPart} method argument
- * through the use of {@code @Valid}. In case of validation failure, a
- * {@link MethodArgumentNotValidException} is thrown and handled automatically by
- * the {@link DefaultHandlerExceptionResolver}.
+ * Automatic validation may be applied if the argument is annotated with
+ * {@code @javax.validation.Valid}. In case of validation failure, a
+ * {@link MethodArgumentNotValidException} is raised and a 400 response status
+ * code returned if {@link DefaultHandlerExceptionResolver} is configured.
*
* @author Rossen Stoyanchev
* @since 3.1
@@ -81,9 +81,9 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM
/**
* Supports the following:
* An @{@link RequestBody} method argument will be validated if annotated with {@code @Valid}.
- * In case of validation failure, a {@link MethodArgumentNotValidException} is thrown and handled
- * automatically in {@link DefaultHandlerExceptionResolver}.
+ * An {@code @RequestBody} method argument is also validated if it is
+ * annotated with {@code @javax.validation.Valid}. In case of validation
+ * failure, {@link MethodArgumentNotValidException} is raised and results
+ * in a 400 response status code if {@link DefaultHandlerExceptionResolver}
+ * is configured.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
@@ -78,13 +82,12 @@ public class RequestResponseBodyMethodProcessor extends AbstractMessageConverter
}
/**
- * Whether to validate the given @{@link RequestBody} method argument. The default implementation checks
- * if the parameter is also annotated with {@code @Valid}.
- * @param argumentValue the validation candidate
- * @param parameter the method argument declaring the validation candidate
- * @return {@code true} if validation should be invoked, {@code false} otherwise.
+ * Whether to validate the given {@code @RequestBody} method argument.
+ * The default implementation looks for {@code @javax.validation.Valid}.
+ * @param argument the resolved argument value
+ * @param parameter the method argument
*/
- protected boolean isValidationApplicable(Object argumentValue, MethodParameter parameter) {
+ protected boolean isValidationApplicable(Object argument, MethodParameter parameter) {
Annotation[] annotations = parameter.getParameterAnnotations();
for (Annotation annot : annotations) {
if ("Valid".equals(annot.annotationType().getSimpleName())) {
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 b505c69ca81..8e3013da681 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
@@ -27,7 +27,8 @@ import org.springframework.web.util.UrlPathHelper;
import org.springframework.web.util.WebUtils;
/**
- * A {@link AbstractCookieValueMethodArgumentResolver} that resolves the cookie value through the {@link HttpServletRequest}.
+ * An {@link AbstractCookieValueMethodArgumentResolver} that resolves cookie
+ * values from an {@link HttpServletRequest}.
*
* @author Rossen Stoyanchev
* @since 3.1
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 0646a7ef7fd..ff028065243 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
@@ -16,32 +16,29 @@
package org.springframework.web.servlet.mvc.method.annotation.support;
-import java.beans.PropertyEditor;
+import java.util.Collections;
import java.util.Map;
import javax.servlet.ServletRequest;
-import org.springframework.beans.BeanUtils;
import org.springframework.core.MethodParameter;
-import org.springframework.core.convert.converter.Converter;
import org.springframework.validation.DataBinder;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.WebDataBinder;
-import org.springframework.web.bind.annotation.ModelAttribute;
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.method.annotation.support.ModelAttributeMethodProcessor;
import org.springframework.web.servlet.HandlerMapping;
+import org.springframework.web.servlet.mvc.method.annotation.ServletRequestDataBinderFactory;
/**
- * A Servlet-specific {@link ModelAttributeMethodProcessor} variant with the following further benefits:
- * Also adds a fall-back strategy to instantiate a model attribute from a
+ * URI template variable combined with type conversion, if the model attribute
+ * name matches to a URI template variable name.
*
* @author Rossen Stoyanchev
* @since 3.1
@@ -49,39 +46,37 @@ import org.springframework.web.servlet.HandlerMapping;
public class ServletModelAttributeMethodProcessor extends ModelAttributeMethodProcessor {
/**
- * @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.
+ * @param annotationNotRequired if {@code true}, any non-simple type
+ * argument or return value is regarded as a model attribute even without
+ * the presence of a {@code @ModelAttribute} annotation in which case the
+ * attribute name is derived from the model attribute's type.
*/
- public ServletModelAttributeMethodProcessor(boolean useDefaultResolution) {
- super(useDefaultResolution);
+ public ServletModelAttributeMethodProcessor(boolean annotationNotRequired) {
+ super(annotationNotRequired);
}
/**
- * Instantiates the model attribute by trying to match the model attribute name to a path variable.
- * If a match is found an attempt is made to convert the String path variable to the expected
- * method parameter type through a registered {@link Converter} or {@link PropertyEditor}.
- * If this fails the call is delegated back to the parent for default constructor instantiation.
+ * Add a fall-back strategy to instantiate the model attribute from a URI
+ * template variable and type conversion, assuming the model attribute
+ * name matches to a URI variable name. If instantiation fails for _any_
+ * reason, the call is delegated to the base class.
*/
@Override
- @SuppressWarnings("unchecked")
protected Object createAttribute(String attributeName,
MethodParameter parameter,
WebDataBinderFactory binderFactory,
NativeWebRequest request) throws Exception {
- Map This implementation downcasts to {@link ServletRequestDataBinder} before invoking the bind operation.
+ * Downcast {@link WebDataBinder} to {@link ServletRequestDataBinder} before binding.
+ * @see ServletRequestDataBinderFactory
*/
@Override
protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) {
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 23042cb3b61..de3a9c25ae2 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
@@ -29,7 +29,6 @@ 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;
/**
* Resolves response-related method argument values of types:
@@ -53,11 +52,10 @@ public class ServletResponseMethodArgumentResolver implements HandlerMethodArgum
}
/**
- * {@inheritDoc}
- * Sets the {@link ModelAndViewContainer#setRequestHandled(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...)
+ * Set {@link ModelAndViewContainer#setRequestHandled(boolean)} to
+ * {@code false} to indicate that the method signature provides access
+ * to the response. If subsequently the underlying method returns
+ * {@code null}, the request is considered directly handled.
*/
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java
index c8977750b01..0e35d629ae7 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java
@@ -59,7 +59,6 @@ import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
-import org.springframework.web.servlet.mvc.method.annotation.support.DefaultMethodReturnValueHandler;
/**
* A test fixture for {@link WebMvcConfigurationSupport}.
@@ -285,7 +284,7 @@ public class WebMvcConfigurationSupportTests {
@Override
public void addReturnValueHandlers(List The default implementation checks if target object name is included
+ * in the attribute names specified in the {@code @InitBinder} annotation.
*/
- protected boolean isBinderMethodApplicable(HandlerMethod binderMethod, WebDataBinder binder) {
+ protected boolean invokeInitBinderMethod(HandlerMethod binderMethod, WebDataBinder binder) {
InitBinder annot = binderMethod.getMethodAnnotation(InitBinder.class);
Collection 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.
+ * An {@code @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.
*
- * A {@link WebDataBinder} is invoked to apply type conversion to resolved cookie values that don't yet match
- * the method parameter type.
+ * A {@link WebDataBinder} may be invoked to apply type conversion to the
+ * resolved cookie value.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
@@ -40,8 +40,9 @@ import org.springframework.web.bind.annotation.CookieValue;
public abstract class AbstractCookieValueMethodArgumentResolver 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
+ * @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);
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/AbstractWebArgumentResolverAdapter.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/AbstractWebArgumentResolverAdapter.java
index fc6879f299d..4f8bc923ffa 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/AbstractWebArgumentResolverAdapter.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/AbstractWebArgumentResolverAdapter.java
@@ -21,7 +21,6 @@ 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;
@@ -29,18 +28,18 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
- * 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.
+ * An abstract base class adapting a {@link WebArgumentResolver} to the
+ * {@link HandlerMethodArgumentResolver} contract.
*
- * 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.
+ * Note: This class is provided for backwards compatibility.
+ * However it is recommended to re-write a {@code WebArgumentResolver} as
+ * {@code HandlerMethodArgumentResolver}. Since {@link #supportsParameter}
+ * can only be implemented by actually resolving the value and then checking
+ * the result is not {@code WebArgumentResolver#UNRESOLVED} any exceptions
+ * raised must be absorbed and ignored since it's not clear whether the adapter
+ * doesn't support the parameter or whether it failed for an internal reason.
+ * The {@code HandlerMethodArgumentResolver} contract also provides access to
+ * model attributes and to {@code WebDataBinderFactory} (for type conversion).
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
@@ -53,7 +52,7 @@ public abstract class AbstractWebArgumentResolverAdapter implements HandlerMetho
private final WebArgumentResolver adaptee;
/**
- * Create a {@link AbstractWebArgumentResolverAdapter} with the {@link WebArgumentResolver} instance to delegate to.
+ * Create a new instance.
*/
public AbstractWebArgumentResolverAdapter(WebArgumentResolver adaptee) {
Assert.notNull(adaptee, "'adaptee' must not be null");
@@ -61,12 +60,13 @@ public abstract class AbstractWebArgumentResolverAdapter implements HandlerMetho
}
/**
- * See the class-level documentation for an important consideration about exceptions arising in this method.
+ * Actually resolve the value and check the resolved value is not
+ * {@link WebArgumentResolver#UNRESOLVED} absorbing _any_ exceptions.
*/
public boolean supportsParameter(MethodParameter parameter) {
try {
NativeWebRequest webRequest = getWebRequest();
- Object result = adaptee.resolveArgument(parameter, webRequest);
+ Object result = this.adaptee.resolveArgument(parameter, webRequest);
if (result == WebArgumentResolver.UNRESOLVED) {
return false;
}
@@ -82,21 +82,21 @@ public abstract class AbstractWebArgumentResolverAdapter implements HandlerMetho
}
/**
- * Provide access to a {@link NativeWebRequest}.
+ * Required for access to NativeWebRequest in {@link #supportsParameter}.
*/
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.
+ * Delegate to the {@link WebArgumentResolver} instance.
+ * @exception IllegalStateException if the resolved value is not assignable
+ * to the method parameter.
*/
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
Class> paramType = parameter.getParameterType();
- Object result = adaptee.resolveArgument(parameter, webRequest);
+ Object result = this.adaptee.resolveArgument(parameter, webRequest);
if (result == WebArgumentResolver.UNRESOLVED || !ClassUtils.isAssignableValue(paramType, result)) {
throw new IllegalStateException(
"Standard argument type [" + paramType.getName() + "] in method " + parameter.getMethod() +
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 c66019a9256..b80b1c50685 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
@@ -28,10 +28,12 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
- * Resolves method arguments of type {@link Errors} and {@link BindingResult}.
+ * Resolves {@link Errors} method arguments.
*
- * 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}.
+ * An {@code Errors} method argument is expected to appear immediately after
+ * the model attribute in the method signature. It is resolved by expecting the
+ * last two attributes added to the model to be the model attribute and its
+ * {@link BindingResult}.
*
* @author Rossen Stoyanchev
* @since 3.1
@@ -57,8 +59,8 @@ public class ErrorsMethodArgumentResolver implements HandlerMethodArgumentResolv
}
throw new IllegalStateException(
- "An Errors/BindingResult argument must follow a model attribute argument. " +
- "Check your handler method signature: " + parameter.getMethod());
+ "An Errors/BindingResult argument is expected to be immediately after the model attribute " +
+ "argument in the controller method signature: " + parameter.getMethod());
}
}
\ 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 05586ca08fc..292312056c2 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
@@ -25,14 +25,14 @@ import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.context.request.NativeWebRequest;
/**
- * Resolves method arguments annotated with @{@link Value}.
+ * Resolves method arguments annotated with {@code @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.
+ * An {@code @Value} does not have a name but gets resolved from the default
+ * value string, which may contain ${...} placeholder or Spring Expression
+ * Language #{...} expressions.
*
- * A {@link WebDataBinder} is invoked to apply type conversion to resolved argument values that don't yet match
- * the method parameter type.
+ * A {@link WebDataBinder} may be invoked to apply type conversion to
+ * resolved argument value.
*
* @author Rossen Stoyanchev
* @since 3.1
@@ -40,8 +40,9 @@ import org.springframework.web.context.request.NativeWebRequest;
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
+ * @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);
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 5e82f3e65c0..dd1efa95662 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
@@ -23,7 +23,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.core.MethodParameter;
import org.springframework.validation.BindException;
-import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
@@ -36,15 +35,18 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
- * 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.
+ * Resolves method arguments annotated with {@code @ModelAttribute} and handles
+ * return values from methods annotated with {@code @ModelAttribute}.
+ *
+ * Model attributes are obtained from the model or if not found possibly
+ * created with a default constructor if it is available. Once created, the
+ * attributed is populated with request data via data binding and also
+ * validation may be applied if the argument is annotated with
+ * {@code @javax.validation.Valid}.
*
- * A model attribute argument is obtained from the model or otherwise is created with a default constructor.
- * Data binding and validation are applied through a {@link WebDataBinder} instance. Validation is applied
- * only when the argument is also annotated with {@code @Valid}.
- *
- * Also handles return values from methods annotated with an @{@link ModelAttribute}. The return value is
- * added to the {@link ModelAndViewContainer}.
+ * When this handler is created with {@code annotationNotRequired=true},
+ * any non-simple type argument and return value is regarded as a model
+ * attribute with or without the presence of an {@code @ModelAttribute}.
*
* @author Rossen Stoyanchev
* @since 3.1
@@ -53,26 +55,27 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
protected Log logger = LogFactory.getLog(this.getClass());
- private final boolean useDefaultResolution;
+ private final boolean annotationNotRequired;
/**
- * @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.
+ * @param annotationNotRequired if {@code true}, any non-simple type
+ * argument or return value is regarded as a model attribute even without
+ * the presence of a {@code @ModelAttribute} annotation in which case the
+ * attribute name is derived from the model attribute's type.
*/
- public ModelAttributeMethodProcessor(boolean useDefaultResolution) {
- this.useDefaultResolution = useDefaultResolution;
+ public ModelAttributeMethodProcessor(boolean annotationNotRequired) {
+ this.annotationNotRequired = annotationNotRequired;
}
/**
- * @return true if the parameter is annotated with {@link ModelAttribute} or if it is a
- * simple type without any annotations.
+ * @return true if the parameter is annotated with {@link ModelAttribute}
+ * or in default resolution mode also if it is not a simple type.
*/
public boolean supportsParameter(MethodParameter parameter) {
if (parameter.hasParameterAnnotation(ModelAttribute.class)) {
return true;
}
- else if (this.useDefaultResolution) {
+ else if (this.annotationNotRequired) {
return !BeanUtils.isSimpleProperty(parameter.getParameterType());
}
else {
@@ -81,13 +84,13 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
}
/**
- * 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 BindException if data binding and validation result in an error and the next method parameter
- * is neither of type {@link Errors} nor {@link BindingResult}.
- * @throws Exception if a {@link WebDataBinder} could not be created.
+ * Resolve the argument from the model or if not found instantiate it with
+ * its default if it is available. The model attribute is then populated
+ * with request values via data binding and optionally validated
+ * if {@code @java.validation.Valid} is present on the argument.
+ * @throws BindException if data binding and validation result in an error
+ * and the next method parameter is not of type {@link Errors}.
+ * @throws Exception if WebDataBinder initialization fails.
*/
public final Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
@@ -119,16 +122,13 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
}
/**
- * Creates an instance of the specified model attribute. This method is invoked only if the attribute is
- * not available in the model. This default implementation uses the no-argument constructor.
- * Subclasses can override to provide additional means of creating the model attribute.
- *
- * @param attributeName the name of the model attribute
- * @param parameter the method argument declaring the model attribute
- * @param binderFactory a factory for creating {@link WebDataBinder} instances
+ * Extension point to create the model attribute if not found in the model.
+ * The default implementation uses the default constructor.
+ * @param attributeName the name of the attribute, never {@code null}
+ * @param parameter the method parameter
+ * @param binderFactory for creating WebDataBinder instance
* @param request the current request
- * @return the created model attribute; never {@code null}
- * @throws Exception raised in the process of creating the instance
+ * @return the created model attribute, never {@code null}
*/
protected Object createAttribute(String attributeName,
MethodParameter parameter,
@@ -138,9 +138,8 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
}
/**
- * Bind the request to the target object contained in the provided binder instance.
- *
- * @param binder the binder with the target object to apply request values to
+ * Extension point to bind the request to the target object.
+ * @param binder the data binder instance to use for the binding
* @param request the current request
*/
protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) {
@@ -148,12 +147,12 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
}
/**
- * Whether to validate the given model attribute argument value.
- * @param argumentValue the validation candidate
- * @param parameter the method argument declaring the validation candidate
- * @return {@code true} if validation should be applied, {@code false} otherwise.
+ * Whether to validate the model attribute.
+ * The default implementation checks for {@code @javax.validation.Valid}.
+ * @param modelAttribute the model attribute
+ * @param parameter the method argument
*/
- protected boolean isValidationApplicable(Object argumentValue, MethodParameter parameter) {
+ protected boolean isValidationApplicable(Object modelAttribute, MethodParameter parameter) {
Annotation[] annotations = parameter.getParameterAnnotations();
for (Annotation annot : annotations) {
if ("Valid".equals(annot.annotationType().getSimpleName())) {
@@ -164,10 +163,11 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
}
/**
- * Whether to raise a {@link BindException} in case of data binding or validation errors.
- * @param binder the binder on which validation is to be invoked
- * @param parameter the method argument for which data binding is performed
- * @return true if the binding or validation errors should result in a {@link BindException}, false otherwise.
+ * Whether to raise a {@link BindException} on bind or validation errors.
+ * The default implementation returns {@code true} if the next method
+ * argument is not of type {@link Errors}.
+ * @param binder the data binder used to perform data binding
+ * @param parameter the method argument
*/
protected boolean isBindExceptionRequired(WebDataBinder binder, MethodParameter parameter) {
int i = parameter.getParameterIndex();
@@ -177,10 +177,25 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
return !hasBindingResult;
}
+ /**
+ * Return {@code true} if there is a method-level {@code @ModelAttribute}
+ * or if it is a non-simple type when {@code annotationNotRequired=true}.
+ */
public boolean supportsReturnType(MethodParameter returnType) {
- return returnType.getMethodAnnotation(ModelAttribute.class) != null;
+ if (returnType.getMethodAnnotation(ModelAttribute.class) != null) {
+ return true;
+ }
+ else if (this.annotationNotRequired) {
+ return !BeanUtils.isSimpleProperty(returnType.getParameterType());
+ }
+ else {
+ return false;
+ }
}
+ /**
+ * Add non-null return values to the {@link ModelAndViewContainer}.
+ */
public void handleReturnValue(Object returnValue,
MethodParameter returnType,
ModelAndViewContainer mavContainer,
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 2e175e4a67a..5fb98180804 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
@@ -25,7 +25,7 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
- * Resolves {@link Model} method arguments and handles {@link Model} return values.
+ * Resolves {@link Model} arguments and handles {@link Model} return values.
*
* A {@link Model} return type has a set purpose. Therefore this handler
* should be configured ahead of handlers that support any return value type
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 e9f9643f519..72204f23763 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,17 +31,17 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
- * Resolves {@link Map} method arguments annotated with an @{@link RequestHeader}.
- * See {@link RequestHeaderMethodArgumentResolver} for individual header values with an @{@link RequestHeader}.
+ * Resolves {@link Map} method arguments annotated with {@code @RequestHeader}.
+ * For individual header values annotated with {@code @RequestHeader} see
+ * {@link RequestHeaderMethodArgumentResolver} instead.
*
- * 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.
+ * The created {@link Map} contains all request header name/value pairs.
+ * The method parameter type may be a {@link MultiValueMap} to receive all
+ * values for a header, not only the first one.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @since 3.1
- * @see RequestHeaderMethodArgumentResolver
*/
public class RequestHeaderMapMethodArgumentResolver implements HandlerMethodArgumentResolver {
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 8ad38595e3b..beaf0f81b5f 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
@@ -26,15 +26,16 @@ import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.context.request.NativeWebRequest;
/**
- * 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}.
+ * Resolves method arguments annotated with {@code @RequestHeader} except for
+ * {@link Map} arguments. See {@link RequestHeaderMapMethodArgumentResolver} for
+ * details on {@link Map} arguments annotated with {@code @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.
+ * An {@code @RequestHeader} is a named value 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.
*
- * A {@link WebDataBinder} is invoked to apply type conversion to resolved request header values that
- * don't yet match the method parameter type.
+ * 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
@@ -43,8 +44,9 @@ import org.springframework.web.context.request.NativeWebRequest;
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
+ * @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 have expressions
*/
public RequestHeaderMethodArgumentResolver(ConfigurableBeanFactory beanFactory) {
super(beanFactory);
diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/SessionStatusMethodArgumentResolver.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/SessionStatusMethodArgumentResolver.java
index 895bf5022d0..11af589df18 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/SessionStatusMethodArgumentResolver.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/SessionStatusMethodArgumentResolver.java
@@ -24,8 +24,8 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
- * Resolves {@link SessionStatus} arguments by obtaining it from the
- * {@link ModelAndViewContainer}.
+ * Resolves a {@link SessionStatus} argument by obtaining it from
+ * the {@link ModelAndViewContainer}.
*
* @author Rossen Stoyanchev
* @since 3.1
diff --git a/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/ModelAttributeMethodProcessorTests.java b/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/ModelAttributeMethodProcessorTests.java
index 371040f7eea..fdca12571d3 100644
--- a/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/ModelAttributeMethodProcessorTests.java
+++ b/org.springframework.web/src/test/java/org/springframework/web/method/annotation/support/ModelAttributeMethodProcessorTests.java
@@ -137,7 +137,7 @@ public class ModelAttributeMethodProcessorTests {
public void supportedReturnTypesInDefaultResolutionMode() throws Exception {
processor = new ModelAttributeMethodProcessor(true);
assertTrue(processor.supportsReturnType(returnParamNamedModelAttr));
- assertFalse(processor.supportsReturnType(returnParamNonSimpleType));
+ assertTrue(processor.supportsReturnType(returnParamNonSimpleType));
}
@Test
- *
- *
- *
*
- *
- *
*/
public boolean supportsParameter(MethodParameter parameter) {
@@ -193,15 +193,13 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM
}
/**
- * Whether to validate the given @{@link RequestPart} method argument.
- * The default implementation return {@code true} if the argument value is not {@code null}
- * and the method parameter is annotated with {@code @Valid}.
- * @param argumentValue the validation candidate
- * @param parameter the method argument declaring the validation candidate
- * @return {@code true} if validation should be invoked, {@code false} otherwise.
+ * Whether to validate the given {@code @RequestPart} method argument.
+ * The default implementation looks for {@code @javax.validation.Valid}.
+ * @param argument the resolved argument value
+ * @param parameter the method argument
*/
- protected boolean isValidationApplicable(Object argumentValue, MethodParameter parameter) {
- if (argumentValue == null) {
+ protected boolean isValidationApplicable(Object argument, MethodParameter parameter) {
+ if (argument == null) {
return false;
}
else {
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 0dd3f2e0bd7..74e07211bb2 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
@@ -35,12 +35,16 @@ import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
/**
- * Resolves method arguments annotated with @{@link RequestBody} and handles return values from methods
- * annotated with {@link ResponseBody}.
+ * Resolves method arguments annotated with {@code @RequestBody} and handles
+ * return values from methods annotated with {@code @ResponseBody} by reading
+ * and writing to the body of the request or response with an
+ * {@link HttpMessageConverter}.
*
- *
- *
- * that casts
- * instance to {@link ServletRequestDataBinder} prior to invoking data binding.
+ * A Servlet-specific {@link ModelAttributeMethodProcessor} that applies data
+ * binding through a WebDataBinder of type {@link ServletRequestDataBinder}.
+ *
+ *