METHODS

All accessor methods return the current value when called with no arguments, while returning the object reference itself when called with a new value. This allows the set-attribute calls to be chained together.

new(optional key/value pairs)

$client = SOAP::Lite->new(proxy => $endpoint)

Constructor. Many of the accessor methods defined here may be initialized at creation by providing their name as a key, followed by the desired value. The example provides the value for the proxy element of the client.

transport(optional transport object)

$transp = $client->transport( );

Gets or sets the transport object used for sending/receiving SOAP messages.

Provides access to the SOAP::Packager object that the client uses to manage the use of attachments. The default packager is a MIME packager, but unless you specify parts to send, no MIME formatting will be done.

The proxy is the server or endpoint to which the client is going to connect. This method allows the setting of the endpoint, along with any extra information that the transport object may need when communicating the request.

This method is actually an alias to the proxy method of SOAP::Transport. It is the same as typing:

It may be preferable to set a new endpoint without the additional work of examining the new address for protocol information and checking to ensure the support code is loaded and available. This method allows the caller to change the endpoint that the client is currently set to connect to, without reloading the relevant transport code. Note that the proxy method must have been called before this method is used.

service(service URL)

$client->service('http://svc.perl.org/Svc.wsdl');

SOAP::Lite offers some support for creating method stubs from service descriptions. At present, only WSDL support is in place. This method loads the specified WSDL schema and uses it as the basis for generating stubs.

outputxml(boolean)

$client->outputxml('true');

When set to a true value, the raw XML is returned by the call to a remote method.

By default, the serializer tries to automatically deduce types for the data being sent in a message. Setting a false value with this method disables the behavior.

readable(boolean)

$client->readable(1);

This method is a shortcut for:

$client->serializer->readable(boolean);

When this is used to set a true value for this property, the generated XML sent to the endpoint has extra characters (spaces and new lines) added in to make the XML itself more readable to human eyes (presumably for debugging). The default is to not send any additional characters.

headerattr(hash reference of attributes)

$obj->headerattr({ attr1 => 'value' });

Allows for the setting of arbitrary attributes on the header object. Keep in mind the requirement that any attributes not natively known to SOAP must be namespace-qualified. If using $session->call ($method, $callData, $callHeader), SOAP::Lite serializes information as

Allows for the setting of arbitrary attributes on the body object. Keep in mind the requirement that any attributes not natively known to SOAP must be namespace-qualified. See headerattr

default_ns($uri)

Sets the default namespace for the request to the specified uri. This overrides any previous namespace declaration that may have been set using a previous call to ns() or default_ns(). Setting the default namespace causes elements to be serialized without a namespace prefix, like this:

Some .NET web services have been reported to require this XML namespace idiom.

ns($uri,$prefix=undef)

Sets the namespace uri and optionally the namespace prefix for the request to the specified values. This overrides any previous namespace declaration that may have been set using a previous call to ns() or default_ns().

If a prefix is not specified, one will be generated for you automatically. Setting the namespace causes elements to be serialized with a declared namespace prefix, like this:

Some .NET web services have been reported to require this XML namespace idiom.

soapversion(optional value)

$client->soapversion('1.2');

If no parameter is given, returns the current version of SOAP that is being used by the client object to encode requests. If a parameter is given, the method attempts to set that as the version of SOAP being used.

The value should be either 1.1 or 1.2.

envprefix(QName)

$client->envprefix('env');

This method is a shortcut for:

$client->serializer->envprefix(QName);

Gets or sets the namespace prefix for the SOAP namespace. The default is SOAP.

The prefix itself has no meaning, but applications may wish to chose one explicitly to denote different versions of SOAP or the like.

encprefix(QName)

$client->encprefix('enc');

This method is a shortcut for:

$client->serializer->encprefix(QName);

Gets or sets the namespace prefix for the encoding rules namespace. The default value is SOAP-ENC.

While it may seem to be an unnecessary operation to set a value that isn't relevant to the message, such as the namespace labels for the envelope and encoding URNs, the ability to set these labels explicitly can prove to be a great aid in distinguishing and debugging messages on the server side of operations.

encoding(encoding URN)

$client->encoding($soap_12_encoding_URN);

This method is a shortcut for:

$client->serializer->encoding(args);

Where the earlier method dealt with the label used for the attributes related to the SOAP encoding scheme, this method actually sets the URN to be specified as the encoding scheme for the message. The default is to specify the encoding for SOAP 1.1, so this is handy for applications that need to encode according to SOAP 1.2 rules.

