4

I have a question about data binding in Spring MVC.

I have a Controller which accepts a JSON request in the form of @RequestBody. I have all the JSR 303 validations in place and it works like a charm.

  • JSON Request

    public class TestJSONRequest {
    
        @Size(min=10,message="{invalid.demo.size}")
        String demo;
    
        int code;
    }
    
  • Controller

    @Controller
    @RequestMapping("/test")
    public class TestController {
    
        public void testEntry(@RequestBody TestJSONRequest jsonRequest,ModelMap map)
    
          Set<ConstraintViolation<TestJSONRequest>> violationList = validator.val(jsonRequest);
          ....
          ....
          TestJSONResponse response = // Do complex Logic.
          modelMap.addattribute("TestJSONResponse",response);
        }
    }
    

But JSR 303 validations kick in once the incoming JSON data is bound to the Request object.

If I send ab in the code field of the input JSON request, binding would itself fail.

How do I handle that?

I want to catch those data binding errors and do some kind of generalized error handling in my controller.

Could you please help me out on this?

P.S - I am using Spring 3.0.3

Daniel Serodio
  • 4,229
  • 5
  • 37
  • 33
user1166031
  • 258
  • 6
  • 14

1 Answers1

4

According to the current Spring documentation (V3.1) :

Unlike @ModelAttribute parameters, for which a BindingResult can be used to examine the errors, @RequestBody validation errors always result in a MethodArgumentNotValidException being raised. The exception is handled in the DefaultHandlerExceptionResolver, which sends a 400 error back to the client.

Now you can to tell Spring that you'd like to handle this, by creating a new method, as follows:

@ExceptionHandler(MethodArgumentNotValidException.class)
public String handleValidation(MethodArgumentNotValidException e, ModelMap map) {
    List<ObjectError> errors = e.getBindingResult() .getAllErrors();
    // your code here...
    return "path/to/your/view";
}

Finally, have a read of the Spring docs wrt @ExceptionHandler. There's most likely some useful information there.

Muel
  • 4,309
  • 1
  • 23
  • 32
  • Thanks for the info. I am using Spring 3.0.3.. MethodArgumentNotValidException is available only in v3.1 I suppose.. I will not be able to change the spring version as there is a framework on top of the mvc development which is not in my control..Also, in my controller, I don't give the view name as such. I just set the attributes in the model map and the front end template reads the map for the necessary info. Does the return type of methods annotated with @ExceptionHandler should always be a String ? – user1166031 Jul 31 '12 at 00:17
  • It can be a `String` or a `ModelAndView` or you can do stuff like return a `Map` and have it converted to JSON by using `@RequestMapping(produces="application/json")` and `@ResponseBody`. – Muel Jul 31 '12 at 00:23
  • oh ok... But I am not suign Spring 3.1. So, I wont be able to use MethodArgumentNotValidException. is there anything that I can do to catch the binding issues ? – user1166031 Jul 31 '12 at 00:25
  • You might be able to create your own binder for `TestJSONRequest` if it's the binding that's failing. Have a look at `@InitBinder`. As always with Spring, you'll be able to get a solution, but the challenge is finding the correct entry point in the Spring framework! Sometimes a bit of debugging is required. – Muel Jul 31 '12 at 00:46
  • Am not sure how to achieve this by InitBinder ... Should we write custom editor class for each type we use in the Input JSON request... Is there any other efficient way? When ever binding failed, it threw a org.codehaus.JSonMappingException. I tried to get this exception in the method annotated with @ExceptionHandler but the control never came to the method... – user1166031 Jul 31 '12 at 21:05
  • Yep, sorry. I was thinking about this after I left work and forgot that binders are only for field by field validation! – Muel Jul 31 '12 at 23:50