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
Related
I wanted to externalize my configuration properties so planned to use - PropertyPlaceholderconfigurer - here is my context file:
<bean id="helloBean" class="com.springex1.HelloWorld">
<property name="name" value="test!{my.db.jdbc.driver}" />
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" id="testPropertyConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="location" value="classpath:/springdb.properties"/>
<property name="placeholderPrefix" value="test!{"/>
<property name="placeholderSuffix" value="}"/>
<property name="order" value="0"/>
</bean>
Simple java class - HelloWorld.java
public class HelloWorld {
private String name;
public void setName(String name) {
this.name = name;
}
public void printHello() {
System.out.println("Hello ! " + name);
}
My properties file:
my.db.jdbc.driver=xyz
foo=bar
All of this works fine. Note that the first property is being injected
my.db.jdbc.driver=xyz
while the second property
foo=bar
is not being used - but spring works fine and does not complain
Now I decided to override the properties - so decided to add the propertyOverrideConfigurer
<bean id="propertyOverrideConfigurer"
class="org.springframework.beans.factory.config.PropertyOverrideConfigurer">
<property name="location" value="classpath:/override.properties" />
<property name="order" value="20" />
</bean>
Added the override.properties:
helloBean.name=oracle.jdbc.OracleDriver
This works as expected and prints - oracle.jdbc.OracleDriver
Now my understanding was that I wanted to override the additional property
foo=baz
And then code failed :
Exception in thread "main" org.springframework.beans.factory.BeanInitializationException: Could not process key 'foo' in PropertyOverrideConfigurer; nested exception is org.springframework.beans.factory.BeanInitializationException: Invalid key 'foo': expected 'beanName.property'
This part is understood - spring is looking for bean name 'helloBean' and then its corresponding attribute.
While the issue is understood - my question is - in PropertyPlaceholderConfigurer I can define additional properties which are not injected and it works fine.
But - PropertyOverrideConfigurer - any property defined must get injected and for that to happen - there must be a bean with attributes available
I cannot really have additional properties hanging around in case of PropertyOverrideConfigurer - which does not sound right.
am I missing something that can ignore this error ?
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").
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)
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 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.