Issue
I am logging the request body if some custom exception occurs. For this, I have added a filter which caches the HttpServletRequest
object using the ContentCachingRequestWrapper
. Here is the code sample for that:
@Component
public class RequestWrapperFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
filterChain.doFilter(new ContentCachingRequestWrapper(httpServletRequest), httpServletResponse);
}
}
And, my controller class looks something like this:
@PostMapping(Paths.INSPECTION_IMAGE_SUBMIT_REQUEST_V1)
public ResponseEntity<ResponseObject> processThisRequest(
@RequestBody RequestObject requestObject //how am I able to access this requestObject?
) throws Exception {
return someService.process(requestBody);
}
So, how am I able to use this requestObject
? Since, in the filter class, I have cached this, therefore, the getReader()
method must have already been called on this, right? So I should not be able to read the requestObject
, right?
Solution
======EDIT======
Look at how ContentCachingRequestWrapper
works
javax.servlet.http.HttpServletRequest wrapper that caches all content read from the input stream and reader, and allows this content to be retrieved via a byte array.
Cached does not mean it read the input stream and save in memory, but whenever bytes is read from the wrapped stream, the cacher will write same bytes to its internal buffer.
So your requestObject
is only read once in the entire filter chain, when you create the ContentCachingRequestWrapper
in your filter, it does not cache anything yet.
Other part of framework will read the cached content by invoking the ContentCachingRequestWrapper#getContentAsByteArray
method (not read from the stream again, as it already read). (Note that the content only available after the body reader finish reading the input stream, if you invoke before, you will receive incomplete data)
======END EDIT======
Can use RequestBodyAdviceAdapter
@ControllerAdvice
public class RequestAdvice extends RequestBodyAdviceAdapter {
@Override
@Nonnull
public Object afterBodyRead(@Nonnull Object body, @Nonnull HttpInputMessage inputMessage,
@Nonnull MethodParameter parameter, @Nonnull Type targetType,
@Nonnull Class<? extends HttpMessageConverter<?>> converterType) {
// Do something with the payload
return super.afterBodyRead(body, inputMessage, parameter, targetType, converterType);
}
}
Answered By - Mạnh Quyết Nguyễn