So far, we have only
Although the examples that we have shown so far involve only a client and a web service to which the client sends a SOAP message, in practice, a SOAP message may pass through one or more intermediate systems before reaching its ultimate destination. For the purposes of this discussion, an intermediate system is not like a network router, which is concerned only with passing a transport-level packet from node to node until it
As an example of the use of an intermediate system, suppose that a business wants to make it possible for other businesses to place stock orders by building a SOAP message that contains a purchase order, in response to which it expects confirmation of the order and payment details. Before the order is
When the client sends the purchase order, it is required to include a header that identifies it in a way that is determined by the business providing the service. In practice, this would probably involve the use of some secure mechanism, such as public key cryptography and the inclusion of a certificate to identify the client.
The system to which the purchase order is sent looks for this header,
The message is now forwarded to an internal system that handles the purchase order and ultimately returns a response to the order itself.
In the SAAJ API, each SOAPMessage can have a single SOAPHeader element. By default, this element is empty. Headers are created by adding XML elements to the SOAPHeader . Each such header element must be namespace-qualified and may contain an attribute that identifies the system that is intended to process it, known as the actor attribute. The value of this attribute is defined to be a URI and, in practice, it is often a URL, although it need not be. There are three cases to consider:
When there is no actor attribute, the header is deemed to be intended for the ultimate recipient of the message.
A header containing an actor attribute with this value (which a SAAJ application can conveniently refer to by using the constant value SOAPConstants.URI_SOAP_ACTOR_NEXT ) is intended for the first system that receives it.
In this case, the header is intended for the system whose URI matches the value of the attribute.
When a SOAP message is received, the headers must be checked for any that are intended for the recipient. If there are any, the following rules apply:
The header must be removed from the message.
If the receiver understands the header, then it may process the header and act upon it. As a result, it may add one or more new headers to the message (which may be identical to the received header). If the header contains the mustUnderstand attribute from the SOAP envelope namespace, and the value of this attribute is 1, the receiver must process the header ” or else return a fault to the originator if it chooses not to do so or cannot do so for some reason.
If the receiver does not understand a header that is addressed to it, it may choose to silently ignore it, unless the mustUnderstand attribute is present and has the value 1, in which case it must return a fault to the originator.
If a fault is returned as a result of the mustUnderstand attribute, then the fault code must have the value soap-env:MustUnderstand and the fault actor must be set to the URI of the system that generated the fault. A system that processes a header may also generate a fault for reasons that are related to the content of the header. In all cases, a fault that arises from header processing may not include a detail element.
Header elements are created using the
SOAPHeader
addHeaderElement( )
method, which requires a
SOAPHeader header = message.getSOAPPart().getEnvelope( ).getHeader( );
SOAPHeaderElement headerElement = header.addHeaderElement(
soapFactory.createName("AuthInfo"));
headerElement.addNamespaceDeclaration(null, "urn:headerDemo");
headerElement.setMustUnderstand(true);
headerElement.addChildElement("UserName").addTextNode("JWSUserName");
headerElement.addChildElement("Password").addTextNode("JWSPassword");
The header element is called
AuthInfo
and its namespace is
urn:headerDemo
, which is an arbitrarily
headerElement.addNamespaceDeclaration(null, "urn:headerDemo");
makes this namespace the default for this element and its subelements, so that the element
The
SOAPHeaderElement
interface has four
public void setActor(String actorURI); public String getActor( ); public void setMustUnderstand(boolean cond); public boolean getMustUnderstand( );
The code in Example 3-17 sets the
mustUnderstand
attribute to
1
(by virtue of the fact that its argument has the value true), but does not set the actor attribute at all, which implies that the header is to be processed by the ultimate recipient of the message, and must be
<soap-env:Envelope xmlns:soap-env=
"http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header>
<AuthInfo xmlns="urn:headerDemo" soap-env:mustUnderstand="1">
<UserName>JWSUserName</UserName>
<Password>JWSPasswordJWSPassword</Password>
</AuthInfo>
</soap-env:Header>
<soap-env:Body/>
</soap-env:Envelope>
The default value of the mustUnderstand attribute is , which means that the header can be removed without being processed by its target.
When a SOAP message is received, there are three ways to handle the header entries that it contains once a reference to the SOAPHeader has been obtained:
Get an iterator over all of the child elements of the SOAPHeader . This returns all of the SOAPHeaderElement objects in the message.
Get an iterator over all of the headers intended for a given actor. This returns a subset of the SOAPHeaderElement objects in the message.
Get an iterator over all of the headers intended for a given actor and also remove them from the message.
A message recipient must process all headers for which the actor attribute is set to next or to its own URI, and must remove them once they have been processed. The SOAPHeader interface provides two methods that locate the headers intended for a given actor URI:
public Iterator examineHeaderElements(String actorURI); public Iterator extractHeaderElements(String actorURI);
The difference between these two methods is that the second
[12] It is not clear from the SAAJ specification whether this is the intended behavior or just a bug. In my opinion, it would be better if this call returned only those headers with the actor attribute set to next .
// Gets all the SOAPHeaderElements Iterator iter = soapHeader.getChildElements( );
|
|
|
|