Saturday, May 29, 2010

Axis 2 and Transfer-Encoding Chunked

We upgraded one of our clients from Axis 1.2 to Axis 2 and it was observed that calls to the downstream system started failing. Checked with the backend guys and they confirmed that our IP address showed up in their access logs, so the handshake had succeeded. But the request xml was not received at their end.

The first step was to plug in tcpmon and trace the data sent over the wire. (TCPMon is a utility that allows the user to monitor the messages passed along in TCP based conversation). If Eclipse is your preferred IDE, download up the TCPMon Eclipse plugin, copy the same to the ECLIPSE_HOME/plugins directory, go to Window -> Show View -> Other -> TCP Monitor -> TCP Monitor and it will open the TCPMon View. Change the endpoint to the TCP Listener endpoint and configure the actual downstream endpoint in TCPMon.

Logs indicated that Transfer-Encoding was being sent as "chunked". Now this was different from the Axis 1.2 logs which had Content-Length set in the HTTP header. Reading up the Axis2 documentation threw some more light on the topic.

By default Apache Axis 1.2 uses 'org.apache.axis.transport.http.HTTPSender' and this in turn uses HTTP/1.0, hence the default behaviour is to set Content-Length. But with Axis 2 which uses HTTP/1.1, the default is Transfer-Encoding set to "chunked". When the data is sent in chunked format, there are some special characters introduced in the payload (refer the snippet below). If the downstream system is a legacy system which does not support HTTP 1.1 (as is ours) and is unable to parse the message due to these additional characters, it returns a Soap Fault Exception.

The solution to this is to disable HTTP chunking as follows.
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.CHUNKED, Boolean.FALSE);

That said, if this issue is caught in the development stage, check if the team hosting the web service can support HTTP Chunking, since it is the preferred approach, especially when dealing with large messages like messages with attachments (MTOM).


HTTP Header using Axis 2
POST /test HTTP/1.1
Content-Type: text/xml; charset=UTF-8
SOAPAction: "http://test.com/wsdl/07/08/10#testDiagnosticRequest"
User-Agent: Axis2
Host: 127.0.0.1:8086
Transfer-Encoding: chunked
1aa









"
0

HTTP Header using Axis 1.2
Content-Type: text/xml; charset=utf-8
Accept: application/soap+xml, application/dime, multipart/related, text/*
User-Agent: Axis/1.2.1
Host: 127.0.0.1:8086
Cache-Control: no-cache
Pragma: no-cache
SOAPAction: "urn:GAT__Inbox/OpCreate"
Content-Length: 6698


...

3 comments:

Anonymous said...

Thanks a lot for this ramble.
It saved me a many sleepless nights (although i did spend too many already, trying to figure out what's wrong with our message). Once i disabled chunking, content-length appeared in the header and web service successfully received the message. Just thought to let you know that you didn't ramble in vain :)
Cheers mate!
Dejan

Rema said...

@kosmos2 - hey thanks. glad it helped somebody. and a reminder to self to keep rambling :)

Anonymous said...

All I can say, is THANK YOU! Took me the good part of 2 days to figure out why my Axis2 client (ZSI server) was getting faults. I looked with wireshark at what was sent and received and saw "Transfer-Encoding: chunked"
As soon as I added
"addPropertyToOperationClient(_operationClient,org.apache.axis2.transport.http.HTTPConstants.CHUNKED, Boolean.FALSE);"
to my axis2 stub, the soap service returned data. Thank you again!