Spring MVC custom errors and internationalization - validation

In my web application, I handle errors with annotations. Everything works fine and I can use custom messages via the "message" parameter.
#Digits(fraction = 0, integer = 3, message="my custom error message...")
private String price;
Now I'm trying to internationalize this message with a .properties files, but I certainly miss something and I can't get it to work.
My spring config :
<beans:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<beans:property name="basenames" value="classpath:i18n/messages, classpath:i18n/errors" />
<beans:property name="defaultEncoding" value="UTF-8" />
</beans:bean>
<beans:bean name="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<beans:property name="validationMessageSource">
<beans:ref bean="messageSource" />
</beans:property>
</beans:bean>
<beans:bean id="localeResolver" class="org.springframework.web.servlet.i18n.FixedLocaleResolver">
<beans:property name="defaultLocale" value="fr" />
</beans:bean>
My new bean :
#Digits(fraction = 0, integer = 3)
private String price;
My "errors_fr.properties" file. I've already tried everything :
Digits.myBean.myNestedBean.price = my custom error message...
Digits.myNestedBean.price = my custom error message...
javax.validation.constraints.Digits.myNestedBean.price = my custom error message...
I always get the same generic message from spring, it's like as spring doesn't detect my .properties file. By the way, the message keys above can be found in the BindingResult object when debugging.
What am I missing here ?
Notice that I already have internationalized messages in my jsp's (in the "messages_fr.properties" file) and they work fine.

I had a similar problem in my application, and I hope that this can help you.
As discussed in this thread, http://forum.springsource.org/showthread.php?73240-Roo-JSR-303-Validations-and-Localization, you need to:
define the error messages referred by the annotation in file ValidationMessages.properties
in your annotation, refer to the error message key enclosed in curly brackets:
#Digits(fraction = 0, integer = 3, message="{message.key}")
Hope this helps.

Related

Change configuration on demand without restarting container

Spring MVC + Java 8 + Tomcat 8 stack
I am maintaining my configuration in yaml and flattening the properties using Spring's PropertyPlaceholderConfigurer and maintaining the configuration in a bean.
Today, it has a inherent problem as I am required to restart the server whenever there is a change to the YML files.
I believe there are ways to refresh the bean without restart, but my main concern is how to do in fail safe manner.
Lets assume, there was a request and that time the config was A, and then we refresh the configuration so now its B, but if any subsequent user request was dependent on the configuration, then it will blow up.
Add this configuration to your servlet-context.xml to catch property changes on the fly:
<context:property-placeholder
location="file:${A_CONFIG_LOCATION}/configuration.properties" />
<beans:bean id="propertiesLoader"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<beans:property name="cacheSeconds" value="1" />
<beans:property name="basenames">
<beans:list>
<beans:value>file:${A_CONFIG_LOCATION}/configuration
</beans:value>
</beans:list>
</beans:property>
</beans:bean>
And then you can read property values like this:
#Component
public class PropertiesReader {
private String value = "some_default_value";
#Autowired
MessageSource propertiesLoader;
public String getValue() {
value = propertiesLoader.getMessage("configuration.value", null, null);
return value;
}
}

spring mvc validation messages

