5

I am using perl soap::lite to build a web services client. The implementation works fine for simple methods, which will e.g. require a single scalar argument. EG, the following works fine.

#!/usr/bin/perl

use warnings;
use SOAP::Lite  +trace=>debug;
use strict;
use Data::Dumper;
$SOAP::Constants::PREFIX_ENV = 'SOAP-ENV';
my $base="https://XXXX:60001/GDBIncidentWebService/Config?wsdl&style=rpc";
my $user="XXXX";
my $pwd="XXXX";

my $lite = SOAP::Lite -> readable(1)
                  -> service($base) ;
my @res=$lite->readIncident("123456");
print Dumper(\@res);
exit;
sub SOAP::Transport::HTTP::Client::get_basic_credentials { return $user => $pwd ; }

I need to call one method which requires a more complex set of arguments(a few scalars plus one array of key-value pairs). I figure I should use the SOAP::Data module to serialize my data correctly but fail to get it to work. Even the "simple" methods (like the one above) do not seem to work. EG (just showing lines changed from above script) :

my $arg= SOAP::Data->new()->type('xs:string')-> value("20054106");
my @res=$lite->readIncident($arg);

Yields:

String value expected instead of SOAP::Data reference

Any idea on how to fix this ? Thanks a lot ! For reference here is the wsdl for the method called in my script

 <wsdl:operation name="readIncident">
  <soap:operation soapAction=""/>
  <wsdl:input>
    <soap:body use="literal" namespace="urn:GDBIncidentWebServiceVi" parts="ticketID "/>
  </wsdl:input>
  <wsdl:output>
    <soap:body use="literal" namespace="urn:GDBIncidentWebServiceVi"/>
  </wsdl:output>
</wsdl:operation>

The full WSDL looks like follows - spread into 3 files. Main WSDL file:

 <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" name="GDBIncidentWebServiceWsd" targetNamespace="urn:GDBIncidentWebServiceWsd" xmlns:bns0="urn:GDBIncidentWebServiceWsd/Config/rpc" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
   <wsdl:import location="./bindings/Config_rpc.wsdl" namespace="urn:GDBIncidentWebServiceWsd/Config/rpc"/>
   <wsdl:service name="GDBIncidentWebService">
     <wsdl:port name="ConfigPort_Rpc" binding="bns0:ConfigBinding">
       <soap:address location="http://xxxx/GDBIncidentWebService/Config?style=rpc"/>
     </wsdl:port>
  </wsdl:service>
 </wsdl:definitions>

Bindings file (extract)

<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"  xmlns:ns1="http://www.w3.org/2001/XMLSchema" xmlns:ns0="urn:com.dbag.gde.gdb.types" targetNamespace="urn:GDBIncidentWebServiceWsd/GDBIncidentWebServiceVi/rpc" xmlns:tns="urn:GDBIncidentWebServiceWsd/GDBIncidentWebServiceVi/rpc" xmlns:ns2="urn:java/lang">
       <wsdl:types>
        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:com.dbag.gde.gdb.types" xmlns:tns="urn:com.dbag.gde.gdb.types" elementFormDefault="qualified">
       <xs:complexType name="KeyValuePair">
         <xs:sequence>
            <xs:element name="key" type="xs:string" nillable="true" minOccurs="0"/>
         <xs:element name="value" type="xs:string" nillable="true" minOccurs="0"/>
        </xs:sequence>
      </xs:complexType>
       <xs:complexType name="ArrayOfKeyValuePair">
        <xs:sequence>
           <xs:element maxOccurs="unbounded" minOccurs="0" name="KeyValuePair" type="tns:KeyValuePair" nillable="true"/>
         </xs:sequence>
       </xs:complexType>
      </xs:schema>
     <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:java/lang" xmlns:tns="urn:java/lang" elementFormDefault="qualified">
       <xs:complexType name="ArrayOfString">
         <xs:sequence>
           <xs:element maxOccurs="unbounded" minOccurs="0" name="String" type="xs:string" nillable="true"/>
        </xs:sequence>
      </xs:complexType>
    </xs:schema>
  </wsdl:types>
  <wsdl:message name="createInsourcingIncidentIn">
    <wsdl:part name="externalKey" type="ns1:string"/>
    <wsdl:part name="title" type="ns1:string"/>
    <wsdl:part name="description" type="ns1:string"/>
    <wsdl:part name="impact" type="ns1:string"/>
    <wsdl:part name="urgency" type="ns1:string"/>
    <wsdl:part name="contact" type="ns1:string"/>
    <wsdl:part name="creatorGroup" type="ns1:string"/>
    <wsdl:part name="category1" type="ns1:string"/>
    <wsdl:part name="category2" type="ns1:string"/>
    <wsdl:part name="category3" type="ns1:string"/>
    <wsdl:part name="extReference" type="ns0:ArrayOfKeyValuePair"/>
    <wsdl:part name="attachments" type="ns0:ArrayOfAttachment"/>
    <wsdl:part name="additionalFields" type="ns0:ArrayOfKeyValuePair"/>
    <wsdl:part name="assignmentGroup" type="ns1:string"/>
    <wsdl:part name="assignmentSubGroup" type="ns1:string"/>
    <wsdl:part name="productId" type="ns1:string"/>
    <wsdl:part name="productName" type="ns1:string"/>
    <wsdl:part name="service" type="ns1:string"/>
    <wsdl:part name="customer" type="ns1:string"/>
  </wsdl:message>

  <wsdl:portType name="GDBIncidentWebServiceVi_Rpc">
    <wsdl:operation name="createInsourcingIncident">
      <wsdl:input message="tns:createInsourcingIncidentIn"/>
      <wsdl:output message="tns:createInsourcingIncidentOut"/>
    </wsdl:operation>
   </wsdl:portType>
