I'm investigating an annotation-based approach to validating Spring beans using spring modules. In this tutorial, the following bean (getters and setters omitted) is used as an example:
public final class User {
@NotBlank
@Length(max = 80)
private String name;
@NotBlank
@Email
@Length(max = 80)
private String email;
@NotBlank
@Length(max = 4000)
private String text;
}
The error message that is used if a particular validation rule is disobeyed should follow this format:
bean-class.bean-propery[validation-rule]=Validation Error message
Examples for the class shown above include:
User.email[not.blank]=Please enter your e-mail address.
User.email[email]=Please enter a valid e-mail address.
User.email[length]=Please enter no more than {2} characters.
The fact that the message keys contain the class name presents a couple of problems:
If I have another class (e.g. Person) with an email property that is validated identically to User.email, I need to duplicate the messages, e.g.
Person.email[not.blank]=Please enter your e-mail address.
Person.email[email]=Please enter a valid e-mail address.
Person.email[length]=Please enter no more than {2} characters.
In fact, the documentation claims that is possible to configure a default message for a particular rule (e.g. @Email) like this:
email=email address is invalid
This default message should be used if a bean-specific message for the rule cannot be found. However, my experience is that this simply does not work.
An alternative mechanism for avoiding duplicate messages is to pass the key of the error message to the rule annotation. For example, assume I have defined the following default error message for the @Email rule
badEmail=Email address is invalid
This message should be used if I annotate the relevant property like this:
@Email(errorCode="badEmail")
private String email;
However I tried this, out and again, it just doesn't seem to work. Has anyone found a way to avoid duplicating error messages when using this validation framework?
I took a quick look at the BeanValidator API, and it looks like you might want to try the errorCodeConverter property.
You would need to implement your own ErrorCodeConverter, or use one of the provided implementations?
....
<bean id="validator" class="org.springmodules.validation.bean.BeanValidator"
p:configurationLoader-ref="configurationLoader"
p:errorCodeConverter-ref="errorCodeConverter" />
<bean id="errorCodeConverter" class="contact.MyErrorCodeConverter" />
....
Note: configurationLoader is another bean defined in the config XML used in the tutorial
Example converter:
package contact;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springmodules.validation.bean.converter.ErrorCodeConverter;
public class MyErrorCodeConverter implements ErrorCodeConverter {
private Log log = LogFactory.getLog(MyErrorCodeConverter.class);
@Override
public String convertPropertyErrorCode(String errorCode, Class clazz, String property) {
log.error(String.format("Property %s %s %s", errorCode, clazz.getClass().getName(), property));
return errorCode; // <------ use the errorCode only
}
@Override
public String convertGlobalErrorCode(String errorCode, Class clazz) {
log.error(String.format("Global %s %s", errorCode, clazz.getClass().getName()));
return errorCode;
}
}
Now the properties should work:
MyEmailErrorCode=Bad email
class Foo {
@Email(errorCode="MyEmailErrorCode")
String email
}