Clean up your wire protocol with SOAP, Part 1

An introduction to SOAP basics

1 2 Page 2
Page 2 of 2
<SOAP-ENV:Envelope 
                       xmlns:SOAP-ENV="
http://schemas.xmlsoap.org/soap/envelope/" 
                       xmlns:xsi="
http://www.w3.org/1999/XMLSchema-instance" 
                       xmlns:xsd="http://www.w3.org/1999/XMLSchema">
     <SOAP-ENV:Header>
         <t:Transaction xmlns:t="some-URI" 
SOAP-ENV:mustUnderstand="1">
              5
         </t:Transaction>
     </SOAP-ENV:Header>
    <SOAP-ENV:Body>
         <ns1:sayHelloTo 
                      xmlns:ns1="Hello" 
                     SOAP-ENV:encodingStyle="
http://schemas.xmlsoap.org/soap/encoding/">
             <name xsi:type="xsd:string">Tarak</name>
         </ns1:sayHelloTo>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The above message's header section has a transaction element; it specifies the transaction number that the method invocation must be part of. I say must because the transaction element uses the mustUnderstand attribute. As I mentioned before, the SOAP server must either honor that or fail to process the request. To make matters interesting, let's assume that the SOAP server cannot honor that and therefore fails the request. The response would be similar to this:

Listing 9

<SOAP-ENV:Envelope xmlns:SOAP-ENV="
http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Body>
       <SOAP-ENV:Fault>
           <faultcode>SOAP-ENV:MustUnderstand</faultcode>
           <faultstring>SOAP Must Understand 
Error</faultstring>
       </SOAP-ENV:Fault>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The above code resembles the error message in Listing 7. But note that the detail element is absent. As I mentioned before, the SOAP specification states that this element must present itself if the error occurs while processing the header. In fact, the presence or absence of the detail element can quickly tell you if the error happened while processing the header or the body.

SOAP and HTTP

In my first example I sent the custom XML request to the server via HTTP and glossed over what was involved in doing so. Let's come back to that. How can I send a SOAP request (instead of the custom XML) over HTTP to the server? SOAP naturally follows the HTTP request/response message model, which provides SOAP request parameters in an HTTP request and SOAP response parameters in an HTTP response. In fact, SOAP 1.0 specifically designated HTTP as its transport protocol. SOAP 1.1 has loosened up a bit and, although it still works with HTTP, it also works with other protocols such as SMTP. In this series I will only discuss SOAP in the context of using it with HTTP.

Let's go back to the hello example. If we were to send the SOAP request to the server via HTTP it would look similar to the code below:

Listing 10

POST http://www.SmartHello.com/HelloApplication HTTP/1.0
Content-Type: text/xml; charset="utf-8"
Content-Length: 587
SOAPAction: "http://www.SmartHello.com/HelloApplication#sayHelloTo"
<SOAP-ENV:Envelope 
                       xmlns:SOAP-ENV="
http://schemas.xmlsoap.org/soap/envelope/" 
                       xmlns:xsi="
http://www.w3.org/1999/XMLSchema-instance" 
                       xmlns:xsd="http://www.w3.org/1999/XMLSchema">
     <SOAP-ENV:Header>
     </SOAP-ENV:Header>
    <SOAP-ENV:Body>
         <ns1:sayHelloTo 
                      xmlns:ns1="Hello" 
                     SOAP-ENV:encodingStyle="
http://schemas.xmlsoap.org/soap/encoding/">
             <name xsi:type="xsd:string">Tarak</name>
         </ns1:sayHelloTo>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Listing 10 features basically the same SOAP request as Listing 4 with some HTTP-specific code at the beginning. The first line indicates that this is a POST request that conforms to the rules per HTTP 1.1. The target for the post is http://www.SmartHello.com/HelloApplication. The next line indicates the content type, which must be text/xml when including SOAP entity bodies in HTTP messages. The content length specifies the payload length of the POST request.

The fourth line is SOAP-specific and mandatory. The SOAPAction HTTP request header field indicates the intent of the SOAP HTTP request. The value is a URI identifying the intent. SOAP places no restrictions on the format of the URI. In fact, the URI does not even have to be resolvable to an actual location.

One possible use of the SOAPAction field is by a firewall that looks at the field's value and makes a decision on whether to allow the request to pass through.

Once the server has processed the request, it will return a response to the client that looks like Listing 11 (assuming that there are no errors):

Listing 11

HTTP/1.0 200 OK
Content-Type: text/xml; charset="utf-8"
Content-Length: 615
<SOAP-ENV:Envelope 
                       xmlns:SOAP-ENV="
http://schemas.xmlsoap.org/soap/envelope/"               
                       xmlns:xsi="
http://www.w3.org/1999/XMLSchema-instance" 
                       xmlns:xsd="http://www.w3.org/1999/XMLSchema">
     <SOAP-ENV:Body>
           <ns1:sayHelloToResponse 
                      xmlns:ns1="Hello" 
                      SOAP-ENV:encodingStyle="
http://schemas.xmlsoap.org/soap/encoding/">
                <return xsi:type="xsd:string">Hello John, How are 
you doing?</return>
          </ns1:sayHelloToResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

That is the same SOAP response as shown in Listing 5 with some HTTP-specific code at the beginning. Since there was no error, the first line produces the code 200, which in HTTP speak means "everything's OK." If there were any errors/faults while processing the SOAP message (in the header or body), the returned code would generate 500, which means "internal server error" in HTTP speak. Thus, the first line would look like this:

HTTP 500 Internal Server Error

The HTTP extension framework

