title: Logging the request in case of an internal server error in JAX-RS application
body: <p>Whenever my rest application throws an internal error, I want to log the exact request that made it fail. To do that, I created a ContainerResponseFilter. It checks if the response status is greater than or equal to 500. If it is, it serialises the ContainerRequestContext and persist it on S3.</p>
  
  <pre><code>@Provider
  @ApplicationScoped
  public class GlobalContainerResponseFilter implements ContainerResponseFilter {
      @Override
      public void filter (ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
          if (responseContext.getStatus() &gt;= 500) {
              ContainerRequestContextSerialiser serialiser = new ContainerRequestContextSerialiser();
              // creates a JSON with the URI, headers, form parameters, body of the request, and all the information available on ContainerRequestContext
              String json = serialiser.serialise(requestContext);
              AwsS3Client client = new AwsS3Client();
              client.persist(json, LocalDateTime.now());
          }
      }
  }
  </code></pre>
  
  <p>I am having a hard time dealing with the entity input stream. If it was not read yet, I don't need to serialise it, because it was not the cause of the exception. Maybe the application failed to parse a query parameter, for example. If it was read, I want to serialise it, but I can't, because the stream can't be read again.
  My first idea was to create a ContainerRequestFilter, like this:</p>
  
  <pre><code>@Provider
  @ApplicationScoped
  public class GlobalContainerRequestFilter implements ContainerRequestFilter {
  
      @Override
      public void filter (ContainerRequestContext requestContext) {
          requestContext.setEntityStream(new InputStreamThatCanBeReadAgain(requestContext.getEntityStream()));        
      }
  
      public static class InputStreamThatCanBeReadAgain extends InputStream {
  
          private final InputStream source;
          private final ByteArrayOutputStream os = new ByteArrayOutputStream();
  
          public InputStreamThatCanBeReadAgain (InputStream source) {
              this.source = source;
          }
  
          @Override
          public int read () throws IOException {
              int read = source.read();
              os.write(read);
              return read;
          }
  
          public InputStream getInputStreamToBeReadAgain () {
              return new ByteArrayInputStream(os.toByteArray());
          }
      }
  }
  </code></pre>
  
  <p>Then, on ContainerResponseFilter, I would cast the entity stream to InputStreamThatCanBeReadAgain and get the data I need. But this is duplicating the entity information in memory for every request, even the ones that won't generate an internal error, which is supposed to be the vast majority of them.</p>
  
  <p>So, is there another way to get this done? I suppose the entity information is already present somewhere, and I just need to get its bytes.</p>