Update:The approach and the code available here is a little bit outdated (although still very usable). A newer entry, involving also how to create a generic Validator, is available here
Last week I read an article at java.net about Ajax Form Validation Using Spring and DWR written by Eric Spiegelberg (you should have read it before continuing). I thought the approach was really interesting, exposing your Spring MVC Validators with DWR so they would handle the client side validations as well.
This would be achieved by formatting your validators adequately, creating a function for each field to be validated and then adding some special invocation code that could be called by DWR.
I didn't like the implementation offered though for two reasons mainly, it was very intrusive (a lot of code was added to the Validator) and it forced to configure each Validator in DWR (a lot of work if the number of entities is huge). I thought a more generic style could be managed.
Explaining how it works can get somehow complicated so I will start providing an example. Remember that the full source code and a working example can be downloaded from Internna - Google Code. These are the steps needed to expose your validator:
This would be achieved by formatting your validators adequately, creating a function for each field to be validated and then adding some special invocation code that could be called by DWR.
I didn't like the implementation offered though for two reasons mainly, it was very intrusive (a lot of code was added to the Validator) and it forced to configure each Validator in DWR (a lot of work if the number of entities is huge). I thought a more generic style could be managed.
Explaining how it works can get somehow complicated so I will start providing an example. Remember that the full source code and a working example can be downloaded from Internna - Google Code. These are the steps needed to expose your validator:
- Add the library to your project. Alternatively, just add the needed classes (just a few)
- Create a Validator. It should implement ClassAwareValidator and follow the format already explained (in the beforementioned article at java.net).
- Add the following line to your Spring XML:
<import resource="classpath:dwr/mvc-dwr.xml" /> - Add the validation function to your JSP
public class TrivialValidator extends AbstractClassAwareValidator {
public Class> getSupportedClass() {
return TrivialObject.class;
}
public void validate(Object object, Errors errors) {
validateTrivialField(errors);
}
public void validateTrivialField(Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors,
"trivialField", "Trivial field is requiered");
}
}
public Class> getSupportedClass() {
return TrivialObject.class;
}
public void validate(Object object, Errors errors) {
validateTrivialField(errors);
}
public void validateTrivialField(Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors,
"trivialField", "Trivial field is requiered");
}
}
I'll try to explain how the entrails work now. There's a class (DWRValidator) that handles 90% of the work. It has a function validate(fieldname, fieldvalue) that will be exposed to DWR. This function mimics the work Eric Spiegelberg defined but in a more generic way. It will handle all the validators in the system at once (see AbstractValidatorHolder). The trick is done parsing the fieldName. In your JSP your form fields should indicate the class and field they represent!
The rest of the work is done by AnnotationUrlHandlerMapping class. There's a function configureValidators(applicationContext) that will automatically search for all the validators in the context and add them to the DWRValidator so it can manage the calls correctly.
The rest of the work is done by AnnotationUrlHandlerMapping class. There's a function configureValidators(applicationContext) that will automatically search for all the validators in the context and add them to the DWRValidator so it can manage the calls correctly.
private void configureValidators(ApplicationContext context) {
Map beans = context.getBeansOfType(ValidatorHolder.class);
if (beans != null) {
for (Object beanName : beans.keySet()) {
ValidatorHolder holder = (ValidatorHolder) beans.get(beanName);
Map validatorBeans = context.getBeansOfType(Validator.class);
for (Object validatorBeanName : validatorBeans.keySet())
holder.addValidator(validatorBeans.get(validatorBeanName));
}
}
}
Map beans = context.getBeansOfType(ValidatorHolder.class);
if (beans != null) {
for (Object beanName : beans.keySet()) {
ValidatorHolder holder = (ValidatorHolder) beans.get(beanName);
Map validatorBeans = context.getBeansOfType(Validator.class);
for (Object validatorBeanName : validatorBeans.keySet())
holder.addValidator(validatorBeans.get(validatorBeanName));
}
}
}
The last step involved is adding the validator to the context. Two files are provided (mvc-dwr.xml and simple-mvc-dwr.xml), use one or the other depending on if you have already define a dwrController and the mappings or not.

1 comentarios:
U Rule
ThX again 4 your code. It has been really helpful 4 me.
Publicar un comentario en la entrada