|
|
|
@@ -4,15 +4,23 @@ package SOAP::WSDL;
|
|
|
|
|
use SOAP::Lite;
|
|
|
|
|
use vars qw($VERSION @ISA);
|
|
|
|
|
use XML::XPath;
|
|
|
|
|
use Data::Dumper;
|
|
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
|
|
use Data::Dumper;
|
|
|
|
|
|
|
|
|
|
@ISA = qw(SOAP::Lite);
|
|
|
|
|
|
|
|
|
|
$VERSION = "1.22";
|
|
|
|
|
$VERSION = "1.24";
|
|
|
|
|
|
|
|
|
|
# SOAP::Lite has changed the name for speciying a schema in 0.6?
|
|
|
|
|
# method before: schema
|
|
|
|
|
# method name after: schema_url
|
|
|
|
|
#
|
|
|
|
|
# Actually, we don't care which SOAP::Lite version there is, so we
|
|
|
|
|
# try to support whatever we find...
|
|
|
|
|
#
|
|
|
|
|
my $SCHEMA_URL = $SOAP::Lite::VERSION >= 0.6 ? 'schema_url' : 'schema';
|
|
|
|
|
|
|
|
|
|
sub wsdlinit
|
|
|
|
|
{
|
|
|
|
@@ -51,9 +59,9 @@ sub wsdlinit
|
|
|
|
|
} ## end if ( $self->{ _WSDL }->...
|
|
|
|
|
unless ( $xpath )
|
|
|
|
|
{
|
|
|
|
|
$xpath =
|
|
|
|
|
XML::XPath->new(
|
|
|
|
|
xml => SOAP::Schema->new( schema_url => $self->wsdl )->access );
|
|
|
|
|
no strict qw(refs);
|
|
|
|
|
$xpath = XML::XPath->new(
|
|
|
|
|
xml => $self->schema->$SCHEMA_URL( $self->wsdl() )->access );
|
|
|
|
|
} ## end unless ( $xpath )
|
|
|
|
|
|
|
|
|
|
( $xpath )
|
|
|
|
@@ -137,9 +145,6 @@ sub wsdlinit
|
|
|
|
|
$nsHash->{ 'http://xml.apache.org/xml-soap' } . "|";
|
|
|
|
|
chop $self->{ _WSDL }->{ _type_ns };
|
|
|
|
|
|
|
|
|
|
# TODO make _get_first_port conditional...
|
|
|
|
|
$self->_get_first_port();
|
|
|
|
|
|
|
|
|
|
$self->servicename( $opt{ servicename } ) if ( $opt{ servicename } );
|
|
|
|
|
$self->portname( $opt{ portname } ) if ( $opt{ portname } );
|
|
|
|
|
|
|
|
|
@@ -148,6 +153,81 @@ sub wsdlinit
|
|
|
|
|
|
|
|
|
|
} ## end sub wsdlinit
|
|
|
|
|
|
|
|
|
|
sub _wsdl_init_port
|
|
|
|
|
{
|
|
|
|
|
my $self = shift;
|
|
|
|
|
my $name = shift;
|
|
|
|
|
my $opt = shift;
|
|
|
|
|
my $xpath = $self->_wsdl_xpath;
|
|
|
|
|
my $tns = $self->_wsdl_tns;
|
|
|
|
|
|
|
|
|
|
# Step one: get <service><port...> element
|
|
|
|
|
#
|
|
|
|
|
# This provides us with the address (enpoint/proxy), which we set here
|
|
|
|
|
# and the binding name.
|
|
|
|
|
|
|
|
|
|
# Fetch <soap:address from inside <wsdl:port -
|
|
|
|
|
# so we get both with one xpath query...
|
|
|
|
|
my $path = '/' . $self->_wsdl_wsdlns()
|
|
|
|
|
. 'definitions/'
|
|
|
|
|
. $self->_wsdl_wsdlns() .'service[@name="' . $self->servicename()
|
|
|
|
|
. '"]/'
|
|
|
|
|
. $self->_wsdl_wsdlns() . 'port[@name="' . $name . '"]/'
|
|
|
|
|
. $self->_wsdl_soapns() . 'address';
|
|
|
|
|
|
|
|
|
|
my $address = $xpath->find( $path )->shift
|
|
|
|
|
|| die "Error processing WSDL file - no such port ($path)";
|
|
|
|
|
my $endpoint = $address->getAttribute( 'location' )
|
|
|
|
|
or die "No endpoint address found ($path)";
|
|
|
|
|
|
|
|
|
|
$self->proxy( $endpoint );
|
|
|
|
|
|
|
|
|
|
my $port = $address->getParentNode();
|
|
|
|
|
my $binding_name = $port->getAttribute( 'binding' );
|
|
|
|
|
|
|
|
|
|
# Step two: get the correct <binding...> element.
|
|
|
|
|
# This provides us with the portType name.
|
|
|
|
|
# Remember binding for later usage (in call() ) and
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
# remove the default targetNamespace from messageName
|
|
|
|
|
$binding_name =~ s/^($tns)\:*//;
|
|
|
|
|
|
|
|
|
|
$path = join(
|
|
|
|
|
$self->_wsdl_wsdlns,
|
|
|
|
|
(
|
|
|
|
|
'/',
|
|
|
|
|
'definitions/',
|
|
|
|
|
'binding[@name="' . $binding_name . '"]',
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
my $binding = $xpath->find( $path )->shift()
|
|
|
|
|
or die "no binding found ($path)";
|
|
|
|
|
|
|
|
|
|
$self->{ _WSDL }->{ binding } = $binding;
|
|
|
|
|
|
|
|
|
|
my $portType_name = $binding->getAttribute( 'type' );
|
|
|
|
|
|
|
|
|
|
# remove the default targetNamespace from messageName
|
|
|
|
|
$portType_name =~ s/^($tns)\:*//;
|
|
|
|
|
|
|
|
|
|
$path = join(
|
|
|
|
|
$self->_wsdl_wsdlns,
|
|
|
|
|
(
|
|
|
|
|
'/',
|
|
|
|
|
'definitions/',
|
|
|
|
|
'portType[@name="' . $portType_name . '"]',
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
# warn("looking for $path");
|
|
|
|
|
my $portType = $xpath->find( $path )->shift()
|
|
|
|
|
or die "No portType found ($path)";
|
|
|
|
|
$self->{ _WSDL }->{ portType } = $portType;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub call
|
|
|
|
|
{
|
|
|
|
|
my $self = shift;
|
|
|
|
@@ -170,63 +250,22 @@ sub call
|
|
|
|
|
|| die "Error processing WSDL: no wsdl object";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
my $portType = "";
|
|
|
|
|
my $binding = "";
|
|
|
|
|
# get the first port if none has been set...
|
|
|
|
|
$self->_get_first_port() if (not $self->portname() );
|
|
|
|
|
|
|
|
|
|
my $portName = "";
|
|
|
|
|
# initialize port if not done yet
|
|
|
|
|
$self->_wsdl_init_port( $self->portname() )
|
|
|
|
|
if ( not $self->_wsdl_portType() );
|
|
|
|
|
|
|
|
|
|
$portName = $self->portname;
|
|
|
|
|
$portName or die "Error processing the call: no port found";
|
|
|
|
|
|
|
|
|
|
#look for the binding
|
|
|
|
|
$path = join(
|
|
|
|
|
$self->_wsdl_wsdlns,
|
|
|
|
|
(
|
|
|
|
|
"/", "definitions/",
|
|
|
|
|
"service[\@name='" . ( $self->servicename ) . "']/",
|
|
|
|
|
"port[\@name='" . $portName . "']"
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
my $port = $xpath->find( $path )->shift
|
|
|
|
|
|| die "Error processing WSDL file - no such port ($path)";
|
|
|
|
|
|
|
|
|
|
$binding = $port->findvalue( '@binding' )
|
|
|
|
|
|| die
|
|
|
|
|
"Error processing WSDL: Cannot find the binding for the service $path";
|
|
|
|
|
|
|
|
|
|
#look for the location
|
|
|
|
|
$path .= "/" . $self->_wsdl_soapns . "address";
|
|
|
|
|
|
|
|
|
|
my $address = $xpath->find( $path )->shift
|
|
|
|
|
|| die "Error processing WSDL file - no such address ($path)";
|
|
|
|
|
|
|
|
|
|
$location = $address->findvalue( '@location' )->value
|
|
|
|
|
|| die
|
|
|
|
|
"Error processing WSDL: Cannot find the port for the location in service $path";
|
|
|
|
|
$self->proxy( $location );
|
|
|
|
|
|
|
|
|
|
# remove the default targetNamespace from messageName
|
|
|
|
|
$binding =~ s/^($tns)\:*//;
|
|
|
|
|
$binding =~ s/^($tns)\:*//;
|
|
|
|
|
|
|
|
|
|
$path = join(
|
|
|
|
|
$self->_wsdl_wsdlns,
|
|
|
|
|
( '/', 'definitions/', "binding[\@name='$binding']/\@type" )
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$portType = $self->_wsdl_findvalue( $path, "dieIfError" );
|
|
|
|
|
$portType =~ s/^(.*?)\://;
|
|
|
|
|
|
|
|
|
|
#Now we need to find the operation, in the binding.
|
|
|
|
|
#After that we can extract the SoapAction and the
|
|
|
|
|
#input name, if defined
|
|
|
|
|
my $portType = $self->_wsdl_portType();
|
|
|
|
|
my $binding = $self->_wsdl_binding();
|
|
|
|
|
|
|
|
|
|
$path = join(
|
|
|
|
|
$self->_wsdl_wsdlns,
|
|
|
|
|
(
|
|
|
|
|
'/', 'definitions/', "binding[\@name='$binding']/",
|
|
|
|
|
"operation[\@name='$method']/", $mode
|
|
|
|
|
# '/',
|
|
|
|
|
'operation[@name="' . $method . '"]/',
|
|
|
|
|
$mode
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
@@ -234,58 +273,75 @@ sub call
|
|
|
|
|
$data{ "wsdl_${mode}_name" }
|
|
|
|
|
and $path .= "[\@name='" . $data{ "wsdl_${mode}_name" } . "']";
|
|
|
|
|
|
|
|
|
|
#now we can get the soapaction
|
|
|
|
|
my $soapActionPath =
|
|
|
|
|
"$path/../" . $self->_wsdl_soapns . "operation/\@soapAction";
|
|
|
|
|
my $soapAction = $self->_wsdl_findvalue( $soapActionPath, "" );
|
|
|
|
|
$soapAction and $self->on_action( sub { sprintf "$soapAction" } );
|
|
|
|
|
# warn "Looking for operation $path";
|
|
|
|
|
my $inputMessageName;
|
|
|
|
|
my $binding_operation_message = $binding->find( $path )->shift();
|
|
|
|
|
if ($binding_operation_message)
|
|
|
|
|
{
|
|
|
|
|
my $binding_operation = $binding_operation_message->getParentNode();
|
|
|
|
|
my $soapAction = $binding_operation->getAttribute( 'soapAction' );
|
|
|
|
|
$self->on_action( sub { return "$soapAction" } ) if ($soapAction);
|
|
|
|
|
# warn "soapAction set to $soapAction\n";
|
|
|
|
|
|
|
|
|
|
#if defined, the input message name has to be the leading item
|
|
|
|
|
#in the SOAP call. If not defined, it has to be the operation
|
|
|
|
|
#name. In the case of overloaded calls, it *IS* the parameter passed
|
|
|
|
|
#by the calling script. So
|
|
|
|
|
my $inputMessageName;
|
|
|
|
|
if ( $data{ "wsdl_${mode}_name" } )
|
|
|
|
|
{
|
|
|
|
|
$inputMessageName = $data{ "wsdl_${mode}_name" };
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
$inputMessageName = $self->_wsdl_findvalue( "$path/\@name", "" );
|
|
|
|
|
}
|
|
|
|
|
$inputMessageName or $inputMessageName = $method;
|
|
|
|
|
#if defined, the input message name has to be the leading item
|
|
|
|
|
#in the SOAP call. If not defined, it has to be the operation
|
|
|
|
|
#name. In the case of overloaded calls, it *IS* the parameter passed
|
|
|
|
|
#by the calling script. So
|
|
|
|
|
|
|
|
|
|
if ( $data{ "wsdl_${mode}_name" } )
|
|
|
|
|
{
|
|
|
|
|
$inputMessageName = $data{ "wsdl_${mode}_name" };
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
$inputMessageName = $binding_operation_message->getAttribute('name');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
# just set it right if not set before:
|
|
|
|
|
$inputMessageName ||= $method;
|
|
|
|
|
|
|
|
|
|
$path = join(
|
|
|
|
|
$self->_wsdl_wsdlns,
|
|
|
|
|
(
|
|
|
|
|
'/', 'definitions/',
|
|
|
|
|
"binding[\@name='$binding']/", "operation[\@name='$method']/",
|
|
|
|
|
'/',
|
|
|
|
|
'definitions/',
|
|
|
|
|
'binding[@name="' . $binding->getAttribute('name') . '"]/',
|
|
|
|
|
'operation[@name="' . $method . '"]/',
|
|
|
|
|
"$mode/"
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
. $self->_wsdl_soapns . "body/";
|
|
|
|
|
. $self->_wsdl_soapns . "body";
|
|
|
|
|
|
|
|
|
|
#a call can have an associated, namespace
|
|
|
|
|
my $callNamespace = $self->_wsdl_findvalue( "$path\@namespace", "" );
|
|
|
|
|
$callNamespace or $callNamespace = $self->_wsdl_tns_uri;
|
|
|
|
|
# warn "looking for $path...";
|
|
|
|
|
my $callNamespace;
|
|
|
|
|
my $encodingStyle = q{};
|
|
|
|
|
if (my $operation = $self->_wsdl_find( $path )->shift)
|
|
|
|
|
{
|
|
|
|
|
# warn "found operation:" . Dumper $operation;
|
|
|
|
|
#a call can have an associated, namespace
|
|
|
|
|
$callNamespace = $operation->getAttribute('namespace');
|
|
|
|
|
#the encoding style is required when handling restricted complextypes
|
|
|
|
|
$encodingStyle = $operation->getAttribute( 'encodingStyle' );
|
|
|
|
|
}
|
|
|
|
|
$callNamespace ||= $self->_wsdl_tns_uri;
|
|
|
|
|
|
|
|
|
|
#the encoding style is required when handling restricted complextypes
|
|
|
|
|
my $encodingStyle = "";
|
|
|
|
|
$encodingStyle = $self->_wsdl_findvalue( "$path\@encodingStyle", "" );
|
|
|
|
|
$encodingStyle
|
|
|
|
|
and $self->wsdl_encoding( $self->_wsdl_ns->{ $encodingStyle } );
|
|
|
|
|
$self->wsdl_encoding( $self->_wsdl_ns->{ $encodingStyle } )
|
|
|
|
|
if ($encodingStyle);
|
|
|
|
|
|
|
|
|
|
$path = join(
|
|
|
|
|
$self->_wsdl_wsdlns,
|
|
|
|
|
(
|
|
|
|
|
'/', 'definitions/',
|
|
|
|
|
"portType[\@name='$portType']/",
|
|
|
|
|
"operation[\@name='$method']/", $mode
|
|
|
|
|
'portType[@name="' . $portType->getAttribute('name') . '"]/',
|
|
|
|
|
'operation[@name="' . $method . '"]/',
|
|
|
|
|
$mode
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
#overload: the calling script has to say wich overloading
|
|
|
|
|
#procedure call has to be encoded and forwarded to the server
|
|
|
|
|
# overload: the calling script has to say wich overloading
|
|
|
|
|
# procedure call has to be encoded and forwarded to the server
|
|
|
|
|
|
|
|
|
|
$data{ "wsdl_${mode}_name" }
|
|
|
|
|
and $path .= "[\@name='" . $data{ "wsdl_${mode}_name" } . "']";
|
|
|
|
|
|
|
|
|
@@ -296,10 +352,15 @@ sub call
|
|
|
|
|
|
|
|
|
|
$path = join(
|
|
|
|
|
$self->_wsdl_wsdlns,
|
|
|
|
|
( '/', 'definitions/', "message[\@name='$messageName']/", 'part' )
|
|
|
|
|
( '/', 'definitions/', 'message[@name="' . $messageName . '"]/'
|
|
|
|
|
, 'part' )
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
#An operation without parts is equivalent to a procedure call without parameters
|
|
|
|
|
# warn "looking for $path...";
|
|
|
|
|
|
|
|
|
|
# An operation without parts is equivalent to a procedure
|
|
|
|
|
# call without parameters
|
|
|
|
|
# Though not very common, messages may have more than one part...
|
|
|
|
|
my $parts = $self->_wsdl_find( $path );
|
|
|
|
|
|
|
|
|
|
my @param = ();
|
|
|
|
@@ -325,9 +386,7 @@ sub call
|
|
|
|
|
}
|
|
|
|
|
} ## end sub call
|
|
|
|
|
|
|
|
|
|
# find the first servie and port for convenience - mai go wrong,
|
|
|
|
|
# as it assomes the <port> section in the <service>
|
|
|
|
|
# is named equally to the <porttype> section
|
|
|
|
|
# find the first servie and port for convenience
|
|
|
|
|
|
|
|
|
|
sub _get_first_port
|
|
|
|
|
{
|
|
|
|
@@ -335,8 +394,18 @@ sub _get_first_port
|
|
|
|
|
my $url = shift;
|
|
|
|
|
my $xpath = $self->_wsdl_xpath();
|
|
|
|
|
|
|
|
|
|
my $path =
|
|
|
|
|
'/definitions/service' . '/port/' . $self->_wsdl_soapns . 'address';
|
|
|
|
|
# find /wsdl:definitions/wsdl:service/wsdl:port/soap:address
|
|
|
|
|
# use namespace prefixes from WSDL - they may differ...
|
|
|
|
|
#
|
|
|
|
|
# We head right for the address instead of just fetching the first
|
|
|
|
|
# port - we want to set the SOAP::Lite proxy, and accessing
|
|
|
|
|
# our parent is easier than running repeated XPath queries...
|
|
|
|
|
#
|
|
|
|
|
my $path = '/' . $self->_wsdl_wsdlns() .
|
|
|
|
|
'definitions/'
|
|
|
|
|
. $self->_wsdl_wsdlns() .'service/'
|
|
|
|
|
. $self->_wsdl_wsdlns() . 'port/'
|
|
|
|
|
. $self->_wsdl_soapns() . 'address';
|
|
|
|
|
|
|
|
|
|
my @ports = $xpath->findnodes( $path );
|
|
|
|
|
|
|
|
|
@@ -372,11 +441,30 @@ sub _load_method
|
|
|
|
|
};
|
|
|
|
|
} ## end sub _load_method
|
|
|
|
|
|
|
|
|
|
sub portname {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
if ( @_ )
|
|
|
|
|
{
|
|
|
|
|
my $portname = shift;
|
|
|
|
|
if ( not defined($self->{ _WSDL }->{ portname })
|
|
|
|
|
or ($portname ne ($self->{ _WSDL }->{ portname }) ) )
|
|
|
|
|
{
|
|
|
|
|
$self->{ _WSDL }->{ portname } = $portname;
|
|
|
|
|
$self->_wsdl_init_port( $portname );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ($self->{ _WSDL }->{ 'portname' })
|
|
|
|
|
{
|
|
|
|
|
return $self->{ _WSDL }->{ 'portname' }
|
|
|
|
|
};
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&_load_method( "no_dispatch", "no_dispatch" );
|
|
|
|
|
&_load_method( "wsdl", "wsdl" );
|
|
|
|
|
&_load_method( "wsdl_checkoccurs", "checkoccurs" );
|
|
|
|
|
&_load_method( "servicename", "servicename" );
|
|
|
|
|
&_load_method( "portname", "portname" );
|
|
|
|
|
#&_load_method( "portname", "portname" );
|
|
|
|
|
&_load_method( "wsdl_cache_directory", "cache_directory" );
|
|
|
|
|
&_load_method( "wsdl_encoding", "wsdl_encoding" );
|
|
|
|
|
&_load_method( "_wsdl_ns", "namespaces" );
|
|
|
|
@@ -387,6 +475,8 @@ sub _load_method
|
|
|
|
|
&_load_method( "_wsdl_schemans", "schemans" );
|
|
|
|
|
&_load_method( "_wsdl_soapns", "soapns" );
|
|
|
|
|
&_load_method( "_wsdl_wsdlExplicitNS", "wsdl_wsdlExplicitNS" );
|
|
|
|
|
&_load_method( "_wsdl_binding", "binding" );
|
|
|
|
|
&_load_method( "_wsdl_portType", "portType" );
|
|
|
|
|
|
|
|
|
|
#each call to make finder returns a wrapped version of the xpath calls.
|
|
|
|
|
#find, findvalue, findnodes and so on
|
|
|
|
@@ -443,7 +533,6 @@ sub wsdl_cache_init
|
|
|
|
|
eval { require Cache::FileCache; };
|
|
|
|
|
if ( $@ )
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
# warn about missing Cache::FileCache and set cache hadnle to undef
|
|
|
|
|
warn "File caching is enabled, but you do not have the "
|
|
|
|
|
. "Cache::FileCache module. Disabling Filesystem caching."
|
|
|
|
@@ -452,7 +541,6 @@ sub wsdl_cache_init
|
|
|
|
|
} ## end if ( $@ )
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
# initialize cache from custom parameters if given
|
|
|
|
|
$p->{ cache_root } ||= $self->{ _WSDL }->{ cache_directory };
|
|
|
|
|
$cache = Cache::FileCache->new( $p );
|
|
|
|
@@ -916,7 +1004,7 @@ __END__
|
|
|
|
|
|
|
|
|
|
=head1 NAME
|
|
|
|
|
|
|
|
|
|
SOAP::WSDL
|
|
|
|
|
SOAP::WSDL - SOAP with WSDL support
|
|
|
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
|
|
|
|
|
@@ -934,7 +1022,8 @@ SOAP::WSDL
|
|
|
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
|
|
|
|
|
|
This is a small update to 1.21 - autodetection of servicename and portname
|
|
|
|
|
This is mainly a bugfix update to 1.22, which was a small update to 1.21
|
|
|
|
|
- autodetection of servicename and portname have been
|
|
|
|
|
are re-introduced, so users of 1.20 have no need to change their scripts.
|
|
|
|
|
|
|
|
|
|
1.21 was a new version of SOAP::WSDL, mainly based on the work of
|
|
|
|
@@ -1009,10 +1098,8 @@ WSDL definition.
|
|
|
|
|
# soap message elements to be typed
|
|
|
|
|
$soap->autotype(0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# before calling you *must* specify which service use and which port call
|
|
|
|
|
# you must call it after wsdlinit
|
|
|
|
|
# you can call it multiple times, one for each call
|
|
|
|
|
# you may specify a service and port - if not, SOAP::WSDL will search for
|
|
|
|
|
# the first one appearing in the WSDL
|
|
|
|
|
$soap->servicename('myservice');
|
|
|
|
|
$soap->portname('myport');
|
|
|
|
|
|
|
|
|
@@ -1029,20 +1116,22 @@ WSDL definition.
|
|
|
|
|
|
|
|
|
|
# with headers (see the SOAP documentation)
|
|
|
|
|
|
|
|
|
|
#first define your headers
|
|
|
|
|
@header = (SOAP::Header->name("FirstHeader")->value("FirstValue"),
|
|
|
|
|
SOAP::Header->name("SecontHeader")->value("SecondValue"));
|
|
|
|
|
#first define your headers
|
|
|
|
|
@header = (SOAP::Header->name("FirstHeader")->value("FirstValue"),
|
|
|
|
|
SOAP::Header->name("SecontHeader")->value("SecondValue"));
|
|
|
|
|
|
|
|
|
|
#and then do the call. please note the backslash
|
|
|
|
|
my $som=$soap->call( 'method' ,
|
|
|
|
|
name => 'value' ,
|
|
|
|
|
name => 'value' ,
|
|
|
|
|
"soap_headers",\@header);
|
|
|
|
|
"soap_headers" => \@header);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
=head1 How it works
|
|
|
|
|
|
|
|
|
|
SOAP::WSDL takes the wsdl file specified and looks up the service and the specified port.
|
|
|
|
|
SOAP::WSDL takes the wsdl file specified and looks up the service and the
|
|
|
|
|
specified port.
|
|
|
|
|
|
|
|
|
|
On calling a SOAP method, it looks up the message encoding and wraps all the
|
|
|
|
|
stuff around your data accordingly.
|
|
|
|
|
|
|
|
|
@@ -1066,23 +1155,23 @@ If you want to chose a different one, you can specify the service by calling
|
|
|
|
|
|
|
|
|
|
The call method examines the wsdl file to find out how to encode the SOAP
|
|
|
|
|
message for your method. Lookups are done in real-time using XPath, so this
|
|
|
|
|
incorporates a small delay to your calls (see L</Memory consumption and performance>
|
|
|
|
|
below.
|
|
|
|
|
incorporates a small delay to your calls (see
|
|
|
|
|
L</Memory consumption and performance> below.
|
|
|
|
|
|
|
|
|
|
The SOAP message will include the types for each element, unless you have
|
|
|
|
|
set autotype to a false value by calling
|
|
|
|
|
|
|
|
|
|
$soap->autotype(0);
|
|
|
|
|
|
|
|
|
|
After wrapping your call into what is appropriate, SOAP::WSDL uses the I<call()>
|
|
|
|
|
method from SOAP::Lite to dispatch your call.
|
|
|
|
|
After wrapping your call into what is appropriate, SOAP::WSDL uses the
|
|
|
|
|
I<call()> method from SOAP::Lite to dispatch your call.
|
|
|
|
|
|
|
|
|
|
call takes the method name as first argument, and the parameters passed to that
|
|
|
|
|
method as following arguments.
|
|
|
|
|
call takes the method name as first argument, and the parameters passed to
|
|
|
|
|
that method as following arguments.
|
|
|
|
|
|
|
|
|
|
B<Example:>
|
|
|
|
|
|
|
|
|
|
$som=$soap->call( "SomeMethod" => "test" => "testvalue" );
|
|
|
|
|
$som=$soap->call( "SomeMethod" , "test" => "testvalue" );
|
|
|
|
|
|
|
|
|
|
$som=$soap->call( "SomeMethod" => %args );
|
|
|
|
|
|
|
|
|
@@ -1090,14 +1179,17 @@ B<Example:>
|
|
|
|
|
|
|
|
|
|
SOAP::WSDL uses a two-stage caching mechanism to achieve best performance.
|
|
|
|
|
|
|
|
|
|
First, there's a pretty simple caching mechanisms for storing XPath query results.
|
|
|
|
|
They are just stored in a hash with the XPath path as key (until recently, only
|
|
|
|
|
results of "find" or "findnodes" are cached). I did not use the obvious
|
|
|
|
|
First, there's a pretty simple caching mechanisms for storing XPath query
|
|
|
|
|
results.
|
|
|
|
|
|
|
|
|
|
They are just stored in a hash with the XPath path as key (until recently,
|
|
|
|
|
only results of "find" or "findnodes" are cached). I did not use the obvious
|
|
|
|
|
L<Cache|Cache> or L<Cache::Cache|Cache::Cache> module here, because these
|
|
|
|
|
use L<Storable|Storable> to store complex objects and thus incorporate a performance
|
|
|
|
|
loss heavier than using no cache at all.
|
|
|
|
|
Second, the XPath object and the XPath results cache are be stored on disk using
|
|
|
|
|
the L<Cache::FileCache|Cache::FileCache> implementation.
|
|
|
|
|
use L<Storable|Storable> to store complex objects and thus incorporate a
|
|
|
|
|
performance loss heavier than using no cache at all.
|
|
|
|
|
|
|
|
|
|
Second, the XPath object and the XPath results cache are be stored on disk
|
|
|
|
|
using the L<Cache::FileCache|Cache::FileCache> implementation.
|
|
|
|
|
|
|
|
|
|
A filesystem cache is only used if you
|
|
|
|
|
|
|
|
|
@@ -1106,36 +1198,39 @@ A filesystem cache is only used if you
|
|
|
|
|
|
|
|
|
|
The cache directory must be, of course, read- and writeable.
|
|
|
|
|
|
|
|
|
|
XPath result caching doubles performance, but increases memory consumption - if you lack of
|
|
|
|
|
memory, you should not enable caching (disabled by default).
|
|
|
|
|
XPath result caching doubles performance, but increases memory consumption
|
|
|
|
|
- if you lack of memory, you should not enable caching (disabled by default).
|
|
|
|
|
|
|
|
|
|
Filesystem caching triples performance for wsdlinit and doubles performance for the first
|
|
|
|
|
method call.
|
|
|
|
|
Filesystem caching triples performance for wsdlinit and doubles performance
|
|
|
|
|
for the first method call.
|
|
|
|
|
|
|
|
|
|
The file system cache is written to disk when the SOAP::WSDL object is destroyed.
|
|
|
|
|
It may be written to disk any time by calling the L</wsdl_cache_store> method
|
|
|
|
|
The file system cache is written to disk when the SOAP::WSDL object is
|
|
|
|
|
destroyed.
|
|
|
|
|
|
|
|
|
|
Using both filesystem and in-memory caching is recommended for best performance and
|
|
|
|
|
smallest startup costs.
|
|
|
|
|
It may be written to disk any time by calling the L</wsdl_cache_store> method.
|
|
|
|
|
|
|
|
|
|
Using both filesystem and in-memory caching is recommended for best
|
|
|
|
|
performance and smallest startup costs.
|
|
|
|
|
|
|
|
|
|
=head2 Sharing cache between applications
|
|
|
|
|
|
|
|
|
|
Sharing a file system cache among applications accessing the same web service is
|
|
|
|
|
generally possible, but may under some circumstances reduce performance, and under
|
|
|
|
|
some special circumstances even lead to errors.
|
|
|
|
|
Sharing a file system cache among applications accessing the same web
|
|
|
|
|
service is generally possible, but may under some circumstances reduce
|
|
|
|
|
performance, and under some special circumstances even lead to errors.
|
|
|
|
|
This is due to the cache key algorithm used.
|
|
|
|
|
|
|
|
|
|
SOAP::WSDL uses the SOAP endpoint URL to store the XML::XPath object of the wsdl file.
|
|
|
|
|
In the rare case of a web service listening on one particular endpoint (URL) but using
|
|
|
|
|
more than one WSDL definition, this may lead to errors when applications using
|
|
|
|
|
SOAP::WSDL share a file system cache.
|
|
|
|
|
SOAP::WSDL uses the WSDL's URL to store the XML::XPath object of the
|
|
|
|
|
wsdl file. If you're using more than one WSDL definition on the same URL,
|
|
|
|
|
this may lead to errors when two or more applications using SOAP::WSDL
|
|
|
|
|
share a file system cache.
|
|
|
|
|
|
|
|
|
|
SOAP::WSDL stores the XPath results in-memory-cache in the filesystem cache, using the
|
|
|
|
|
key of the wsdl file with C<_cache> appended. Two applications sharing the file system
|
|
|
|
|
cache and accessing different methods of one web service could overwrite each others
|
|
|
|
|
in-memory-caches when dumping the XPath results to disk, resulting in a slight performance
|
|
|
|
|
drawback (even though this only happens in the rare case of one app being started before
|
|
|
|
|
the other one has had a chance to write its cache to disk).
|
|
|
|
|
SOAP::WSDL stores the XPath results in-memory-cache in the filesystem cache,
|
|
|
|
|
using the URL wsdl file with C<_cache> appended. Two applications sharing the
|
|
|
|
|
file system cache and accessing different methods of one web service could
|
|
|
|
|
overwrite each others in-memory-caches when dumping the XPath results to
|
|
|
|
|
disk, resulting in a slight performance drawback (even though this only
|
|
|
|
|
happens in the rare case of one app being started before the other one has
|
|
|
|
|
had a chance to write its cache to disk).
|
|
|
|
|
|
|
|
|
|
=head2 Controlling the file system cache
|
|
|
|
|
|
|
|
|
@@ -1352,9 +1447,9 @@ It imposes a slight delay for initialization, and for every SOAP method call, to
|
|
|
|
|
On my 1.4 GHz Pentium mobile notebook, the init delay with a simple
|
|
|
|
|
WSDL file (containing just one operation and some complex types and elements)
|
|
|
|
|
was around 50 ms, the delay for the first call around 25 ms and for subsequent
|
|
|
|
|
calls to the same method around 7 ms without and around 6 ms with XPath result caching
|
|
|
|
|
(on caching, see above). XML::XPath must do some caching, too - don't know where
|
|
|
|
|
else the speedup should come from.
|
|
|
|
|
calls to the same method around 7 ms without and around 6 ms with XPath result
|
|
|
|
|
caching (on caching, see above). XML::XPath must do some caching, too -
|
|
|
|
|
don't know where else the speedup should come from.
|
|
|
|
|
|
|
|
|
|
Calling a method of a more complex WSDL file (defining around 10 methods and
|
|
|
|
|
numerous complex types on around 500 lines of XML), the delay for the first
|
|
|
|
@@ -1471,8 +1566,8 @@ Replace whitespace by '@' in E-Mail addresses.
|
|
|
|
|
|
|
|
|
|
=head1 SVN information
|
|
|
|
|
|
|
|
|
|
$LastChangedBy: kutterma $
|
|
|
|
|
$HeadURL: https://svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/branches/1.21/lib/SOAP/WSDL.pm $
|
|
|
|
|
$Rev: 16 $
|
|
|
|
|
$LastChangedBy: kutterma $
|
|
|
|
|
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/branches/1.21/lib/SOAP/WSDL.pm $
|
|
|
|
|
$Rev: 20 $
|
|
|
|
|
|
|
|
|
|
=cut
|