ABL Structured Error Handling: Mike Fechner, Consultingwerk Ltd. Mike - Fechner@consultingwerk - de

Download as pdf or txt
Download as pdf or txt
You are on page 1of 69

ABL Structured Error Handling

Mike Fechner, Consultingwerk Ltd.


[email protected]
ABL Structured Error Handling 2
Consultingwerk Ltd.

▪ Independent IT consulting organization


▪ Focusing on OpenEdge and related technology
▪ Located in Cologne, Germany, subsidiary in UK
▪ Customers in Europe, North America, Australia and South Africa
▪ Vendor of developer tools and consulting services
▪ 28 years of Progress experience (V5 … OE11)
▪ Specialized in GUI for .NET, Angular, OO, Software Architecture,
Application Integration

http://www.consultingwerk.de/ 3
Agenda

▪ Traditional/Classic Error Handling recap


▪ Structured Error Handling
▪ Combining Structured and Classic Err. Handling
▪ STOP Conditions
▪ Error Handling best practices

ABL Structured Error Handling 4


Runtime „conditions“

▪ (Runtime) Error

▪ Application Error

▪ Stop Conditions

▪ Quit Conditions

ABL Structured Error Handling 5


Classic Error Handling

▪ Block oriented error handling


▪ Error handling directives (ON ERROR …)
▪ Intuitively used by experienced ABL developers
▪ Made more sense in TTY data entry

▪ NO-ERROR option on a number of statement


▪ ERROR-STATUS System Handle
▪ RETURN ERROR <return value>
▪ NO-UNDO for variables and temp-tables
ABL Structured Error Handling 6
Error handling sequence in a block

▪ Stops execution of current block

▪ Display error message

▪ Undo transaction or sub-transaction (if present)

▪ Branch action (RETRY, LEAVE, NEXT)


ABL Structured Error Handling 7
Default branching options per block type

(CATCH/
FINALLY)

ABL Structured Error Handling 8


Routine-level blocks

▪ .p file, .w file
▪ Internal procedure
▪ User-defined function
▪ Database trigger
▪ User-interface trigger
▪ Class method, including
– Constructor
– GET/SET
– Destructor
ABL Structured Error Handling 9
ABL Structured Error Handling 10
ABL Structured Error Handling 11
ABL Structured Error Handling 12
ABL Structured Error Handling 13
Classic Error Handling Issues

▪ Default Branching not always optimal for non TTY UI processing

ABL Structured Error Handling 14


Classic Error Handling Issues

▪ Calling statements with NO-ERROR leaves ERROR-STATUS


behind
▪ ERROR-STATUS:ERROR and RETURN-VALUE need to be reset
by
– ERROR-STATUS:ERROR = FALSE NO-ERROR
– RETURN "" .
▪ Otherwise confusing if (pending) error was already handled or not

ABL Structured Error Handling 15


Agenda

▪ Traditional/Classic Error Handling recap


▪ Structured Error Handling
▪ Combining Structured and Classic Err. Handling
▪ STOP Conditions
▪ Error Handling best practices

ABL Structured Error Handling 16


Structured Error Handling

▪ Alternative way of handling errors in the ABL


▪ Adds error handling constructs known form OO languages such
as C# and Java to the ABL
▪ Based on OO-ABL elements
▪ Usable and useful with procedural code without exception (such
as classic error handling can be used in OO)
▪ Available since 10.1C, enhanced in 10.2A (garbage collection),
11.3 (block-level default), 11.4 (serializable error classes), 11.7
(stop-conditions)

ABL Structured Error Handling 17


FINALLY

▪ Clean up code block, can be attached to the end of every


undoable block
▪ Executed when block succeeds, errors, executed per iteration of
block (loops)
▪ Can be nested
▪ Available since 10.1C

▪ Must use! For everyone using dynamic queries etc… every code
that requires clean up at runtime

ABL Structured Error Handling 18


It should become your routine
to add FINALLY Block close
enough to CREATE object
statement

ABL Structured Error Handling 19


CATCH

▪ Block to handle runtime errors in the surrounding block


▪ When error occurs:
– Block execution (iteration) stops
– Transaction or sub-transaction undone
– CATCH block execution
▪ CATCH Block allows to inspect the error
▪ Any undoable block is a TRY block (no explicit TRY block needed
in the ABL)

ABL Structured Error Handling 20


ABL Structured Error Handling 21
CATCH

▪ CATCH block filters errors by type


▪ Multiple CATCH blocks can handle specific errors
▪ Should order CATCH blocks by specific to generic types
▪ First CATCH block matching the error that occurs handles it,
following CATCH blocks will not handle the error

ABL Structured Error Handling 22


ABL Structured Error Handling 23
Error classes
class Progress.Lang

Obj ect

inherits

«interface»
«.NET» Error ProError
System.Exception implements implements

inherits inherits inherits

SysError AppError SoapFaultError

ABL Structured Error Handling 24


ABL Structured Error Handling 25
ABL Structured Error Handling 26
Custom Error Class