I have a problem figuring out how to pass validation properties from spring to the externalized messages. I am using spring 4, and already included "validation-api-1.1.0.Final" and "hibernate-validator-5.2.1.Final".
my Model:
#Size(min=20, max=64)
private String email;
I am still getting the message of "email shouldn't be empty TCH {2} {1} {0}" when I return to the form.
My validationMessages.properties has the following line in it:
Size.virement.email=email shouldn't be empty TCH {2} {1} {0}
I also tried using {min} and {max}, as well as %1 and %0. None of these work.
My xml config for spring has the following configuration:
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:content/ValidationMessages</value>
<value>classpath:content/Language</value>
...
</list>
</property>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
I also did include the spring-context-4.1.5.RELEASE library.
Any idea ??
Note that I am using thymeleaf to render the view.
Thx in advance.
You basically have an error message template, which you would like to populate with the values of the given constraint.
I think you can achieve this with an custom ConstraintValidor.
See the Hibernate reference here, especially the section 3.1.2.1:
https://docs.jboss.org/hibernate/validator/4.1/reference/en-US/html/validator-customconstraints.html
I hope it gives some idea!
Try to add:
<mvc:annotation-driven validator="validator"/>
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="validationMessageSource" ref="messageSource"/>
</bean>
Example:
Size.user.name=Invalid username
And please note that user in is value of ModelAttribute in your Controller (#ModelAttribute("user").

Spring-mvc validation error not being picked from property file

Using spring-mvc build in JSR303 bean validation and its working fine except for one issue, messages are not being picked from property file.
My Web-application is being created with maven and this is current structure
Main
-java
-resources
-bundles
-message.properties
-webapp
XML file
<beans:bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<beans:property name="basenames">
<beans:list>
<beans:value>bundles/messages</beans:value>
<beans:value>bundles/shipping</beans:value>
<beans:value>bundles/payment</beans:value>
</beans:list>
</beans:property>
</beans:bean>
--
validator
<beans:bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<beans:property name="validationMessageSource" ref="messageSource"/>
</beans:bean>
annotation-driven
<annotation-driven>
<message-converters>
<beans:bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter">
<beans:property name="supportedMediaTypes">
<beans:list>
<beans:value>image/jpeg</beans:value>
<beans:value>image/gif</beans:value>
<beans:value>image/png</beans:value>
</beans:list>
</beans:property>
</beans:bean>
</message-converters>
</annotation-driven>
Java File
#NotEmpty(message="{registration.firstName.invalid}")
public String getFirstName() {
return firstName;
}
Some how on my JSP page, I am getting these messages This field is required, not sure what is issue
My Data class is having following structure
PersistableCustomer extends SecuredCustomer
SecuredCustomer extends CustomerEntity
Even after passing message source to validator, its not picking up message from custom property file.
I am taking a wild guess here... usually JSR-303 message interpolator is taking messages from ValidationMessages.properties. If you want your validator to use Spring's message source, you need to configure it that way:
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="validationMessageSource" ref="messageSource" />
</bean>
<mvc:annotation-driven validator="validator" />

Model object validation in Spring MVC 3

I am using Spring MVC 3 and I try to use the validation annotation for the model object.
However I found that this validation will only work if there are no exceptions thrown.
Take this pojo for example:
public class Person{
private String name;
#Min(30)
private int age;
}
Now,I will create new Person instance through the html form, the validation work if the type of the age is int.
But if not (for example, user input a string for the age), it will throw an exception.
And I want to know where to catch this exception and put its message in the error form field?
UPDATE:
servlet-context.xml
<mvc:annotation-driven />
<mvc:view-controller path="/" view-name="home" />
<context:component-scan base-package="com.king.controller" />
<mvc:resources mapping="/res/**" location="/res/" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
Try adding in your resource message properties file a property with typeMismatch key.
In a generic way for any typeMismatch error:
typeMismatch=This is a not valid type
or more specific, to a concrete property:
typeMismatch.person.age=This is a not valid a type
This will prevent Spring to throw an exception and corresponding message will be added to your errors.
Hope this helps.
Update:
You have to add this bean in your servlet-context.xml:
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
p:basename="/WEB-INF/messages/validation" />
And add file validation.properties in /WEB-INF/messages folder with values mentioned above (typeMismatch...).

Hibernate Validation and localized error messages?

hibernate and i want to provide localized error messages for hibernate annotations
so i created to properties files ValidatorMessages.properties, ValidatorMessages_ar.properties
and put them in resources folder, and i am using messageSource to read from property files:
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:messages</value>
<value>classpath:errors</value>
<value>classpath:app</value>
<value>classpath:ValidatorMessages</value>
</list>
</property>
<property name="defaultEncoding" value="UTF-8" />
</bean>
and in the class i use something like:
#NotNull(message = "{validation.notEmpty.password}")
private string password;
and when calling the validator i use:
Validator validator = Validation.buildDefaultValidatorFactory()
.getValidator();
Set<ConstraintViolation<MyClass> cvs = validator
.validate(myObject);
for (ConstraintViolation<MyClass> cv : cvs) {
String field = cv.getPropertyPath().toString();
result.addError(new FieldError("version", field, cv.getMessage()));
}
if (result.hasErrors()) {
initModel();
result.reject("add.version.errors");
return "manageVersions";
}
it works fine with english, it displays english messages correctly, but when switching to arabic it still displays the english messages instead of arabic, although that
LocaleContextHolder.getLocale() indicates that the language is changed and it's arabic, so is there are something missing with the configuration or any ideas what might cause that ?
In your Spring config when you are setting up your validator bean, I think you need to set the message interpolator:
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="messageInterpolator" ref="interpolator" />
</bean>
where the interpolator bean would be of type LocaleContextMessageInterpolator (see here for more info). Hibernate Validator doesn't automatically know to look at LocaleContextHolder.
You might also need to set validationMessageSource property but I think its defaulted properly since you are at least getting the English error messages.

Resources