typelookup

$client->typelookup;

This method is a shortcut for:

$client->serializer->typelookup;

Gives the application access to the type-lookup table from the serializer object. See the section on SOAP::Serializer.

uri(service specifier)

Deprecated - the uri subroutine is deprecated in order to provide a more intuitive naming scheme for subroutines that set namespaces. In the future, you will be required to use either the ns() or default_ns() subroutines instead of uri().

$client->uri($service_uri);

This method is a shortcut for:

$client->serializer->uri(service);

The URI associated with this accessor on a client object is the service-specifier for the request, often encoded for HTTP-based requests as the SOAPAction header. While the names may seem confusing, this method doesn't specify the endpoint itself. In most circumstances, the uri refers to the namespace used for the request.

Often times, the value may look like a valid URL. Despite this, it doesn't have to point to an existing resource (and often doesn't). This method sets and retrieves this value from the object. Note that no transport code is triggered by this because it has no direct effect on the transport of the object.

multirefinplace(boolean)

$client->multirefinplace(1);

This method is a shortcut for:

$client->serializer->multirefinplace(boolean);

Controls how the serializer handles values that have multiple references to them. Recall from previous SOAP chapters that a value may be tagged with an identifier, then referred to in several places. When this is the case for a value, the serializer defaults to putting the data element towards the top of the message, right after the opening tag of the method-specification. It is serialized as a standalone entity with an ID that is then referenced at the relevant places later on. If this method is used to set a true value, the behavior is different. When the multirefinplace attribute is true, the data is serialized at the first place that references it, rather than as a separate element higher up in the body. This is more compact but may be harder to read or trace in a debugging environment.

parts( ARRAY )

Used to specify an array of MIME::Entity's to be attached to the transmitted SOAP message. Attachments that are returned in a response can be accessed by SOAP::SOM::parts().

self

$ref = SOAP::Lite->self;

Returns an object reference to the default global object the SOAP::Lite package maintains. This is the object that processes many of the arguments when provided on the use line.

The following method isn't an accessor style of method but neither does it fit with the group that immediately follows it:

call(arguments)

$client->call($method => @arguments);

As has been illustrated in previous chapters, the SOAP::Lite client objects can manage remote calls with auto-dispatching using some of Perl's more elaborate features. call is used when the application wants a greater degree of control over the details of the call itself. The method may be built up from a SOAP::Data object, so as to allow full control over the namespace associated with the tag, as well as other attributes like encoding. This is also important for calling methods that contain characters not allowable in Perl function names, such as A.B.C.

The next four methods used in the SOAP::Lite class are geared towards handling the types of events than can occur during the message lifecycle. Each of these sets up a callback for the event in question:

on_action(callback)

$client->on_action(sub { qq("$_[0]") });

Triggered when the transport object sets up the SOAPAction header for an HTTP-based call. The default is to set the header to the string, uri#method, in which URI is the value set by the uri method described earlier, and method is the name of the method being called. When called, the routine referenced (or the closure, if specified as in the example) is given two arguments, uri and method, in that order.

.NET web services usually expect / as separator for uri and method. To change SOAP::Lite's behaviour to use uri/method as SOAPAction header, use the following code:

$client->on_action( sub { join '/', @_ } );

on_fault(callback)

$client->on_fault(sub { popup_dialog($_[1]) });

Triggered when a method call results in a fault response from the server. When it is called, the argument list is first the client object itself, followed by the object that encapsulates the fault. In the example, the fault object is passed (without the client object) to a hypothetical GUI function that presents an error dialog with the text of fault extracted from the object (which is covered shortly under the SOAP::SOM methods).

on_nonserialized(callback)

$client->on_nonserialized(sub { die "$_[0]?!?" });

Occasionally, the serializer may be given data it can't turn into SOAP-savvy XML; for example, if a program bug results in a code reference or something similar being passed in as a parameter to method call. When that happens, this callback is activated, with one argument. That argument is the data item that could not be understood. It will be the only argument. If the routine returns, the return value is pasted into the message as the serialization. Generally, an error is in order, and this callback allows for control over signaling that error.

on_debug(callback)

$client->on_debug(sub { print @_ });

Deprecated. Use the global +debug and +trace facilities described in SOAP::Trace

