Я работаю над проектом, и я использовал Hibernate Validator. Недавно я попытался использовать Interpolation with message expressions (с функциями EL) в моих сообщениях проверки, но я получаю несогласованные результаты (насколько мне известно).Проблема с выражениями сообщений в валидаторе hibernate
Согласно документации на сообщение интерполяции шаги, параметры сообщения (те заключенные в «{..}
„) разрешаемые до оценки выражений сообщений (те заключенные в“${..}
»). Отсюда я делаю вывод, что это разрешено написать сообщение, как это:
${validatedValue > someValue ? '{x.y.z.message}' : '{x.y.w.message}'}
и ожидать, что сообщение литерала, ключ либо x.y.z.message
или x.y.w.message
быть результатом, где x.y.z.message
и x.y.w.message
считаются действительными и уже определенные ключи сообщений в правильно загруженном ресурсном пакете.
Чтобы прояснить вещи, я написал тест, используя TestNG и побежал против hibernate-validator-5.0.1.Final и спящего-валидатора-5.1.0-альфа. Как отмечается в тестовых комментариях, результаты, полученные этими релизами, различаются по этой конкретной проблеме, которая подсказывает мне ошибку реализации. Сначала я подумал, что это может иметь отношение к [HV-798], но это кажется глубже.
Вот тестовый пример:
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import javax.validation.constraints.Size;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
public class HibernateValidationTest
{
public class Entity
{
public int caseIndex;
@Size(min = 4, max = 10, message = "${validatedValue.length() < min ? 'Error msg.#1' : 'Error msg.#2'}")
public String getMessage1()
{
if (caseIndex == 0)
return "abc";
return "abcd";
}
@Size(min = 4, max = 10, message = "{javax.validation.constraints.Size.message}")
public String getMessage2()
{
if (caseIndex == 1)
return "abc";
return "abcd";
}
@Size(min = 4, max = 10, message = "{javax.validation.constraints.Size.message} (${validatedValue.length() < min ? 'Error msg.#3' : '{javax.validation.constraints.Size.message}'})")
public String getMessage3()
{
if (caseIndex == 2)
return "abc";
return "abcd";
}
}
@Test
public void testValidatorBug()
{
Validator validator = javax.validation.Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<Entity>> violations;
ConstraintViolation<Entity> violation;
Entity entity = new Entity();
/**
* PASS
*/
entity.caseIndex = 0;
violations = validator.validate(entity);
assertEquals(violations.size(), 1);
violation = violations.iterator().next();
assertEquals(violation.getMessage(), "Error msg.#1");
/**
* PASS
*/
entity.caseIndex = 1;
violations = validator.validate(entity);
assertEquals(violations.size(), 1);
violation = violations.iterator().next();
assertEquals(violation.getMessage(), "size must be between 4 and 10");
/**
* FAIL
*
* Violation message:
*
* - on version hibernate-validator-5.0.1.Final:
* size must be between 4 and 10 (${validatedValue.length() < min ? 'Error msg.#3' : '{javax.validation.constraints.Size.message}'})
*
* - on hibernate-validator-5.1.0-20131114.015215-37:
* {javax.validation.constraints.Size.message} (${validatedValue.length() < min ? 'Error msg.#3' : '{javax.validation.constraints.Size.message}'})
*/
entity.caseIndex = 2;
violations = validator.validate(entity);
assertEquals(violations.size(), 1);
violation = violations.iterator().next();
assertEquals(violation.getMessage(), "size must be between 4 and 10 (Error msg.#3)");
}
}
В этом тесте Entity.getMessage3()
демонстрирует проблему, которая перехватывается последней частью теста. Основываясь на моем понимании, это сообщение должно быть size must be between 4 and 10 (Error msg.#3)
, но size must be between 4 and 10 (${validatedValue.length() < min ? 'Error msg.#3' : '{javax.validation.constraints.Size.message}'})
на версии 5.0.1 и {javax.validation.constraints.Size.message} (${validatedValue.length() < min ? 'Error msg.#3' : '{javax.validation.constraints.Size.message}'})
на 5.1.0.Alpha.
Можете ли вы любезно оценить это и утвердить проблему или помочь мне найти мою собственную ошибку.
Спасибо за ваше время.
Спасибо, я буду ждать, когда некоторые хедз-апы на это. Между тем я потратил время на трассировку этого внутри источников спящего режима и нашел частную константу шаблона RegEx 'ResourceBundleMessageInterpolator.MESSAGE_PARAMETER_PATTERN' - тот, который вызывает проблему, когда используется внутри 'ResourceBundleMessageInterpolator.interpolateMessage (сообщение String, контекст контекста, локаль Locale)'. Шаблон '' ((\\\\ *) \\ {[^ \\}] +? \\}) "явно игнорирует вложенность пар фигурных фигурных скобок и заканчивается при первом появлении закрывающей фигурной скобки, и это корень проблемы. –
Я исправил это, изменив паттеры как 'MESSAGE_PARAMETER_PATTERN = Pattern.compile (" ((\\\\ *) \\ {[^ \\} \\ {] +? \\}) ")' и 'MESSAGE_EXPRESSION_PATTERN = Pattern.compile ("((\\\\ *) \\ $? \\ {[^ \\} \\ {] +? \\})") '. Применение этого и перестройка HV прошло все мои тесты. Было бы замечательно, если бы вы могли оценить и утвердить это как исправление для этой проблемы. –
Прежде всего, мы придумаем вывод о том, поддерживается ли эта форма гнездования или нет. Возможно, вы захотите отследить [BVAL-469] (https://hibernate.atlassian.net/browse/BVAL-469). В настоящее время, если вы нашли решение, которое работает для вас, я рекомендую вам переместить адаптированный 'ResourceBundleMessageInterpolator' в свою собственную базу кода и настроить механизм проверки для использования этого пользовательского интерполятора либо в' META-INF/validation.xml 'или при загрузке валидатора через API. – Gunnar