I was struggling to get my Spring MVC validation to return to the page submitted page when I had errors. I finally solved the problem by noticing that BindingResult needs to be next to form parameter I'm validating.
For example if I amend the checkPersonInfo method in the spring.io tutorial(http://spring.io/guides/gs/validating-form-input/) to -
@RequestMapping(value="/", method=RequestMethod.POST)
public String checkPersonInfo(@Valid Person person, BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
return "form";
}
return "redirect:/results";
}
Then it will work and redirect to the form page, but if I change it to -
@RequestMapping(value="/", method=RequestMethod.POST)
public String checkPersonInfo(@Valid Person person, Model model, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "form";
}
return "redirect:/results";
}
Then it redirects to /errors
What is the cause of this?
The BindingResult
has to follow the object that is bound. The reason is that if you have more objects that are bound you must know which BindingResult
belongs to which object.
Yeah, Today I took a long time to check why cannot back to the submitted page but goes to a default whitelable error page.
After debugging got the source code
// org.springframework.web.method.annotation.ModelAttributeMethodProcessor#resolveArgument
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
throw new BindException(binder.getBindingResult());
}
if BindingResult
does not follow @Valid
, causes isBindExceptionRequired(binder, parameter)
return true and then directly throw exception so cannot execute code in controller method.
// org.springframework.web.method.annotation.ModelAttributeMethodProcessor#isBindExceptionRequired
protected boolean isBindExceptionRequired(WebDataBinder binder, MethodParameter methodParam) {
int i = methodParam.getParameterIndex();
Class<?>[] paramTypes = methodParam.getMethod().getParameterTypes();
boolean hasBindingResult = (paramTypes.length > (i + 1) && Errors.class.isAssignableFrom(paramTypes[i + 1]));
return !hasBindingResult;
}
You can potentially have multiple model attributes in your request handler, each with their own binding result. To accomodate this, Spring decided to bind binding result parameters to the previous paramater.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With