Many applications require services beyond those provided by traditional HTTP. As a result, such applications extend the traditional HTTP protocol. However, these extensions are proprietary to the application itself. The HTTP extension framework attempts to solve that problem by describing a generic extension mechanism for HTTP. Among other things, the HTTP extension framework adds the M-POST method, where M stands for mandatory. An HTTP request is called a mandatory request if it includes at least one mandatory extension declaration. Include a mandatory extension declaration by using the Man or the C-Man header fields. The method name of a mandatory request must be prefixed by M-, hence the mandatory POST method is called M-POST.

SOAP 1.0 required that a client start off with an HTTP POST request and send an M-POST request only if the server returned an HTTP error 510. SOAP 1.1 places no such restriction on a client, thus allowing it to start off with either request type. Below is the same request that we've considered so far presented in M-POST form:

Listing 12

M-POST http://www.SmartHello.com/HelloApplication HTTP/1.1
Content-Type: text/xml; charset="utf-8"
Content-Length: 587
Man: "http://schemas.xmlsoap.org/soap/envelope/"; ns=01
01-SOAPAction: "http://www.SmartHello.com/HelloApplication#sayHelloTo"
<SOAP-ENV:Envelope 
                       xmlns:SOAP-ENV="
http://schemas.xmlsoap.org/soap/envelope/" 
                       xmlns:xsi="
http://www.w3.org/1999/XMLSchema-instance" 
                       xmlns:xsd="http://www.w3.org/1999/XMLSchema">
     <SOAP-ENV:Header>
     </SOAP-ENV:Header>
    <SOAP-ENV:Body>
         <ns1:sayHelloTo 
                      xmlns:ns1="Hello" 
                     SOAP-ENV:encodingStyle="
http://schemas.xmlsoap.org/soap/encoding/">
             <name xsi:type="xsd:string">Tarak</name>
         </ns1:sayHelloTo>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

As far as the actual SOAP message goes, Listing 12 doesn't differ from Listing 10. The header does feature a few dissimilarities. For example, instead of a POST request, we have an M-POST request. As described above, every mandatory HTTP request such as M-POST requires at least one mandatory extension declaration. Here we have one: the Man field describes a mandatory end-to-end extension declaration and maps the header-prefix 01 to the namespace http://schemas.xmlsoap.org/soap/envelope/. Note how this prefix is attached to the SOAPAction field.

Once the server processes the request, it will return a response to the client that looks like the code below (assuming that there are no errors):

Listing 13

HTTP/1.0 200 OK
Ext:
Content-Type: text/xml; charset="utf-8"
Content-Length: 615
<SOAP-ENV:Envelope 
                       xmlns:SOAP-ENV="
http://schemas.xmlsoap.org/soap/envelope/"               
                       xmlns:xsi="
http://www.w3.org/1999/XMLSchema-instance" 
                       xmlns:xsd="http://www.w3.org/1999/XMLSchema">
     <SOAP-ENV:Body>
           <ns1:sayHelloToResponse 
                      xmlns:ns1="Hello" 
                      SOAP-ENV:encodingStyle="
http://schemas.xmlsoap.org/soap/encoding/">
                <return xsi:type="xsd:string">Hello John, How are
you doing?</return>
          </ns1:sayHelloToResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Again, the response in Listing 13 resembles the one returned for a POST request -- shown in Listing 11 -- except for the Ext field.

In using SOAP via HTTP, it is interesting to see that the actual SOAP message (the SOAP envelope and everything within it) always remains the same as the message with no protocol. That fact can be extrapolated to conclude that HTTP is not the only protocol that SOAP works with. For example, SOAP can easily work with the SMTP or any custom homegrown protocol. The only requirement is that both sides -- the client and the server -- understand the protocol.

SOAP does not define everything

So far I've discussed different aspects that SOAP defines, but there are a number of areas that SOAP does not define. The authors of the SOAP specification explicitly exclude the more involved aspects of building an object model, as well as anything that's already been built. The reason for that can be found upon examining the goals of SOAP. Besides extensibility, a major design goal of SOAP is simplicity. To keep SOAP simple, the authors decided to define only those aspects that were absolutely critical for creating a lightweight protocol. For example, SOAP does not define/specify anything about distributed garbage collection, type safety or versioning, bidirectional HTTP communications, message-box carrying or pipeline processing, object-by-reference, or no-object activation. SOAP is meant to be simple -- a protocol a developer could implement in a couple of days using any programming language on any operating system. When you think about it, this is actually a blessing since SOAP can easily be adapted to existing technologies for building distributed systems, even technologies as different as CORBA and DCOM.

Until next time ...

In this article I introduced you to the basics of SOAP and discussed some of the reasons behind its design. But this is only the tip of the SOAP iceberg. To find out more about SOAP, refer to the Resources section for a link to the SOAP specification. As far as this series goes, what I've included here is all you need to know about the specification.

In Part 2, I will introduce you to Apache's SOAP implementation. With that implementation, you will create a simple distributed application that uses SOAP as the wire protocol.

A certified Java programmer, Tarak Modi is an architect at North Highland, which specializes in management and technology consulting. He has a master's degree in computer engineering and an MBA concentrating in information systems. He has several years of experience working with C++ and Java and technologies such as DCOM, CORBA, RMI, and EJB. He has written articles for leading software magazines including JavaWorld and is currently working on a book on Java Message Service with Manning Publications. To find out more about Tarak, his articles, and upcoming book, please visit his Website at http://tmodi.home.att.net/

Learn more about this topic

1 2 Page 2
Page 2 of 2