This guide explains how to use SOAP compression with Apache Axis. Both request and response messages are compressed. To compress and decompress SOAP messages on the client side, an Axis extension for gzip is used. The counterpart on the server side is a Servlet filter.
The solution presented in this document is based on Web standards and should work in conjunction with other SOAP implementations. For example, SOAP::Lite for Perl can be used as client and Axis can be used as server.
Requirements
To use this solution, a Servlet 2.3 compliant Web container, e.g. Tomcat 5, and Axis version 1.1 or higher are required. Links for downloading the Servlet filter and the Axis extension are included in this article.
Configuring the Server
The configuration of the client and the server are independent. First, you can set up and test the server. After the server configuration is working you can move on to the client side.
We will use a Servlet filter to decompress the requests and compress the responses. Although a lot of other filters can only compress the response, our free filter can both compress the response and decompress the request. To use the filter for SOAP compression, it has to be added to the Axis Web application containing the Web Services. The filter is packaged into the library 2wayfilter-1.2.jar. Download the library and copy it into the Axis Web application's lib folder.
Now, you can configure the Web application to use the filter. Include the following filter and filter-mapping elements in the Web application's deployment descriptor. The deployment descriptor is in the file web.xml in the folder WEB-INF.
<web-app> ... <filter> <filter-name>2WayFilter</filter-name> <filter-class>com.osmoticweb.gzipfilter.GZIP2WayFilter</filter-class> </filter> <filter-mapping> <filter-name>2WayFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> ... </web-app>
Restart the Web application. For example, by shutting down and restarting Tomcat.
After restarting the Web application, the configuration can be tested. A simple Web page inside the Web application is needed for the test. The Axis index page will work.
Hint: If there is no suitable page inside the Web application, just copy a static HTML file into the Web application's root directory.
To run the test, the index page is requested from the Web browser. To see if the configuration is working, the messages between client and server have to be intercepted and displayed. Tcpmon is a standalone utility included in the Axis distribution. For this How-To, tcpmon will serve as the interceptor to show the exchanged HTTP messages.
The tcpmon utility requires the axis.jar library in the classpath. Tcpmon can be started from the command line.
java org.apache.axis.utils.tcpmon
After starting tcpmon, a new session can be added to intercept our calls. For the test, we will use listen port 2000. The session will act as a listener for the target host 127.0.0.1 on target port8080. See the screenshot below.
Now the test page can be requested from a Web browser that supports HTTP compression, for example, Mozilla, Firefox and Microsoft Internet Explorer.
To use the interceptor, the URL of the test page has to be modified. Instead of port 8080, we will use port 2000 on which the tcpmon session is listening. The page should be rendered the same way as it would without the interceptor.
The request and response message can now be examined in tcpmon. The request message should contain an Accept-Encoding header field containing the value gzip to indicate that the browser will accept gzip compressed responses. The compression Servlet filter on the server side should have recognized this field and compressed the response. The header of a compressed response message remains uncompressed and contains a Content-Encodingheader field indicating the encoding algorithm. The body is compressed and appears in the monitor as a strange looking string instead of a plaintext message.
Configuring the Client
To use the compression feature of the server, the client must be able to compress requests and decompress responses. Apache Axis can be extended with the SOAP compression transport sender which supports compression and decompression of SOAP messages. The extension can be installed without recompiling or modifying Axis itself.
Download the library soap-compression-1.2.jar containing the extension and place it into the classpath of the Axis client. The library contains the classcom.osmoticweb.soapcompression.CompressionHTTPSender which can be used instead of the built-in sender. To instruct the Axis client to use the new class a client side deployment descriptor is necessary. Create a file named client-config.wsdd, with the following content, and place it in the directory where the Axis client is started. See the Axis WSDD Reference for more details about the deployment descriptor.
The compression sender is compatible with Axis 1.1 or newer. The configuration is different depending on which version of Axis is used. The difference lies in how parameters are declared in the file client-config.wsdd. Use the corresponding configuration for your Axis version. For details see the SOAP compression sender description.
Axis 1.2 Beta or Newer
<?xml version="1.0" encoding="UTF-8"?> <deployment name="defaultClientConfig" xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <transport name="http" pivot="java:com.osmoticweb.soapcompression.CompressionHTTPSender"> <parameter name="compressRequest" value="true"/> <parameter name="acceptEncodingHeader" value="true"/> </transport> <transport name="local" pivot="java:org.apache.axis.transport.local.LocalSender"/> <transport name="java" pivot="java:org.apache.axis.transport.java.JavaSender"/> </deployment>
Axis 1.1
<?xml version="1.0" encoding="UTF-8"?> <deployment name="defaultClientConfig" xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <transport name="http" pivot="java:com.osmoticweb.soapcompression.CompressionHTTPSender"> <requestFlow> <handler type="java:com.osmoticweb.soapcompression.PutOptionsHandler"> <parameter name="compressRequest" value="true"/> <parameter name="acceptEncodingHeader" value="true"/> </handler> </requestFlow> </transport> <transport name="local" pivot="java:org.apache.axis.transport.local.LocalSender"/> <transport name="java" pivot="java:org.apache.axis.transport.java.JavaSender"/> </deployment>
Turning Compression On and Off
The compression of the request and the decompression of the response can be configured separately using parameter elements inside the transport element. To turn on compression of requests, set the parameter compressRequest to true. To get compressed responses the client has to tell the server that it accepts encoded messages using the Accept-Encoding header field. The acceptEncodingHeader parameter causes the client to send the Accept-Encodingheader with a value of "gzip".
To test the installation you can use the following client for the Version Web Service. This pre-configured Web Service is part of the Axis Web application included in the Axis distribution.
package com.osmoticweb.soapcompression; import javax.xml.namespace.QName; import javax.xml.rpc.*; public class GetVersionClient { private static String endpoint= "http://localhost:2000/axis/services/Version";; public static void main(String[] args) throws Exception { ServiceFactory sf = ServiceFactory.newInstance(); Service service = sf.createService(null); Call call = service.createCall(); call.setTargetEndpointAddress(endpoint); call.setOperationName(new QName("http://localhost:8080/axis/services/Version", "getVersion")); System.out.println(call.invoke(new Object[] {})); } }
The endpoint of this client points to tcpmon on port 2000 in order to intercept the calls to the server. Don't be confused because the namespace for the operation is different from the endpoint URL.
If everything is done correctly, you should see messages like the ones in the screenshot below. The request and the response are compressed. The request message contains an Accept-Encoding header and both contain a Content-Encoding header.
Troubleshooting
If the solution is not working, check to see if a firewall is configured on the client or server. We found that the Norton firewall modifies the Accept-Encoding header, which disables the compression, in order to inspect HTTP communication for security purposes.
Summary
In real world applications, performance is an issue, especially if a large amount of data has to be exchanged. The XML representation of data in SOAP messages inflates the data transferred, thus reducing speed. SOAP compression alleviates this obstacle without giving up the advantages of XML. There is little difference between binary remote protocols and compressed SOAP messages when it comes to transmission performance.