Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieve Request Body in Exception Mapper

I'm trying to retrieve the body of a request in a JAX-RS ExceptionMapper. Here is my code so far:

@Provider @Componenet
public class BaseExceptionMapper implements ExceptionMapper<Exception> {

    @Context private HttpServletRequest request;

    @Override
    public Response toResponse(Exception ex) {

        // Trying to retrieve request body for logging throws an error
        String requestBody = IOUtils.toString(request.getInputStream());

    }

}

So my dilemma is I can't get the request body for logging because the servlet API wont allow you to call request.getInputStream() / request.getReader() more than once for a request (and JAX-RS Is obviously calling it to parse the request). Does anyone know if there is a way to do what I'm trying to do?

like image 331
Brian DiCasa Avatar asked Nov 11 '11 14:11

Brian DiCasa


1 Answers

This question is a bit older, but still the answer may help others. My Example also depends on Commons-Io.

You can create a ContainerRequestFilter and use TeeInputStream to proxy/copy the original InputStream:

@Provider
@Priority(Priorities.ENTITY_CODER)
public class CustomRequestWrapperFilter implements ContainerRequestFilter { 

    @Override
    public void filter(ContainerRequestContext requestContext)
            throws IOException {
        ByteArrayOutputStream proxyOutputStream = new ByteArrayOutputStream();
        requestContext.setEntityStream(new TeeInputStream(requestContext.getEntityStream(), proxyOutputStream));
        requestContext.setProperty("ENTITY_STREAM_COPY", proxyOutputStream);
    }

}

And use @Inject with javax.inject.Provider in your ExceptionMapper to get the ContainerRequest injected.

The ExceptionMapper would look like this:

@Provider
public class BaseExceptionMapper implements ExceptionMapper<Exception> {

    @Inject
    private javax.inject.Provider<ContainerRequest> containerRequestProvider;

    @Override
    public Response toResponse(Exception exception) {
        ByteArrayOutputStream bos = (ByteArrayOutputStream) containerRequestProvider
                .get().getProperty("ENTITY_STREAM_COPY");
        String requestBody = bos.toString();
        ...
    }

}

When I have also used the @Component annotation my ExceptionMapper was not used. I think that @Provider is sufficient.

like image 93
friedeas Avatar answered Oct 24 '22 08:10

friedeas