spring mvc validation messages - spring

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").

Related

How to get key value from properties file at runtime using spring

I want to get the changed key value from properties file at runtime.
test.properties file:
name = Hi
I have made Thread sleep with 5 sec and changed the key value as "Hello" but it is not getting changed.
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:test.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:test</value>
</list>
</property>
<property name="cacheSeconds" value="1" />
</bean>
<bean id="tempBean" name="tempBean1" class="org.sri.spring.temp.Temp"
lazy-init="false" scope="prototype">
<constructor-arg type="String" value="${name}" />
</bean>
The ${name} placeholder inside the XML configuration is resolved using the PropertySourcesPlaceholderConfigurer which, as you may notice, has nothing in common with your reloadable messageSource.
It wouldn't work either way because Spring instantiates the tempBean only once: on application startup, by passing the value of ${name} to the constructor. The bean itself is not aware of where the value came from (and in particular, it doesn't care if the properties file gets edited).
If you really think it's a good idea to do it†, you can inject the entire messageSource into your tempBean, and get the current value in each call, e.g.:
public class Temp {
#Autowired // or wired in XML, constructor, etc.
private MessageSource messages;
public String sayHello() {
return messages.getMessage("name", null, Locale.getDefault());
}
}
† injecting a configuration-related object makes testing more difficult and is arguably bad design (mixing concerns). Have a look at the Spring Cloud Config project as it's likely that this is how the future is going to look like.
I do not think that Spring will update already existing beans when the properties change.
Try to create a new bean (prototype scope)

Spring Message Interpolation Argument Replacement using Hibernate Validator

https://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html/chapter-message-interpolation.html
According to the hibernate validation documentation, the following can be done where {min} and {max} parameters are replaced in error message accordingly.
#Size(
min = 2,
max = 14,
message = "The license plate must be between {min} and {max} characters long"
)
I am using this notation in a Spring application but these arguments are not replaced.
I get back "The license plate must be between min and max characters long"
Do I need to configure the validator differently to make this work?
Here is my configuration:
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>messages</value>
</list>
</property>
<property name="defaultEncoding" value="UTF-8"/>
<property name="useCodeAsDefaultMessage" value="true"/>
</bean>
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="validationMessageSource" ref="messageSource"/>
</bean>
I find the reason. It's caused by the property "useCodeAsDefaultMessage", we can't set it to "true",just use default value "false". It seems that if it is true, just get the messages from the properties file in the "basenames", and don't use the default message file in the classpath root path or "org/hibernate/validator"!

How to set default method for Delegate method of MultiActionController ?

I'm using Spring MVC for a web app project and I'm trying to avoid using annotations.
I came across as far as getting MultiActionController and delegate working.
The question is, how do I set the default method in the delegate of a MultiActionController ?
By MultiActionController, I mean something like this
public class TestController1 extends MultiActionController{
public TestController1(){
System.out.println("TestController1 initialising...");
}
}
My xml settings are...
<bean id="multiactionController1" class="test.TestController1">
<property name="delegate" ref="testDelegater1"/>
<property name="methodNameResolver" ref="paramResolver"/>
</bean>
<!-- Delegaters -->
<bean id="testDelegater1" class="test.TestController1Delegator"/>
<!-- param method name resolver -->
<bean id="paramResolver" class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
<property name="paramName" value="action"/>
</bean>
<!-- Simple Url Handler Mapping -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<map>
<entry key="/multiaction1/**" value-ref="multiactionController1"/>
<entry key="/item/**" value-ref="itemController"/>
</map>
</property>
</bean>
So when I send a request like '*/item' , notice it doesn't have an action parameter, instead of giving me an error I would like to have a default method.
Use following implementation of MethodNameResolver, it has defaultMethodName property.
org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver
I was able to solve this by following instructions in this page.
http://www.cwinters.com/blog/2004/02/18/spring_setting_a_default_action_for_multiactioncontroller.html
As far as I've figured, you need to implement your own MethodNameResolver that returns default method name if no method name has been specified.
I Hope this helps : )

Spring validations default messages

I need to get the resolved error messages programmatically in the controller. The default validation message for typeMismatch errors are not populating from my messages.properties file. I have a form backing object where a field is an Integer. If I submit a string for that field I get:
Failed to convert property value of type 'java.lang.String' to required type 'java.lang.Integer' for property 'establishedYear'; nested exception is java.lang.NumberFormatException: For input string: "1995a"
as the default message in the ObjectError. Here's my controller that output it:
#RequestMapping(method = RequestMethod.POST)
public #ResponseBody FormJSONResponse postForm(#Valid ProfileEditCompanyForm profileEditCompanyForm, BindingResult result) throws Exception {
if (result.hasErrors()) {
for (ObjectError objectError : result.getAllErrors()) {
System.out.println(objectError.getDefaultMessage()); // THIS IS NOT MY MESSAGE, BUT SHOULD BE
}
}
... other stuff ...
}
So I added a messages.properties to WEB-INF/classes with some test messages to see if I could override that default message:
typeMismatch.profileEditCompanyForm.establishedYear=test 1
typeMismatch.establishedYear=test 2
typeMismatch.java.lang.Integer=test 3
typeMismatch=test 4
profileEditCompanyForm.establishedYear=test 5
establishedYear=test 6
In my app-servlet.xml file I have:
<mvc:annotation-driven conversion-service="conversionService" validator="validator"/>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages" />
</bean>
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="validationMessageSource" ref="messageSource"/>
</bean>
Why isn't it picking up any of my messages from my messages.properties file?
Try this in you Spring context instead:
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="WEB-INF/classes/messages" />
</bean>
Then inside "WEB-INF/classes" folder create a file call: "messages.properties"
Take note for the content of "messages.properties" you have to provide it like this :
typeMismatch.pathValueInsideYourJSPform:input= Your Message
Hope this helps you !
here is a sample also
Try specifying the complete path and try
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="WEB-INF/messages" />
</bean>
Apparently I have to run the FieldError objects through the Spring MessageSource. I was hoping this was done automatically. I found my answer here:
How to get error text in controller from BindingResult

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