Defines a final end block for any 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 its END statement.
For any
ABL block statement, the FINALLY statement defines an optional end
block that contains ABL code to execute at the conclusion of all
other processing in the associated block or once at the conclusion
of each iteration of an associated iterating block. This is the
syntax for the FINALLY statement and its related blocks:
Syntax
block-statements
FINALLY :
finally-logic
END [ FINALLY ] .
[ block-end-statement ]
|
-
block-statements
- All of the statements of an enclosing associated ABL block, including
an external procedure block, except for its block-end-statement. The enclosing associated block can be any ABL block,
including another FINALLY block
-
finally-logic
- All statements allowed in a FINALLY block, which can include any valid
ABL statement. For more information on FINALLY block execution, see the Notes for this reference
entry.
-
block-end-statement
- For all associated ABL blocks except a main external procedure block,
the END statement terminating the enclosing associated block of the
FINALLY block. External procedure blocks have no terminating END statement.
Examples
As
shown in r-finally01.p, the FINALLY block executes before
any flow-of-control (LEAVE, NEXT, RETRY, RETURN, or THROW) options
are executed for the associated block. For iterating blocks, the
FINALLY block executes after each iteration of the block.
r-finally01.p
DO ON ERROR UNDO, LEAVE:
/* Since Customer 1000 does not exist, the FIND statement raises ERROR and
execution goes to the FINALLY block before the LEAVE option executes. */
FIND Customer 1000.
MESSAGE "This message never appears because of ERROR condition."
VIEW-AS ALERT-BOX BUTTONS OK.
FINALLY:
MESSAGE "Inside FINALLY block." VIEW-AS ALERT-BOX BUTTONS OK.
/* LEAVE DO block here */
END FINALLY.
END. /* DO */
MESSAGE "Out of DO block." VIEW-AS ALERT-BOX BUTTONS OK.
|
In r-finally02.p, after
ERROR is raised, execution goes to the CATCH block and then to the
FINALLY block.
r-finally02.p
DO ON ERROR UNDO, LEAVE:
/* Since Customer 1000 does not exist, the FIND statement raises ERROR and
execution goes to CATCH block. */
FIND Customer 1000.
MESSAGE "This message never appears because of ERROR condition."
VIEW-AS ALERT-BOX BUTTONS OK.
CATCH eSysError AS Progress.Lang.SysError:
/* Handler code for SysError condition */
MESSAGE "Inside CATCH block." VIEW-AS ALERT-BOX BUTTONS OK.
/* Execution goes to FINALLY before leaving DO block. */
END CATCH.
FINALLY:
/* Your code */
MESSAGE "Inside FINALLY block." VIEW-AS ALERT-BOX BUTTONS OK.
/* LEAVE DO block here. */
END FINALLY.
END. /* DO */
MESSAGE "Out of DO block." VIEW-AS ALERT-BOX BUTTONS OK.
|
In r-finally03.p, after
ERROR is raised, execution goes to the CATCH block, which re-throws
the error. However, the FINALLY block executes before the error
goes to the CATCH block associated with the procedure block.
r-finally03.p
DO ON ERROR UNDO, LEAVE:
/* Since Customer 1000 does not exist, the FIND statement raises ERROR and
execution goes to CATCH block. */
FIND Customer 1000.
MESSAGE "This message never appears because of ERROR condition."
VIEW-AS ALERT-BOX BUTTONS OK.
CATCH eSysError AS Progress.Lang.SysError:
/* Handler code for SysError condition */
MESSAGE "Inside CATCH block." VIEW-AS ALERT-BOX BUTTONS OK.
/* Execution goes to FINALLY before leaving DO block. */
UNDO, THROW eSysError.
END CATCH.
FINALLY:
/* Your code */
MESSAGE "Inside FINALLY block." VIEW-AS ALERT-BOX BUTTONS OK.
END FINALLY.
END. /* DO */
CATCH eSysError AS Progress.Lang.SysError:
MESSAGE "Out of DO block and inside CATCH block for procedure block"
VIEW-AS ALERT-BOX BUTTONS OK.
END CATCH.
|
Notes
- There
can be only one FINALLY block in any associated block. The FINALLY
statement must come after all other executable statements in the
associated block. If the associated block contains CATCH statements,
the FINALLY block must come after all CATCH blocks. Note that the
FINALLY statement can be used in a block with no CATCH blocks.
- The FINALLY block executes as an end block of the associated block. This
means that the FINALLY block cannot execute until the associated block executes. The
FINALLY block executes once for each iteration of its associated block. This means you can
only execute the FINALLY block during the execution of the associated block. The FINALLY
block executes on success or failure of the associated block. However, the FINALLY block
also does not execute under certain conditions.
Thus, the FINALLY
block executes:
- After successful execution of the associated block
- After each successful iteration of an iterating associated
block
- After ERROR is raised in the associated block and a CATCH block
handles the error
- After ERROR is raised in the associated block and no CATCH handles
the error
The FINALLY block will not execute:
- If a STOP condition is raised within, but not handled by the
associated block
- If a QUIT statement within the associated block is in effect, but
its QUIT condition is not handled by the associated block
- The purpose of a FINALLY block is to hold clean-up code that
must execute regardless of what else executed in the associated
block. It can include code to delete objects and dynamic objects,
write to logs, close outputs, and other routine tasks. Because it
executes even if the ERROR condition is raised, the FINALLY block
is also a useful part of a structured error handling scheme.
- Since it executes after an invoked CATCH block, the FINALLY
block can also be used to perform common post-CATCH clean up tasks,
rather than repeating common code in all the CATCH blocks present
in the associated block.
- The transaction of the associated block is either complete (success)
or undone (failure) when FINALLY executes. Therefore, any UNDO statement
within the FINALLY block will only undo the work in the FINALLY block.
- The FINALLY block is an undoable block with implicit ON ERROR UNDO,
THROW error handling, and like all blocks, FINALLY blocks implicitly throw all stop
objects. You cannot explicitly override the ON ERROR directive for a FINALLY block. If a
statement within the FINALLY block raises ERROR, the FINALLY block will be undone, and
ERROR will be raised in the block that encloses the associated block of the FINALLY block.
Error is not raised in the associated block. Otherwise, infinite looping could occur. The
same is true if the FINALLY block raises STOP.
Thus, a statement that
raises ERROR or STOP within a FINALLY end block causes the following to occur:
- UNDO the FINALLY block.
- LEAVE the FINALLY block and its associated block.
- THROW the error or stop object to the block enclosing its associated
block. If the FINALLY block is at the routine level, the error or stop object gets
thrown to the caller of the routine.
The same behavior occurs for an explicit UNDO, THROW statement in
a FINALLY block.
- The code in any FINALLY block can contain explicit flow-of-control options:
LEAVE, NEXT, RETRY, RETURN, or THROW. Since FINALLY is an undoable
block, LEAVE, NEXT, and RETRY without a label apply to the FINALLY
block itself and not to the associated block.
If you want LEAVE,
NEXT, or RETRY to apply to the associated block, use label syntax
with these statements. Flow of control statements in a FINALLY block
override pending flow of control from a CATCH block.
- When the flow of control statements LEAVE, NEXT, RETRY, and RETURN
appear in a FINALLY block, they do not override an error or stop object thrown from the
associated block. An error or stop object thrown from the associated block takes
precedence.
- If a function or non-VOID method contains a FINALLY block, and the
FINALLY block contains a RETURN statement with a return value that
conflicts with the RETURN statement in the main block of the function
or method, the return value set in the FINALLY block takes precedence.
- If a function or non-VOID method throws an error from its main block
(including the result of a RETURN ERROR statement), and the function
or method also contains a FINALLY block with a RETURN statement,
the error is ignored and the return value from the FINALLY block is
set.
- If the AVM detects an unhandled STOP or QUIT condition in the associated
block, the FINALLY block does not run and the AVM processes the condition. If the
associated block has an ON STOP or ON QUIT phrase, or a compatible stop CATCH block, the
corresponding STOP or QUIT condition is handled and released by the time the AVM is ready
to execute the FINALLY block, and the FINALLY block executes. See the ON STOP phrase and
CATCH statement reference entries for a description of STOP condition behavior and
handling. See the ON QUIT phrase reference entry for a description of QUIT condition
behavior and handling.
- Stop object support is available as a Technology Preview only in
OpenEdge Release 11.7.