Come faccio a risolvere in modo dinamico i parametri di messaggi con Hibernate Validator?
-
16-10-2019 - |
Domanda
Sto usando Hibernate Validator e vorrei risolvere nome della categoria in un messaggio di errore. Si consideri questo scenario semplice:
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.
Si supponga che ho un'implementazione di lavoro di HazardousCategoryConstraint. I validatore controlla il nome di ogni categoria con un elenco di nomi con restrizioni. Quando chiamo validate (InventoryReport) ottengo il numero di errori mi aspetto eccetto quando sono la stessa stringa. Mi piacerebbe vedere il nome della Categoria risolto in ogni messaggio. Qualcuno mi può punto ad un esempio di come risolvere i parametri in modo dinamico, o mostrarmi come?
Soluzione
IMO, la soluzione più semplice è quella di creare un'implementazione personalizzata di javax.validation.MessageInterpolator
. Delegare il lavoro principale per ResourceBundleMessageInterpolator
di Hibernate Validator e fare il lavoro di sostituzione richiesto 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.