SOAP Messages


We have already seen the overall structure of a SOAP message, as defined by the SOAP Envelope, in Figure 3-4. All SOAP messages, no matter how lengthy or complex, ultimately conform to this structure. The only caveat is there must be at least one body block within the SOAP body element in a message and there does not necessarily have to be a SOAP header or any SOAP header blocks. There is no upper limit on the number of header or body blocks, however. A sample SOAP message is presented here in Figure 3-5:

Figure 3-5. A simple SOAP message.
 <?xml version="1.0" encoding="UTF-8"?> <env:Envelope     xmlns:env="http://www.w3.org/2002/06/soap-envelope" >  <env:Header>     <tx:transaction-id         xmlns:tx="http://transaction.example.org"      env:encodingStyle="http://transaction.example.org/enc"         env:role= "http://www.w3.org/2002/06/soap-envelope/role/ultimateReceiver"         env:mustUnderstand="true">            decd7461-4ef2138d-7b52e370-fed8a006-ca7ea17     </tx:transaction-id>  </env:Header>  <env:Body xmlns:bank="http://bank.example.org">     <bank:credit-account env:encodingStyle=                    "http://www.w3.org/2002/06/soap-encoding">         <bank:account>12345678</bank:account>         <bank:sort>10-11-12</bank:sort>         <bank:amount currency="usd">123.45</bank:amount>     </bank:credit-account>     <bank:debit-account>         <bank:account>87654321</bank:account>         <bank:sort>12-11-10</bank:sort>         <bank:amount currency="usd">123.45</bank:amount>     </bank:debit-account>  </env:Body> </env:Envelope> 

The structure of all SOAP messages (including that shown in Figure 3-5) maps directly onto the abstract model shown in Figure 3-2. Figure 3-5 contains a typical SOAP message with a single header block (which presumably has something to do with managing transactional integrity), and a body containing two elements (which presumably instructs the recipient of the message to perform an operation on two bank accounts). Both the Header and Body elements are contained within the outer Envelope element, which acts solely as a container.

SOAP Envelope

The SOAP Envelope is the container structure for the SOAP message and is associated with the namespace http://www.w3.org/2002/06/soap-envelope. An example is shown in Figure 3-6 where the namespace is associated with the prefix env:

Figure 3-6. The SOAP envelope element.
 <?xml version="1.0" encoding="UTF-8"?> <env:Envelope     xmlns:env="http://www.w3.org/2002/06/soap-envelope" >   <!-- Optional header blocks -->   <env:Header>     ...   </env:Header>   <!-- Single mandatory body element -->   <env:Body xmlns:bank="http://bank.example.org">     ...   </env:Body> </env:Envelope> 

The Envelope contains up to two child elements, the Header and the Body (where the Body element is mandatory). Aside from acting as a parent to the Header and the Body elements, the Envelope may also hold namespace declarations that are used within the message.

SOAP Header

The Header element provides a mechanism for extending the content of a SOAP message with out-of-band information designed to assist (in some arbitrary and extensible way) the passage of the application content in the Body section content through a Web services-based application.

The SOAP header space is where much of the value in Web services resides, since it is here that aspects like security, transactions, routing, and so on are expressed. Every Web services standard has staked its claim on some part of the SOAP header territory, but in a mutually compatible way. The fact that SOAP headers are extensible enough to support such diverse standards is a major win, since it supports flexible protocol composition tailored to suit specific application domains.


A SOAP header has the local name Header associated with the http://www.w3.org/2002/06/soap-envelope namespace. It may also contain any number of namespace qualified attributes and any number of child elements, known as header blocks. In the absence of any such header blocks, the Header element itself may be omitted from the Envelope. A sample header block is shown in Figure 3-7.

Figure 3-7. A SOAP header element.
 <?xml version="1.0" encoding="UTF-8"?> <env:Envelope     xmlns:env="http://www.w3.org/2002/06/soap-envelope" >   <!-- Optional header blocks -->   <env:Header>     <tx:transaction-id         xmlns:tx="http://transaction.example.org"      env:encodingStyle="http://transaction.example.org/enc"         env:role= "http://www.w3.org/2002/06/soap-envelope/role/ultimateReceiver"         env:mustUnderstand="true">            decd7461-4ef2138d-7b52e370-fed8a006-ca7ea17     </tx:transaction-id>   </env:Header>   <!-- Single mandatory body element -->   <env:Body xmlns:bank="http://bank.example.org">     ...   </env:Body> </env:Envelope> 