Note that this method will not work as expected: Instead of affecting the debugging behaviour of the object called on, it will globally affect the debugging behaviour for all objects of that class.

WRITING A SOAP CLIENT

This chapter guides you to writing a SOAP client by example.

The SOAP service to be accessed is a simple variation of the well-known hello world program. It accepts two parameters, a name and a given name, and returns "Hello $given_name $name".

We will use "Martin Kutter" as the name for the call, so all variants will print the following message on success:

Hello Martin Kutter!

SOAP message styles

There are three common (and one less common) variants of SOAP messages.

Typed, positional parameters. Widely used in scripting languages. The type of the arguments is included in the message. Arrays and the like may be encoded using SOAP encoding rules (or others).

rpc/literal

As-is, positional parameters. The type of arguments is defined by some pre-exchanged interface definition.

document/encoded

Specified message with typed elements. Rarely used.

document/literal

Specified message with as-is elements. The message specification and element types are defined by some pre-exchanged interface definition.

As of 2008, document/literal has become the predominant SOAP message variant. rpc/literal and rpc/encoded are still in use, mainly with scripting languages, while document/encoded is hardly used at all.

You will see clients for the rpc/encoded and document/literal SOAP variants in this section.

Example implementations

RPC/ENCODED

Rpc/encoded is most popular with scripting languages like perl, php and python without the use of a WSDL. Usual method descriptions look like this:

Differences between the implementations

You may have noticed that there's little difference between the rpc/encoded, rpc/literal and the document/literal example's implementation. In fact, from SOAP::Lite's point of view, the only differences between rpc/literal and document/literal that parameters are always named.

In our example, the rpc/encoded variant already used named parameters (by using two messages), so there's no difference at all.

You may have noticed the somewhat strange idiom for passing a list of named parameters in the rpc/literal example:

DEFAULT SETTINGS

Though this feature looks similar to autodispatch they have (almost) nothing in common. This capability allows you specify default settings so that all objects created after that will be initialized with the proper default settings.

If you wish to provide common proxy() or uri() settings for all SOAP::Lite objects in your application you may do:

AnySOAP::Lite properties can be propagated this way. Changes in object copies will not affect global settings and you may still change global settings with SOAP::Lite->self call which returns reference to global object. Provided parameter will update this object and you can even set it to undef:

SOAP::Lite->self(undef);

The use SOAP::Lite syntax also lets you specify default event handlers for your code. If you have different SOAP objects and want to share the same on_action() (or on_fault() for that matter) handler. You can specify on_action() during initialization for every object, but you may also do:

use SOAP::Lite
on_action => sub {sprintf '%s#%s', @_};

