Revised validation javadoc, plus protected validate/isBindingErrorFatal template methods

Issue: SPR-12655
This commit is contained in:
Juergen Hoeller 2015-02-10 19:28:30 +01:00
parent 981aefc2c0
commit 7585be85f3
5 changed files with 60 additions and 37 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -144,6 +144,16 @@ public class PayloadArgumentResolver implements HandlerMethodArgumentResolver {
} }
} }
/**
* Validate the payload if applicable.
* <p>The default implementation checks for {@code @javax.validation.Valid},
* Spring's {@link org.springframework.validation.annotation.Validated},
* and custom annotations whose name starts with "Valid".
* @param message the currently processed message
* @param parameter the method parameter
* @param target the target payload object
* @throws MethodArgumentNotValidException in case of binding errors
*/
protected void validate(Message<?> message, MethodParameter parameter, Object target) { protected void validate(Message<?> message, MethodParameter parameter, Object target) {
if (this.validator == null) { if (this.validator == null) {
return; return;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -56,7 +56,7 @@ import org.springframework.web.method.support.ModelAndViewContainer;
*/ */
public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler { public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler {
protected Log logger = LogFactory.getLog(this.getClass()); protected final Log logger = LogFactory.getLog(getClass());
private final boolean annotationNotRequired; private final boolean annotationNotRequired;
@ -72,8 +72,8 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
/** /**
* @return true if the parameter is annotated with {@link ModelAttribute} * Returns {@code true} if the parameter is annotated with {@link ModelAttribute}
* or in default resolution mode also if it is not a simple type. * or in default resolution mode, and also if it is not a simple type.
*/ */
@Override @Override
public boolean supportsParameter(MethodParameter parameter) { public boolean supportsParameter(MethodParameter parameter) {
@ -151,7 +151,9 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
/** /**
* Validate the model attribute if applicable. * Validate the model attribute if applicable.
* <p>The default implementation checks for {@code @javax.validation.Valid}. * <p>The default implementation checks for {@code @javax.validation.Valid},
* Spring's {@link org.springframework.validation.annotation.Validated},
* and custom annotations whose name starts with "Valid".
* @param binder the DataBinder to be used * @param binder the DataBinder to be used
* @param parameter the method parameter * @param parameter the method parameter
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -37,6 +37,7 @@ import org.springframework.http.converter.GenericHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.validation.Errors;
import org.springframework.web.HttpMediaTypeNotSupportedException; import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodArgumentResolver;
@ -79,6 +80,7 @@ public abstract class AbstractMessageConverterMethodArgumentResolver implements
return Collections.unmodifiableList(result); return Collections.unmodifiableList(result);
} }
/** /**
* Create the method argument value of the expected parameter type by * Create the method argument value of the expected parameter type by
* reading from the given request. * reading from the given request.
@ -162,4 +164,17 @@ public abstract class AbstractMessageConverterMethodArgumentResolver implements
return new ServletServerHttpRequest(servletRequest); return new ServletServerHttpRequest(servletRequest);
} }
/**
* Whether to raise a handler method invocation exception on validation errors.
* @param parameter the method argument
* @return {@code true} if the next method argument is not of type {@link Errors}
* @since 4.1.5
*/
protected boolean isBindingErrorFatal(MethodParameter parameter) {
int i = parameter.getParameterIndex();
Class<?>[] paramTypes = parameter.getMethod().getParameterTypes();
boolean hasBindingResult = (paramTypes.length > (i + 1) && Errors.class.isAssignableFrom(paramTypes[i + 1]));
return !hasBindingResult;
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -222,7 +222,18 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM
return null; return null;
} }
private void validate(WebDataBinder binder, MethodParameter parameter) throws MethodArgumentNotValidException { /**
* Validate the request part if applicable.
* <p>The default implementation checks for {@code @javax.validation.Valid},
* Spring's {@link org.springframework.validation.annotation.Validated},
* and custom annotations whose name starts with "Valid".
* @param binder the DataBinder to be used
* @param parameter the method parameter
* @throws MethodArgumentNotValidException in case of a binding error which
* is meant to be fatal (i.e. without a declared {@link Errors} parameter)
* @see #isBindingErrorFatal
*/
protected void validate(WebDataBinder binder, MethodParameter parameter) throws MethodArgumentNotValidException {
Annotation[] annotations = parameter.getParameterAnnotations(); Annotation[] annotations = parameter.getParameterAnnotations();
for (Annotation ann : annotations) { for (Annotation ann : annotations) {
Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class); Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class);
@ -240,18 +251,6 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM
} }
} }
/**
* Whether to raise a {@link MethodArgumentNotValidException} on validation errors.
* @param parameter the method argument
* @return {@code true} if the next method argument is not of type {@link Errors}
*/
private boolean isBindingErrorFatal(MethodParameter parameter) {
int i = parameter.getParameterIndex();
Class<?>[] paramTypes = parameter.getMethod().getParameterTypes();
boolean hasBindingResult = (paramTypes.length > (i + 1) && Errors.class.isAssignableFrom(paramTypes[i + 1]));
return !hasBindingResult;
}
/** /**
* Inner class to avoid hard-coded dependency on Servlet 3.0 Part type... * Inner class to avoid hard-coded dependency on Servlet 3.0 Part type...

View File

@ -112,7 +112,18 @@ public class RequestResponseBodyMethodProcessor extends AbstractMessageConverter
return argument; return argument;
} }
private void validate(WebDataBinder binder, MethodParameter parameter) throws Exception { /**
* Validate the request part if applicable.
* <p>The default implementation checks for {@code @javax.validation.Valid},
* Spring's {@link org.springframework.validation.annotation.Validated},
* and custom annotations whose name starts with "Valid".
* @param binder the DataBinder to be used
* @param parameter the method parameter
* @throws MethodArgumentNotValidException in case of a binding error which
* is meant to be fatal (i.e. without a declared {@link Errors} parameter)
* @see #isBindingErrorFatal
*/
protected void validate(WebDataBinder binder, MethodParameter parameter) throws MethodArgumentNotValidException {
Annotation[] annotations = parameter.getParameterAnnotations(); Annotation[] annotations = parameter.getParameterAnnotations();
for (Annotation ann : annotations) { for (Annotation ann : annotations) {
Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class); Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class);
@ -122,7 +133,7 @@ public class RequestResponseBodyMethodProcessor extends AbstractMessageConverter
binder.validate(validationHints); binder.validate(validationHints);
BindingResult bindingResult = binder.getBindingResult(); BindingResult bindingResult = binder.getBindingResult();
if (bindingResult.hasErrors()) { if (bindingResult.hasErrors()) {
if (isBindExceptionRequired(binder, parameter)) { if (isBindingErrorFatal(parameter)) {
throw new MethodArgumentNotValidException(parameter, bindingResult); throw new MethodArgumentNotValidException(parameter, bindingResult);
} }
} }
@ -131,20 +142,6 @@ public class RequestResponseBodyMethodProcessor extends AbstractMessageConverter
} }
} }
/**
* Whether to raise a {@link MethodArgumentNotValidException} on validation errors.
* @param binder the data binder used to perform data binding
* @param parameter the method argument
* @return {@code true} if the next method argument is not of type {@link Errors}.
*/
private boolean isBindExceptionRequired(WebDataBinder binder, MethodParameter parameter) {
int i = parameter.getParameterIndex();
Class<?>[] paramTypes = parameter.getMethod().getParameterTypes();
boolean hasBindingResult = (paramTypes.length > (i + 1) && Errors.class.isAssignableFrom(paramTypes[i + 1]));
return !hasBindingResult;
}
@Override @Override
protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, protected <T> Object readWithMessageConverters(NativeWebRequest webRequest,
MethodParameter methodParam, Type paramType) throws IOException, HttpMediaTypeNotSupportedException { MethodParameter methodParam, Type paramType) throws IOException, HttpMediaTypeNotSupportedException {