Spring Boot add Request Body in the Error Response Entity

I have my own Exceptionhandler which is extending ResponseEntityExceptionHandler

I am able to capture the error but the request body is empty at the time of error response creation

override fun handleHttpMessageNotReadable(e:HttpMessageNotReadableException, headers:HttpHeaders , status:HttpStatus , webRequest: WebRequest):ResponseEntity<Any>{ val rsp = ErrResponse( Data( HttpStatus.BAD_REQUEST.name, e.message!! ),**REQUEST-BODY-NEEDED**[customFilter.payload]) return super.handleExceptionInternal(e, rsp,headers, HttpStatus.BAD_REQUEST, webRequest) } 

So i have used customRequestfilter to get the body and captured the body there but the order precendence is low for customRequestFilter it will be get executed only after the request . So is there a any way to Capture the request body on the error response?

CustomRequestFilter

@Component public class CustomRequestFilter extends OncePerRequestFilter{ public String payload; public Map<String, Object> reqLog =null; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request); int status = HttpStatus.BAD_REQUEST.value(); filterChain.doFilter(wrappedRequest, response); if (status == response.getStatus()) { reqLog = getTrace(wrappedRequest, status); payload = getBody(wrappedRequest, reqLog);/** ITS CAPTURING THE BODY HERE SUCCESSFULLY**/ logTrace(wrappedRequest, reqLog); } } 
5

1 Answer

Wow, that was tricky! Anyway...

Create your custom HttpInputMessage, which will delegate to the original one.

class CachedHttpInputMessage implements HttpInputMessage { private final HttpInputMessage httpInputMessage; private ByteArrayOutputStream outputStream; CachedHttpInputMessage(final HttpInputMessage httpInputMessage) { this.httpInputMessage = httpInputMessage; } @Override public InputStream getBody() throws IOException { if (outputStream == null) { outputStream = new ByteArrayOutputStream(); final InputStream body = httpInputMessage.getBody(); final byte[] buffer = new byte[1024]; while (true) { final int length; if (!((length = body.read(buffer)) > -1)) { break; } outputStream.write(buffer, 0, length); } outputStream.flush(); } return new ByteArrayInputStream(outputStream.toByteArray()); } @Override public HttpHeaders getHeaders() { return httpInputMessage.getHeaders(); } } 

Build your custom HttpMessageConverter, extending the right one based on the currently used one (Jackson, Gson, etc.), and register it as first.

class CustomHttpMessageConverter extends MappingJackson2HttpMessageConverter { @Override public Object read( final Type type, final Class<?> contextClass, final HttpInputMessage inputMessage) throws IOException { return super.read(type, contextClass, new CachedHttpInputMessage(inputMessage)); } @Override protected Object readInternal( final Class<?> clazz, final HttpInputMessage inputMessage) throws IOException { return super.readInternal(clazz, new CachedHttpInputMessage(inputMessage)); } } 

(alternatively you could create a generic wrapper, like with the CachedHttpInputMessage, and wrap each pre-configured HttpMessageConverter, just update the list passed as input to extendMessageConverters)


@Configuration class WebConfiguration implements WebMvcConfigurer { @Override public void extendMessageConverters(final List<HttpMessageConverter<?>> converters) { converters.add(0, new CustomHttpMessageConverter()); } ... } 

Throw away the custom Filter, and inside the ExceptionHandler read the body using

final HttpInputMessage inputMessage = e.getHttpInputMessage(); final InputStream body = inputMessage.getBody(); 

Done!
Remember to clean-up the code a bit and handle all the possible exceptions.

11

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

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

You Might Also Like