views:

629

answers:

4

I am communicating to a Tomcat Server using a Java ME application on my mobile device.
I was wondering if I could compress my requests/responses using Gzip to reduce the number of bytes sent over the network.

+1  A: 

On the server side, you can enable it as described here, but the mobile application will need a library that can decompress gzip, such as this one. Might be a bit of work to get it working though...

Mike K
+2  A: 

Since you are using Tomcat, consider the possibility of putting an instance of Apache HTTP Server in front of the Tomcat server.

This can be done using the mod_jk module for Apache HTTP Server. Once you have done that, you can use mod_gzip/mod_deflate in Apache.

Of course, your client should have the ability to handle the compressed responses, for this to work. If you force your client to work with compressed responses, the client will end up displaying gibberish, since it would have been (usually) expecting plain text responses. You will find the definite indicator of the client's capability to handle compressed responses, in the client's Accept-Encoding headers.

This can be done programatically, using a servlet or a servlet filter that writes to a ZipOutputStream or GZipOutputStream, if you want to avoid the introduction of the Apache HTTP Server in the network. You will find some pointers on how to do this at the OReilly OnJava.com site.

Vineet Reynolds
You can do gzip compression in Tomcat without adding Apache. Look at the compression attribute of the HTTP connector: http://tomcat.apache.org/tomcat-5.5-doc/config/http.html
Taylor Leese
Yes, I know, but there is a reason why compression is done on the HTTP Server as against the application server - distribution of server load. One wouldn't want the application server to be burdened with response compression apart from it's usual task of running application logic. Besides, Apache HTTP server has much better performance characteristics than Tomcat.
Vineet Reynolds
+1  A: 

You can compress the content of an HTTP request or response, but not the headers. See section 3.6 of the HTTP 1.1 spec, and the later section that describes the Content-Encoding header.

EDIT: The flip side of this is that there is no guarantee that an HTTP server side will accept any particular compression format. And depending on the quality of the server-side implementation of HTTP, it might not even recognize that the request content has been compressed. So you don't want to do this unless you know that the server-side supports compressed request content.

Stephen C
+7  A: 

Modern phones have so much CPU power and the network is relatively slow so compression makes perfect sense. It's quite easy to do also.

On the J2ME side, you do something like this (assuming you use HttpConnection),

  hc.setRequestProperty("Accept-Encoding", "gzip, deflate");
  if (hc.getResponseCode() == HttpConnection.HTTP_OK) {
      InputStream in = hc.openInputStream();
      if ("gzip".equals(hc.getEncoding())) 
         in = new GZIPInputStream(in);
  ...

We use GZIPInputStream from tinyline but I am sure there are others,

http://www.tinyline.com/utils/index.html

On the server side, it's all built-in. Just add following attributes to the Connector in server.xml on Tomcat,

<Connector 
compression="on"
compressionMinSize="2048"
compressableMimeType="text/html,application/json"
... />
ZZ Coder
As Stephen C says will this only compress the data or also the HTTP headers?
Kevin Boyd
@Kevin, this will not compress headers. If headers were to be compressed, how will the client determine how they were compressed - GZIP is just one method of compression.
Vineet Reynolds
@Kevin. That is correct. The headers are not compressible using standards-based HTTP.
Stephen C
Look at only sending the absolute necessary headers.
Thorbjørn Ravn Andersen
If you compress headers, it wouldn't be HTTP anymore. You can also do that but you will need a compression tunnel. J2ME doesn't support this so there will be much more work.
ZZ Coder