0

Я работаю над проектом, и я использовал 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.

Можете ли вы любезно оценить это и утвердить проблему или помочь мне найти мою собственную ошибку.

Спасибо за ваше время.

ответ

0

После листать вокруг этого я решил последовать @Gunnar рекомендации и поскольку мы используем OSGi мне удалось сделать быстрый Path Bundle Class трюк, чтобы иметь измененную ResourceBundleMessageInterpolator место до исходного, который автоматически подобран HV ,

0

Это, похоже, связано с вложением параметров сообщения в выражениях EL.

Чтение спецификации спецификации, я не вижу причины, почему это не должно быть позволено, но я не уверен, что мы намеренно хотели бы поддержать это дело (я думаю, что мы представили бы пример в этом случае) , I have forwarded этот вопрос, чтобы посмотреть, что думают другие на BV EG.

Hibernate Validator в настоящее время обнаруживает такое гнездование и создает исключение в этом случае. Вот почему сообщение интерполяции остается неизменным (это задано спецификацией).

+0

Спасибо, я буду ждать, когда некоторые хедз-апы на это. Между тем я потратил время на трассировку этого внутри источников спящего режима и нашел частную константу шаблона RegEx 'ResourceBundleMessageInterpolator.MESSAGE_PARAMETER_PATTERN' - тот, который вызывает проблему, когда используется внутри 'ResourceBundleMessageInterpolator.interpolateMessage (сообщение String, контекст контекста, локаль Locale)'. Шаблон '' ((\\\\ *) \\ {[^ \\}] +? \\}) "явно игнорирует вложенность пар фигурных фигурных скобок и заканчивается при первом появлении закрывающей фигурной скобки, и это корень проблемы. –

+0

Я исправил это, изменив паттеры как 'MESSAGE_PARAMETER_PATTERN = Pattern.compile (" ((\\\\ *) \\ {[^ \\} \\ {] +? \\}) ")' и 'MESSAGE_EXPRESSION_PATTERN = Pattern.compile ("((\\\\ *) \\ $? \\ {[^ \\} \\ {] +? \\})") '. Применение этого и перестройка HV прошло все мои тесты. Было бы замечательно, если бы вы могли оценить и утвердить это как исправление для этой проблемы. –

+0

Прежде всего, мы придумаем вывод о том, поддерживается ли эта форма гнездования или нет. Возможно, вы захотите отследить [BVAL-469] (https://hibernate.atlassian.net/browse/BVAL-469). В настоящее время, если вы нашли решение, которое работает для вас, я рекомендую вам переместить адаптированный 'ResourceBundleMessageInterpolator' в свою собственную базу кода и настроить механизм проверки для использования этого пользовательского интерполятора либо в' META-INF/validation.xml 'или при загрузке валидатора через API. – Gunnar