I'm using Hibernate Validator and would like to resolve the category's name in an error message. Consider this simple scenario:
public class Category {
private String name;
}
public class Product {
@HazardousCategoryConstraint(message = "{haz.cat.error}")
private Category category;
private String name;
}
public class InventoryReport {
@Valid
private List<Product> products;
}
ValidationMessages.properties
haz.cat.error={name} is a product in the hazardous category list.
Assume that I have a working implementation of HazardousCategoryConstraint. The validator checks each Category's name against a list of restricted names. When I call validate(InventoryReport) I get the number of errors I expect except they are the same string. I'd like to see the Category's name resolved into each message. Can someone point me to an example of how to resolve parameters dynamically, or show me how to?
Hibernate Validator allows to express and validate application constraints. The default metadata source are annotations, with the ability to override and extend through the use of XML. It is not tied to a specific application tier or programming model and is available for both server and client application programming.
Note that since Hibernate 5, Hibernate deprecated several of its specific validation constraint classes in favor to standard JSR 380-bean validation classes. Note also that the Hibernate Validator 6 library is actually the reference implementation of this JSR.
In the setUp() method, a Validator instance is retrieved from the ValidatorFactory . Validator instances are thread-safe and may be reused multiple times.
Hibernate Validator Annotation Processor It helps to detect glitches such as: Putting a constraint to bean properties which are not supported by that constraint (e.g. putting @Date to a String) Annotating the setter of a bean property instead of the getter. Adding constraints to static fields or methods.
IMO, the simple solution is to create custom implementation of javax.validation.MessageInterpolator
. Delegate the main work to Hibernate Validator's ResourceBundleMessageInterpolator
and do the required replacement work in CustomMessageInterpolator
.
public class CustomMessageInterpolator extends org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator {
private static final Pattern MESSAGE_PARAMETER_PATTERN = Pattern.compile( "(\\{[^\\}]+?\\})" );
@Override
public String interpolate(String message, Context context) {
String resolvedMessage = super.interpolate(message, context);
resolvedMessage = replacePropertyNameWithPropertyValues(resolvedMessage, context.getValidatedValue());
return resolvedMessage;
}
private String replacePropertyNameWithPropertyValues(String resolvedMessage, Object validatedValue) {
Matcher matcher = MESSAGE_PARAMETER_PATTERN.matcher( resolvedMessage );
StringBuffer sb = new StringBuffer();
while ( matcher.find() ) {
String parameter = matcher.group( 1 );
String propertyName = parameter.replace("{", "");
propertyName = propertyName.replace("}", "");
PropertyDescriptor desc = null;
try {
desc = new PropertyDescriptor(propertyName, validatedValue.getClass());
} catch (IntrospectionException ignore) {
matcher.appendReplacement( sb, parameter );
continue;
}
try {
Object propertyValue = desc.getReadMethod().invoke(validatedValue);
matcher.appendReplacement( sb, propertyValue.toString() );
} catch (Exception ignore) {
matcher.appendReplacement( sb, parameter );
}
}
matcher.appendTail( sb );
return sb.toString();
}
}
@Test
public void validate() {
Configuration<?> configuration = Validation.byDefaultProvider().configure();
ValidatorFactory validatorFactory = configuration.messageInterpolator(new CustomMessageInterpolator()).buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
Product p = new Product();
Category cat = new Category();
cat.setName("s"); //assume specified name is invalid
p.setCategory(cat);
Set<ConstraintViolation<Product>> violations = validator.validate(p);
for(ConstraintViolation<Product> violation : violations) {
System.out.println(violation.getMessage());
}
}
Output
s is a product in the hazardous category list.
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