05 March 2013

TL;DR: In your Spring MVC controller handler method, make sure that the BindingResult argument is immediately after the command or model argument.

Ran into something of an odd behavior in my Spring MVC application: The following code works fine: requests come in and if there are request attributes whose names map to JavaBean-style properties on the SignInAttempt POJO, an instance of that POJO is created and populated with the values from the request. This POJO is then made available in the Spring MVC controller methods that depend on them, like this one below. If there is a JSR 303 @Valid annotation on the POJO, as in this case, Spring MVC will validate that the POJO itself complies with the constraints. If it doesn't, it will bind the errors it finds in the BindngResult object, as message keys (like Email.signInAttempt.username) which can be used to display errors to the client.

public String signin(@ModelAttribute @Valid SignInAttempt signInAttempt, BindingResult result, Model model)

What won't work so well is if you bind position the BindingResult anywhere besides immediately after the model / command / POJO itself as we have above. Thus, all of the following configurations will fail with an exception.

public String signin(@ModelAttribute @Valid SignInAttempt signInAttempt, Model m, BindingResult result  ) 

public String signin(@ModelAttribute @Valid SignInAttempt signInAttempt, @RequestParam String username, BindingResult result  ) 

// etc.

So, takeaway and rule of thumb: all model object arguments must be succeeded by a BindingResult in your Spring MVC request handler method.