I'm using ResponseEntityExceptionHandler
in a Spring Boot-based application, to capture errors in a single place and output a consistent error payload.
Everything works as expected.
ResponseEntityExceptionHandler
has a method handleHttpMessageNotReadable
that can be used to "react" on a client sending an invalid message (in my case a JSON payload).
Again, everything works as expected. If a client POST
an invalid JSON document, the code in the handleHttpMessageNotReadable
is executed correctly.
Now, for monitoring purposes, I would like to log the invalid JSON.
This is the code I'm using inside the handleHttpMessageNotReadable
method, to get hold of the payload.
String line = null;
StringBuffer jb = new StringBuffer();
try {
BufferedReader reader = servletWebRequest.getRequest().getReader();
while ((line = reader.readLine()) != null)
jb.append(line);
} catch (IOException e) {
e.printStackTrace();
}
As expected, I get an exception because the stream has been already consumed by Jackson, for actually parsing the JSON payload:
java.lang.IllegalStateException: getInputStream() has already been called for this request
What would be a simple approach to access the original POST payload?
Would it be possible to throw a custom exception which would contain the original payload (MyException extends HttpMessageNotReadableException
)?
The request body is converted from JSON into a java type by org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
If erros occur, the HttpMessageNotReadableException is thrown in the super class org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter#readJavaType
You can subclass MappingJackson2HttpMessageConverter, overwrite readJavaType(..) and try to throw your own exception or a customized HttpMessageNotReadableException there.
Most likely you will need to clone the input stream, use one to try to deserialize the JSON, and another to use in case you need to throw an exception. This may impact performance, but if thats not a problem, you may give it a try....