Spring REST using Jackson - 400 bad request logging

SpringSpring Mvc

Spring Problem Overview


I have spring REST set up fine using Jackson/JSON and everything works.

But I knowingly introduced an error in the structure of the message which resulted in a 400 - Bad Request. But there was no log output on the server. The error I would be expecting would be something like "Jackson unknown property exception" or whatever but it was caught and a 400 error was sent to the client, but no log of the exception on the server.

I don't want to debug everything on the server clearly, but I want Spring network level exceptions like this clearly labelled as error.

What is the correct way to switch this on?

Thanks!

Spring Solutions


Solution 1 - Spring

@ExceptionHandler
@ResponseStatus(HttpStatus.BAD_REQUEST)
public void handle(HttpMessageNotReadableException e) {
    logger.warn("Returning HTTP 400 Bad Request", e);
}

Solution 2 - Spring

Building on @Jukka's answer, you can enable this globally for all controllers using @ControllerAdvice (introduced in Spring 3.2). It does require a little code on your end, but in my experience you usually end up needing a global error handling configuration anyways and this allows you to set breakpoints / easily inspect the problems.

An example of this is below:

@ControllerAdvice
public class ControllerConfig {

    @ExceptionHandler
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public void handle(HttpMessageNotReadableException e) {
        log.warn("Returning HTTP 400 Bad Request", e);
        throw e;
    }
}

Solution 3 - Spring

In case anyone else stumbles on this issue, the following worked for me in Spring Boot 2 / Spring 5 and didn't require a code change.

I set the log level for org.springframework.web.servlet.mvc.method.annotation to DEBUG. In my case I was seeing 400 responses in my client code but no logging on the server side (even with a custom error handler). After changing that log level the problem was obvious:

DEBUG 172.19.0.16     cs              2018-Jun-08 20:55:08.415 [https-jsse-nio-443-exec-9] - method.annotation.RequestResponseBodyMethodProcessor[line ?] - Read [class java.lang.String] as "application/xml;charset=UTF-8" with [org.springframework.http.converter.xml.MarshallingHttpMessageConverter@2de50ee4]
DEBUG 172.19.0.16     cs              2018-Jun-08 20:55:08.418 [https-jsse-nio-443-exec-9] - method.annotation.ServletInvocableHandlerMethod[line ?] - Failed to resolve argument 0 of type 'java.lang.String'
org.springframework.beans.TypeMismatchException: Failed to convert value of type 'core.dto.RequestDTO' to required type 'java.lang.String'

Solution 4 - Spring

In my case, the problem was in my @ControllerAdvice-annoted class, which extended ResponseEntityExceptionHandler. As I got that handler code from some random tutorial about custom exception handling, I didn't bother to check what that superclass was doing (my custom exception handling worked just fine).

The problem is ResponseEntityExceptionHandler.handleException() handles MethodArgumentNotValidException along with other Spring MVC exceptions, delegating handling logic to specific handle- methods. As I did not provide an implementation for any of such methods (in this case handleMethodArgumentNotValid()) to return my own response body, I ended up with the default implementation that returns a response with null body :).

Solution

Override the methods you need or don't extend that class at all.

Check ResponseEntityExceptionHandler docs for the list of hanler- methods implemented.

Solution 5 - Spring

You can set log level to debug for this property.

logging.level.org.springframework.web: DEBUG

Solution 6 - Spring

I don't think that it is mandatory to extend ResponseEntityExceptionHandler. You can create multiple handler methods in ControllerAdvice class annotated with ExceptionHandler and you can return any kind of response. Please check below link for more details and code example. https://www.thetechnojournals.com/2019/11/how-to-handle-exceptions-in-rest.html

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEurig JonesView Question on Stackoverflow
Solution 1 - SpringJukkaView Answer on Stackoverflow
Solution 2 - SpringDavid WelchView Answer on Stackoverflow
Solution 3 - SpringMikeView Answer on Stackoverflow
Solution 4 - SpringL_ArmView Answer on Stackoverflow
Solution 5 - SpringNaveen MuthusamyView Answer on Stackoverflow
Solution 6 - SpringAshok PrajapatiView Answer on Stackoverflow