If present, each header block must be namespace qualified (according to the rules set out in the SOAP schema), may specify how it has been encoded (i.e., which schema constrains it) through the encodingStyle attribute, may specify its consumer through the role attribute, and may demand that it is understood by SOAP infrastructure that encounters its message through the mustUnderstand attribute. The SOAP specification stipulates that it is illegal for the role and mustUnderstand attributes to appear anywhere other than in header block declarations.

The sender of a SOAP message should not place them anywhere else, and a receiver of such a malformed message must ignore these attributes if they are out of place. These attributes are of fundamental importance to SOAP processing (and thus Web services) and warrant further discussion. The vehicle for this discussion is the example SOAP message shown in Figure 3-5 where we see a header block called transaction-id that provides the necessary out-of-band information for the application payload to be processed within a transaction (using a hypothetical transaction processing protocol).

The role Attribute

The role attribute controls the targeting of header blocks to particular SOAP nodes (where a SOAP node is an entity that is SOAP-aware). The role attribute contains a URI that identifies the role being played by the intended recipient of its header block. The SOAP node receiving the message containing the header block must check through the headers to see if any of the declared roles are applicable. If there are any matches, the header blocks must be processed or appropriate faults generated.

Although any URI is valid as a role for a SOAP node to assume, the SOAP specification provides three common roles that fit into the canonical SOAP processing model as part of the standard:

  • http://www.w3.org/2002/06/soap-envelope/role/none: No SOAP processor should attempt to process this header block, although other header blocks may reference it and its contents, allowing data to be shared between header blocks (and thus save bandwidth in transmission).

  • http://www.w3.org/2002/06/soap-envelope/role/next: Every node must be willing to assume this role since it dictates that header block content is meant for the next SOAP node in the message chain. If a node knows in advance that a subsequent node does not need a header block marked with the "next" role, then it is at liberty to remove that block from the header.

  • http://www.w3.org/2002/06/soap-envelope/role/ultimateReceiver: The ultimate receiver is the final node in the message chain. Header blocks referencing this role attribute (or equivalently referencing no role attribute) should be delivered to this last node. It always implicitly plays the role of "next" given that the last node always comes after some other node even in the simplest case where the last node comes immediately after the initiator.

Figure 3-8 highlights the role attribute from our example SOAP message in Figure 3-5:

Figure 3-8. The role attribute.
 <env:Header>   <tx:transaction-id       xmlns:tx="http://transaction.example.org"      env:encodingStyle="http://transaction.example.org/enc"       env:role= "http://www.w3.org/2002/06/soap-envelope/role/ultimateReceiver"       env:mustUnderstand="true">          decd7461-4ef2138d-7b52e370-fed8a006-ca7ea17   </tx:transaction-id> </env:Header> 

The role attribute in Figure 3-8 has the value http://www.w3.org/2002/06/soap-envelope/role/ultimateReceiver, which means the contents of the header block are intended for the final SOAP processing node in this interaction (i.e., the recipient Web service). According to the SOAP processing model, this Web service must be capable of processing the application payload (in the SOAP body) in accordance with the transaction processing specification in the header block.

The mustUnderstand Attribute

If the mustUnderstand attribute is set to true, it implies that any SOAP infrastructure that receives the message containing that header block must be able to process it correctly or issue an appropriate fault message. Those header blocks that contain the mustUnderstand="true" attribute are known as mandatory header blocks since they must be processed by any nodes playing the matching roles. Header blocks missing their mustUnderstand attribute should still be examined by nodes that play the appropriate role. If a failure to act on a role occurs, it is not deemed to be critical and further processing may occur since by missing the mustUnderstand attribute they are not considered mandatory, as shown in Figure 3-9.

