Skip to main content

SOAP Fault Handling

This topic describes how to handle faults within a web service and within a web client.

Also see Using Try-Catch.

Note that the SOAPPREFIX parameter affects the prefix used in any SOAP faults; see Specifying the SOAP Envelope Prefix.

Default Fault Handling in a Web Service

By default, when your InterSystems IRIS® data platform web service encounters an error, it returns a standard SOAP message containing a fault. The following shows an example (for SOAP 1.1). The SOAP envelope is omitted in this example:

<SOAP-ENV:Body>
 <SOAP-ENV:Fault>
  <faultcode>SOAP-ENV:Server</faultcode>
  <faultstring>Server Application Error</faultstring>
  <detail>
     <error xmlns='https://www.myapp.org' >
       <text>ERROR #5002: ObjectScript error: <DIVIDE>zDivide^FaultEx.Service.1</text>
     </error>
  </detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>

Returning Custom SOAP Faults in an InterSystems IRIS Web Service

To create and return a custom SOAP fault, do the following within the appropriate area of your code that traps errors:

  1. Create a fault object that contains the appropriate information. To do so, call one of the following methods of your web service: MakeFault(), MakeFault12(), MakeSecurityFault(), or MakeStatusFault(). These are discussed in the following subsection.

    Or create a fault object manually, as described in later in this topic.

  2. Call the ReturnFault() method of the web service, passing the fault object as an argument. Note that ReturnFault()) does not return to its caller; it just sends the fault and terminates processing of the web method.

The following shows an example:

Method Divide(arg1 As %Numeric, arg2 As %Numeric) As %Numeric [ WebMethod ]
{
  Try {
    Set ans=arg1 / arg2
    } Catch {

        //<detail> element must contain element(s) or whitespace
        //specify this element by passing valid XML as string argument to MakeFault() 
        set mydetail="<mymessage>Division error detail</mymessage>"

        set fault=..MakeFault($$$FAULTServer,"Division error",mydetail)
        
        // ReturnFault must be called to send the fault to the client.
        // ReturnFault will not return here.
        Do ..ReturnFault(fault)
      }
  Quit ans
}

Methods to Create Faults

MakeFault()
classmethod MakeFault(pFaultCode As %String, 
                      pFaultString As %String, 
                      pDetail As %String = "", 
                      pFaultActor As %String = "") as %SOAP.Fault

Returns a fault object suitable for SOAP 1.1. Here:

  • pFaultCode is used within the <faultcode> element of the SOAP fault. Set this property equal to one of the SOAP 1.1 macros listed in Macros for SOAP Fault Codes.

  • pFaultString is used within the <faultstring> element of the SOAP fault. Specify a string that indicates the reason for the fault, as intended for users to see.

  • pDetail is used within the <detail> element of the SOAP fault. Use this to specify information about the cause of the fault.

    If specified, this argument should be a string containing valid XML that can be used within the <detail> element. InterSystems IRIS does not verify that the string you provide is valid; it is the responsibility of your application to check this.

  • pFaultActor specifies the URI of the SOAP node on the SOAP message path that caused the fault to happen.

    This is useful if the SOAP message travels through several nodes in the SOAP message path, and the client needs to know which node caused the error. It is beyond the scope of this documentation to discuss this advanced topic.

MakeFault12()
classmethod MakeFault12(pFaultCode As %String, 
            pFaultString As %String,
            pDetail As %String = "", 
            pFaultActor As %String = "") as %SOAP.Fault

Returns a fault object suitable for SOAP 1.2. Use this method only the SoapVersion property of the web service is "1.2". For a discussion of how InterSystems IRIS handles the SOAP versions of request messages, see Specifying Parameters of the Web Service.

For details on the arguments, see MakeFault().

MakeSecurityFault()
classmethod MakeSecurityFault(pFaultCode As %String, 
                              securityNamespace As %String) as %SOAP.Fault

Returns a fault object appropriate for a security failure. Specify FaultCode as one of the following: "FailedAuthentication", "FailedCheck", "InvalidSecurity", "InvalidSecurityToken", "SecurityTokenUnavailable", "UnsupportedAlgorithm", or "UnsupportedSecurityToken".

The namespace for this security fault is found in the SecurityNamespace property.

MakeStatusFault()
classmethod MakeStatusFault(pFaultCode As %String, 
                            pFaultString As %String, 
                            pStatus As %Status = "", 
                            pFaultActor As %String = "") as %SOAP.Fault

Returns a fault object based on a value in a %StatusOpens in a new tab object.

pStatus is the %StatusOpens in a new tab object to use.

For details on the other arguments, see MakeFault().

Macros for SOAP Fault Codes

