Java server, PHP client, array of complexType, Deserializer error
| From: | Peter | Date: | Tue, 17 Jan 2006 03:48:14 +0000 |
| Subject: | Java server, PHP client, array of complexType, Deserializer error | ||
| Groups: | php.soap | ||
| Request: | Send a blank email to php-soap+get-2085@lists.php.net to get a copy of this message | ||
This seems to be a recurring problem, but I have yet to find an answer.
I have implemented a web service written in Java, hosted on an Oracle Application Server (version
9.0.4).
The web service makes heavy use of custom objects, written as Java Beans on the server-side, and
implemented as complex types in the WSDL. The objects are really just collections of variables.
Using PHP 5.0.3 with its built-in SOAP implementation, I am able to consume the WSDL w/out errors
and make most calls using PHP classes to emulate the WSDL's complex types. The problem comes
in when a transaction requires an array of one of the complex types.
Java-based clients have no problems; neither do .NET-based ones.
I built a simple example that illustrates the problem; let's get right into it. This is a live
example, so you can do some testing on your own if you'd like.
The service is here:
http://vrcweb1.vrcis.com/custserv/CustomerService
The WSDL can be found here:
http://vrcweb1.vrcis.com/custserv/CustomerService?WSDL
There is one operation: EchoBars. It accepts an array of Bar objects, then returns that array.
The Bar object has one field: NAME, of type string.
This is the PHP code I use to invoke EchoBars:
$WSDL = "http://vrcweb1.vrcis.com/custserv/CustomerService?WSDL";
$client = new SoapClient($WSDL);
$b1 = new Bar();
$b1->NAME = "bar none";
try{$client->EchoBars(array(1=>$b1));}catch(Exception $Ex){echo $Ex;}
This is the request it generates:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="CustomerService"
xmlns:ns2="http://www.vrcis.com/CustomerServiceAPIV1"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:EchoBars>
<BARS
SOAP-ENC:arrayType="ns2:Bar[1]"
xsi:type="ns2:ArrayOfBar">
<item xsi:type="ns2:Bar">
<NAME xsi:type="xsd:string">bar none</NAME>
</item>
</BARS>
</ns1:EchoBars>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Which request returns this error message:
No Deserializer found to deserialize a http://www.vrcis.com/CustomerServiceAPIV1:ArrayOfBar
using encoding style http://schemas.xmlsoap.org/soap/encoding/.
Here is a request that works:
<?xml version='1.0' encoding='UTF-8'?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<ns1:EchoBars
xmlns:ns1="CustomerService"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<BARS
xmlns:ns2="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns2:Array"
xmlns:ns3="http://www.vrcis.com/CustomerServiceAPIV1"
ns2:arrayType="ns3:Bar[1]">
<item xsi:type="ns3:Bar">
<NAME xsi:type="xsd:string">bar none</NAME>
</item>
</BARS>
</ns1:EchoBars>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Notice that the only real difference between the two requests is the type of the BARS element. In
the PHP-generated one it is "<my namespace>:ArrayOfBar", while it is
"<SOAP-ENC namespace>:Array" in the other one.
There are other differences, but they are all naming conventions and don't apply.
To generate another request that works, goto http://www.soapclient.com/soaptest.html.
It'll generate a request that is substantively the same as the one above.
I think I know what's happening, I just don't know why, or if there's a way to make
it "happen" correctly. Or some way to reformat my WSDL so that PHP interprets it
correctly.
The way I understand it, in the WSDL, arrays of complex types are defined with a level of
indirection:
<complexType name="Bar">
</complexType>
<complexType name="ArrayOfBar">
<attribute arrayType="Bar[]"/>
</complexType>
It seems to work kinda like pointers in C: ArrayOfBar holds a reference to an array of Bar objects.
What appears to be happening is that PHP is not following that reference, but is instead grabbing
the value of the variable rather than dereferencing it and using _that_ value (to use pointer
lingo).
So, my questions:
1. Is the WSDL formatted the right way for PHP? Could it be formatted differently, so as to coerce
PHP into supplying the correct "type" for the BARS element?
2. Is there any option or flag in PHP's SOAP implementation that will set up PHP to read the
WSDL differently?
3. Does anyone know what the heck I'm talking about? ;-)
Thanks,
-Peter