It worked for me yesterday, and then I did something, and now I'm trying to fix it for hours, and I just can't get it to work.
I have a Spring MVC application containing <form:form> that I want to display custom error messages ( <form:errors> ) from a .properties file when the user enters incorrect information. What is โincorrectlyโ defined in JSR-303 annotations.
Excerpt from the form:
<form:form method="post" action="adduserprofile" modelAttribute="bindableUserProfile"> <table> <tr> <td><form:label path="firstName">Voornaam</form:label></td> <td> <form:input path="firstName"/> <form:errors path="firstName" /> </td> </tr> <tr> <td><form:label path="lastName">Achternaam</form:label></td> <td> <form:input path="lastName"/> <form:errors path="lastName" /> </td> </tr>
Excerpt from BindableUserProfile:
@NotNull @Size(min = 3, max = 40, message="{errors.requiredfield}") public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @NotNull @Size(min = 3, max = 40, message="errors.requiredfield") public String getLastName() { return lastName; }
Excerpt from the controller:
@RequestMapping(value = "/edit/{userProfileId}", method = RequestMethod.GET) public String createOrUpdate(@PathVariable Long userProfileId, Model model) { if (model.containsAttribute("bindableUserProfile")) { model.addAttribute("userProfile", model.asMap().get("bindableUserProfile")); } else { UserProfile profile = userProfileService.findById(userProfileId); if (profile != null) { model.addAttribute(new BindableUserProfile(profile)); } else { model.addAttribute(new BindableUserProfile()); } } model.addAttribute("includeFile", "forms/userprofileform.jsp"); return "main"; } @RequestMapping(value = "/adduserprofile", method = RequestMethod.POST) public String addUserProfile(@Valid BindableUserProfile userProfile, BindingResult result, Model model) { if (result.hasErrors()) { return createOrUpdate(null, model); } UserProfile profile = userProfile.asUserProfile(); userProfileService.addUserProfile(profile); return "redirect:/userprofile"; }
Excerpt from application-context.xml
<bean name="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="messages/messages"/> </bean> <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> <property name="validationMessageSource"> <ref bean="messageSource"/> </property> </bean>
There are two files in resources / messages: messages_en.properties and messages_nl.properties. Both have the same simple content:
errors.requiredfield=This field is required!!!
- When I submit a form with an empty name, I see in the addUserProfile () controller method that the errors have actually been found.
- When I submit a form with an empty first name, the message identifier is displayed next to the field, that is, the literal text "errors.requiredfield" or "{errors.requiredfield}" in the case of the last name.
- When I change the value of the message attribute to "Foo" than "Foo", it displays as an error message. Therefore, the error mechanism itself is working fine.
- The MessageSource bean from application-context.xml must be correct because it says that it cannot find property files when the base name changes.
- Empty input is not caught by the NotNull annotation. Spring sees empty input as an empty string, and not as null.
So, it seems that the property files are found, and the validation annotations are processed correctly, but Spring does not understand that it should replace the message keys with messages from the property files.