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:

> capitalize_array('abc', 'def', >'GHi')

The return value is an array reference:

--- SOAP RESULT ---
$VAR1 = bless( [
                'ABC',
                'DEF',
                'GHI'
                         ], 'Array' );
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)

Listing 3. SOAP Request

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.

Listing 4. SOAP Response in XML

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):

Listing 5. Debugging Output

______________________

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState