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.