This entry describes my recent foray into creating a Simple Object Access Protocol (SOAP) client. Perhaps some will find the information useful and others can provide some helpful hints in the comments.

The web service I wanted to access exports a method that returns an array of strings each with a particular structure (this will be important later). The details of this service are not important so let’s call the method getList. Since this client would be run from a Linux command line and I wanted to brush-up on my Python programming skills, I went to work looking for an appropriate SOAP library for Python. A search on Google led me to two primary choices, SOAPpy and ZSI, both part of the Python Web Services project. SOAPpy looked to be the easier to use and so I installed SOAPpy version 0.12.0 and started with this bit of code:

With the SOAP debugging turned on, I could see that the server was returning the expected list of items—the XML parser was simply preventing me from getting at them. As it turned out, there was indeed a duplicated xsi:type="soapenc:Array" attribute in the returned SOAP message. The bug reports above imply that this issue is fixed in Axis 1.3; however, since the particular Axis SOAP servlet I needed to use was part of a bundled system (that I didn’t have control over), upgrading Axis was not an option.

The Workaround

The workaround (actually a “hack”) that I used was to temporarily redirect the SOAP debugging output sent to stdout to an internal buffer. From there, I could leverage the fact that the returned strings had a nice structure to extract them from the buffer using a regular expression:

I should mention that before I resorted to this hack, I did try using ZSI and even cSOAP (a C library for SOAP). ZSI gave a richer set of controls over the SOAP protocol; however, I found that with so many knobs to fiddle with, I could only elicit from the server a 500 Internal Server Error response at the HTTP layer with a corresponding Server.userException response at the SOAP layer. Even if I could get the outgoing SOAP message to be accepted by the server, I wasn’t sure if I wouldn’t have the same parsing problem as I did with the SOAPpy implementation. With cSOAP, I went straight to my C programming roots. Unfortunately, the installation documentation was a little sparse and I didn’t pursue this very far before the above hack came to mind.

Of course, I would rather not have had to resort to the workaround. My current implementation is more brittle than it should be. For a web service this simple, I would have preferred XML-RPC.