CATCH statement
Defines an error-handling end block for any undoable ABL block. An end block is an ABL block that can occur only within another block. The block containing the end block is known as the associated block. End-blocks must occur between the last line of executable code in the associated block and the END statement.
The CATCH end block executes when an error raised in the associated block is compatible with the error type specified in the CATCH block. To be compatible, the error type must be the error type specified in the CATCH statement, or it must be a sub-type (sub-class) of the specified type. CATCH blocks take precedence over any implicit or explicit ON ERROR directives for the associated block. This is the syntax for the CATCH statement and its related blocks:
Syntax
block-statements
error-variable
The variable name that references the error object generated by the error condition. Typically, you do not define theerror-variable
ahead of time with the DEFINE VARIABLE statement. The AVM recognizes a new variable name on the CATCH statement as a newerror-variable
definition. Each CATCH in an associated block must have a uniqueerror-variable
. You can reuse anerror-variabl
e name in a different associated block, as long as its type is compatible with the new definition.[ CLASS ]error-class
catch-logic
block-end-statement
ExamplesThe following code fragment shows CATCH blocks for associated DO blocks:
In the following example, the CATCH block will catch any ABL system error:
Notes
- One or more CATCH blocks are positioned at the end of the associated block. If a FINALLY end block is also used, the CATCH blocks comes before the FINALLY block. The syntax for an associated block using end blocks is as follows:
Note that a CATCH block can also contain a CATCH or FINALLY block, just as a FINALLY block can contain a CATCH or FINALLY block. For more information on FINALLY blocks, see the FINALLY statement reference entry.Thus, the following blocks can have a CATCH block:- ABL issues a compile-time error if a CATCH end block is present in a simple
DO
block, since simpleDO
blocks do not have error handling capabilities.DO
blocks must have either TRANSACTION or an ON ERROR directive in order to have a CATCH. For example:
- The code within a CATCH block is only executed if an ERROR of type
error-class
(or a sub-type) is raised within the body of the associated block. This behavior is also true if any sub-routine called by the associated block returns or raises an error of typeerror-class
. WhenERROR
is raised, if there is an active transaction, the associated block is undone before the AVM begins executing the statements within the CATCH block.- An associated block may have multiple CATCH blocks, each of which handles a different error class. If an error type satisfies multiple CATCH statements, the AVM will execute the code in the first CATCH block that matches the error type. It will not execute multiple CATCH blocks. Therefore, if multiple CATCH blocks are specified, the CATCH block for the more specialized error classes should come first, as shown:
- The compiler will issue a warning message if a block contains a CATCH block that is not reachable. For example, the following code will cause the compiler to issue a warning, since the CATCH of
myAppError
can never be executed:
- It is valid to have both an explicit ON ERROR directive and a CATCH on the same associated block. You might want to CATCH certain error types and handle them directly, and have all other error types handled by the ON ERROR directive of the associated block.
If error is raised in a block and is not handled by a CATCH block, then the error is handled by the ON ERROR directive of the associated block. This could be an explicit ONERROR phrase, or the implicit (default) ON ERROR directive for the block type.
- A CATCH block can have a
CATCH
block within it. In this case, the contained CATCH block only handles errors raised within the CATCH block. To prevent infinite looping, any UNDO, THROW statement within the top-level CATCH block or any CATCH block nested within it immediately throws the error to the block that contains the associated block of the top-level CATCH block. For example:
- The CATCH block is an end block of its associated block. A CATCH block can only execute after the execution (or each iteration) of the associated block. The CATCH block only executes when error is raised in the associated block and the CATCH error type is compatible with the type of the raised error. Any transaction within the associated block will be undone and records will be released before the CATCH block executes.
- The CATCH block is an undoable block with implicit ON ERROR UNDO, THROW error handling. You cannot explicitly override the ON ERROR directive for a CATCH block. If a statement within the CATCH block raises ERROR and there is no nested CATCH block, the CATCH block will be undone, and the ERROR will be raised in the block that encloses the associated block of the CATCH. So a statement that raises ERROR within a CATCH end block causes the following to occur:
The same behavior occurs for an explicit UNDO, THROW statement in a CATCH block. For example:
- If there is a FINALLY block in the associated block, the FINALLY code will be executed before ERROR gets raised in the block enclosing the associated block.
- The scope of buffers referenced in a CATCH block is the smallest enclosing block outside of the associated block that encompasses all references to the buffer.
In this example, DO TRANSACTION and CATCH both reference the Customer buffer:
As the result of the reference to the Customer buffer in the CATCH block in the previous example, the scope of the Customer buffer is raised to the procedure level (myproc.p), since the smallest enclosing block of the DO TRANSACTION is the procedure block.- The code in any CATCH block can contain an explicit flow-of-control directive, meaning LEAVE, NEXT, RETRY, RETURN, or THROW. (RETRY and THROW require UNDO.) Since CATCH is an undoable block, LEAVE, NEXT, and RETRY without a label will apply to the CATCH block itself and not the associated block.
If you want LEAVE, NEXT, or RETRY to apply to the associated block of a CATCH block, you must use the existing label syntax for these statements.An explicit UNDO, THROW in a CATCH block causes the AVM to raise ERROR in the block that encloses the associated block of the CATCH block; not the associated block itself.In this example, LEAVE in the CATCH applies to the CATCH:
In this example, the procedure gives the user three chances to get the right order number:
In this example, LEAVE the FOR EACH in the occurrence of aPrinterDown
application error:
If there is no explicit flow-of-control statement in the CATCH block, the AVM will leave the CATCH block and execute the default error action for the associated block after executing the last statement in the CATCH block and any code within a FINALLY block. This means RETRY for all blocks. When no input blocking statements are present, the AVM prevents infinite looping by changing the RETRY to NEXT for iterating blocks or LEAVE for non-iterating blocks.Note: For more information on infinite loop protection in error handling, see OpenEdge Getting Started: ABL Essentials.In the following code, if an Acme.Error.myAppError is caught the explicit UNDO, THROW statement causes the caught error to be thrown to the block enclosing the FOR EACH (remember that UNDO, THROW in a CATCH means leave associated block, then throw). However, if a Progress.Lang.SysError is caught the AVM will execute a NEXT on the FOR EACH block. For example:
- The presence of a CATCH in an undoable block causes the AVM to suppress Progress system error messages for all statements within the block, in the same way that NO-ERROR works on individual statements. If there is a CATCH on Progress.Lang.SysError, the message(s) will be added to the Progress.Lang.SysError object that is available in the CATCH. If there is no CATCH on Progress.Lang.SysError, and the Progress.Lang.SysError is not re-thrown (by way of ON ERROR UNDO, THROW on the block), the error messages from the Progress.Lang.SysError will be written to the current output destination and the AVM will execute the ON ERROR directive for the block.
In this example, a CATCH handles the error and the error message is suppressed:
In this example, there is no CATCH block that handles the error and the error message is not suppressed:
See alsoON ERROR phrase, RETURN statement, ROUTINE-LEVEL ON ERROR UNDO, THROW statement, UNDO statement
OpenEdge Release 10.2B
|