Tuesday, March 12, 2013

JAX-WS with Axis2 - How to Disable Chunking


History (skip to solution if you want a quick fix)

I've been working with a new team to help them start using JAX-WS to consume some web services, last report I had all was going well.  Then I got an instant message from one of the developers saying that they were switching to JAX-RPC because the JAX-WS client wasn't working.  I asked them to send me their WSDL and Schemas and asked for more details to see if I could find out what wasn't working.  They had generated the client using RAD's (Rational Application Developer) gui version of wsimport to create the code from the wsdl.  This worked fine when using IBM's web service thin client jar as the JAX-WS runtime, their test of the client worked fine.  So, using the IBM JAX-WS runtime worked perfectly.  But since they were going to be deploying to WAS 6.1 (without the WS Feature pack), they would have no native JAX-WS runtime, so they were going to use Axis2 1.6.0 as their JAX-WS runtime as I'd suggested.  This way when they moved to WAS 8 later on, they could just remove the Axis2 jars and still function just fine on the WAS 8 JAX-WS runtime.

However, we found that by switching to the Axis2 JAX-WS runtime, the message that was sent was rejected by the provider.  After some investigation, I discovered the reason was that Axis2 was "chunking" the http message.  (Learn more about chunked transfer encoding)  The provider apparently could not process this chunked message and would respond with "javax.xml.ws.soap.SOAPFaultException: org.xml.sax.SAXParseException: Premature end of file."

I knew that if I could simply disable sending a chunked message with Axis2 all would be fine.  Well, if you google for "Axis2 Disable Chunked encoding" or something similar, you will find all kinds of help *IF* you are using Axis2's custom API.  If you are using JAX-WS with Axis2, there's no help to be found (at least that I could find).  I did find one suggestion about using a JAX-WS handler to create the "Content-Length" http header.  So, I tried this and it did seem to stop the chunking, but it also cause my request to have some junk after the http header and before the SOAP envelope.  I couldn't find how to set the "Content-length" header without messing up the generated request.  I could set other http headers and not see the "junk", but of course then I'd get chunking.  So, I started looking at other options.

I found this post that talked in terms of Axis2 custom API to disable chunking using the ServiceClient to get to the options and then turning it off through the Axis2 options.:

myStub._getServiceClient().getOptions().setProperty(HTTPConstants.CHUNKED, false);

My issue was that I couldn't get to the ServiceClient or to the Axis2 options directly because I was using the JAX-WS API and not Axis2's custom APIs.  However, after a long time of debugging and trial and error, I found that if I set this property on the SOAPMessageContext it would effectively disable chunking...


Solution: (to disable Transfer-encoding : chunked in JAX-WS using Axis2)

I created a JAX-WS handler simply set HTTPConstants.CHUNKED to "false" on the SOAPMessageContext like this:


        public boolean handleMessage(SOAPMessageContext smc) {

smc.put(HTTPConstants.CHUNKED, "false");


return true;
}

This solution worked for me and disabled the chunking and allowed the call to complete successfully.   I will warn that the constant comes from org.apache.axis2.transport.http.HTTPConstants ... so, now my JAX-WS solution is coupled to a specific implementation (Axis2) of the JAX-WS runtime.  However, when this app team moves to WAS 8 or another server that has a different runtime, they can simply remove this handler.


Hope this helps someone else out there.

1 comment:

  1. Thanks. Helped our team resolved the issue as well.

    ReplyDelete