Browse Source

SpringValidatorAdapter allows for fine-tuning the FieldError representation

Issue: SPR-12819
pull/760/head
Juergen Hoeller 10 years ago
parent
commit
c43acd7675
  1. 68
      spring-context/src/main/java/org/springframework/validation/beanvalidation/SpringValidatorAdapter.java

68
spring-context/src/main/java/org/springframework/validation/beanvalidation/SpringValidatorAdapter.java

@ -1,5 +1,5 @@ @@ -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");
* you may not use this file except in compliance with the License.
@ -117,12 +117,12 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation. @@ -117,12 +117,12 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
*/
protected void processConstraintViolations(Set<ConstraintViolation<Object>> violations, Errors errors) {
for (ConstraintViolation<Object> violation : violations) {
String field = violation.getPropertyPath().toString();
String field = determineField(violation);
FieldError fieldError = errors.getFieldError(field);
if (fieldError == null || !fieldError.isBindingFailure()) {
try {
ConstraintDescriptor<?> cd = violation.getConstraintDescriptor();
String errorCode = cd.getAnnotation().annotationType().getSimpleName();
String errorCode = determineErrorCode(cd);
Object[] errorArgs = getArgumentsForConstraint(errors.getObjectName(), field, cd);
if (errors instanceof BindingResult) {
// Can do custom FieldError registration with invalid value from ConstraintViolation,
@ -135,16 +135,10 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation. @@ -135,16 +135,10 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
errors.getObjectName(), errorCodes, errorArgs, violation.getMessage()));
}
else {
Object invalidValue = violation.getInvalidValue();
if (!"".equals(field) && (invalidValue == violation.getLeafBean() ||
(field.contains(".") && !field.contains("[]")))) {
// Possibly a bean constraint with property path: retrieve the actual property value.
// However, explicitly avoid this for "address[]" style paths that we can't handle.
invalidValue = bindingResult.getRawFieldValue(field);
}
Object rejectedValue = getRejectedValue(field, violation, bindingResult);
String[] errorCodes = bindingResult.resolveMessageCodes(errorCode, field);
bindingResult.addError(new FieldError(
errors.getObjectName(), nestedField, invalidValue, false,
errors.getObjectName(), nestedField, rejectedValue, false,
errorCodes, errorArgs, violation.getMessage()));
}
}
@ -163,6 +157,35 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation. @@ -163,6 +157,35 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
}
}
/**
* Determine a field for the given constraint violation.
* <p>The default implementation returns the stringified property path.
* @param violation the current JSR-303 ConstraintViolation
* @return the Spring-reported field (for use with {@link Errors})
* @since 4.2
* @see javax.validation.ConstraintViolation#getPropertyPath()
* @see org.springframework.validation.FieldError#getField()
*/
protected String determineField(ConstraintViolation<Object> violation) {
return violation.getPropertyPath().toString();
}
/**
* Determine a Spring-reported error code for the given constraint descriptor.
* <p>The default implementation returns the simple class name of the descriptor's
* annotation type. Note that the configured
* {@link org.springframework.validation.MessageCodesResolver} will automatically
* generate error code variations which include the object name and the field name.
* @param descriptor the JSR-303 ConstraintDescriptor for the current violation
* @return a corresponding error code (for use with {@link Errors})
* @since 4.2
* @see javax.validation.metadata.ConstraintDescriptor#getAnnotation()
* @see org.springframework.validation.MessageCodesResolver
*/
protected String determineErrorCode(ConstraintDescriptor<?> descriptor) {
return descriptor.getAnnotation().annotationType().getSimpleName();
}
/**
* Return FieldError arguments for a validation error on the given field.
* Invoked for each violated constraint.
@ -196,6 +219,29 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation. @@ -196,6 +219,29 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
return arguments.toArray(new Object[arguments.size()]);
}
/**
* Extract the rejected value behind the given constraint violation,
* for exposure through the Spring errors representation.
* @param field the field that caused the binding error
* @param violation the corresponding JSR-303 ConstraintViolation
* @param bindingResult a Spring BindingResult for the backing object
* which contains the current field's value
* @return the invalid value to expose as part of the field error
* @since 4.2
* @see javax.validation.ConstraintViolation#getInvalidValue()
* @see org.springframework.validation.FieldError#getRejectedValue()
*/
protected Object getRejectedValue(String field, ConstraintViolation<Object> violation, BindingResult bindingResult) {
Object invalidValue = violation.getInvalidValue();
if (!"".equals(field) && (invalidValue == violation.getLeafBean() ||
(field.contains(".") && !field.contains("[]")))) {
// Possibly a bean constraint with property path: retrieve the actual property value.
// However, explicitly avoid this for "address[]" style paths that we can't handle.
invalidValue = bindingResult.getRawFieldValue(field);
}
return invalidValue;
}
//---------------------------------------------------------------------
// Implementation of JSR-303 Validator interface

Loading…
Cancel
Save