I've read some Q&As and guides (like Hibernate Documentation) as to how to work with Hibernate's ConstrainValidator, but none of them mention clearly how to interpolate a value in a specific position of a validation error message when creating your own custom validation annotation.
For example, if I have a validation error message that looks like this:
foo.bar.error=This value '{myValue}' is wrong.
I would like to obtain the following message if the validation fails:
The value 'some wrong value' is wrong.
The validation would be used like this:
public class SomeClass {
@CustomAnnotation(message="{foo.bar.error}")
public MyObject myObject;
...
}
public class MyObject {
private String myValue;
...
}
In this way, we can create different custom annotations for validation purposes. You can find the full source code here. It is easy to create and use custom annotations in Java. Java developers will be relieved of redundant code by using custom annotations.
By default, ValidationMessages. properties can be located in root of my classpath.
Basically you need to use the ValidatorFactory to obtain a Validator interface, then call validate(c) on that interface, where the parameter c is an instance of the class containing the bean validation annotations.
A custom validation annotation can also be defined at the class level to validate more than one attribute of the class. A common use case for this scenario is verifying if two fields of a class have matching values.
I've found a way to interpolate the message without much fuzz.
First set your ValidationMessages.properties
(or wherever your validation messages are stored) as before:
foo.bar.error=This value '{wrongValue}' is wrong.
Create your annotation like you normally would:
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented
@Constraint(validatedBy = CustomValueValidator.class)
@Target(FIELD)
@Retention(RUNTIME)
public @interface CustomAnnotation {
String message() default "{foo.bar.error}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Implement your constraint validator like this:
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class CustomValueValidator
implements ConstraintValidator<CustomAnnotation, MyObject> {
@Override
public void initialize(final CustomAnnotation constraintAnnotation) {
// Extract any value you would need from the annotation
}
@Override
public boolean isValid(final MyObject myObject,
final ConstraintValidatorContext context) {
boolean valid;
// Add your validations over the 'myObject' object
if (!valid) {
((ConstraintValidatorContextImpl) context)
.addMessageParameter("wrongValue", myObject.getMyValue());
}
return valid;
}
}
Now all that is left is to use the annotation:
public class SomeClass {
// I'm using the default message. You could override it as a parameter
@CustomAnnotation
public MyObject anotherObject;
...
}
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