Figure 3-9. The mustUnderstand attribute.
 <env:Header>   <tx:transaction-id       xmlns:tx="http://transaction.example.org"      env:encodingStyle="http://transaction.example.org/enc"       env:role="http://www.w3.org/2002/06/soap-envelope/role/ultimateReceiver"       env:mustUnderstand="true">          decd7461-4ef2138d-7b52e370-fed8a006-ca7ea17   </tx:transaction-id> </env:Header> 

The SOAP specification states that SOAP senders should not generate, but SOAP receivers must accept the SOAP mustUnderstand attribute information item with a value of "false" or "0". That is, a SOAP message should contain the literal values "true" and "false" in mustUnderstand attributes, not the characters "1" and "0".


In our example shown in Figure 3-9, the mustUnderstand attribute is set to true because it is imperative that the processing node must perform the account debit-credit within a transaction. If it cannot support transactional processing, then we would prefer that it leaves the accounts well alone particularly if it is our money being transferred.

The encodingStyle Attribute

The encodingStyle attribute is used to declare how the contents of a header block were created. Knowing this information allows a recipient of the header to decode the information it contains. SOAP allows many encoding schemes and provides one of its own as an optional part of the spec. However, we will not dwell on such matters since this attribute is used not only in header blocks but in the body as well, and is covered in much more depth later in this chapter.

SOAP Body

In contrast to the intricacies of the SOAP header space, the body section of a SOAP envelope is straightforward, being simply a container for XML application payload. In fact the SOAP specification states "[T]his specification mandates no particular structure or interpretation of these elements, and provides no standard means for specifying the processing to be done." In our example in Figure 3-5, the application content housed by the SOAP Body consists of two elements that are interpreted as commands to debit and credit a bank account, which collectively amount to a funds transfer. The only constraints the SOAP specification places on the SOAP body are that it is implicitly targeted at the ultimateRecipient of the application content and that the ultimate recipient must understand its contents.

SOAP Faults

By contrast to its standard role as the simple carrier of application payload, the SOAP Body also acts in a far more interesting way as the conduit for propagating exceptions between the parties in a Web services application. The SOAP Fault is a reserved element predefined by the SOAP specification whose purpose is to provide an extensible mechanism for transporting structured and unstructured information about problems that have arisen during the processing of SOAP messages or subsequent application execution. Since the fault mechanism is predefined by the SOAP specification, SOAP toolkits are able to use this mechanism as a standard mechanism for distributed exception handling.

The SOAP Fault element belongs to the same namespace as the SOAP Envelope and contains two mandatory child elements: Code and Reason, and three optional elements: Node, Role, and Detail. An example of a SOAP Fault is shown in Figure 3-10 below. The fault is generated in response to the message shown in Figure 3-5 where the message conveyed information on a bank account cash transfer. To understand precisely what has caused the fault, we must understand each of the elements of which it is composed.

Figure 3-10. An example SOAP fault.
 <?xml version="1.0" ?> <env:Envelope      xmlns:env="http://www.w3.org/2002/06/soap-envelope"      xmlns:bank="http://bank.example.org">     <env:Body>         <env:Fault>             <env:Code>                 <env:Value>env:Receiver</env:Value>                 <env:Subcode>                     <env:Value>bank:bad-account</env:Value>                 </env:Subcode>             </env:Code>             <env:Reason lang="en-UK">              The specified account does exist at this branch             </env:Reason>             <env:Detail>                 <err:myfaultdetails                   xmlns:err= "http://bank.example.org/fault">                     <err:invalid-account-sortcode>                         <bank:sortcode>                             10-11-12                         </bank:sortcode>                         <bank:account>                             12345678                         </bank:account>                     </err:invalid-account-sortcode >                 </err:myfaultdetails>             </env:Detail>         </env:Fault>     </env:Body> </env:Envelope> 

The first child element of the Fault is the Code element, which contains two subelements: a mandatory element called Value and an optional element called Subcode. The Value element can contain any of a small number of fault codes as qualified names (sometimes abbreviated to QName) from the http://www.w3.org/2002/06/soap-envelope namespace, as per Figure 3-11, where each QName identifies a reason why the fault was generated.

Figure 3-11. SOAP fault codes.

Fault Code

Description

VersionMismatch

Occurs when SOAP infrastructure has detected mutually incompatible implementations based on different versions of the SOAP specification.

