Как динамически разрешить параметры сообщения с помощью Hibernate Validator? - PullRequest
16 голосов
/ 22 января 2011

Я использую Hibernate Validator и хотел бы разрешить имя категории в сообщении об ошибке.Рассмотрим простой сценарий:

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.

Предположим, у меня есть работающая реализация HazardousCategoryConstraint.Валидатор проверяет имя каждой категории по списку ограниченных имен.Когда я вызываю validate (InventoryReport), я получаю ожидаемое количество ошибок, за исключением того, что они представляют собой одну и ту же строку.Мне бы хотелось, чтобы название категории было разрешено в каждом сообщении.Может кто-нибудь указать мне пример того, как динамически разрешать параметры, или показать, как это сделать?

1 Ответ

10 голосов
/ 25 января 2011

IMO, простое решение - создать собственную реализацию javax.validation.MessageInterpolator.Поручите основную работу в ResourceBundleMessageInterpolator Hibernate Validator и выполните необходимые замены в 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());
        }
    }

Выход

s is a product in the hazardous category list.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...