XML

Simple SOAP Payloads

As you can see, SOAP uses HTTP as the request/response messaging transport. We can add a SOAP request payload in the request message and a response payload in the response message. In this way, we can issue an RPC to any component using HTTP.

The Payload for a Request Message

The SOAP specification defines several SOAP elements that can be used with a SOAP request: envelope, head, and body. The envelope is a container for the head and body. The head contains information about the SOAP message, and the body contains the actual message. Namespaces are used to distinguish the SOAP elements from the other elements of the payload. For example, SOAP-ENV:Envelope, SOAP-ENV:Head, and SOAP-ENV:Body are used in a SOAP document.

The SOAP schema for the envelope will look as follows:

  <?xml version="1.0" ?>
  <!-- XML Schema for SOAP v 1.1 Envelope -->
  <!-- Copyright 2000 DevelopMentor, International Business
  Machines Corporation, Lotus Development Corporation,
  Microsoft, UserLand Software -->
  <schema xmlns="http://www.w3.org/1999/XMLSchema"
      xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/"
      targetNamespace="http://schemas.xmlsoap.org/soap/envelope/">
      <!-- SOAP envelope, header, and body -->
      <element name="Envelope" type="tns:Envelope"/>
      <complexType name="Envelope">
          <element ref="tns:Header" minOccurs="0"/>
          <element ref="tns:Body" minOccurs="1"/>
          <any minOccurs="0" maxOccurs="*"/>
          <anyAttribute/>
      </complexType>
      <element name="Header" type="tns:Header"/>
      <complexType name="Header">
          <any minOccurs="0" maxOccurs="*"/>
          <anyAttribute/>
      </complexType>
      <element name="Body" type="tns:Body"/>
      <complexType name="Body">
          <any minOccurs="0" maxOccurs="*"/>
          <anyAttribute/>
      </complexType>
      <!-- Global Attributes.  The following attributes are
           intended to be usable via qualified attribute names on
           any complex type referencing them.
      -->
      <attribute name="mustUnderstand" default="0">
          <simpleType base="boolean">
              <pattern value="0|1"/>
          </simpleType>
      </attribute>
      <attribute name="actor" type="uri-reference"/>
      <!-- 'encodingStyle' indicates any canonicalization
       conventions followed in the contents of the containing
       element.  For example, the value
       'http://schemas.xmlsoap.org/soap/encoding/' indicates
       the pattern described in SOAP specification.
      -->
  <simpleType name="encodingStyle" base="uri-reference"
      derivedBy="list"/>
      <attributeGroup name="encodingStyle">
          <attribute name="encodingStyle"
              type="tns:encodingStyle"/>
      </attributeGroup>
      <!-- SOAP fault reporting structure -->
      <complexType name="Fault" final="extension">
          <element name="faultcode" type="qname"/>
          <element name="faultstring" type="string"/>
          <element name="faultactor" type="uri-reference"
              minOccurs="0"/>
          <element name="detail" type="tns:detail" minOccurs="0"/>
      </complexType>
      <complexType name="detail">
          <any minOccurs="0" maxOccurs="*"/>
          <anyAttribute/>
      </complexType>
  </schema>

A SOAP request including the payload defined in the schema would look like this:

  POST /Order HTTP/1.1
  Host: www.northwindtraders.com
  Content-Type: text/xml
  Content-Length: nnnn
  SOAPAction: "urn:northwindtraders.com:PO#UpdatePO"
  <SOAP-ENV:Envelope
  xmlns:xsi="http://www.w3.org/1999/XMLSchema/instance"
     xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope"
     xsi:schemaLocation=
        "http://www.northwindtraders.com/schemas/NPOSchema.xsd">
     <SOAP-ENV:Body xsi:type="NorthwindBody">
        <UpdatePO>
           <orderID>0</orderID>
           <customerNumber>999</customerNumber>
           <item>89</item>
           <quantity>3000</quantity>
           <return>0</return>
        </UpdatePO>
     </SOAP-ENV:Body>
  </SOAP-ENV:Envelope>