</wsdl:definitions>

Operation definition

    <wsdl:operation name="createInsourcingIncident">
      <soap:operation soapAction=""/>
      <wsdl:input>
        <soap:body use="literal" namespace="urn:GDBIncidentWebServiceVi" parts="externalKey title description impact urgency contact creatorGroup category1 category2 category3 extReference attachments additionalFields assignmentGroup assignmentSubGroup productId productName service customer "/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" namespace="urn:GDBIncidentWebServiceVi"/>
      </wsdl:output>
    </wsdl:operation>
PPX
  • 61
  • 4
  • 1
    Maybe [this will help](http://www.perlmonks.org/?node_id=920498). – Tim Biegeleisen May 22 '15 at 08:23
  • 1
    And [this](http://search.cpan.org/dist/SOAP-Lite/lib/SOAP/Data.pod) will help even more. It shows you how the Perl code will map to XML. You will need to look at your WSDL for more information and we probably cannot give you a definitive answer. – Tim Biegeleisen May 22 '15 at 08:26
  • Researching further : I see hints that if I want to serialize using the SOAP::Data module, I should (must ?) not use the service wsdl at all but rather create the SOAP::Lite handle using proxy and uri. Is this true ? I could not find solid evidence about that... – PPX May 22 '15 at 12:43
  • Post your WSDL and we can probably give you real code to use. – Tim Biegeleisen May 23 '15 at 17:04
  • Apologies for the delay - I was offsite. – PPX Jun 04 '15 at 06:49
  • I attached the relevant parts of the WSDL to the initial question. Thank you ! – PPX Jun 04 '15 at 07:07
  • Would anyone be able to comment on this basic question above ? Researching further : I see hints that if I want to serialize using the SOAP::Data module, I should (must ?) not use the service wsdl at all but rather create the SOAP::Lite handle using proxy and uri. Is this true ? I could not find solid evidence about that.. – PPX Jun 04 '15 at 08:33

1 Answers1

1

Update and resolution. It looks like using the proxy/uri method to create the SOAP::Lite object (instead of simply referencing the WSDL "service") strings is mandatory if you want to pass complex data Therefore the code now looks as follows for the simple request :

 my $base="https://XXXXX/GDBIncidentWebService/Config?wsdl&style=rpc";
 my $uri="urn:GDBIncidentWebServiceVi"
 my $ticketID='20054106';
 my $lite = SOAP::Lite -> proxy($base)
             -> uri($uri);
 my $res = $lite -> readIncident(SOAP::Data->('ticketID' => $ticketID))
             -> result;
 print Dumper($res);
PPX
  • 61
  • 4