Spring form ModelAttribute field validation to avoid 400 Bad Request Error

http-status-code-400, java, modelattribute, spring

Solution

You can use `<form:errors>` for a binding error.

It looks like this:

Controller:

@RequestMapping(value="edit", method=RequestMethod.POST)
public ModelAndView acceptEdit(@ModelAttribute ArticleFormModel model, 
    BindingResult errors, HttpServletRequest request)
{
  if (errors.hasErrors()) {
    // error handling code goes here.
  }
  ...
}

`errors` parameter is needed to be placed on the right after the model.

See below for details (Example 17.1):

http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-methods

jsp:

<form:form modelAttribute="articleFormModel" ... >
  ...
  <form:errors path="price" />
</form:form>

message properties file:

typeMismatch.articleFormModel.price=customized error message

Problem

I've got an `ArticleFormModel` containing data sent by normal `html form` which is injected by Spring using `@ModelAttribute` annotation, i.e. ``` @RequestMapping(value="edit", method=RequestMethod.POST) public ModelAndView acceptEdit(@ModelAttribute ArticleFormModel model, HttpServletRequest request, BindingResult errors) { //irrelevant stuff } ``` Everything works perfectly fine up to some point. The problem is that the `ArticleFormModel` contains a `double` field (`protected`, set using normal setter). Everything works fine as long as data sent by user is a number. When they type a word, all I get is `400 Bad Request Http Error`. I've already registered a `WebDataBinder` for this controller ``` @InitBinder protected void initBinder(WebDataBinder binder) throws ServletException { binder.setValidator(validator); } ``` where `validator` is an instance of a custom class implementing `org.springframework.validation.Validator` interface but I don't know what to do next. I'd like to be able to parse the model, get valid HTTP response and display error message in the form. The `initBinder()` method is called and I can call `validator.validate()` from it but it doesn't change the error (for that wrong data). I'm aware that I could use a setter to parse the string, check if it's a number, if not, store that info in a variable, then retrieve that variable during validation, but that seems to be too much work. There has to be an easier way to force a type on the field without getting an error. Also, the issue is in data binding, not validation, so I feel that it should be placed in the respective code layer. I was also thinking about implementing `java.beans.PropertyEditor` and calling `binder.registerCustomEditor()`, but I'm lacking a reliable knowledge source. Client-side validation (checking if data is number via JavaScript) isn't a possibility. TL;DR: How can I force a field to be of specific type for a `@ModelAttribute` item without getting `400 Bad Request Http Error`?

Original source