Using a Custom ResourceBundle with a Hibernate Validator

I am trying to configure my own message source for Hibernate Validator 4.1 through Spring 3.0. I set up the necessary configuration:

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

The translation is done from my message source, but it seems that replacement tokens in the messages themselves are viewed in the message source, i.e. for a:

 my.message=the property {prop} is invalid 

there are calls to search for 'prop' in messageSource. Going to ResourceBundleMessageInterpolator.interpolateMessage I note that javadoc states:

Starts message interpolation according to the algorithm specified in JSR 303.

Note: Views in custom packages are recursive, while default searches are not!

It seems to me that recursion will always take place for a user-defined package, so I can not translate standard messages, for example, for Size.

How can I connect my own message source and be able to replace the parameters in the message?

+12
spring hibernate-validator bean-validation
source share
1 answer

It looks like recursion will always take place for a user-defined package, so in fact I can not translate standard messages for example, for size.

The Hibernate Validator ResourceBundleMessageInterpolator creates two instances of the ResourceBundleLocator (for example, PlatformResourceBundleLocator), one for UserDefined validation messages, userResourceBundleLocator, and the other for JSR-303 Standard validation messages, defaultResourceBundleLocator.

Any text that appears in two braces, for example. {someText} in the message is considered as replacementToken. ResourceBundleMessageInterpolator is trying to find an appropriate value that can replace replaceToken in ResourceBundleLocators.

  • first in UserDefinedValidationMessages (which is recursive)
  • then in DefaultValidationMessages (which is not recursive).

So, if you put the standard JSR-303 message in a custom ResourceBundle, say validation_erros.properties , it will be replaced with your custom message. See IN THIS EXAMPLE The standard NotNull check message "cannot be null" is replaced with the custom message "MyNotNullMessage".

How can I connect my own message to the source and have the parameters replaced in the message?
my.message = property {prop} is invalid

After going through both ResourceBundleLocators, the ResourceBundleMessageInterpolator finds an additional replacement for replaceTokens with an allowed message (enabled by both packages). These replaceToken are nothing more than Annotation attribute names ; if such replaceTokens are in a permitted Message, they are replaced with Annotation attribute values .

ResourceBundleMessageInterpolator.java [Line 168, 4.1.0.Final]

 resolvedMessage = replaceAnnotationAttributes( resolvedMessage, annotationParameters ); 

By providing an example to replace {prop} with a custom value, I hope this helps you ....

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 {}; } 

MyNotNullValidator.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 

Test

 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()); } } 

Exit

 Custom Message:- userName cannot be null 
+17
source share

All Articles