How to perform Spring validation in MultiActionController
?
views:
798answers:
3
+2
A:
Let's write the following one
public class Person {
private String name;
private Integer age;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
And your MultiActionController
import static org.springframework.validation.ValidationUtils.*;
@Component
public class PersonController extends MultiActionController {
public PersonController() {
setMethodNameResolver(new InternalPathMethodNameResolver());
setValidators(new Validator[] {new Validator() {
public boolean supports(Class clazz) {
return clazz.isAssignableFrom(Person.class);
}
public void validate(Object command, Errors errors) {
rejectIfEmpty(errors, "age", "", "Age is required");
rejectIfEmptyOrWhitespace(errors, "name", "", "Name is required");
}
}});
}
public ModelAndView add(HttpServletRequest request, HttpServletResponse response, Person person) throws Exception {
// do something (save our Person object, for instance)
return new ModelAndView();
}
}
MultiActionController defines a property called validators where you should provide any Validator used by your MultiActionController. Here you can see a piece of code which is responsible for validating your Command object inside MultiActionController
ServletRequestDataBinder binder = ...
if (this.validators != null)
for (int i = 0; i < this.validators.length; i++) {
if (this.validators[i].supports(command.getClass())) {
ValidationUtils.invokeValidator(this.validators[i], command, binder.getBindingResult());
}
}
}
/**
* Notice closeNoCatch method
*/
binder.closeNoCatch();
closeNoCatch method says
Treats errors as fatal
So if your Validator returns any Error, closeNoCatch will throw a ServletRequestBindingException. But, you can catch it inside your MultiActionController method, as follows
public ModelAndView hanldeBindException(HttpServletRequest request, HttpServletResponse response, ServletRequestBindingException bindingException) {
// do what you want right here
BindException bindException = (BindException) bindingException.getRootCause();
return new ModelAndView("personValidatorView").addAllObjects(bindException.getModel());
}
In order to test, let's do the following one
@Test
public void failureValidation() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setRequestURI("http://127.0.0.1:8080/myContext/person/add.html");
/**
* Empty values
*/
request.addParameter("name", "");
request.addParameter("age", "");
PersonController personController = new PersonController();
ModelAndView mav = personController.handleRequest(request, new MockHttpServletResponse());
BindingResult bindingResult = (BindingResult) mav.getModel().get(BindingResult.MODEL_KEY_PREFIX + "command");
/**
* Our Validator rejected 2 Error
*/
assertTrue(bindingResult.getErrorCount() == 2);
for (Object object : bindingResult.getAllErrors()) {
if(object instanceof FieldError) {
FieldError fieldError = (FieldError) object;
System.out.println(fieldError.getField());
}
}
}
Arthur Ronald F D Garcia
2010-04-30 18:53:06
A:
this.validators does not work, as validators is a private property of the parent class use this.getValidators() public getter method
Umesh
2010-07-30 09:00:46