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());
}
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With