views:

703

answers:

2

I am attempting to access a web service using SOAP through Perl and am having issues calling the service's functions that require parameters. The XSD that dictates the SOAP call says,

<xs:complexType name="getVersion"> 
<xs:sequence/> 
</xs:complexType> 
<xs:complexType name="getVersionResponse"> 
<xs:sequence> 
<xs:element minOccurs="0" name="return" type="xs:string"/> 
</xs:sequence> 
</xs:complexType>
...
<xs:complexType name="enumerateEntities"> 
<xs:sequence> 
<xs:element name="entityId" type="xs:int"/> 
<xs:element minOccurs="0" name="entityType" type="tns:entityType"/> 
</xs:sequence> 
</xs:complexType> 
<xs:complexType name="enumerateEntitiesResponse"> 
<xs:sequence> 
<xs:element maxOccurs="unbounded" minOccurs="0" name="return" nillable="true" type="xs:int"/> 
</xs:sequence> 
</xs:complexType>

According to the docs for the service, the signatures for the two functions are:

String getVersion ()
int[] enumerateEntities (int entityId, EntityType entityType)

I am able to call the first function, which requires no input parameters, using:

#!/usr/bin/perl

use SOAP::Lite;
my $uri = 'http://wsdl.mydomain.com/';
my $service = SOAP::Lite
 -> uri($uri)
 -> on_action(sub { sprintf '"Call by on_action: %s"',shift})
 -> proxy('http://192.168.1.100:8688/MyService/services/MyService.MyServicePort/');

$method = SOAP::Data->name("MyService")->attr({xmlns => $uri});
$getVersion = SOAP::Data->name("getVersion")->attr({xmlns=>$uri});#line 11
my $theResult = $service->getVersion;

unless ($theResult->fault){ print "Version: "; print $theResult->result;}
else {print $theResult->faultstring;}

...but my attempt (below) at calling a function with parameters by changing line 11 on have been futile.

...
@entityId = SOAP::Data->type('int')->name('entityId')->value(0);
@entityType = SOAP::Data->type('EntityType')->name('entityType')->value(NODE);
$enumerateEntities = SOAP::Data->name("enumerateEntities",@entityId,@entityType)->attr({xmlns=>$uri});
my $result2 = $service->enumerateEntities;
print $result2->result;

What am I doing wrong that is preventing me from calling functions of the service with parameters?


Edit: Here's the updated sample code with using SOAP::WSDL

#!/usr/bin/perl

use SOAP::WSDL;
use Data::Dumper;

my $service = SOAP::WSDL->new(
   wsdl => 'http://192.168.1.100:8688/MyService/services/MyService.MyServicePort?wsdl',
   outputhash => 1
);
+2  A: 

Use SOAP::WSDL to consume the service wsdl, it also marshals from and (optionally) to plain perl data structures for you. Highly recommended module.

Something like the following:

use SOAP::WSDL;
use Data::Dumper;

my $soap = SOAP::WSDL->new(
  wsdl => 'http://server/pathtoservice?WSDL',
  outputhash => 1
);
my $res = $soap->call('method', { foo => 1, bar =>2 });
die $res->faultstring if $res->fault;
print Dumper($res->result);
David Toso
I do this but am told, "Cannot import namespace ...without base uri. Use >parse_uri< or >set_uri< to set one. I have the uri from my example above. How do I set it using SOAP::WSDL?
Mat
I'm having a similar problem, and I've tried this solution, and the parameters just don't make it through to the outgoing request. http://stackoverflow.com/questions/1765248
aidan
Can you supply the service and WSDL urls for testing?The above works for me against many services.
David Toso
Are you supplying the [WSDL url] or the [proxy path] to SOAP::WSDL->new ? (Former is correct, latter is not).
David Toso
If the service doesn't serve up the WSDL, you can use the 'file:/' url scheme for the wsdl param of the constructor.
David Toso
I am using the WSDL url. I updated the original post to reflect the SOAP::WSDL code I'm using. When run, I get the, ">parse_uri< or >set_uri<" error mentioned in my first response. With my original code, I can call a non-parameterized function of the service and get appropriate results. How do I call parameterized functions?Thanks!
Mat
Also, I added my usage of SOAP::WSDL to the original post.
Mat
What do you get when you run wsdl2perl.pl (from the SOAP::WSDL distribution) on the WSDL file/url ? Does it terminate without error?If you have access to wsdl.exe from visual studio, does that like the WSDL (terminate without error)? If you know, what platform/technology/framework was used to produce the webservice? The WSDL ?
David Toso
A: 

You can try using SOAP::Lite if you are having problems with the WSDL:

remember, you can always use:

use SOAP::Lite qw(trace);

to see the exact XML you are sending to see how close you are.

I don't have time to test this out, but here is my best guess off the top of my head:

my $soap = SOAP::Lite
 -> uri($uri)
 -> on_action(sub { sprintf '"Call by on_action: %s"',shift})
 -> proxy('http://192.168.1.100:8688/MyService/services/MyService.MyServicePort/');

my $id = SOAP::Data->type('int')->name('entityId')->value(0);
my $type= SOAP::Data->type('EntityType')->name('entityType')->value(NODE);
$soap->enumerateEntities($id, $param);
tster