SOAP::Lite, parameter-addressing

843 Views Asked by At

I am using SOAP::Lite to use a WSDL-defined webservice.

My request (that is working fine) is like that.

<soapenv:Envelope xmlns:soapenv="http://myabc">
 <soapenv:Header/>
 <soapenv:Body>
  <foo>
     <p1>max</p1>
     <p2>frank</p2>
  </foo>
.... 

My perl code.

my $service = SOAP::Lite->service ("http://mywsdl");
my $ret = $service->foo ("max", "frank");

That is working too.

But I like to name/address my parameters p1 and p2 to have more flexibility.

I tried it with a hash

my %params = (p1 => "max", p2 => "frank");

and also with SOAP::Data.

my @params = (
 SOAP::Data->name (p1 => "max"), 
 SOAP::Data->name (p2 => "frank"));

But it is not working that way.

String value expected instead of SOAP::Data reference

Any ideas how to name my parameters?

EDIT

I like to use wsdl service. So how do I know how the service functions expect their parameters?? Thats the core of my question. I thought about the naming of parameters for a workaround.

3

There are 3 best solutions below

10
user3606329 On

I don't think you can name the parameters if you create the stubs from the service descriptions by calling service().

If you want to assign values to the parameters, there is an example available on CPAN.

Function sayHello

 <sayHello xmlns="urn:HelloWorld">
   <name xsi:type="xsd:string">Kutter</name>
   <givenName xsi:type="xsd:string">Martin</givenName>
 </sayHello>

SOAP request

 use SOAP::Lite;
 my $soap = SOAP::Lite->new( proxy => 'http://localhost:81/soap-wsdl-test/helloworld.pl');
 $soap->default_ns('urn:HelloWorld');
 my $som = $soap->call('sayHello',
    SOAP::Data->name('name')->value('Kutter'),
    SOAP::Data->name('givenName')->value('Martin')
 );
 die $som->faultstring if ($som->fault);
 print $som->result, "\n";

You have to replace the value of proxy to http://mywsdl, name and givenName to p1 and p2, sayHello to foo and urn:HelloWorld to your WSDLs namespace.

I also recommend to check this. All the requests can be done without SOAP::Lite.

1
Borodin On

If you want to specify the names of the parameters then you should avoid creating a service, which is mostly intended to avoid such housekeeping

If you simply call the method and supply its parameters then it should do what you want

$client->call(foo =>
   SOAP::Data->name( p1 => 'max' ),
   SOAP::Data->name( p2 => 'frank' )
);

Note that

SOAP::Data->name( p1 => 'max' )

is an undocumented contraction of

SOAP::Data->name('p1')->value('max')

or

SOAP::Data->new( name => 'p1', value => 'max' )
4
Patrick Mevzek On

If you would like to use a WSDL file (welcome to hell), you need to use SOAP::WSDL instead of SOAP::Lite. Then you will have an utility called wsdl2perl.pl. If you run it on your wsdl file it will create a lot of perl code, including some classes for each service defined in the wsdl file.

Then in your code you instantiate a new instance of the specific endpoint you want to use, and then you call on this object methods named after the services offered on this endpoint (you do not use the call method anymore), passing a hash reference with all parameters.

You will still need to know what parameters are expected because there is not a lot of introspection available (you can have a workaround that because if you pass an unknown parameter name to the classes they will die and in the error message you will have the list of available parameters, so you can catch that and parse the error string. Ugly, but I did not find another way to do it).