NOTE
Notice that the default Body declaration is overridden by using an xsi:type attribute associating NorthwindBody with the Body element. A schema that defines NorthwindBody and the additional elements, such as UpdatePO, will be shown in the section "A Schema for the Body Content of the SOAP Message" later in this chapter.

Because the Body element contains the any element in the SOAP schema, you could also have written SOAP body as follows:

  <SOAP-ENV:Envelope
     xmlns:xsi="http://www.w3.org/1999/XMLSchema/instance"
     xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope">
     <SOAP-ENV:Body xsi:type="NorthwindBody">
        <m:UpdatePO xmlns:m=
           "http://www.northwindtraders.com/schemas/NPOSchema.xsd">
           <orderID>0</orderID>
           <customerNumber>999</customerNumber>
           <item>89</item>
           <quantity>3000</quantity>
           <return>0</return>
        </m:UpdatePO>
     </SOAP-ENV:Body>
  </SOAP-ENV:Envelope>

As you can see, the payload of a SOAP request is an XML document that contains the parameter values of the method. The HTTP header of this package has identified the UpdatePO method of the Order object as the recipient of this method call. The top-level element of the method call must have the same name as the method identified in SOAPAction.

The elements contained within the top element are the parameters for the method. The preceding example contains four parameters: orderID, customerNumber, item, and quantity. In Microsoft Visual Basic, this method could be written as follows:

  Public Sub UpdatePO(byval orderID as Integer, _
      byval customerNumber as Integer, _
      byval item as Integer, _
      byval quantity as Integer, _
      byref return as Integer)

In Java, this method would look like this:

  public class UpdatePO {public int orderID;
      public int customerNumber;
      public int item;
      public int quantity;
      public int return;}

When you are building the request, you will include one element for each in or in/out parameter. This technique of associating one element with each parameter is also known as the element-normal form (ENF). The name of each element is the name of the parameter the element is associated with.

The request can also contain a header element that includes additional information. There are no predefined elements in the header element-you can include any element you want, as long as it is either prefixed by a namespace or the header type is overridden using xsi:type and a type defined in a schema.

We can add a header element to our payload example as shown here:

  <SOAP-ENV:Envelope
     xmlns:xsi="http://www.w3.org/1999/XMLSchema/instance"
     xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope"
     xsi:schemaLocation=
        "http://www.northwindtraders.com/schemas/NPOSchema.xsd">
     <SOAP-ENV:Header xsi:type="NorthwindHeader">
        <GUID>
        10000000-0000-abcd-0000-000000000001
        </GUID>
     </SOAP-ENV:Header>
     <SOAP-ENV:Body xsi:type="NorthwindBody">
        <UpdatePO>
           <orderID>0</orderID>
           <customerNumber>999</customerNumber>
           <item>89</item>
           <quantity>3000</quantity>
           <return>0</return>
        </UpdatePO>
     </SOAP-ENV:Body>
  </SOAP-ENV:Envelope>

Because the any element is used in the header element in the SOAP schema, we could also rewrite the SOAP header as follows:

  <SOAP-ENV:Header>
        <COM:GUID xmlns:COM="http://comobject.Northwindtraders.com">
           10000000-0000-abcd-0000-000000000001
        </COM:GUID>
  </SOAP-ENV:Header>

In this case, we have created an element named GUID. It will be up to the receiving application to interpret this header, but it's likely that it will be used to instantiate the correct COM object. These additional elements can be considered processing instructions.

You can include a predefined attribute named mustUnderstand as an attribute of a header element. The mustUnderstand attribute can be used to indicate whether the header information is essential for processing of the information. If the header information is essential, mustUnderstand should be set to true. If the receiving element cannot recognize the processing instruction and mustUnderstand is set to 1, the message must be rejected. Thus, we could have the following header element:

  <SOAP-ENV:Header xsi:type="Transaction">
        <transactionID mustUnderstand="1">
           10000000
        </transactionID >
  </SOAP-ENV:Header>

In this case, we are creating an element named TransactionID. This element must be understood by the receiving application, or the message will be rejected.