Comment puis-je résoudre dynamiquement les paramètres de message avec Hibernate Validator?
-
16-10-2019 - |
Question
J'utilise Hibernate Validator et voudrais résoudre le nom de la catégorie dans un message d'erreur. Considérez ce scénario simple:
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.
Supposons que j'ai une implémentation fonctionnelle de HazardousCategoryConstraint. Le validateur du nom de chaque catégorie à une liste restreinte de noms. Quand j'appelle validate (InventoryReport) je reçois le nombre d'erreurs, je pense, sauf qu'ils sont la même chaîne. Je voudrais voir le nom de la catégorie dans chaque message résolu. point que quelqu'un peut me à un exemple de la façon dynamique aux paramètres de détermination, ou me montrer comment?
La solution
OMI, la solution simple est de créer la mise en œuvre personnalisée de javax.validation.MessageInterpolator
. Déléguer le travail principal à la ResourceBundleMessageInterpolator
Hibernate Validator et faire le travail de remplacement requis 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());
}
}
Sortie
s is a product in the hazardous category list.