in reply to Re^6: SOAP::Lite with client using service
in thread SOAP::Lite with client using service
The problem is that the server is not complying with the contract that the WSDL file states, the client is receiving in the body of the response something like:
Whereas the WSDL is promising that the returned body is going to be something like:<namesp1:getResponse xmlns:namesp1="http://127.0.0.1/testSoap"> <s-gensym3> <age xsi:type="xsd:int">0</age> <phone xsi:type="xsd:string" /> <ID xsi:type="xsd:int">0</ID> <surname xsi:type="xsd:string">Bar</surname> <first xsi:type="xsd:string">Foo</first> </s-gensym3> </namesp1:getResponse>
The problem is exacerbated with the SOAP::Lite because it essentially ignores the types of the messages in the WSDL (it basically only pays attention to the operations and the bindings) it doesn't hold you to the contract so you are not seeing the problem with the Perl client, whereas clients using other toolkits are likely to be more strict.<ns:get_IN xmlns:ns="http://127.0.0.1/testSoap"> <Map xmlns="http://xml.apache.org/xml-soap"> <item> <key>age</key> <value>0</value> </item> <item> <key>phone</key> <value></value> </item> <item> <key>ID</key> <value>0</value> </item> <item> <key>surname</key> <value>Bar</value> </item> <item> <key>first</key> <value>Foo</value> </item> </Map> </ns:get_IN>
Now you have two ways of fixing this, either change the WSDL to match the actual return from your server or change the the server code to match the WSDL, the first has the problem that to some extent the server response is not-predetermined (note the <gensym3> element in the response above), however you may feel that the second is coupling you module too tightly to the webservices toolkit, personally I would take the pragmatic view and do a bit of both ;-)
Firstly you want to change your module so that it does the equivalent of:
(I have obviously omitted your database stuff as I can't reproduce it here). The basic thing is that you change the $userinfo to a ARRAYREF, blessed as "Map" and each element is a HASHREF with the keys 'key' and 'value' blessed as 'item' - this will then serialize with about the correct schema. The only other issue which is easier to deal with in the WSDL is that you need to change the name of the message get_IN to getResponse (which is sort of conventional anyway) you need to change it in both places it appears:package testSoap; + sub get { print STDERR "module called\n"; + my ( $self, $id ) = @_; my $userinfo = [ bless ({ key => 'ID', value => 0 }, "item"), bless ({ key => 'first', value => 'Foo' }, "item"), bless ({ key => 'surname', value => 'Bar' }, "item"), bless ({ key => 'age', value => 0 }, "item"), bless ({ key => 'phone', value => '' }, "item") ]; + return bless $userinfo, "Map"; + } + 1;
And then you should be away. I also made a mistake in the Schema part of the WSDL you need to replace:<message name="getResponse"> <part name="user" type="apachesoap:Map"/> </message> <portType name="webServicePortType"> <operation name="get"> <input message="tns:get_OUT"/> <output message="tns:getResponse"/> </operation> </portType>
with<xsd:element maxOccurs="1" minOccurs="0" name="item" type="apachesoap: +item"/>
or you are only allowed one item.<xsd:element maxOccurs="unbounded" minOccurs="0" name="item" type="apa +chesoap:item"/>
/J\
|
|---|