Saturday March 10, 2018
In this article I'll be demonstrating two ways to compress Apache CXF SOAP requests and responses to conserve network resources--Fast Infoset (FI) and GZip compression. We'll modify the introductory DoubleIt web service tutorial to test this functionality along with Wireshark to see how the SOAP requests and responses change as a result. The code modifications necessary are quite minimal, just a few lines over one or two source files.
As a reference point, let's use Wireshark to see the SOAP request and response for a standard DoubleIt call without compression:
POST /doubleit/services/doubleit HTTP/1.1
Content-Type: text/xml; charset=UTF-8
Accept: */*
SOAPAction: ""
User-Agent: Apache-CXF/3.2.2
Cache-Control: no-cache
Pragma: no-cache
Host: localhost:8080
Connection: keep-alive
Content-Length: 224
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:DoubleIt xmlns:ns2="http://www.example.org/schema/DoubleIt">
<numberToDouble>10</numberToDouble>
</ns2:DoubleIt>
</soap:Body>
</soap:Envelope>
HTTP/1.1 200
Content-Type: text/xml;charset=UTF-8
Content-Length: 238
Date: Sat, 10 Mar 2018 16:09:14 GMT
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:DoubleItResponse xmlns:ns2="http://www.example.org/schema/DoubleIt">
<doubledNumber>20</doubledNumber>
</ns2:DoubleItResponse>
</soap:Body>
</soap:Envelope>
First, let's activate fast infoset, both client- and service-side. The negotiation process involves the SOAP client sending an uncompressed Accept: application/fastinfoset HTTP header in the first SOAP request. If the server is configured to support FI, it will return a compressed SOAP response with a content type of application/fastinfoset. Subsequently all SOAP requests and responses between the client and web service provider will then use FI. However, if the server is not configured to use FI the server will return an uncompressed SOAP response with the usual text/xml Content-Type. The following table shows how to activate FI:
| Component | How to implement Fast Infoset Compression |
|---|---|
| CXF Web Service Provider |
Add the FastInfoset dependency to your project. Then attach the @FastInfoset feature to either the Service Endpoint Interface (SEI) or SEI implementation:
@WebService(targetNamespace = "http://www.example.org/contract/DoubleIt"...
@org.apache.cxf.annotations.FastInfoset
public class DoubleItPortTypeImpl implements DoubleItPortType {
....
}
Alternative configuration options: Can configure via the org.apache.cxf.feature.FastInfosetFeature either on the ServerFactoryBean or the cxf:bus. As the FastInfosetFeature just installs the two FI interceptors, those interceptors can also be added programmatically to the web service endpoint. Note FI will be activated only if the client requests it. The feature's |
| CXF SOAP Client |
Add the FastInfoset dependency to your project. Then add the FastInfoset interceptors to the SOAP client class:
public class WSClient {
public static void main (String[] args) {
DoubleItService service = new DoubleItService();
DoubleItPortType port = service.getDoubleItPort();
Client client = ClientProxy.getClient(port);
client.getInInterceptors().add(new org.apache.cxf.interceptor.FIStaxInInterceptor());
client.getOutInterceptors().add(new org.apache.cxf.interceptor.FIStaxOutInterceptor());
...
}
}
Alternative: add the FastInfosetFeature to the ClientFactoryBean. Note FI will be activated only if the service is configured to provide it. FI can be forced from the client to the service without negotiation using the methods described above for the web service provider, however there is no guarantee the service provider will be able to process it. |
Now, let's check the results over the wire:
POST /doubleit/services/doubleit HTTP/1.1
Content-Type: text/xml; charset=UTF-8
Accept: application/fastinfoset, */*
SOAPAction: ""
User-Agent: Apache-CXF/3.2.2
Cache-Control: no-cache
Pragma: no-cache
Host: localhost:8080
Connection: keep-alive
Content-Length: 224
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:DoubleIt xmlns:ns2="http://www.example.org/schema/DoubleIt">
<numberToDouble>10</numberToDouble>
</ns2:DoubleIt>
</soap:Body>
</soap:Envelope>
HTTP/1.1 200
Content-Type: application/fastinfoset
Transfer-Encoding: chunked
Date: Sat, 10 Mar 2018 17:39:16 GMT
.....8..soap(http://schemas.xmlsoap.org/soap/envelope/.?...Envelope?...Body8..ns2%http://www.example.org/schema/DoubleIt.?...DoubleItResponse<.doubledNumber.20....POST /doubleit/services/doubleit HTTP/1.1
Content-Type: application/fastinfoset
Accept: application/fastinfoset, */*
SOAPAction: ""
User-Agent: Apache-CXF/3.2.2
Cache-Control: no-cache
Pragma: no-cache
Host: localhost:8080
Connection: keep-alive
Content-Length: 155
.....8..soap(http://schemas.xmlsoap.org/soap/envelope/.?...Envelope?...Body8..ns2%http://www.example.org/schema/DoubleIt.?...DoubleIt<
numberToDouble.0....HTTP/1.1 200
Content-Type: application/fastinfoset
Transfer-Encoding: chunked
Date: Sat, 10 Mar 2018 17:39:16 GMT
.....8..soap(http://schemas.xmlsoap.org/soap/envelope/.?...Envelope?...Body8..ns2%http://www.example.org/schema/DoubleIt.?...DoubleItResponse<.doubledNumber.0....
For GZIP, follow the below table for configuration information. The negotiation process involves the SOAP client sending an Accept-Encoding: gzip HTTP header in the first SOAP request. If the server is configured to support GZIP compression, it will return a compressed SOAP response with the Content-Encoding: gzip HTTP Header. Subsequently all SOAP requests and responses between the client and web service provider will then use GZIP. If the server is not configured to use GZIP then SOAP requests and responses will be sent as normal, uncompressed.
| Component | How to implement GZIP Compression |
|---|---|
| CXF Web Service Provider | Attach the @org.apache.cxf.annotations.GZIP annotation to DoubleItPortTypeImpl, or either the GZIPFeature or its two corresponding interceptors as described in the previous table for the FI configuration. Note the annotation, feature and GZIPOutInterceptor all provide an optional |
| CXF SOAP Client | Attach the GZIPFeature or the GZIP interceptors (along with the threshold value, if desired) as described in the previous table for FI. |
The results with GZIP are shown below. I set the threshold to zero, both client- and service-side, to ensure compression of all messages. (Note following Wireshark's HTTP stream will uncompress by default, causing one to think no compression is occurring. To see the compressed values as below, right-click any packet part of the SOAP calls and choose "Follow->TCPStream" instead.)
POST /doubleit/services/doubleit HTTP/1.1
Content-Type: text/xml; charset=UTF-8
Accept: */*
Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0
SOAPAction: ""
User-Agent: Apache-CXF/3.2.2
Cache-Control: no-cache
Pragma: no-cache
Host: localhost:8080
Connection: keep-alive
Content-Length: 224
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:DoubleIt xmlns:ns2="http://www.example.org/schema/DoubleIt">
<numberToDouble>10</numberToDouble>
</ns2:DoubleIt>
</soap:Body>
</soap:Envelope>HTTP/1.1 200
Content-Encoding: gzip
Vary: Accept-Encoding
Content-Type: text/xml;charset=UTF-8
Content-Length: 158
Date: Sat, 10 Mar 2018 18:03:20 GMT
..........m.... .D....X.#A.F.^<..T6..,..........d&.fW1.(.aFG.w.w.e..M?.Q...GoX.........)A.U...>.
...M...xC..x....M) \.....:.k33m..:......l......s.l../&.......
POST /doubleit/services/doubleit HTTP/1.1
Content-Type: text/xml; charset=UTF-8
Accept: */*
Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0
Content-Encoding: gzip
SOAPAction: ""
User-Agent: Apache-CXF/3.2.2
Cache-Control: no-cache
Pragma: no-cache
Host: localhost:8080
Connection: keep-alive
Content-Length: 150
..........].1..0.E..z..1F!......`.!..:m..q..
.....l.\..8....)....c...4..;....*W.?...k..kf.../k"......5.>A_])E..B...f=|...Ch............u..?..7Y.......HTTP/1.1 200
Content-Encoding: gzip
Vary: Accept-Encoding
Content-Type: text/xml;charset=UTF-8
Content-Length: 157
Date: Sat, 10 Mar 2018 18:03:20 GMT
..........m.... .D....X.. .../...*.{..t.......x..d..*&..)<.Q...]`Y.}7..%.....E../h.C....tZ5...S..;y..wxNW.H..n...........l3.4..6i/..q.[.kC...b........Q.7....
Posted by Glen Mazza in Web Services at 07:00AM Mar 10, 2018 | Comments[0]
Sunday March 04, 2018
Summary: This article shows how to use Apache CXF interceptors as an alternative to JAX-WS handlers for web service providers and SOAP clients.
[Read More]Posted by Glen Mazza in Web Services at 06:00AM Mar 04, 2018 | Comments[0]
Sunday February 25, 2018
Summary: JAX-WS handlers provide a way to factor out functionality common for multiple SOAP web service providers and clients. Learn how to add JAX-WS handlers to your Apache CXF-based solutions.
[Read More]Posted by Glen Mazza in Web Services at 07:00AM Feb 25, 2018 | Comments[0]
Saturday February 03, 2018
See how the payloads of Apache CXF SOAP requests and responses can be XML schema-validated.
[Read More]Posted by Glen Mazza in Web Services at 07:00AM Feb 03, 2018 | Comments[0]
Sunday June 25, 2017
Summary: Software AG's Apache-licensed Quartz Job Scheduler can be used to run a wide range of tasks at predefined intervals. This tutorial shows how to use Quartz to schedule Apache CXF SOAP calls at recurring intervals.
[Read More]Posted by Glen Mazza in Web Services at 07:00AM Jun 25, 2017 | Comments[0]
Sunday June 11, 2017
Summary: For WSDL-first web services, explains how to upgrade your SOAP calls from the SOAP 1.1 to SOAP 1.2 standard.
[Read More]Posted by Glen Mazza in Web Services at 07:00AM Jun 11, 2017 | Comments[1]
Sunday May 14, 2017
Posted by Glen Mazza in Web Services at 07:00AM May 14, 2017 | Comments[0]
Sunday May 07, 2017
Summary: Learn how to use the Wireshark network analyzer to read your SOAP requests and responses over the wire.
[Read More]Posted by Glen Mazza in Web Services at 07:00AM May 07, 2017 | Comments[0]