views:

982

answers:

2

I am attempting to write validators under the Spring MVC framework, but there is a glaring omission in the documentation. When calling passing an error to the Errors object most of the methods expect an String parameter named errorCode. These errorCodes, if I understand correctly serve as stand ins for specific error messages. But I can't for the life figure out where these codes are mapped to.

Here is an example of what I am referring to from Spring MVC's Javadoc;

 public class UserLoginValidator implements Validator {

    private static final int MINIMUM_PASSWORD_LENGTH = 6;

    public boolean supports(Class clazz) {
       return UserLogin.class.isAssignableFrom(clazz);
    }

    public void validate(Object target, Errors errors) {
       ValidationUtils.rejectIfEmptyOrWhitespace(errors, "userName", "field.required");
       ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "field.required");
       UserLogin login = (UserLogin) target;
       if (login.getPassword() != null
             && login.getPassword().trim().length() < MINIMUM_PASSWORD_LENGTH) {
          errors.rejectValue("password", "field.min.length",
                new Object[]{Integer.valueOf(MINIMUM_PASSWORD_LENGTH)},
                "The password must be at least [" + MINIMUM_PASSWORD_LENGTH + "] characters in length.");
       }
    }
 }

Can anyone enlighten me?

+2  A: 

They are resolved by your MessageSource and a MessagesCodeResolver.

Here is the relevant section in the reference manual:

Outputting messages corresponding to validation errors is the last thing we need to discuss. In the example we've shown above, we rejected the name and the age field. If we're going to output the error messages by using a MessageSource, we will do so using the error code we've given when rejecting the field ('name' and 'age' in this case). When you call (either directly, or indirectly, using for example the ValidationUtils class) rejectValue or one of the other reject methods from the Errors interface, the underlying implementation will not only register the code you've passed in, but also a number of additional error codes.

matt b
Where do you define what MessageCodeResolver to use?
James McMahon
a default instance (DefaultMessageCodesResolver) is used if you don't specify one. You should just need to register a MessageSource though and that will be used automatically.
matt b
How do you register a MessageSource? I see messageCodesResolver as bean property. But is there a way to set a MessageCodeResolver as universal across the entire application?
James McMahon
http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#context-functionality-messagesource
matt b
+1  A: 

I'm using the default message resolver.

In my dispatcher-servlet.xml, I have

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename" value="messages"/>
</bean>

and then in the top level of my classes directory I have a text file called "messages.properties" that contains mappings like this:

error.firstname.null=Please enter your first name.
error.lastname.null=Please enter your last name.

If you wanted to use a custom MessageCodesResolver you can implement the MessageCodeResolver interface and then define your resolver for a given controller like this:

There isn't currently a way to define a custom MessageCodeResolver globally; there's an enhancement request for that here. One approach using bean inheritance to make all controller beans inherit from one controller bean definition, is described here.

JacobM
Thanks for the information, this gives me enough to make use of my validator. But in the interest of learning what would I do if I wanted to rewire in a custom MessageCodeResolver, where would I go? Also just for prosperity ResourceBundleMessageSource's javadoc is at http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/context/support/ResourceBundleMessageSource.html.
James McMahon
If you want to use a custom MessageCodeResolver, you can assign one for a given controller. One approach, then, is to use bean inheritance to make all controller beans inherit from one controller bean definition, as described here: http://forum.springsource.org/showthread.php?t=46336 There isn't currently a way to define a custom MessageCodeResolver globally; there's an enhancement request for that here: https://jira.springsource.org/browse/SPR-5187
JacobM