7

I have a Spring MVC Controller and an Exception Handler. When an exception occurs, I want the Exception Handler to log all the GET/POST data that was sent in the request. How can this be achieved?

Controller:

@Controller
@RequestMapping("/foo")
public class FooController {
    private final FooService fooService;

    @PostMapping("/bar")
    @ResponseBody
    public BarObject doSomething(@RequestBody final FooContext context) 
    {
        return fooService.doSomething(context);
    }
}

Exception Handler:

@ControllerAdvice
public class ExceptionController {

    private final Logger log = LoggerFactory.getLogger(ExceptionController.class);

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ErrorMessage handleException(final HttpServletRequest request, final Exception exception) {
        //Retrieve request data 
        //request.getQueryString() 
        // How to get POST data if we cannot access @RequestBody?)
        log.error(request.getRequestURI(), exception);
        return new ErrorMessage(request.getRequestURI(), exception.getLocalizedMessage());
}

1 Answer 1

8

Well the request body is in the HttpServletRequest.

You could access the RAW request body by doing something like:

String body = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));

from the exception handler method. (using java 8).

Then you can parse the body string as a POJO.

EDIT

It's been noted that the avobe answer does not work. This happens because when the body is parsed (with @RequestBody) the http connection stream is closed, hence the request body cannot be accessed again. Howver you could inject a property directly to the httpRequest from your controller method and then access the value in your Exception handler:

@RestController
@RequestMapping(ApiVersion.V1.prefix)
public class BatchController {
    @PostMapping("/batch")
    public @ResponseBody BatchResponse runBatch(@RequestBody BatchRequest batchRequest, HttpServletRequest request) throws IOException {
        System.out.println(batchRequest.getName());
        request.setAttribute("batchRequest" , batchRequest);
        throw new IllegalArgumentException("Some error");
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public @ResponseBody BatchResponse handle(HttpServletRequest request) {
        BatchRequest batchRequest = (BatchRequest) request.getAttribute("batchRequest");
        System.out.println("handling exception");
        return new BatchResponse(batchRequest.getName());
    }
}

Hope this helps

Sign up to request clarification or add additional context in comments.

1 Comment

I get an IllegalStateException exception when I call request.getReader() in the handleException method: Controller$ErrorMessage com.foo.core.ExceptionController.handleException(javax.servlet.http.HttpServletRequest,java.lang.Exception) java.lang.IllegalStateException: STREAMED at org.eclipse.jetty.server.Request.getReader(Request.java:1158)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.