Skip to main content

JAX-WS RI and Compression

Posted by jitu on July 6, 2007 at 2:50 PM PDT


JAX-WS RI provides way to send/receive compressed messages on the client side. On the server side, many of the servlet containers like Glassfish, Tomcat provide support for compression. JAX-WS applications can take advantage of this to save bandwidth. First, let us see how we can configure the servlet containers.

See Tomcat documentation on how to configure compression. I configured Tomcat as follows:

  <Connector port="8080" 
    ...
    compression="on"
    compressionMinSize="20"
    compressableMimeType="text/xml"
  />

Similarly, see JeanFrancois's blog on how to configure GlassFish for compression. I configured GlassFish domain as follows:

  <http-listener port="8080" ...  >
    ...
    <property name="compression" value="on"/>
    <property name="compressionMinSize" value="20"/>
    <property name="compressableMimeType" value="text/xml"/>
  </http-listener>

Now, let us see how we can configure JAX-WS clients to use compression. The client sends Accept-Encoding HTTP header to indicate its capabilities to process compressed data. If the server sends compressed data (contains Content-Encoding HTTP header), JAX-WS RI client runtime automatically uncompresses the response data. The wire traffic would like like this:

---[HTTP request]---
Accept-Encoding: gzip
SOAPAction: "urn:test:hello"
Content-Type: text/xml;charset="utf-8"
Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
<S:Envelope ... </S:Envelope>
---[HTTP response 200]---
Date: Tue, 03 Jul 2007 19:04:19 GMT
Content-encoding: gzip
Content-type: text/xml;charset=utf-8
null: HTTP/1.1 200 OK
Transfer-encoding: chunked
Server: Apache-Coyote/1.1
Vary: Accept-Encoding
[GZIP Compressed SOAP Envelope]

The way to add Accept-Encoding HTTP header is as follows:

stub = ...
Map<String, List<String>> httpHeaders = new HashMap<String, List<String>>();
httpHeaders.put("Accept-Encoding", Collections.singletonList("gzip"));
Map<String, Object> ctxt = ((BindingProvider)stub).getRequestContext();
ctxt.put(MessageContext.HTTP_REQUEST_HEADERS, httpHeaders);

JAX-WS RI client can also send requests with compression, but currently Tomcat and GlassFish do not uncompress the requests. Also JAX-WS server runtime doesn't uncompress these requests(does anybody need it ?). So it is useful only when a server can process these requests. Anyway, the way you do this with RI is:

httpHeaders.put("Content-Encoding", Collections.singletonList("gzip"));

This tip is also captured in JAX-WS RI User Guide.


Comments

You had asked for a use case for client compression. One ...

You had asked for a use case for client compression. One which we have encountered would be asynchronus callbacks. I.e client registers for status updates from a service. The service is expected to asynchrounslly send a message to a client supplied service when ever status changes. It would be nice if the client could specify that it supports gzip in the registration call and the service (acting as client to the callback service) would then gzip the status messages.

Jeff Gaer

Client-side JAX-WS does not decompress

Hi Jitu, Thanks for the example.

If the server sends compressed data (contains Content-Encoding HTTP header), JAX-WS RI client runtime automatically uncompresses the response data.

I am trying to get this to work here, with JAX-WS RI 2.0 deployed on both the server (Tomcat 5.5) and the client (Java SE 1.5 application with JAX-WS packages). It is working great on the server-side, I configured Tomcat and responses are returned compressed, I tested it with soapUI and intercepting the response with tcpmon.

Now I am trying to get it to work with the native client. I added the HTTP headers, but now my client cannot handle the response:

Unable to create StAX reader or writer at com.sun.xml.ws.streaming.XMLStreamReaderFactory.createXMLStreamReader(XMLStreamReaderFactory.java:187) at com.sun.xml.ws.streaming.XMLStreamReaderFactory.createXMLStreamReader(XMLStreamReaderFactory.java:152) at com.sun.xml.ws.encoding.StreamSOAPCodec.createXMLStreamReader(StreamSOAPCodec.java:226) at com.sun.xml.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:108) [...] Caused by: javax.xml.stream.XMLStreamException at com.sun.xml.stream.XMLReaderImpl.setInputSource(XMLReaderImpl.java:203) at com.sun.xml.stream.XMLReaderImpl.(XMLReaderImpl.java:183) at com.sun.xml.stream.ZephyrParserFactory.getXMLStreamReaderImpl(ZephyrParserFactory.java:289)

Apparently the HTTP response is not decompressed by the client automatically... it seems like it is trying to decode XML from the compressed data or something. Can you help me out?

 Can you start a thread

 Can you start a thread at http://forums.java.net/jive/forum.jspa?forumID=46