The SOAP specification clearly establishes SOAP’s role as a protocol for defining a messaging system as well as remote procedure calls. Although the O in SOAP stands for Object, nothing in the specification suggests that the intention of SOAP is to provide any sort of object or component runtime. To the contrary, SOAP makes no attempt to define mechanisms for object invocation, garbage collection, and so on. SOAP does, however, provide the necessary mechanisms for building object-oriented systems on top of its infrastructure.
HTTP as a Base Transport
Version 1.0 of the specification mandated HTTP as its base transport, but version 1.1 has decoupled SOAP from HTTP to allow SOAP to be used in a messaging paradigm. This leaves the door wide open for a variety of other transports to carry SOAP such as FTP, SMTP, and others.
Regardless of the transport, there is always some underlying work that must be done to invoke a method on a server. For SOAP as an RPC mechanism, this means constructing a valid HTTP request message.
By default, clients should start by using the POST method; only in the case where this fails with an HTTP status of 405 Method Not Allowed should they attempt the request using M-POST. With the existing Web infrastructure, POST seems to be the reasonable choice at this point and time.
Although it is slightly easier to construct and parse the header fields for a POST than for an M-POST, conforming to M-POST can force clients to provide more detail about the client’s request. Consider the examples of POST versus M-POST in the following listing.
Listing 1 – POST Versus M-POST
POST /Script.pl HTTP/1.1 Host: www.mcp.com Accept: text/* Content-type: text/xml Content-length: nnnn SOAPAction: the-method-uri#DoSomething M-POST /Script.pl HTTP/1.1 Host: www.mcp.com Accept: text/* Content-type: text/xml Content-length: nnnn Man: "urn:schemas-xmlsoap-org:soap.v1"; ns=01 01-SOAPAction: the-method-uri#DoSomething
The original SOAP specification v0.9 originally forced M-POST calls to occur before POST calls, thus forcing clients to provide more detail with the first request.
In SOAP v1.0, the specification called for POST calls to occur before M-POST, due to the limited adoption of M-POST.
SOAP recommends that a SOAPAction header field be provided with each SOAP request, such that the server can gather call information without having to parse the entire SOAP payload. At this point, SOAPAction is optional, and clients only have to use it when mandated by the server. However, it is expected that many of you will want to include SOAPAction in your SOAP implementations, so your server can know the intention of the request message.
Using XML in SOAP
One of the simplest aspects of SOAP is that it only requires calls to conform to proper XML syntax. No other XML technologies are required to make SOAP work, although XML Namespaces and XML Schemas make SOAP development much easier.
SOAP recommends the use of namespaces because they provide a mechanism to scope elements and attributes to various contexts. The specification states that clients are able to dictate whether or not namespaces are to be used in a conversation with the server. On the other hand, servers are responsible for ensuring that clients that use namespaces use them correctly. Servers also have the option to process requests that do not contain namespaces or, at a minimum, to respond with a fault.
The namespace ‘urn:schemas-xmlsoap-org:soap.v1’ is the proposed namespace value for SOAP. This value is simply an URN that should be used to qualify SOAP element and attribute names and does not necessarily reflect any particular resource on the Internet.
SOAP also uses the id/href attribute pairs to distinguish between unique entities within the SOAP payload. This is necessary for providing multi-reference elements in the request and response payloads, such that you serialize the element once and reference it as many times as necessary.
To execute a SOAP method call, the SOAP payload must be constructed with a <SOAP:Envelope> root element containing an optional <SOAP:Header> element and a mandatory <SOAP:Body> element.
The <SOAP:Header> element is used to encapsulate extended information about the call. The <SOAP:Body> element contains the actual method call (as its first child element) and the associated method parameters as either embedded or independent elements.
Figure 1 shows the basic structure of a SOAP payload.
Listing 2 shows the basic SOAP structure in use.
Listing 2 – Basic SOAP Structure
<SOAP-ENV:Envelope xmlns:SOAP-ENV= "http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle= "http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Header> <r:RequestNumber xmlns_r="Request-URI"> 2 </r:RequestNumber> </SOAP-ENV:Header> <SOAP-ENV:Body> <m:GetTemperature xmlns_m="Thermostat-URI"> <City>Orlando</City> <State>FL</State> </m:GetTemperature> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Here, the header contains a namespace-qualified element called RequestNumber that keeps track of the number of times this request has been made.
The body contains a namespace-qualified method name GetTemperature that contains the city and state parameters.
By qualifying the method name, you are implicitly qualifying its embedded elements so they do not require a namespace prefix.
When a method call has been requested, the server has several options. It can return an HTTP error code or a SOAP fault containing a SOAP/application error, or it can return the results of the method execution. Both the fault and the method results use the standard SOAP payload syntax (that is, <Envelope>, <Body>, and so on).
A SOAP fault consists of four elements–a faultcode, faultstring, runcode, and an optional detail element, as shown in Listing 3.
Listing 3 – SOAP Fault
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <SOAP-ENV:Fault> <faultcode>300</faultcode> <faultstring>Invalid Request</faultstring> <runcode>1</runcode> </SOAP-ENV:Fault> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Just as with the
Any application fault details that need to be included with the fault must be properly typed and qualified using the <detail> element as shown in Listing 4.
Listing 4 – Application Fault Details
<SOAP-ENV:Fault> <faultcode>300</faultcode> <faultstring>Invalid Request</faultstring> <runcode>1</runcode> <detail xmlns_e="GetTemperatureErr-URI" xmlns_xsi="http://www.w3.org/1999/XMLSchema-instance" xsi_type="e:GetTemperatureFault"> <number>5575910</number> <description>Sensor Failure</description> <file>GetTemperatureClass.cpp</file> <line>481</line> </detail> </SOAP-ENV:Fault>
Notice that the <detail> element uses the XML Schema instance xsi:type attribute to denote its content type, e:GetTemperatureFault, which is also namespace qualified.
Constructing detailed faults in this way allows the client to fully interpret the application fault when necessary.
Representation of Types in the Payload
One of the most difficult aspects of SOAP to understand is the way types are represented in the payload. It’s hard to anticipate the many ways parameters can or should be serialized.
SOAP has the capability to serialize any combination of simple and compound types as supported in modern-day programming languages. This is mostly because of SOAP’s inclusion of the XML Schema work that is underway to define a standard mechanism for constructing metadata.
SOAP uses the concept of an accessor as the means to acquire a named value in the payload. Named values include parameters as well as the named parts of a compound type.
There are two kinds of values in a SOAP payload. The first kind is called a single-reference value and can only be referenced by one accessor. Consider the following XML fragment:
In this case, both the <Car> element and the <Automobile> element contain their own unique Corvette values. This means that each Corvette value has only been referenced by its surrounding element (that is, accessor) and no other.
The second kind of value in a SOAP payload is called a multi-reference value and can be referenced by one or more accessors. Let’s examine a similar XML fragment that uses multi-reference values:
<Car href="#somecar" /> <Automobile id="somecar">Corvette</Automobile>
In this example, Corvette is referenced by two accessors, the Car accessor and the Automobile accessor; thus, it is considered a multi-reference value.
The purpose for distinguishing between single-reference and multi-reference values helps to deal with identity issues of serializing (that is, marshaling) data across the wire. For instance, if two method parameters reference the same value, in some cases you will want the XML to reflect this identity and in other cases you won’t. Our book, Understanding SOAP provides an in-depth look at identity and serialization techniques in chapter 6, “SOAP and Data: Data Types.”
SOAP also distinguishes between elements that are independent and elements that are embedded. Independent elements are at the highest level of serialization, such as elements contained within SOAP-ENV:Body, and represent instances of types. The name of the independent element is typically the name of the type that it represents. Consider the following XML:
<SOAP-ENV:Envelope xmlns_SOAP= "http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle= "http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <m:MyMethod xmlns_m="Method-URI"> <Car href="#somecar" /> </m:MyMethod> <Automobile id="somecar">Corvette</Automobile> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
In this example, since by definition <SOAP-ENV:Body> is an element that can stand alone, any direct descendants of <SOAP-ENV:Body> are considered independent elements. In this case, <m:MyMethod> is an independent element that describes the method and <Automobile> is an independent element describing an Automobile type.
Embedded elements are anything that’s not considered an independent element, and they represent accessors. The name of the embedded element is the same as the name of the accessor that it represents. Referring to the last example, the <Car> element is an embedded element and accessor since the <m:MyMethod> element is an independent element that is at the highest level of the serialization.
The SOAP specification provides a set of rules that define how the preceding constructs should be used to serialize data. It also addresses the more specific procedures that should be followed when serializing particular types such as arrays and strings.
About the Authors
Kennard Scribner is a principle software consultant specializing in COM and component development. He is also founder and president of EnduraSoft Corporation, a software company specializing in the creation of custom components.
Mark C. Stiver is a consulting software engineer with one of the world’s largest supplies of information services for the legal and business industry. Currently he is involved in the design and development of XML-based interfaces for integrating large-scale systems.
© Copyright Sams Publishing, All Rights Reserved