2010-11-23 5 views
12

Я пытаюсь настроить собственный источник сообщений для Hibernate Validator 4.1 до Spring 3.0. Я создал необходимую конфигурацию:Использование настраиваемого ResourceBundle с валидатором Hibernate

<!-- JSR-303 --> 
<bean id="validator" 
    class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> 
    <property name="validationMessageSource" ref="messageSource"/> 
</bean> 

Переводов подаются из моего источника сообщения, но мне кажется, что замена токены в сообщениях сами искомые в источнике сообщения, т.е. для:

my.message=the property {prop} is invalid 

есть вызовы, чтобы найти 'prop' в messageSource. Войдя в ResourceBundleMessageInterpolator.interpolateMessage Замечу, что Javadoc гласит:

Запускает сообщение интерполяции в соответствии с алгоритмом, указанным в JSR 303.

Примечание: Посмотрите окна в связках пользователей является рекурсивным тогда выглядят окна в пачке по умолчанию не!

Это похоже на то, что рекурсия всегда будет иметь место для заданного пользователем пакета, поэтому я не могу переводить стандартные сообщения, например, для Size.

Как подключить собственный источник сообщений и иметь возможность заменять параметры в сообщении?

+0

Я не понимаю, почему то расслоение конкретного пользователя берется первый мешает вам перевод сообщения для `@ Size`. Не могли бы вы уточнить? – 2010-11-23 19:57:32

+0

@Grzegorz - это не связанный с пользователем пакет, который сначала рассматривается, а это - на мой взгляд - проблема, это то, что токены рекурсивно разрешены в пользовательском комплекте. – 2010-11-23 20:56:24

ответ

17

Это смотрит на меня как рекурсии всегда будет иметь место для указанного пользователя пучка в , так что в итоге я не могу переводить стандартные сообщения как один для размера.

ResourceBundleMessageInterpolator Hibernate Validator создает два экземпляра ResourceBundleLocator (т.е. PlatformResourceBundleLocator) один для сообщений проверки UserDefined - userResourceBundleLocator, а другие для JSR-303 стандартных сообщений проверки - defaultResourceBundleLocator.

Любой текст, который появляется в двух фигурных скобках, например. {someText} в сообщении рассматривается как replacementToken. ResourceBundleMessageInterpolator пытается найти соответствующее значение, которое может заменить replaceToken в ResourceBundleLocators.

  1. сначала в UserDefinedValidationMessages (который является рекурсивным),
  2. тогда в DefaultValidationMessages (который не является рекурсивным).

Итак, если вы поместите стандартное сообщение JSR-303 в пользовательский ResourceBundle, скажем, validation_erros.properties, оно будет заменено вашим пользовательским сообщением. См. В этом EXAMPLE Стандартное сообщение проверки NotNull «не может быть null» заменено пользовательским сообщением «MyNotNullMessage».

Как я могу подключить в моем собственном источнике сообщение и быть в состоянии иметь параметры быть заменены в сообщении?
мой.сообщение = свойство {} проп является недействительным

После прохождения обоих ResourceBundleLocators, ResourceBundleMessageInterpolator находит для более replaceTokens в resolvedMessage (решенных обоими пучками). Эти заменыToken - это только имена атрибутов Annotation, если такие replaceTokens находятся в разрешенномMessage, они заменяются значениями соответствующих атрибутов аннотации.

ResourceBundleMessageInterpolator.java [Line 168, 4.1.0.Final]

resolvedMessage = replaceAnnotationAttributes(resolvedMessage, annotationParameters); 

Обеспечивая пример, чтобы заменить {} проп с таможенной стоимости, я надеюсь, что это поможет ....

MyNotNull.java

@Constraint(validatedBy = {MyNotNullValidator.class}) 
public @interface MyNotNull { 
    String propertyName(); //Annotation Attribute Name 
    String message() default "{myNotNull}"; 
    Class<?>[] groups() default { }; 
    Class<? extends Payload>[] payload() default {}; 
} 

MyNotNullVa lidator.java

public class MyNotNullValidator implements ConstraintValidator<MyNotNull, Object> { 
    public void initialize(MyNotNull parameters) { 
    } 

    public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) { 
     return object != null; 
    } 
} 

User.java

class User { 
    private String userName; 

    /* whatever name you provide as propertyName will replace {propertyName} in resource bundle */ 
    // Annotation Attribute Value 
    @MyNotNull(propertyName="userName") 
    public String getUserName() { 
     return userName; 
    } 
    public void setUserName(String userName) { 
     this.userName = userName; 
    } 
} 

validation_errors.properties

notNull={propertyName} cannot be null 

Тестовые

public void test() { 
    LocalValidatorFactoryBean factory = applicationContext.getBean("validator", LocalValidatorFactoryBean.class); 
    Validator validator = factory.getValidator(); 
    User user = new User("James", "Bond"); 
    user.setUserName(null); 
    Set<ConstraintViolation<User>> violations = validator.validate(user); 
    for(ConstraintViolation<User> violation : violations) { 
     System.out.println("Custom Message:- " + violation.getMessage()); 
    } 
} 

Выход

Custom Message:- userName cannot be null