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
|
- RE: Possible Bug in RPCProvider.java array handling Kamran Kashanian
- RE: Possible Bug in RPCProvider.java array handling Glen Daniels