I have a bean with validation annotations. I am going to trigger the validation manually using the following code:
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, validationGroup);
My question is, 1.) how do you get the field that failed validation and 2.) How to get the associated message?
I do not want to use .properties file. There is no front-end to display. But its a service and I need to send response with failed validation message and field that failed validation.
How do you get the field that failed validation?
The field that failed validation will be returned in the MethodConstraintViolationException. You retrieve the individual violations by calling getConstraintViolations() and then the field can be retrieved by getPropertyPath() and walking the nodes.
However, if you have a case where the field name returned in the response does not match the name of the property in the bean, for example if you are returning snake case responses (i.e. user_name), but your bean property name is username, you have to get a little more creative.
In this scenario you can store the name of the field as a Payload on the bean validation annotation.
Response Field:
@JsonProperty("user_name")
@NotEmpty(message = ErrorMessageKeys.USERNAME_REQUIRED,
payload = {FieldNamePayload.UserName.class})
private String username;
Payload Class:
public class FieldNamePayload
{
/**
* Represents the field name "user_name"
*/
public static class UserName implements ValuePayload
{
private static final String value = "user_name";
@Override
public String getValue()
{
return value;
}
}
}
Retrieving the Payload in your Exception Mapper:
List<MethodConstraintViolation<?>> violations = new ArrayList<MethodConstraintViolation<?>>(exception.getConstraintViolations());
for(MethodConstraintViolation<?> violation : violations)
{
String field = getFieldName(violation);
String message = violation.getMessage();
for(Class<? extends Payload> payload : new ArrayList<Class<? extends Payload>>(violation.getConstraintDescriptor().getPayload()))
{
//Retrieve field name from constraint payload
if(payload.isAssignableFrom(FieldNamePayload.UserName.class))
{
field = getPayloadValue(payload);
}
}
//Create an error response here!
}
How do you get the associated message?
By default the bean validation framework looks up the messages in localized files at the root of the classpath with the following naming convention:
ValidationMessages.properties for the default locale.ValidationMessages_{locale}.properties when localization is requiredIf you want to override this behavior and change where the validation messages are being retrieved from you can use hibernate's validation provider and implement a custom ResourceBundleLocator which you would add to the ResourceBundleMessageInterpolator.
ValidatorFactory validatorFactory = Validation
.byProvider(HibernateValidator.class)
.configure()
.messageInterpolator(
new ResourceBundleMessageInterpolator(
new MyCustomResourceBundleLocator()))
.buildValidatorFactory();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With