and this handler will be the default handler for all your SOAP objects. You can override it if you specify a handler for a particular object. See t/*.t for example of on_fault() handler.

Be warned, that since use ... is executed at compile time alluse statements will be executed before script execution that can make unexpected results. Consider code:

SETTING MAXIMUM MESSAGE SIZE

One feature of SOAP::Lite is the ability to control the maximum size of a message a SOAP::Lite server will be allowed to process. To control this feature simply define $SOAP::Constants::MAX_CONTENT_SIZE in your code like so:

@paramsout = $r->paramsout; # gives you ARRAY of out parameters
$paramout1 = $paramsout[0]; # gives you 'res2', same as ($r->paramsout)[0]
$paramout2 = $paramsout[1]; # gives you 'res3', same as ($r->paramsout)[1]

Generally, if server returns return (1,2,3) you will get 1 as the result and 2 and 3 as out parameters.

If the server returns return [1,2,3] you will get an ARRAY reference from result() and undef from paramsout().

Results can be arbitrary complex: they can be an array references, they can be objects, they can be anything and still be returned by result() . If only one parameter is returned, paramsout() will return undef.

Furthermore, if you have in your output parameters a parameter with the same signature (name+type) as in the input parameters this parameter will be mapped into your input automatically. For example:

Autobinding gives it to you. That will work with objects also with one difference: you do not need to worry about the name and the type of object parameter. Consider the PingPong example (examples/My/PingPong.pm and examples/pingpong.pl):

STATIC AND DYNAMIC SERVICE DEPLOYMENT

Let us scrutinize the deployment process. When designing your SOAP server you can consider two kind of deployment: static and dynamic. For both, static and dynamic, you should specify MODULE, MODULE::method, method or PATH/ when creating useing the SOAP::Lite module. The difference between static and dynamic deployment is that in case of 'dynamic', any module which is not present will be loaded on demand. See the "SECURITY" section for detailed description.

When statically deploying a SOAP Server, you need to know all modules handling SOAP requests before.

You should also use static binding when you have several different classes in one file and want to make them available for SOAP calls.

DYNAMIC DEPLOYMENT EXAMPLE

use SOAP::Transport::HTTP;
# name is unknown, module will be loaded on demand
SOAP::Transport::HTTP::CGI
# deployed module should be present here or client will get 'access denied'
-> dispatch_to('/Your/Path/To/Deployed/Modules', 'My::Examples')
-> handle;

For dynamic deployment you can specify the name either directly (in that case it will be required without any restriction) or indirectly, with a PATH. In that case, the ONLY path that will be available will be the PATH given to the dispatch_to() method). For information how to handle this situation see "SECURITY" section.

SUMMARY

dispatch_to(
# dynamic dispatch that allows access to ALL modules in specified directory
PATH/TO/MODULES
# 1. specifies directory
# -- AND --
# 2. gives access to ALL modules in this directory without limits
# static dispatch that allows access to ALL methods in particular MODULE
MODULE
# 1. gives access to particular module (all available methods)
# PREREQUISITES:
# module should be loaded manually (for example with 'use ...')
# -- OR --
# you can still specify it in PATH/TO/MODULES
# static dispatch that allows access to particular method ONLY
MODULE::method
# same as MODULE, but gives access to ONLY particular method,
# so there is not much sense to use both MODULE and MODULE::method
# for the same MODULE
);

In addition to this SOAP::Lite also supports an experimental syntax that allows you to bind a specific URL or SOAPAction to a CLASS/MODULE or object.

URI is checked before SOAPAction. You may use both the dispatch_to() and dispatch_with() methods in the same server, but note that dispatch_with() has a higher order of precedence. dispatch_to() will be checked only after URI and SOAPAction has been checked.

COMPRESSION

SOAP::Lite provides you option to enable transparent compression over the wire. Compression can be enabled by specifying a threshold value (in the form of kilobytes) for compression on both the client and server sides:

Note: Compression currently only works for HTTP based servers and clients.

SECURITY

For security reasons, the existing path for Perl modules (@INC) will be disabled once you have chosen dynamic deployment and specified your own PATH/. If you wish to access other modules in your included package you have several options:

Switch to static linking:

use MODULE;
$server->dispatch_to('MODULE');

Which can also be useful when you want to import something specific from the deployed modules:

use MODULE qw(import_list);

Change use to require. The path is only unavailable during the initialization phase. It is available once more during execution. Therefore, if you utilize require somewhere in your package, it will work.

Wrap use in an eval block:

eval 'use MODULE qw(import_list)'; die if $@;

Set your include path in your package and then specify use. Don't forget to put @INC in a BEGIN{} block or it won't work. For example,

BEGIN { @INC = qw(my_directory); use MODULE }

INTEROPERABILITY

Microsoft .NET client with SOAP::Lite Server

In order to use a .NET client with a SOAP::Lite server, be sure you use fully qualified names for your return values. For example:

Some users have said that Microsoft .NET prefers the value of the Content-type header to be a mimetype exclusively, but SOAP::Lite specifies a character set in addition to the mimetype. This results in an error similar to:

Server found request content type to be 'text/xml; charset=utf-8',
but expected 'text/xml'

SOAP::Lite uses the SOAP encoding (section 5 of the soap 1.1 spec), and the default for .NET Web Services is to use a literal encoding. So elements in the request are unqualified, but your service expects them to be qualified. .Net Web Services has a way for you to change the expected message format, which should allow you to get your interop working. At the top of your class in the asmx, add this attribute (for Beta 1):

There is a bug in Perl 5.8's UNIVERSAL::AUTOLOAD functionality that prevents the +autodispatch functionality from working properly. The workaround is to use dispatch_from instead. Where you might normally do something like this:

It is likely that you have install Perl in two different locations and the location of ActiveState's Perl is not the first instance of Perl specified in your PATH. To rectify, rename the directory in which the non-ActiveState Perl is installed, or be sure the path to ActiveState's Perl is specified prior to any other instance of Perl in your PATH.

Dynamic libraries are not found

If you are using the Apache web server, and you are seeing something like the following in your webserver log file:

Can't load '/usr/local/lib/perl5/site_perl/.../XML/Parser/Expat/Expat.so'
for module XML::Parser::Expat: dynamic linker: /usr/local/bin/perl:
libexpat.so.0 is NEEDED, but object does not exist at
/usr/local/lib/perl5/.../DynaLoader.pm line 200.

Then try placing the following into your httpd.conf file and see if it fixes your problem.

Using SOAP::Lite (or XML::Parser::Expat) in combination with mod_perl causes random segmentation faults in httpd processes. To fix, try configuring Apache with the following:

RULE_EXPAT=no

If you are using Apache 1.3.20 and later, try configuring Apache with the following option:

./configure --disable-rule=EXPAT

See http://archive.covalent.net/modperl/2000/04/0185.xml for more details and lot of thanks to Robert Barta <rho@bigpond.net.au> for explaining this weird behavior.

If this doesn't address the problem, you may wish to try -Uusemymalloc, or a similar option in order to instruct Perl to use the system's own malloc.

Thanks to Tim Bunce <Tim.Bunce@pobox.com>.

CGI scripts do not work under Microsoft Internet Information Server (IIS)

CGI scripts may not work under IIS unless scripts use the .pl extension, opposed to .cgi.

Java SAX parser unable to parse message composed by SOAP::Lite

In some cases SOAP messages created by SOAP::Lite may not be parsed properly by a SAX2/Java XML parser. This is due to a known bug in org.xml.sax.helpers.ParserAdapter. This bug manifests itself when an attribute in an XML element occurs prior to the XML namespace declaration on which it depends. However, according to the XML specification, the order of these attributes is not significant.

http://www.megginson.com/SAX/index.html

Thanks to Steve Alpert (Steve_Alpert@idx.com) for pointing on it.

PERFORMANCE

Processing of XML encoded fragments

SOAP::Lite is based on XML::Parser which is basically wrapper around James Clark's expat parser. Expat's behavior for parsing XML encoded string can affect processing messages that have lot of encoded entities, like XML fragments, encoded as strings. Providing low-level details, parser will call char() callback for every portion of processed stream, but individually for every processed entity or newline. It can lead to lot of calls and additional memory manager expenses even for small messages. By contrast, XML messages which are encoded as base64Binary, don't have this problem and difference in processing time can be significant. For XML encoded string that has about 20 lines and 30 tags, number of call could be about 100 instead of one for the same string encoded as base64Binary.

Since it is parser's feature there is NO fix for this behavior (let me know if you find one), especially because you need to parse message you already got (and you cannot control content of this message), however, if your are in charge for both ends of processing you can switch encoding to base64 on sender's side. It will definitely work with SOAP::Lite and it may work with other toolkits/implementations also, but obviously I cannot guarantee that.

If you want to encode specific string as base64, just do SOAP::Data->type(base64 => $string) either on client or on server side. If you want change behavior for specific instance of SOAP::Lite, you may subclass SOAP::Serializer, override as_string() method that is responsible for string encoding (take a look into as_base64Binary()) and specify new serializer class for your SOAP::Lite object with:

my $server = new SOAP::Transport::HTTP::Daemon # or any other server
serializer => My::Serializer->new,
..... other parameters

If you want to change this behavior for all instances of SOAP::Lite, just substitute as_string() method with as_base64Binary() somewhere in your code afteruse SOAP::Lite and before actual processing/sending:

Be warned that last two methods will affect all strings and convert them into base64 encoded. It doesn't make any difference for SOAP::Lite, but it may make a difference for other toolkits.

BUGS AND LIMITATIONS

No support for multidimensional, partially transmitted and sparse arrays (however arrays of arrays are supported, as well as any other data structures, and you can add your own implementation with SOAP::Data).

Limited support for WSDL schema.

XML::Parser::Lite relies on Unicode support in Perl and doesn't do entity decoding.

RELATED MODULES

Transport Modules

SOAP::Lite allows one to add support for additional transport protocols, or server handlers, via separate modules implementing the SOAP::Transport::* interface. The following modules are available from CPAN:

As a valued partner and proud supporter of MetaCPAN, StickerYou is
happy to offer a 10% discount on all Custom Stickers,
Business Labels, Roll Labels,
Vinyl Lettering or Custom Decals. StickerYou.com
is your one-stop shop to make your business stick.
Use code METACPAN10 at checkout to apply your discount.