ABL Structured Error Handling 27


CATCH Custom Error

ABL Structured Error Handling 28


Demo

▪ Locate Consultingwerk.Exceptions.Exception in
http://help.consultingwerkcloud.com/smartcomponent_library/rele
ase/

ABL Structured Error Handling 29


Raising errors … THROW

▪ DEFINE VARIABLE err AS <myerror> .


err = NEW <myerror> (parameter) .
err:CustomProperty = 42 .
UNDO, THROW err .

▪ UNDO, THROW NEW <myerror> (parameter) .

▪ RETURN ERROR NEW <myerror> (parameter) .

ABL Structured Error Handling 30


AppError constructors

▪ NEW AppError ()
▪ NEW AppError (CHARACTER)
▪ NEW AppError (CHARACTER, INTEGER)

▪ Attention: AppError (CHARACTER) and AppError


(CHARACTER, INTEGER)
behave differently
▪ Signature suggest the INTEGER
is for an optional parameter

ABL Structured Error Handling 31


AppError constructors

▪ UNDO, THROW NEW AppError


(„this text is NOT shown“) .
▪ UNDO, THROW NEW AppError
(„this text is shown to the user“, 42) .
▪ First statement initializes an AppError with a ReturnValue
assigned (RETURN ERROR)
▪ Second statement initializes an AppError with a message and
severity/number assigned!
▪ AVM only displays errors with message
ABL Structured Error Handling 32
ABL Structured Error Handling 33
THROW Branch option on blocks …

▪ <block statement> ON ERROR UNDO, THROW:


▪ FOR EACH Customer ON ERROR UNDO,
THROW

▪ When errors occur in the block, pass error for


handling to next outer block
– Next outer block may also throw
▪ Iterating block will NOT iterate any further
▪ First error terminates everything
▪ No more infinitive loops caused by errors!
ABL Structured Error Handling 34
ABL Structured Error Handling 35
Problem: UNDO, THROW from routine

ABL Structured Error Handling 36


Problem: UNDO, THROW from routine

UNDO, THROW

ABL Structured Error Handling 37


ROUTINE-LEVEL ON ERROR UNDO, THROW

▪ Declarative statement, available since 10.1C


▪ Must be placed before any executable statements, including
DEFINE‘s
▪ May be after USING

▪ Changes ERROR Branching option for ALL routine blocks in


compile unit to ON ERROR UNDO, THROW
▪ No effect on loops, DO TRANSACTION, DO ON ERROR

ABL Structured Error Handling 38


ABL Structured Error Handling 39
BLOCK-LEVEL ON ERROR UNDO, THROW

▪ Declarative statement, available since 11.3


▪ Must be placed before any executable statements, including
DEFINE‘s
▪ May be after USING

▪ Changes default ERROR Branching option for ALL blocks in


compile unit to ON ERROR UNDO, THROW
▪ May be redefined on loops, DO TRANSACTION, DO ON ERROR
▪ Make this your default for new code, when on 11.3 +
ABL Structured Error Handling 40
ABL Structured Error Handling 41
BLOCK-LEVEL ON ERROR UNDO, THROW

▪ Don’t get used to BLOCK-LEVEL ON ERROR when still deploying


to 10.1C – 11.2
▪ Don’t switch between ROUTINE-LEVEL and BLOCK-LEVEL
using PROVERSION preprocessor

▪ Error handling should be tested during development


▪ And behave 100% the same way at runtime
▪ Surprises in error handling are expensive …

ABL Structured Error Handling 42


Re-THROW

ABL Structured Error Handling 43


Re-THROW of Progress.Lang.SysError

▪ Runtime error often the root cause for application raised error
▪ Application raised error may be adding context

▪ Unexpected SysError should be re-thrown

▪ Developers need to “track” possible runtime error numbers


themselves – as no (complete) list of errors expected per ABL
statement or Widget method is available
▪ Attention: Error message numbers may change with new
Openedge releases (like DYNAMIC-INVOKE in 11.6)
ABL Structured Error Handling 44
Agenda

▪ Traditional/Classic Error Handling recap


▪ Structured Error Handling
▪ Combining Structured and Classic Err. Handling
▪ STOP Conditions
▪ Error Handling best practices

ABL Structured Error Handling 45


Combining Structured and Classic Err. Hndl

▪ THROW and classic error handling fully compatible


▪ AppError or any of the runtime error handled based on branch
action of receiving block:
– RETRY
– NEXT
– LEAVE
– RETURN

ABL Structured Error Handling 46


ON ERROR UNDO, RETRY
Because of FRAME based UI

ABL Structured Error Handling 47


ON ERROR UNDO, RETRY
Because of FRAME based UI

ABL Structured Error Handling 48


Combining Structured and Classic Error Handling

▪ All errors available through ERROR-STATUS system handle


▪ AppError with ReturnValue same impact as RETURN ERROR
<return-value>

ABL Structured Error Handling 49


Recommendation

▪ Do not add ROUTINE-LEVEL or BLOCK-LEVEL Error Handling to


existing code without testing!
▪ Users may be used to executing reports with a few „Item record
not on file“ messages
▪ Adding ROUTINE-LEVEL or BLOCK-LEVEL error handling will
severely impact the program flow!
▪ Users may not be able to receive the report they need to get their
job done – and may have only little understanding for a developer
now happy with better error handling

ABL Structured Error Handling 50


Agenda

▪ Traditional/Classic Error Handling recap


▪ Structured Error Handling
▪ Combining Structured and Classic Err. Handling
▪ STOP Conditions
▪ Error Handling best practices

ABL Structured Error Handling 51


STOP Conditions

▪ Critical system error


▪ RUN non-existing .p file
▪ .r code CRC does not match schema
▪ trigger r. code not matching the CRC stored in DB schema
▪ DB connection missing/lost
▪ …
▪ STOP-AFTER (unfortunately)

ABL Structured Error Handling 52


STOP Condition handling

▪ UNDO blocks until it reaches an ON STOP Block


▪ AVM may decide to skip ON STOP and proceed with reverting …
▪ Eventually may restart client startup procedure

▪ FINALLY Blocks are NOT executed!


– (change in OpenEdge 11.7!!!)

ABL Structured Error Handling 53


Convert STOP into AppError

▪ STOP can be handled by RETURN ERROR


▪ FINALLY will be executed

ABL Structured Error Handling 54


Handling of STOP Conditions (OpenEdge 11.7)

▪ Technology preview of handling STOP conditions based on


structured error handling added in OpenEdge 11.7
▪ Public beta test for that feature
▪ -catchStop 1 Startup Parameter, requires recompilation

▪ It is expected that in OpenEdge 12 –catchStop 1 becomes the


new default

ABL Structured Error Handling 55


STOP Condition Handling classes

▪ No Progress.Lang.Error
– Progress.Lang.Stop - STOP Statement
– Progress.Lang.LockConflict - -lkwtmo exceeded
– Progress.Lang.StopAfter - STOP-AFTER exceeded
– Progress.Lang.UserInterrrupt - CTRL-BREAK

▪ Progress.Lang.Error derived
– Progress.Lang.StopError - RUN invalid.p, etc.

ABL Structured Error Handling 56


ABL Structured Error Handling 57
Agenda

▪ Traditional/Classic Error Handling recap


▪ Structured Error Handling
▪ Combining Structured and Classic Err. Handling
▪ STOP Conditions
▪ Error Handling best practices

ABL Structured Error Handling 58


Errors should be exceptional

▪ Errors are called “Exception” in .NET and Java

▪ Don‘t use errors as alternative RETURN-VALUE


▪ Errors should not happen on a regular basis
▪ Error handling is an relatively expensive operation
▪ Block-Transaction will be undone in every case

ABL Structured Error Handling 59


CATCH in every Event handlers

▪ When using structured error handling, every UI event handler


should have a CATCH
– Classic ABL GUI
– TTY
– GUI for .NET
▪ If you don’t show messages by then the AVM will do
▪ Only way to create nice and feature-rich error dialog

ABL Structured Error Handling 60


ABL Structured Error Handling 61
CATCH in worker methods

▪ Non UI code, batch routines, code that is calculating values etc.


▪ Worker methods on the other end, should not show error
messages, all errors should be thrown
▪ Worker methods should only CATCH error that can be handled
with no user interaction
– open query if not open, then re-run
– delete dynamic query widget, when QUERY-PREPARE-
FAILED
– perform any kind of useful alternative action or clean-up on
error
ABL Structured Error Handling 62
Avoid NO-ERROR

▪ This cannot be handled with a CATCH block

▪ hQuery:QUERY-PREPARE (“…”) NO-ERROR

▪ Only way to handle this is ERROR-STATUS:ERROR or explicit


checks
– IF AVAILABLE Customer

▪ ERROR-STATUS:ERROR valid until next statement is executed


with NO-ERROR
ABL Structured Error Handling 63
InnerException Pattern

▪ Known from .NET


▪ Useful to „upgrade“ certain runtime errors to application errors
(similar to RE-THROW)
▪ Keep original error information, such as Stack-Trace,
ReturnValue, error messages, custom properties
▪ When error happens, it happens, … all I can do in some locations
is to add context data, to simplify debugging
▪ See Consultingwerk.Exceptions.Exception and DataAccess class

ABL Structured Error Handling 64


ABL Structured Error Handling 65
Code Review

▪ Consultingwerk.Exceptions.Exception
– InnerException Implementation
– SessionInfo from AppServer to Client

ABL Structured Error Handling 66


Assertions

▪ Concept for validating method parameters


▪ Verify a value
▪ Throw an error when expected condition is not met
▪ Static methods
▪ Simple way to provide consistent errors for common issues

ABL Structured Error Handling 67


Example from BufferAssert

▪ Consultingwerk.Assertion.BufferAssert:HasField (hBuffer,
“CustNum”) .

ABL Structured Error Handling 68


Questions?

http://www.consultingwerk.de/ 69

You might also like