The SOAP include file (%soap.inc) defines macros for some of the standard SOAP fault codes; these are listed in the following table. You can use these macros to specify SOAP fault codes. The table notes the version or versions of SOAP to which each macro applies.

ObjectScript Macros for SOAP Fault Codes
Macro SOAP Version(s) When to Use This Macro
$$$FAULTVersionMismatch 1.1 and 1.2 When the web service receives a SOAP message that contained an invalid element information item instead of the expected envelope element information item.

A mismatch occurs if either the namespace or the local name do not match.

$$$FAULTMustUnderstand 1.1 and 1.2 When the web service receives a SOAP message that contained an unexpected element that was marked with mustUnderstand="true"
$$$FAULTServer 1.1 When other server-side errors occur.
$$$FAULTClient 1.1 When the client made an incomplete or incorrect request.
$$$FAULTDataEncodingUnknown 1.2 When the arguments are encoded in a data encoding unknown to the receiver.
$$$FAULTSender 1.2 When the sender made an incomplete, incorrect, or unsupported request.
$$$FAULTReceiver 1.2 When the receiver cannot handle the message because of some temporary condition, for example, when it is out of memory.

Creating a Fault Object Manually

If you need more control than is given by the steps in the previous section, you can create and return a custom SOAP fault as follows:

  1. Create a fault object manually.

    To do so, create an instance of %SOAP.FaultOpens in a new tab (for SOAP 1.1) or %SOAP.Fault12Opens in a new tab (for SOAP 1.2) and then set its properties, as described in the following sections.

    Note:

    You can use %SOAP.FaultOpens in a new tab in all cases. If a web service receives a SOAP 1.2 request and needs to return a fault, the web service automatically converts the fault to SOAP 1.2 format.

  2. Call the ReturnFault() method of the web service, passing the fault object as an argument. Note that ReturnFault()) does not return to its caller; it just sends the fault and terminates processing of the web method.

SOAP 1.1 Faults

This section provides information on %SOAP.FaultOpens in a new tab, which represents SOAP 1.1 faults. This section includes the following:

Example SOAP Fault

For reference, here is an example of a SOAP 1.1 fault, including the SOAP envelope:

<SOAP-ENV:Envelope 
xmlns:SOAP-ENV='https://schemas.xmlsoap.org/soap/envelope/' 
xmlns:xsi='https://www.w3.org/2001/XMLSchema-instance' 
xmlns:s='https://www.w3.org/2001/XMLSchema' 
xmlns:flt="https://myfault.org" >
  <SOAP-ENV:Body>
    <SOAP-ENV:Fault>
      <faultcode>SOAP-ENV:Server</faultcode>
      <faultstring>Division error</faultstring>
      <detail><mymessage>Division error detail</mymessage></detail>
    </SOAP-ENV:Fault>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

%SOAP.Fault Properties

InterSystems IRIS represents a SOAP 1.1 fault as an instance of %SOAP.FaultOpens in a new tab, which has the following properties:

detail

Used within the <detail> element of the SOAP fault. Use this to specify information about the cause of the fault.

If specified, this argument should be a string containing valid XML that can be used within the <detail> element. InterSystems IRIS does not verify that the string you provide is valid; it is the responsibility of your application to check this.

faultcode

Used within the <faultcode> element of the SOAP fault. Set this property equal to one of the SOAP 1.1 macros listed in Macros for SOAP Fault Codes.

faultstring

Used within the <faultstring> element of the SOAP fault. Specify a string that indicates the reason for the fault, as intended for users to see.

faultactor

Specifies the URI of the SOAP node on the SOAP message path that caused the fault to happen.

This is useful if the SOAP message travels through several nodes in the SOAP message path, and the client needs to know which node caused the error. It is beyond the scope of this documentation to discuss this advanced topic.

faultPrefixDefinition

Specifies a namespace prefix declaration that is added to the envelope of the SOAP fault. Use a value of the following form:

xmlns:prefix="namespace"

Where prefix is the prefix and namespace is the namespace URI.

For example:

 set fault.faultPrefixDefinition = "xmlns:FLT=""https://myfault.com"""

The %SOAP.FaultOpens in a new tab class also provides the AsString() method, which returns the fault object as a string.

SOAP 1.2 Faults

This section provides information on %SOAP.Fault12Opens in a new tab and related classes, which represent SOAP 1.2 faults. This section includes the following:

Example SOAP Fault

