20

I would like to catch json mapping exception in my restful service in case input json is not valid.

It throws org.codehaus.jackson.map.JsonMappingException, but I don't how to or where to catch this exception. I want to catch this exception and send back appropriate error response.

@JsonInclude(JsonInclude.Include.NON_NULL)
@Generated("org.jsonschema2pojo")
@JsonPropertyOrder({
        "name",
        "id"
})
public class Customer {
    @JsonProperty("name")
    private String name;

    @JsonProperty("id")
    private String id;
     <setter/getter code>
}

public class MyService {
   @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public final Response createCustomer(@Context HttpHeaders headers,
            Customer customer) {
        System.out.println("Customer data: " + customer.toString());
        return Response.ok("customer created").build();
    }
}

Everything works fine, but if json body is not well formed then it throws JsonMappingException exception. I want to catch this exception.

Daniel Kutik
  • 6,997
  • 2
  • 27
  • 34
Neel
  • 303
  • 1
  • 4
  • 15

2 Answers2

25

What finally worked for me was to declare an ExceptionMapper provider for JsonMappingException, such as

import org.codehaus.jackson.map.JsonMappingException;
import org.springframework.stereotype.Component;

import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

@Component
@Provider
public class JsonMappingExceptionMapper implements ExceptionMapper<JsonMappingException> {
    @Override
    public Response toResponse(JsonMappingException exception) {
        return Response.status(Response.Status.BAD_REQUEST).build();
    }
}
itzg
  • 1,081
  • 2
  • 13
  • 11
  • This approach looks good, but where I can throw and catch this exception so I can send back appropriate response in JsonMappingExceptionMapper. toResponse(). I've implemented JsonMappingExceptionMapper same as in you example but it won't call toResponse method, It throws JsonMappingException but I'm not able to catch it. Any idea where and how I can catch JsonMappingException ?? – Neel Jan 30 '15 at 18:16
  • Yes, it should get thrown by Jersey if the POST body doesn't deserialize into the `Customer` object. Be sure you have registered that `JsonMappingExceptionMapper` with the Jersey application...in my case I am registering them via the Spring component integration. – itzg Feb 02 '15 at 00:40
  • Where have you placed this component in your application? – Daniel Vilas-Boas Jan 08 '20 at 12:48
  • @DanielVilas-Boas, you'll place that in the same package or deeper than where you have a `@ComponentScan` configuration bean declared or similar. See https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-scanning-autodetection for more information about the Java based config's component scanning. – itzg Jan 09 '20 at 16:54
0

Tested with Jersey 3, Jackson 2.x, and Grizzly HTTP server.

Create an ExceptionMapper as the @Provider to catch the JsonMappingException.

import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;

@Provider
public class CustomJsonExceptionMapper
      implements ExceptionMapper<JsonMappingException> {

  private static final ObjectMapper mapper = new ObjectMapper();

  @Override
  public Response toResponse(JsonMappingException exception) {

      ObjectNode json = mapper.createObjectNode();
      //json.put("error", exception.getMessage());
      json.put("error", "json mapping error");
      return Response.status(Response.Status.BAD_REQUEST)
              .entity(json.toPrettyString())
              .build();
  }

}

Register the above exception mapper in ResourceConfig

public static HttpServer startHttpServer() {

       final ResourceConfig config = new ResourceConfig();
       config.register(YourResource.class);
      
       // custom ExceptionMapper
       config.register(CustomJsonExceptionMapper.class);

       return GrizzlyHttpServerFactory.createHttpServer(BASE_URI, config);
}

Refer to this Jersey and Jackson example.

mkyong
  • 2,179
  • 1
  • 19
  • 14