I have a web service which exposes the following Java method:
 
void addFiles(String session, DocServerFile[] files);
 
When calling this method from a .NET client, the Soap envelope looks as follows:
 
<?xml version="1.0" encoding="utf-8" ?>
  <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://localhost:4040/jdedocserver/AxisServices/DocServerServices" xmlns:types="http://localhost:4040/jdedocserver/AxisServices/DocServerServices/encodedTypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
      <q1:addFiles xmlns:q1="addFiles">
        <session xsi:type="xsd:string">4c7d72e2368ef4697005e12002d547f9</session>
        <files href="#id1" />
      </q1:addFiles>
      <soapenc:Array id="id1" xmlns:q2="DocServerServices" soapenc:arrayType="q2:DocServerFile[1]">
        <Item href="#id2" />
      </soapenc:Array>
      <q3:DocServerFile id="id2" xsi:type="q3:DocServerFile" xmlns:q3="DocServerServices">
        <path xsi:type="xsd:string">/SampleRepository/Address Book/t.txt</path>
        <contentType xsi:type="xsd:string">type</contentType>
      <contentLength xsi:type="xsd:long">3</contentLength>
      <content xsi:type="xsd:base64Binary">MTIz</content>
      </q3:DocServerFile>
    </soap:Body>
</soap:Envelope>
 
 
Note that .NET encodes the array parameter outside the method name element (addFiles). This causes Axis to think that the array element is a Soap Document service message and not an RPC style message.
 
I traced the problem to the following code in org.apache.axis.providers.java.RPCProvider.java:
 
            // If this is a regular old SOAPBodyElement, and it's a root,
            // we're probably a non-wrapped doc/lit service.  In this case,
            // we deserialize the element, and create an RPCElement "wrapper"
            // around it which points to the correct method.
            // FIXME : There should be a cleaner way to do this...
1            if (!(bodies.get(bNum) instanceof RPCElement)) {
2                SOAPBodyElement bodyEl = (SOAPBodyElement)bodies.get(bNum);
                // igors: better check if bodyEl.getID() != null
                // to make sure this loop does not step on SOAP-ENC objects
                // that follow the parameters! FIXME?
3                if (bodyEl.isRoot() && operation != null) {
4                    ParameterDesc param = operation.getParameter(bNum);
                    // at least do not step on non-existent parameters!
5                    if(param != null) {
6                        Object val = bodyEl.getValueAsType(param.getTypeQName());
7                        body = new RPCElement("",
8                                              operation.getName(),
9                                              new Object [] { val });
10                    }
                ....
 
 
This code is looping over Soap body elements, and if it finds more than one body element that are root, it assumes that the extra body elements are (according to the comments) "non-wrapped doc/lit service". This is not the case in this instance. The code incorrectly wraps the <soapenc:Array> element into an RPCElement and tries to invoke it (not shown above).
 
I was able to get around the problem by following "igors" advice in the comments, and changing the code in line 3 as follows:
 
if (bodyEl.isRoot() && operation != null && bodyEl.getID() == null) {
 
This is obviously a hack which fixes my problem, but I am sure members of this list can come up with the appropriate fix.
 
Thanks
 
Kamran Kashanian
 
 
 
 

Reply via email to