For reference, here is an example of a SOAP 1.2 fault, including the SOAP envelope:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="https://www.w3.org/2003/05/soap-envelope" xmlns:flt="https://myfault.org">
  <SOAP-ENV:Body>
    <SOAP-ENV:Fault>
      <SOAP-ENV:Code>
        <SOAP-ENV:Value>SOAP-ENV:Receiver</SOAP-ENV:Value>
      </SOAP-ENV:Code>
      <SOAP-ENV:Reason>
        <SOAP-ENV:Text xml:lang="en">Division error</SOAP-ENV:Text>
        <SOAP-ENV:Text xml:lang="it">Errore di applicazione</SOAP-ENV:Text>
        <SOAP-ENV:Text xml:lang="es">Error del uso</SOAP-ENV:Text>
      </SOAP-ENV:Reason>
      <SOAP-ENV:Detail><mymessage>Division error detail</mymessage></SOAP-ENV:Detail>
    </SOAP-ENV:Fault>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

%SOAP.Fault12 Properties

The class %SOAP.Fault12Opens in a new tab represents a SOAP 1.2 fault. This class has the following properties:

Code

An instance of %SOAP.Fault12.CodeOpens in a new tab, discussed in the following section.

Detail

Used within the <detail> element of the SOAP fault. Use this to specify information about the cause of the fault.

If specified, this argument should be a string containing valid XML that can be used within the <detail> element. InterSystems IRIS does not verify that the string you provide is valid; it is the responsibility of your application to check this.

Node

Specifies the URI of the SOAP node on the SOAP message path that caused the fault to happen; optional for the destination node.

This is useful if the SOAP message travels through several nodes in the SOAP message path, and the client needs to know which node caused the error. It is beyond the scope of this documentation to discuss this advanced use of SOAP.

Reason

A list of instances of %SOAP.Fault12.TextOpens in a new tab, discussed in a following section. Each instance contains a reason string and a language code that indicates the language or locality of the reason string. These are used within the <Reason> element.

Role

Role that the node was operating in. See the preceding remarks for Node.

faultPrefixDefinition

Specifies a namespace prefix declaration that is added to the envelope of the SOAP fault. Use a value of the following form:

xmlns:prefix="namespace"

Where prefix is the prefix and namespace is the namespace URI.

For example:

 set fault.faultPrefixDefinition = "xmlns:FLT=""https://myfault.com"""

The %SOAP.Fault12Opens in a new tab class also provides the AsString() method, which returns the fault object as a string.

%SOAP.Fault12.Code Properties

You use %SOAP.Fault12.CodeOpens in a new tab as a value for the Code property of an instance of %SOAP.Fault12Opens in a new tab. The %SOAP.Fault12.CodeOpens in a new tab class has the following properties:

Subcode

An optional subcode.

Value

The value you provide depends on whether you have provided a subcode:

  • If you used a subcode, specify Value as a qname.

  • If you did not use a subcode, specify Value as one of the SOAP 1.2 macros listed in Macros for SOAP Fault Codes.

%SOAP.Fault12.Text Properties

You use %SOAP.Fault12.TextOpens in a new tab as a list element in the Reason property of an instance of %SOAP.Fault12Opens in a new tab. The %SOAP.Fault12.TextOpens in a new tab class has the following properties:

Text

A string indicating the reason for the fault, as intended for users to see.

lang

