Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC for Rest service how do I customize the error "message" when it's a Jackson deserialization error?

I have a RestController with a single method in my Spring Boot app. This method handles POST requests to /foo url. It takes an ID and a DTO object as parameters. The DTO object is being deserialized by Jackson. I have added @Valid to the DTO parameter to validate the couple properties being passed. My problem lies when I pass in a String for a field that should be an int. This triggers an HttpMessageNotReadableException and the "message" that is output contains internal object representation information like class and package names. This error is happening in the Jackson deserialization logic somewhere, prior to the hibernate validation for @Valid. I can create an @ExceptionHandler annotated method in my controller that handles these types of exceptions, but then I'd have to either craft the json output manually or stick with the default message that Spring uses from Jackson.

This is what Spring is outputting when this exception occurs:

{
"timestamp": 1427473174263,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.http.converter.HttpMessageNotReadableException",
"message": "Could not read JSON: Can not construct instance of int from String value 'SHOULDNT BE A STRING': not a valid Integer value\ at [Source: java.io.PushbackInputStream@34070211; line: 1, column: 3] (through reference chain: com.blah.foo.dto.CustomerProductPromotionDTO[\"productId\"]); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of int from String value 'SHOULDNT BE A STRING': not a valid Integer value\ at [Source: java.io.PushbackInputStream@34070211; line: 1, column: 3] (through reference chain: com.blah.foo.dto.CustomerProductPromotionDTO[\"productId\"])",
"path": "/customers/123456/promotions"
}

How do I customize that "message" field?

like image 803
Kevin M Avatar asked Mar 27 '15 16:03

Kevin M


1 Answers

So I figured out what I think is the best way to get around this Jackson error and still using Spring's default rest responses. I didn't realize you could use the @ExceptionHandler in conjunction with @ResponseStatus for these non custom exception types.

 */
@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseStatus(value=HttpStatus.BAD_REQUEST, reason="There was an error processing the request body.")
public void handleMessageNotReadableException(HttpServletRequest request, HttpMessageNotReadableException exception) {
    LOGGER.error("\nUnable to bind post data sent to: " + request.getRequestURI() + "\nCaught Exception:\n" + exception.getMessage());
}
like image 116
Kevin M Avatar answered Sep 18 '22 08:09

Kevin M