 |
JAX-WS RI and Compression
Posted by jitu on July 06, 2007 at 02:50 PM | Comments (8)
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.
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
I think one use case for encoding from the client is large documents (like large XML images, or a large C2B Document). But it would be nice to hear from an actual customer. - eduard/o
Posted by: pelegri on July 07, 2007 at 09:36 PM
-
Hello,
Nice blog entry - thanks.
However, using JDK 1.6.0, I am trying to write a command line web service client and this does not seems to work ...
A network analyzer shows me than no HTTP header is added to request, whatever I tried.
A pure copy/paste from your code does not add the Accept-Encoding: header.
Any tip to debug this ?
Thanks
Posted by: sebsto on July 08, 2007 at 08:50 AM
-
salesforce finds compression support really useful and gives a good performance.
Posted by: jitu on July 09, 2007 at 03:35 PM
-
Currently JDK6 doesn't include JAX-WS RI 2.1.1 You need to configure JAX-WS 2.1.1 on top of JDK 6, then the compression would work. See the entry JAX-WS 2.1.1+JDK6. I will let you know if JDK 6 update release includes JAX-WS RI 2.1.1
Posted by: jitu on July 09, 2007 at 03:43 PM
-
Tried your sample, works great. Even better with FI support.
Ability to handle compressed requests would be very welcome though. We have a scenario where more data is sent in the request (from client) than in response (from server, gzipped). I believe ppl with similar upload style WebServices would also benefit.
But request decompression should be done by AppServer (Tomcat, Glassfish), not in JAX-WS IMHO. See also
rfc2616
Posted by: dr_java on September 21, 2007 at 09:09 AM
-
Hello Jitu,
I am trying to get HTTP Compression to work in Glassfish and I have the configuration set up as you describe. I also add the following line to my client code:
((BindingProvider)port).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, Collections.singletonMap("Accept-Encoding",Collections.singletonList("gzip")));
However, as soon as the web service call is made the application throws an exception. The call doesn't even make it over to the server. Here is the exception:
javax.xml.ws.WebServiceException: java.lang.UnsupportedOperationException
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.process(Unknown Source)
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.processRequest(Unknown Source)
at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Unknown Source)
at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Unknown Source)
at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Unknown Source)
at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Unknown Source)
at com.sun.xml.internal.ws.client.Stub.process(Unknown Source)
at com.sun.xml.internal.ws.client.sei.SEIStub.doProcess(Unknown Source)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(Unknown Source)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(Unknown Source)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(Unknown Source)
at $Proxy38.getStandardView(Unknown Source)
at com.easemore.ebxviewer.client.EBXViewerClient.fetchData(EBXViewerClient.java:213)
at com.easemore.ebxviewer.client.EBXViewerClient.myInitComponents(EBXViewerClient.java:147)
at com.easemore.ebxviewer.client.EBXViewerClient.(EBXViewerClient.java:97)
at com.easemore.ebxviewer.client.EBXViewerClient$4.run(EBXViewerClient.java:807)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Caused by: java.lang.UnsupportedOperationException
at java.util.AbstractMap.put(Unknown Source)
... 24 more
Any ideas as to why I would be getting this error? TIA for any suggestions you can offer.
Posted by: lehrian on April 08, 2008 at 02:25 PM
-
Its a bug. You are running into http://forums.java.net/jive/thread.jspa?messageID=243249
Posted by: jitu on April 08, 2008 at 04:02 PM
-
That fixed it. Thank you for your help. I will recommend they change the documentation at https://jax-ws.dev.java.net/guide/HTTP_compression.html.
Posted by: lehrian on April 08, 2008 at 04:21 PM
|