Spring Boot Validation Respond with JSON

hibernate, java, spring, spring-boot, validation

Solution

To handle malformed or non-convertible JSON you can catch the `HttpMessageNotReadableException` class

@ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity handleBadInput(HttpMessageNotReadableException ex) {
   Throwable cause = ex.getCause();

Problem

I'm still new to Spring in general and I'm trying to use Spring boot. I have a (hopefully) quick question. I'm trying to build a ReSTful service which will return JSON. I have followed the Building a RESTful Web Service Guide and can successfully return JSON. I've integrated JPA into my web service so that my data is backed by a database. Now, I need to make a route in which, users can create an object and I would like the object to be validated. I've followed the Validation Form Input Guide but I'm not really trying to create a service that serves up web content. What I want is, whenever a validation error occurs, to return my own custom JSON. Thus far, I haven't been able to find any resources for making this happen though I've tried following Petri's Sweet Rest API Guide which I've found helpful on multiple occasions but doesn't seem to quite work in this scenario. I'm using `hibernate-validator:5.0.1.Final` and hibernate for the following. ``` @Entity @Table(name = "PEOPLE") public class Person{ @Id @Column(unique = true) @GeneratedValue(strategy = GenerationType.AUTO) private long id; @Min(18) private long age; private String name; //Necessary for JPA protected Person() {} public Person(long age, String name) { this.age = age; this.name = name; } // Getters Omitted } ``` Then my PersonController: ``` @Controller public class PersonController { @RequestMapping(value="person/", method=RequestMethod.POST) @ResponseBody public ResponseEntity<Person> create(@Valid @RequestBody Person person) { // Create in DB and return } } ``` This works in the most strict way, in that, if you send garbage JSON to this route, it will return a 400 which is pretty nice. But the body of the response is an HTML page which is not as nice. So, my question is, is there some way to catch a validation error? I've tried adding the following to my Controller but with no success: ``` @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity handleError(MethodArgumentNotValidException ex) { //generate my own error message return new ResponseEntity(customErrorClass, HttpStatus.BAD_GATEWAY); } ``` I'm aware Bad Gateway is not a valid return code, but I used it just to prove that the Exception handler is never called. When I POST to my rest service, I still see 400 Bad Request + HTML. I would assume that there is some sensible default that I can override but I can't seem to figure out where it is. I've tried googling and searching stackoverflow to no luck. Thanks in advance. UPDATE If I modify the Controller to include a `BindingResult` in the method signature: ``` @Controller public class PersonController { @RequestMapping(value="person/", method=RequestMethod.POST) @ResponseBody public ResponseEntity<Person> create(@Valid @RequestBody Person person, BindingResult bindingResult) { if(bindingResult.hasErrors()){ //handle errors and return } else { // Create in DB and return } } } ``` I can get it to work. (Note I also had to add the jasper-el jar to my dependencies) I had tried this before and didn't get it to work but the reason is not intuitive. I was posting with the following JSON: `{ "id" : "foo", "age": 22, "name" : "James Bond" }` According to the JSON Spec, this is valid JSON. Obviously, my Person Model cannot cast the String "foo" to a long. I won't go into whether or not the error should be a 400 or not, my new question is this: How can I catch this 400?

Original source