SOAP fault messages are the mechanism by which SOAP applications report errors “upstream,” to nodes earlier in the message path. It's the mission of this section to provide a full and detailed explanation of SOAP faults so that you can handle them appropriately in your own Web services.
SOAP faults are generated by receivers, either an intermediary or the ultimate receiver of a message. The receiver is required to send a SOAP fault back to the sender only if the Request/Response messaging mode is used. In One-Way mode, the receiver should generate a fault and may store it somewhere, but it must not attempt to transmit it to the sender.
SOAP faults are returned to the receiver's immediate sender. For example, if the third node in a message path generates a fault, that fault message is sent to the second node in the message path and nowhere else. In other words, you don't send the fault to the original sender unless it's also the immediate sender. When that sender receives the fault message, it may take some action, such as undoing operations, and may send another fault further upstream to the next sender if there is one.
Most developers see error handling as a pretty dull subject, so it's often ignored or poorly implemented. The tendency to ignore error handling is natural, but it's not wise. As the saying goes, “Stuff happens”: Things can, and often do, go wrong; it's inevitable that errors will occur in the normal course of events. Because errors are fairly common, it's logical that some time should be dedicated to error handling. The SOAP Note recognizes the importance of error handling and dedicates a considerable amount of verbiage to addressing the issue. Even so, SOAP is not strict enough to avoid interoperability problems, so the BP provides a lot more guidance on the generation and processing of SOAP fault messages.
A SOAP message that contains a Fault element in the Body is called a fault message. A fault message is analogous to a Java exception; it's generated when an error occurs. Fault messages are used in Request/Response messaging. Nodes in the message path generate them when processing a request message. When an error occurs, the receiving node sends a fault message back to the sender just upstream, instead of the anticipated reply message. Faults are caused by improper message formatting, version mismatches, trouble processing a header, and application-specific errors.
When a fault message is generated, the Body of the SOAP message must contain only a single Fault element and nothing else. The Fault element itself must contain a faultcode element and a faultstring element, and optionally faultactor and detail elements. Listing 4-18 is an example of a SOAP fault message.
Listing 4-18 A SOAP Fault Message
<?xml version="1.0" encoding="UTF-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mh="http://www.Monson-Haefel.com/jwsbook/BookQuote" > <soap:Body> <soap:Fault> <faultcode>soap:Client</faultcode> <faultstring> The ISBN value contains invalid characters </faultstring> <faultactor>http://www.xyzcorp.com</faultactor> <detail> <mh:InvalidIsbnFaultDetail> <offending-value>19318224-D</offending-value> <conformance-rules> The first nine characters must be digits. The last character may be a digit or the letter 'X'. Case is not important. </conformance-rules> </mh:InvalidIsbnFaultDetail> </detail> </soap:Fault> </soap:Body> </soap:Envelope>
Note that the Fault element and its children are part of the SOAP namespace, just as the SOAP Envelope and Body elements are.
Did you notice in Listing 4-18 that the children of the Fault element weren't qualified with the soap prefix? The children of the Fault element may be unqualified.BP In other words, they need not be prefixed with the SOAP 1.1 namespace. Note as well that it's forbidden for the Fault element to contain any immediate child elements other than faultcode, faultstring, faultactor, and detail.BP
4.6.1 The faultcode Element
The faultcode element may use any of four standard SOAP fault codes to identify an error.
SOAP Standard Fault Codes
Client Server VersionMismatch MustUnderstand
Although you're allowed to use arbitrary fault codes, you should use only the four standard codes listed.BP
The faultcode element should contain one of the standard codes listed above, with the appropriate SOAP namespace prefix. Prefixing the code, as in soap:Client, allows for easy versioning of standard fault codes. As SOAP evolves, it's possible that new fault codes will be added. New fault codes can easily be distinguished from legacy fault codes by their namespace prefix. The meaning of a fault code will always correlate to both the code (the local name) and the namespace (the prefix).
The SOAP Note recommends the use of the dot separator between names to discriminate general standard fault codes from specific application subcodes. This convention is not used in J2EE Web services, which prefers the use of XML namespace-based prefixes for SOAP fault codes. If you use one of the standard SOAP fault codes, the namespace prefix must map to the SOAP namespace "http://schemas.xmlsoap.org/soap/envelope/".BP
4.6.1.1 The Client Fault
The Client fault code signifies that the node that sent the SOAP message caused the error. Basically, if the receiver cannot process the SOAP message because there is something wrong with the message or its data, it's considered the fault of the client, the sender. The receiving node generates a Client fault if the message is not well formed, or contains invalid data, or lacks information that was expected, like a specific header. For example, in Listing 4-19, the SOAP fault indicates that the sender provided invalid information.
Listing 4-19 An Example of a SOAP Fault with a Client Fault Code
<?xml version="1.0" encoding="UTF-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" > <soap:Body> <soap:Fault> <faultcode>soap:Client</faultcode> <faultstring>The ISBN contains invalid characters</faultstring> <detail/> </soap:Fault> </soap:Body> </soap:Envelope>
When a node receives a fault message with a Client code, it should not attempt to resend the same message. It should take some action to correct the problem or abort completely.
4.6.1.2 The Server Fault
The Server fault code indicates that the node that received the SOAP message malfunctioned or was otherwise unable to process the SOAP message. This fault is a reflection of an error by the receiving node (either an intermediary or the ultimate receiver) and doesn't point to any problems with the SOAP message itself. In this case the sender can assume the SOAP message to be correct, and can redeliver it after pausing some period of time to give the receiver time to recover.
If, for example, the receiving node is unable to connect to a resource such as a database while processing a SOAP message, it might generate a Server fault. The following is an example of a Server fault, generated when the BookPrice Web service could not access the database to retrieve price information in response to a SOAP message.
<?xml version="1.0" encoding="UTF-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" > <soap:Body> <soap:Fault> <faultcode>soap:Server</faultcode> <faultstring> Database is unavailable.</faultstring> <detail/> </soap:Fault> </soap:Body> </soap:Envelope>
4.6.1.3 The VersionMismatch Fault
A receiving node generates a VersionMismatch fault when it doesn't recognize the namespace of a SOAP message's Envelope element. For example, a SOAP 1.1 node will generate a fault with a VersionMismatch code if it receives a SOAP 1.2 message, because it finds an unexpected namespace in the Envelope. This scenario is illustrated by the fault message in Listing 4-20.
Listing 4-20 An Example of a VersionMismatch Fault
<?xml version="1.0" encoding="UTF-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" > <soap:Body> <soap:Fault> <faultcode>soap:VersionMismatch</faultcode> <faultstring>Message was not SOAP 1.1-conformant</faultstring> <detail/> </soap:Fault> </soap:Body> </soap:Envelope>
The VersionMismatch fault applies only to the namespace assigned to the Envelope, Header, Body, and Fault elements. It does not apply to other parts of the SOAP message, like the header blocks, XML document version, or application-specific elements in the Body.
The VersionMismatch fault is also used in the unlikely event that the root element of a message is not Envelope, but something else. Sending a VersionMismatch fault message back to the sender in this case may not be helpful, however: The sender may be designed to handle a different protocol and doesn't understand SOAP faults.
4.6.1.4 The MustUnderstand Fault
When a node receives a SOAP message, it must examine the Header element to determine which header blocks, if any, are targeted at that node. If a header block is targeted at the current node (via the actor attribute) and sets the mustUnderstand attribute equal to "1", then the node is required to know how to process the header block. If the node doesn't recognize the header block, it must generate a fault with the MustUnderstand code. Listing 4-21 shows an example.
Listing 4-21 A MustUnderstand Fault
<?xml version="1.0" encoding="UTF-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" > <soap:Body> <soap:Fault> <faultcode>soap:MustUnderstand</faultcode> <faultstring>Mandatory header block not understood.</faultstring> <detail/> </soap:Fault> </soap:Body> </soap:Envelope>
4.6.1.5 Non-standard SOAP Fault Codes
It is also possible to use non-standard SOAP fault codes that are prescribed by other organizations and belong to a separate namespace. For example, Listing 4-22 uses a fault code specified by the WS-Security specification.
Listing 4-22 Using Non-standard Fault Codes
<?xml version="1.0" encoding="UTF-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/06/secext"> <soap:Body> <soap:Fault> <faultcode>wsse:InvalidSecurityToken</faultcode> <faultstring>An invalid security token was provided</faultstring> <detail/> </soap:Fault> </soap:Body> </soap:Envelope>
4.6.2 The faultstring Element
The faultstring element is mandatory. It should provide a human-readable description of the fault. Although the faultstring element is required, the text used to describe the fault is not standardized.
Optionally, the faultstring element can indicate the language of the text message using a special attribute, xml:lang.BP The set of valid codes is defined by IETF RFC 1766.4 For example, a Client fault could be generated with a Spanish-language text as shown in Listing 4-23.
Listing 4-23 Using the xml:lang Attribute in the faultstring Element
<?xml version="1.0" encoding="UTF-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" > <soap:Body> <soap:Fault> <faultcode>soap:Client</faultcode> <faultstring xml:lang="es" > El ISBN tiene letras invalidas </faultstring> <detail/> </soap:Fault> </soap:Body> </soap:Envelope>
Although it's not specified, it's assumed that, in the absence of the xml:lang attribute, the default is English (xml:lang="en"). The xml:lang attribute is part of the XML 1.0 namespace, which does not need to be declared in an XML document.
4.6.3 The faultactor Element
The faultactor element indicates which node encountered the error and generated the fault (the faulting node). This element is required if the faulting node is an intermediary, but optional if it's the ultimate receiver. For example, let's assume that an intermediary node in the message path, the authentication node, did not recognize the mandatory (mustUnderstand="1") processed-by header block, so it generated a MustUnderstand fault. In this case the authentication node must identify itself using the faultactor element, as in Listing 4-24.
Listing 4-24 Locating the Source of the Fault Using the faultactor Element
<?xml version="1.0" encoding="UTF-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <soap:Fault> <faultcode>soap:MustUnderstand</faultcode> <faultstring>Mandatory header block not understood. </faultstring> <faultactor> http://www.Monson-Haefel.com/jwsbook/authenticator </faultactor> <detail/> </soap:Fault> </soap:Body> </soap:Envelope>
The faultactor element may contain any URI, but is usually the Internet address of the faulting node, or the URI used by the actor attribute if a header block was the source of the error.
SOAP 1.1 doesn't recognize the concept of a role as distinct from a node. In fact, it lumps these two concepts together into the single concept actor. Thus you can see the faultactor as identifying both the node that generated the fault and the role that it was manifesting when it generated the fault.
4.6.4 The detail Element
The detail element of a fault message must be included if the fault was caused by the contents of the Body element, but it must not be included if the error occurred while processing a header block. The SOAP message in Listing 4-25 provides further details about the invalid ISBN reported in the faultstring element.
Listing 4-25 A SOAP Fault detail Element
<?xml version="1.0" encoding="UTF-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mh="http://www.Monson-Haefel.com/jwsbook/BookQuote" > <soap:Body> <soap:Fault> <faultcode>soap:Client</faultcode> <faultstring> The ISBN value contains invalid characters </faultstring> <detail> <mh:InvalidIsbnFaultDetail> <offending-value>19318224-D</offending-value> <conformance-rules> The first nine characters must be digits. The last character may be a digit or the letter 'X'. Case is not important. </conformance-rules> </mh:InvalidIsbnFaultDetail> </detail> </soap:Fault> </soap:Body> </soap:Envelope>
The detail element may contain any number of application-specific elements, which may be qualified or unqualified, according to their XML schema. In addition, the detail element itself may contain any number of qualified attributes, as long as they do not belong to the SOAP 1.1 namespace, "http://schemas.xmlsoap.org/soap/envelope".BP
It's perfectly legal to use an empty detail element, but you must not omit the detail element entirely if the fault resulted while processing the contents of the original message's Body element.
4.6.4.1 Processing Header Faults: Omitting the detail Element
SOAP provides little guidance on how details about header faults should be provided. It says only that detailed information must be included in the Header element. Some SOAP toolkits place a SOAP Fault element inside the Header element, or nested within a header block, while other toolkits may use a different strategy.
4.6.5 Final Words about Faults
As a developer, it's your responsibility to be aware of the various circumstances under which faults must be generated, and to ensure that your code properly implements the processing of those faults.
This is probably a good time to recap. Faults result from one of several conditions:
-
The message received by the receiver is improperly structured or contains invalid data.
-
The incoming message is properly structured, but it uses elements and namespaces in the Body element that the receiver doesn't recognize.
-
The incoming message contains a mandatory header block that the receiver doesn't recognize.
-
The incoming message specifies an XML namespace for the SOAP Envelope and its children (Body, Fault, Header) that is not the SOAP 1.1 namespace.
-
The SOAP receiver has encountered an abnormal condition that prevents it from processing an otherwise valid SOAP message.
The first two conditions generate what are considered Client faults, faults that relate to the contents of the message: The client has sent an invalid or unfamiliar SOAP message to the receiver. The third condition results in a MustUnderstand fault, and the fourth results in a VersionMismatch fault. The fifth condition is considered a Server fault, which means the error was unrelated to the contents of the SOAP message. A server fault is generated when the receiver cannot process a SOAP message because of an abnormal condition.