~/home of geeks

JAX-RS Bodylogging per Wrapper

· 208 Wörter · 1 Minute(n) Lesedauer

Vor einiger Zeit begegnete mir die Frage, wie man den Body eines JAX-RS Requests loggen könnte. Ein einfacher Wrapper an der richtigen Stelle könnte helfen.

Man kann den Outputstream für die Entity wrappen. Hierzu benutzt man zuerst einen javax.ws.rs.client.ClientRequestFilter und fügt einen eigenen Outputstream.

Client client = ClientBuilder.newClient().register(MyLoggingFilter.class);

public class MyLoggingOutputStreamWrapper extends OutputStream{
  static final Logger logger = Logger.getLogger(...);
  ByteArrayOutputStream myBuffer = new ...
  private OutputStream target;

  public MyLoggingOutputStreamWrapper(OutputStream target) {
      // ...
  }

  // will be smarter to implement write(byte [], int, int) and call it from here 
  public void write(byte [] data){
    myBuffer.write(data);
    target.write(data);
  }

  // ... other methods to delegate to target, especially the other write method

  public void close(){
    // not sure, if converting the buffer to a string is enough. may be in a different encoding than the platform default
    logger.log(myBuffer.toString());
    target.close();
  }
}

@Provider
public class MyLoggingFilter implements ClientRequestFilter{
  // implement the ClientRequestFilter.filter method
  @Override
  public void filter(ClientRequestContext requestContext) throws IOException {
     requestContext.setEntityOutputstream(new MyLoggingOutputStreamWrapper(requestContext.getEntityOutputstream()));
  }

Ich bin mir nicht sicher, an welchem Punkt der Outputstream benutzt wird, um die Daten zu serialisieren. Das könnte beim Aufruf von buildPut() passieren, aber wahrscheinlicher wird es on-the-fly vom webclient benutzt.

Alternativ könnte man auch den zugrunde liegenden HttpClient anzapfen und einen Wrapper oder Listener dranhängen.