Thrown Fault with Catchall
When a <throw> statement executes, its fault value is an expression that evaluates to a string. Faults are not objects, as in other object-oriented languages such as Java; they are string values. When you specify a fault string it needs the extra set of quotes to contain it, as shown below:
<throw fault='"thrown"'/>
When a <throw> statement executes, control immediately goes to the <faulthandlers> block inside the same <scope>, skipping all intervening statements after the <throw>. Inside the <faulthandlers> block, the program attempts to find a <catch> block whose value attribute matches the fault string expression in the <throw> statement. This comparison is case-sensitive.
If there is a <catch> block that matches the fault, the program executes the code within this <catch> block and then exits the <scope>. The program resumes execution at the next statement following the closing </scope> element.
If a fault is thrown, and the corresponding <faulthandlers> block contains no <catch> block that matches the fault string, control goes from the <throw> statement to the <catchall> block inside <faulthandlers>. After executing the contents of the <catchall> block, the program exits the <scope>. The program resumes execution at the next statement following the closing </scope> element. It is good programming practice to ensure that there is always a <catchall> block inside every <faulthandlers> block, to ensure that the program catches any unanticipated errors.
Suppose you have the following BPL. For reasons of space, the <start> and <end> elements are not shown.
This BPL business process does the following:
-
The first <trace> element generates the message before scope.
-
The <scope> element starts the scope.
-
The second <trace> element generates the message before assign.
-
The <throw> element throws a specific, named fault ("MyFault").
-
Control now goes to the <faulthandlers> defined within the <scope>. The <scope> rectangle includes a horizontal dashed line across the middle; the area below this dashed line displays the contents of the <faulthandlers> element. In this case, there is no <catch> but there is a <catchall> element, so control goes there.
Note that InterSystems IRIS skips the third <trace> element.
If we drill down into <catchall>, we see this:
-
Within <catchall>, the first <trace> element generates the message in catchall faulthandler.
-
Within <catchall>, the second <trace> element generates the message that provides information on the fault using $System.Status methods and the special variables %Context and %LastError. The %LastError value as the result of a thrown fault is different from its value as the result of a system error:
-
Within <catchall>, the third <trace> element generates a message that provides information on the fault using the BPL context variable %LastFault. It contains the text derived from the fault expression from the <throw> statement.
-
The <scope> ends.
-
The last <trace> element generates the message after scope.
Event Log Entries
The corresponding Event Log entries look like this:
XData for This BPL
This BPL is defined by the following XData block:
XData BPL
{
<process language='objectscript'
request='Test.Scope.Request'
response='Test.Scope.Response' >
<sequence>
<trace value='"before scope"'/>
<scope>
<trace value='"before assign"'/>
<throw fault='"MyFault"'/>
<trace value='"after assign"'/>
<faulthandlers>
<catchall>
<trace value='"in catchall faulthandler"'/>
<trace value=
'"%LastError "_
$System.Status.GetErrorCodes(..%Context.%LastError)_
" : "_
$System.Status.GetOneStatusText(..%Context.%LastError)'
/>
<trace value='"%LastFault "_..%Context.%LastFault'/>
</catchall>
</faulthandlers>
</scope>
<trace value='"after scope"'/>
</sequence>
</process>
}