MustUnderstand

Issued in the case where a SOAP node has received a header block has with its mustUnderstand attribute set to true, but does not have the capability to correctly process that header block - that is, does not understand the protocol with which that header block is associated.

DataEncodingUnknown

Arises when the content of either a header or body block is encoded according to a schema that the SOAP node reporting the fault does not understand.

Sender

Occurs when the sender propagated a malformed message, including messages with insufficient data to enable the recipient to process it. It is an indication that the message is not to be resent without change.

Receiver

Generated when the recipient of the SOAP message could not process the message content because of some application failure. Assuming the failure is transient, resending the message later may successfully invoke processing.

In Figure 3-10 the contents of the env:Value element is env:Receiver (shown in Figure 3-12), which tells us that it was the SOAP node at the end of the message path (the receiver) that generated the fault and not an intermediate node dealing with the transaction header block.

As shown in Figure 3-13, the Subcode element contains a Value element that gives application-specific information on the fault through the qualified name bank:bad-account. This QName has significance only within the scope of the application that issued it, and as such the Subcode mechanism provides the means for propagating finely targeted application-level exception messages.

Figure 3-12. Identifying the faulting SOAP node.
 <env:Fault>   <env:Code>     <env:Value>env:Receiver</env:Value> 
Figure 3-13. Application-specific fault information.
 <env:Subcode>   <env:Value>bank:bad-account</env:Value> </env:Subcode> 

Though it isn't used in this fault, the Subcode element also makes the SOAP fault mechanism extensible. Like the Code element, the Subcode element also contains a mandatory Value child element and an optional Subcode element, which may contain further nested Subcode elements. The Value element of any Subcode contains a qualified name that consists of a prefix and a local name that references a particular QName within the application-level XML message set.

The Reason element associated with a Code is used to provide a human readable explanation of the fault, which in Figure 3-10 tells us that "The specified account does not exist at this branch". SOAP toolkits often use the contents of the Reason element when throwing exceptions or logging failures to make debugging easier. However, the Reason element is strictly meant for human consumption and it is considered bad practice to use its content for further processing.

The optional Node element provides information on which node in the SOAP message's path caused the fault. The content of the Node element is simply the URI of the node where the problem arose. In Figure 3-10 we do not have a Node element because it is the ultimate recipient of the message that caused the fault, and clearly the sender of the message already knows the URI of the recipient. However if, for example, an intermediate node dealing with the transactional aspects of the transfer failed, then we would expect that the Node element would be used to inform us of the intermediary's failure (and as we shall see, we would not expect a Detail element).

The Node element is complemented by the also optional Role element that provides information pertaining to what the failing node was doing at the point at which it failed. The Role element carries a URI that identifies the operation (usually some Web services standard) and that the party resolving the fault can use to determine what part of the application went wrong. Thus, the combination of Node and Role provides valuable feedback on exactly what went wrong and where.

The SOAP Detail element, as recapped in Figure 3-14, provides in-depth feedback on the fault if that fault was caused as a by-product of processing the SOAP Body.

Figure 3-14. Fault detail in an application-specific form.
 <env:Detail>   <err:myfaultdetails     xmlns:err= "http://bank.example.org/fault">     <err:invalid-account-sortcode>       <bank:sortcode>         10-11-12       </bank:sortcode>       <bank:account>         12345678       </bank:account>     </err:invalid-account-sortcode >   </err:myfaultdetails> </env:Detail> 

The presence of the Detail element provides information on faults arising from the application payload (i.e., the Body element had been at least partially processed by the ultimate recipient), whereas its absence indicates that the fault arose because of out-of-band information carried in header blocks. Thus we would expect that if a Detail block is present, as it is in Figure 3-10 and Figure 3-11, the Node and Role elements will be absent and vice versa.

The contents of the Detail element are known as detail entries and are application-specific and consist of any number of child elements. In Fault detail in an application-specific form. we see the invalid-account-sortcode element which describes the fault is some application specific fashion.



Developing Enterprise Web Services. An Architect's Guide
Developing Enterprise Web Services: An Architects Guide: An Architects Guide
ISBN: 0131401602
EAN: 2147483647
Year: 2003
Pages: 141

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net