By Jim White (Director of Training and Instructor)
In Minnesota where Intertech is located, spring comes a little later that in other parts of the country. This year, I noticed our flowering trees finally came out in full force this week. ?Bout time! It seemed very fitting that I spent the week teaching Spring 3 to a great group of people.
On the last day of class, I got a question from Michelle that I wasn?t able to answer as it was at the very end of our class. She wanted to know how to customize the error message displayed on validation errors triggered by JSR-303 annotations in beans. Great question and I want to use this post to provide her a proper answer that I didn?t get a chance to provide.
Spring 3 and JSR-303 Bean Validation API
As of Spring 3.0, the framework fully supports the JSR-303 Bean Validation API. JSR-303 standardizes validation and allows you to declare validation constraints on bean properties via annotation. An example of a bean annotated with some validation constraints (@Size, @NotNull, @Past, @Min, @Max) is shown below.
1: public class Contact {
2: private Long id = 0L;
3: @Size(min = 1)
4: private String firstName;
5: @NotNull
6: @Size(min = 1)
7: private String lastName;
8: @Past
9: private Date dateOfBirth;
10: private boolean married;
11: @Min(0)
12: @Max(20)
13: private int children;
14: ...
15: }
For more information about JSR-303 and the bean validation API, see here. You can also find a good tutorial blog on some of the annotations here.
Custom Error Messages
Michelle?s question centered on how to provide a custom error message on a JSP that uses a bean like Contact as its command bean. A default message is displayed when a property if found in violation of the constraint. For example, here is the form to edit/add a Contact.
1: <form:form action="addcontact.request" method="post"
2: commandName="contact">
3: <table border="1">
4: <tr>
5: <th> </th>
6: <th><spring:message code="editcontact.heading"/></th>
7: </tr>
8: <tr>
9: <td bgcolor="cyan"><spring:message code="editcontact.label.firstname"/></td>
10: <td><form:input path="firstName" size="40" /><font
11: color="#FF0000"><form:errors path="firstName*" /></font></td>
12: </tr>
13: <tr>
14: <td bgcolor="cyan"><spring:message code="editcontact.label.lastname"/></td>
15: <td><form:input path="lastName" size="40" /><font
16: color="#FF0000"><form:errors path="lastName*" /></font></td>
17: </tr>
18: <tr>
19: <td bgcolor="cyan"><spring:message code="editcontact.label.dob"/></td>
20: <td><form:input path="dateOfBirth" size="40" /><font
21: color="#FF0000"><form:errors path="dateOfBirth*" /></font></td>
22: </tr>
23: <tr>
24: <td bgcolor="cyan"><spring:message code="editcontact.label.married"/></td>
25: <td><form:checkbox path="married" /><font color="#FF0000"><form:errors
26: path="married" /></font></td>
27: </tr>
28: <tr>
29: <td bgcolor="cyan"><spring:message code="editcontact.label.children"/></td>
30: <td><form:input path="children" size="5" /><font
31: color="#FF0000"><form:errors path="children*" /></font></td>
32: </tr>
33: <tr>
34: <td><input type="submit" value="<spring:message code="editcontact.button.save"/>" /></td>
35: <td><input type="reset" value="<spring:message code="editcontact.button.reset"/>" /></td>
36: </tr>
37: </table>
38: <a href="index.jsp"><spring:message code="editcontact.link.mainpage"/></a>
39: </form:form>
Without any changes to the defaults, the error messages displayed on the form are less than pleasing.
Option 1 ? add a message parameter to the annotation
The first option to correcting this issue and providing your own custom error message is to add a message parameter to the validation annotations. Some sample error messages are shown in the code below along with a picture of the same form using those messages.
1: public class Contact {
2: private Long id = 0L;
3: @Size(min = 1, message="Contact first name is required.")
4: private String firstName;
5: @NotNull(message="Contact cannot be left empty.")
6: @Size(min = 1, message="Contact last name is required.")
7: private String lastName;
8: @Past(message="Contact date of birth must be a date in the past.")
9: private Date dateOfBirth;
10: private boolean married;
11: @Min(value=0, message="A contact cannot have fewer than 0 children")
12: @Max(value=20, message="A contact cannot have more than 20 children")
13: private int children;
14: ...
15: }

Option 2 ? Use the Message Bundle
While providing custom messages right in the bean with the validations is convenient, you may elect to use the custom messages in your applications message resource bundles. Using a resource bundle allows your application support internationalization/localization concerns.
To setup an application to use resource message bundles, add the following bean to your Spring bean configuration file.
1: <bean id="messageSource"
2: class="org.springframework.context.support.ResourceBundleMessageSource">
3: <property name="basenames">
4: <list>
5: <value>messages</value>
6: </list>
7: </property>
8: </bean>
In this example, the default message bundle file would be messages.properties (located somewhere on the application?s classpath).
You can override the default validation annotation messages in the messages.properties by specifying the annotation and the new default message as shown below.
1: #example messages.properties
2: #override @Size default message
3: Size=Your must provide an entry.
4: #override @Min default message
5: Min=Your entry is too small.
6: #override @Max default message
7: Max=Your entry is too large.
8: #override @Past default message
9: Past=Your entry must be a date in the past.

This is nice, but you will notice that the messages are not very custom to the context. Since the same annotation may be used in multiple locations (i.e. on multiple beans), the message must be kept fairly generic.
You can further customize the messaging and still keep it external to the code by using dot notation with the property and/or command bean name and property to further specify which message to use from the bundle. In the example below, messages specific to firstName and lastName fields are provided while also providing more specific contact bean date of birth and children messages.
1: #example messages.properties
2: #override @Size default message
3: Size.firstName=First names cannot be empty.
4: Size.lastName=Last names cannot be empty.
5: #override @Min default message
6: Min.contact.children=You must specify a number of children >= 0.
7: #override @Max default message
8: Max.contact.children=You must specify a number of children <= 20.
9: #override @Past default message
10: Past.contact.dateOfBirth=Birth dates must be a date in the past.

My thanks to Michelle for providing an excellent question. Hope this helps Michelle and others looking to customize JSR-303 validation messages in Spring.
Need Spring Training?
If you or someone you work with could benefit from Spring 3 training, please visit our web site and sign up today for Complete Spring 3 Framework. You can also contact Dan McCabe ? head of training sales ? at DMcCabe@intertech.com.