Introducing SOAP

SOAP is something you may find a use for, even if you're not intersted in three-tier web applications.

Testing Our Server

Now that our standalone SOAP server is running, we should
test it to see if it works. In order to do that, we must create a
SOAP request, send it to the server and then parse through the
XML-encoded SOAP response that it returns. Luckily, SOAP::Lite
includes such a utility, SOAPsh.pl. This small program allows us to
create and send SOAP requests interactively, displaying the
results. SOAPsh.pl alone justifies the download of SOAP::Lite, even
if you are planning to work with another SOAP library for
Perl.

If we are running our standalone SOAP server on localhost
(i.e., on the same computer as we run SOAPsh.pl), and if we are
running it on port 8080, we can invoke it as follows:

perl SOAPsh.pl http://localhost:8080/ Text/Caps

Notice how the first argument to SOAPsh.pl is the URL of the
SOAP server, and the second argument is the object that we want to
invoke. You can avoid a lot of grief by remembering that the second
argument must be passed using a URL-style object hierarchy divider,
namely a slash (/). Typing “Text::Caps” rather than “Text/Caps”
will confuse the SOAP server and result in hard-to-debug errors.

If your invocation of SOAPsh.pl succeeds, you will see the
following prompt:

Usage: method[(parameters)]
>

The “>” sign indicates that it's your turn to type and
you can invoke any method for the object to which you've connected.
You may now call any method that the object supports, including any
parameters. So to capitalize a word, I simply type:

> capitalize('abc')

Because my SOAP client and server are both on the same computer,
the response is nearly instantaneous. SOAPsh.pl prints out:

--- SOAP RESULT ---
$VAR1 = 'ABC';

Hey, that's pretty great! I just invoke an object method across the
network. That wasn't so hard, was it?

SOAP would be nice if we could send simple scalars back and
forth. But we can send and receive a variety of data types. For
example, we can invoke capitalize_array, sending a list of
arguments:

The returned array reference looks a bit funny because it has been
turned into a format that SOAP::Lite can send and retrieve. We will
soon see how our programs can ignore this intermediate format,
seamlessly exchanging complex data structures over the Internet.

Examining the SOAP

As you can see, it's possible to work with SOAP without
understanding the underlying XML-encoded data. However, debugging
SOAP problems often requires that you look at the XML as well as
the HTTP headers that are sent in the request and the
response.

SOAP::Lite objects support the on_debug( ) method, which
takes a subroutine reference as an argument. This subroutine is
invoked for each SOAP transaction, meaning that we can log
information to the disk or screen. The simplest use of on_debug( )
is as follows:

on_debug(sub{print STDERR @_})

In other words, we ask SOAP::Lite to send a copy of
everything to STDERR. This provides us with a marvelous opportunity
to see what happens behind the scenes. After we invoke this method,
SOAPsh.pl reminds us that we invoked a local method rather than a
SOAP method:

--- METHOD RESULT ---
SOAP::Lite=HASH(0x82e1174)

With debugging turned on, our invocation of capitalize(abc) from
before gets translated into a SOAP request (see Listing 3)

As you can see, the request is divided into a header and a
body, as with all HTTP requests. And as with a normal HTTP request,
we indicate an action (“POST”) along with a URL, as a
Content-Length (indicating the number of bytes in the request) and
the Content-Type (which is always going to be “text/xml”).

Then the fun begins: the final header is SOAPAction, which
names the object and method that are being invoked. The SOAPAction
header is designed to allow corporate firewalls to filter out
dangerous objects and methods from being invoked. Currently,
however, it would seem that support for SOAPAction is relatively
hard to find. Besides, information about both the object and its
method are buried inside of the XML request and response
themselves, making the header unnecessary for parsing
purposes.

The XML itself begins with an XML declaration and then a SOAP
envelope. Inside the envelope is an optional header (not shown in
this particular invocation) and a mandatory body. The body names
the object and method that we wish to invoke, as well as any
arguments that we might have passed.

This XML is parsed into the native operating system and
language format and is then passed along to the target object. The
object returns a response value to the SOAP server which then
creates a SOAP response in XML as seen in Listing 4.

The response, like the request, uses HTTP and HTTP headers to
pass some metadata, including the server type, date, content
length, type (“text/xml”) and even the type of SOAP server being
run.

The envelope for this particular response, like the request,
contains no header. However, it does contain a body, in which the
return value (of type “xsd:string”) is returned. While the
request uses a namespace of “namesp3:capitalize”, the response
uses a namespace of “namesp1:capitalizeResponse”. This is
standard in SOAP; XML namespaces are used to identify whether the
message contains a request or a response and for which method the
response is being sent.

Without any explanation, Listing 5 is the similar debugging
output from a call to capitalize_array(reuven, shira,
atara):

Trending Topics

Webinar: 8 Signs You’re Beyond Cron

Scheduling Crontabs With an Enterprise Scheduler
11am CDT, April 29th

Join Linux Journal and Pat Cameron, Director of Automation Technology at HelpSystems, as they discuss the eight primary advantages of moving beyond cron job scheduling. In this webinar, you’ll learn about integrating cron with an enterprise scheduler.