A code that corresponds to the language or locality in which the fault text is phrased. For information, see the W3 web site (https://www.w3.org/Opens in a new tab).

Adding WS-Addressing Header Elements When Faults Occur

Your InterSystems IRIS web service can add WS-Addressing header elements when faults occur. To do this, include the following additional steps within the fault handling of your web service:

  1. Choose a fault destination and a fault action to use in case of faults.

  2. Using these as arguments, call the GetDefaultResponseProperties() class method of %SOAP.Addressing.PropertiesOpens in a new tab. This returns an instance of %SOAP.Addressing.PropertiesOpens in a new tab that is populated with values as typically needed.

  3. Optionally set other properties of the instance of %SOAP.Addressing.PropertiesOpens in a new tab, as needed.

    For details, see the class documentation for %SOAP.Addressing.PropertiesOpens in a new tab.

  4. Set the FaultAddressing property of your web service equal to the instance of %SOAP.Addressing.PropertiesOpens in a new tab.

Adding Other Header Elements When Faults Occur

In addition to or instead of the options discussed in the previous section, your InterSystems IRIS web service can add custom header elements when faults occur. To do this:

  1. Create a subclass of %SOAP.HeaderOpens in a new tab. In this subclass, add properties to contain the additional data.

    See Adding and Using Custom Header Elements.

  2. Within the fault handling of your web service (as described earlier in this topic), include the following additional steps:

    1. Create an instance of your header subclass.

      Note:

      Despite the name of this class, this object is really a SOAP header element, not an entire header. A SOAP message has one header, which contains multiple elements.

    2. Set its properties as needed.

    3. Insert this header element into the FaultHeaders array property of the web service. To do so, call the SetAt() of that property. The key that you provide is used as the main header element name.

For example, consider the following custom header class:

Class Fault.CustomHeader Extends %SOAP.Header
{

Parameter XMLTYPE = "CustomHeaderElement";

Property SubElement1 As %String;

Property SubElement2 As %String;

Property SubElement3 As %String;

}

We could modify the web method shown previously as follows:

Method DivideAlt(arg1 As %Numeric, arg2 As %Numeric) As %Numeric [ WebMethod ]
{
  Try {
    Set ans=arg1 / arg2
    } Catch {

        //<detail> element must contain element(s) or whitespace
        //specify this element by passing valid XML as string argument to MakeFault() 
        set mydetail="<mymessage>Division error detail</mymessage>"

        set fault=..MakeFault($$$FAULTServer,"Division error",mydetail)

        //Set fault header
        Set header=##class(CustomHeader).%New()
        Set header.SubElement1="custom fault header element"
        Set header.SubElement2="another custom fault header element"
        Set header.SubElement3="yet another custom fault header element"
        Do ..FaultHeaders.SetAt(header,"CustomFaultElement")

        // ReturnFault must be called to send the fault to the client.
        // ReturnFault will not return here.
        Do ..ReturnFault(fault)
      }
  Quit ans
}

When the web client invokes the Divide() web method and uses 0 as the denominator, the web service responds as follows:

<?xml version='1.0' encoding='UTF-8' standalone='no' ?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV='https://schemas.xmlsoap.org/soap/envelope/' 
xmlns:xsi='https://www.w3.org/2001/XMLSchema-instance' 
xmlns:s='https://www.w3.org/2001/XMLSchema' xmlns:flt="https://myfault.org" >
  <SOAP-ENV:Header>
<CustomHeaderElement xmlns:hdr="https://www.mynamespace.org">
    <SubElement1>custom fault header element</SubElement1>
    <SubElement2>another custom fault header element</SubElement2>
    <SubElement3>yet another custom fault header element</SubElement3>
</CustomHeaderElement>
</SOAP-ENV:Header>
  <SOAP-ENV:Body>
...

Here line breaks were added for readability.

Handling SOAP Faults and Other Errors in an InterSystems IRIS Web Client

In an InterSystems IRIS web client, you can use the TRY-CATCH mechanism or the older $ZTRAP mechanism.

In either case, when an InterSystems IRIS web client receives an error, InterSystems IRIS sets the special variables $ZERROR and %objlasterror:

  • If the error is a SOAP fault, the value of $ZERROR starts with <ZSOAP>, and %objlasterror contains the status error that is formed from the received SOAP fault.

    In addition, the client instance has a property named SoapFault, which is an instance of %SOAP.FaultOpens in a new tab or %SOAP.Fault12Opens in a new tab (depending on the SOAP version used in the web service). You can use the information in this property. For more information on %SOAP.FaultOpens in a new tab and %SOAP.Fault12Opens in a new tab, see the previous sections.

  • If the error is not a SOAP fault, use your normal error handling (typically using $ZERROR). It is your responsibility to specify how to proceed.

Example 1: Try-Catch

The following method uses TRY-CATCH:

ClassMethod Divide(arg1 As %Numeric, arg2 As %Numeric) As %Numeric
{
    Set $ZERROR=""
    Set client=##class(FaultClient.DivideSoap).%New()

    Try {
        Set ans=client.Divide(arg1,arg2)
        }
    Catch {
        If $ZERROR["<ZSOAP>" {
            Set ans=%objlasterror
            } 
            Else {
            Set ans=$$$ERROR($$$ObjectScriptError,$ZERROR)
        }
    }
    
    Quit ans
}

This method uses system macros defined in the %systemInclude include file, so the class that contains this method starts with the following:

Include %systemInclude 

Example 2: $ZTRAP

The following example uses the older $ZTRAP mechanism. In this case, when an InterSystems IRIS web client receives an error, control is transferred to the label indicated by the $ZTRAP special variable (if that label is defined).

ClassMethod DivideWithZTRAP(arg1 As %Numeric = 1, arg2 As %Numeric = 2) As %Numeric
{
    Set $ZERROR=""
    Set $ZTRAP="ERRORTRAP"
    Set client=##class(FaultClient.DivideSoap).%New()
    Set ans=client.Divide(arg1,arg2)
    Quit ans
 
    //control goes here in case of error
ERRORTRAP 
    if $ZERROR["<ZSOAP>" 
    {
         quit client.SoapFault.Detail
        } 
    else 
    {
        quit %objlasterror
       }
}

SSL Handshake Errors

If an InterSystems IRIS web client uses an SSL connection and a SSL handshake error has occurred, then the SSLError property of the client contains text that describes the SSL error.

FeedbackOpens in a new tab