users@jersey.java.net

[Jersey] Re: WebClient, LoggingFilter, MessageBodyWriter and HTTP Headers

From: Maarten Boekhold <boekhold_at_gmx.com>
Date: Sun, 17 Jan 2016 15:31:10 +0400

Hmmm,

Looks like the sequence is kinda like this:

 1. LoggingFilter.filter(ClientRequestContext)
     1. Add request headers to a StringBuilder instance
     2. Replace output EntityStream with a LoggingStream that wraps the
        StringBuilder from (1) and the original output stream
 2. LoggingFilter.aroundWriteTo()
     1. Calls MessageBodyWriter.writeTo() (through
        WriterInterceptorContext.proceed())
     2. Add request body (entity stream) to StringBuilder
     3. Log contents of StringBuilder

Which means that the HTTP header modifications I make in
MessageBodyWriter.writeTo() are never logged.

Isn't it possible, in case of requests, to move the logging of the
request headers to inside aroundWriteTo(), just after the call to
writerInterceptorContext.proceed()? The Jersey documentation does say
explicitly that request headers can still be modified inside a
MessageBodyWriter, so it would be nice if those modified headers can be
logged as well.

Maarten

On 2016-01-17 14:52, Maarten Boekhold wrote:
> Hi all,
>
> I've got a client application using jersey-client 2.19 that uses a
> MessageBodyWriter to write SOAPMessage entities to the HTTP request:
>
> @Provider @Produces({SOAPConstants.SOAP_1_1_CONTENT_TYPE, SOAPConstants.SOAP_1_2_CONTENT_TYPE})
> public static class SoapMessageBodyWriterimplements MessageBodyWriter<SOAPMessage> {
> @Override public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
> return SOAPMessage.class.isAssignableFrom(type); }
>
> @Override public long getSize(SOAPMessage soapMessage, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
> return -1; // return value is ignored since JAX-RS 2.0 }
>
> @Override public void writeTo(SOAPMessage soapMessage, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
> throws IOException, WebApplicationException {
>
> @SuppressWarnings("unchecked")
> final Iterator<MimeHeader> headers = soapMessage.getMimeHeaders().getAllHeaders(); while (headers.hasNext()) {
> final MimeHeader hdr = headers.next(); if (!hdr.getName().equals(HttpHeaders.CONTENT_LENGTH)) {
> httpHeaders.add(hdr.getName(), hdr.getValue()); System.out.println(hdr.getName() +": " + hdr.getValue()); }
> }
>
> try {
> soapMessage.writeTo(entityStream); }catch (SOAPException se) {
> throw new IOException("failed to write SOAP message to stream", se); }
> }
> }
>
> At the same time I have registered a LoggingFilter so that I can see
> all HTTP traffic in my log file:
> final java.util.logging.Logger traceLogger =
> java.util.logging.Logger.getLogger(WebClientSoapClient.class.getPackage().getName()); final LoggingFilter filter =new LoggingFilter(traceLogger, tracePayload); config.register(filter);
>
> However, it looks like the LoggingFilter is not logging all the
> request headers:
>
> The System.out.println statement inside my MessageBodyWriter
> implementation prints:
>
> Accept: text/xml, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
> SOAPAction: "http://..."
> Content-Type: text/xml; charset=utf-8
>
> But I only see the following output from the LoggingFilter:
>
> Jan 17, 2016 2:39:26 PM org.glassfish.jersey.filter.LoggingFilter log
> INFO: 1 * Sending client request on thread main
> 1 > POST http://.....
> 1 > Content-Type: text/xml
> <SOAP-ENV:Envelope
> xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
>
> Any idea what's happening here? Perhaps LoggingFilter (well,
> ClientRequestContext) is not holding the latest updated version of
> MultivaluedMap<String, Object> httpHeaders?
>
> Maarten
>