Progress Programming Tips

By Rod Gaither (rdg@worldinfo.com)


PPT-18  Error processing issues

Tip:

[Warning - long topic]

Professional applications need to handle errors and unknown
situations in a consistent and controlled manner.  For the most
part I am talking about application errors here while touching
on some system error situations.  Managing these problems such
that the application can either recover or at least exit
gracefully is what makes a robust application.  Below are some
areas for concern and some options for error processing. This
is by no means an exhaustive list but gives a decent grounding
in what error handling is about.


1. Error control for blocks in Progress

Before any effort at error management can be attempted you need
to be aware of what Progress brings to the table to help you.
These tools include error control options for block constructs
- DO, REPEAT, FOR EACH, PROCEDURE/TRIGGER, the database
transaction services, and your own programming efforts.

These block properties allow you to tell Progress to take
specific block level actions - UNDO then RETRY, LEAVE, NEXT or
RETURN when the Progress ERROR condition is raised.  To use in
combination with RETRY progress provides the RETRY function so
you can test for the occurrence of a RETRY within a block.

For a complete discussion of these features see the Programming
Handbook - Chapter 3 & 4 (v8) Block Properties, Condition
Handling and Messages.  In general, the Programming Handbook
should be REQUIRED reading for all Progress developers.  Also
critical to this equation is the ON ERROR phrase.  Related
conditions are ENDKEY, STOP and QUIT which have ON phrases as
well.

In addition to the error handling itself you need to be aware
of the impact on transactions and subtransactions when an error
occurs.  It is the combination of error handling and transactions that
enable you to write applications that maintain data and application
integrity.  An EXTREMELY simplified description is that the work done
within the transaction scope is undone so that the data in the
database is returned to its previous state. For the moment lets just
say that you need to use error and transaction processing to control
what "Unit of Work" gets done or undone with regards to DB
interaction.

The last category of error handling is handled by your own
application logic.  This is accomplished by using all that is
presented above to control lower level language situations and
your own programs/statements to verify and handle application
based validations and processing control.


2. Using NO-ERROR and the ERROR-STATUS handle.

With the advent of version 7 Progress added the ERROR-STATUS
system handle.  This handle allows you to use the NO-ERROR
option on (many) statements and then test the status of the
ERROR-STATUS attribute ERROR.  This in combination with the other
attributes and methods of ERROR-STATUS allow you the developer to trap
the default Progress errors and take control of the error management.

Unfortunately the move from a block oriented, procedural language to
one that supports event driven processing was a tough one for PSC. 
With the advantage of hindsight it seems obvious to me that having an
ERROR-STATUS handle without having ERROR events or "Exceptions" (see
below) is only a partial solution.  As it is implemented today you
must constantly scatter checks for errors if you want to manage the
error conditions yourself rather than take the Progress default
action.


3. Decision branch management

Statements such as IF and CASE that affect the control flow of
your code need to have blocks/statements for handling errors.
The CASE statement comes with an OTHERWISE construct to act as
a catch all in case the variable used doesn't meet any of the
WHEN selections.  For the IF/THEN you can also specify an ELSE.
Not every instance of these constructs requires handling the
"other" condition but you should be very careful to be sure
when it is acceptable to continue when the standard branch is
not executed.

An example -

IF AVAILABLE(table) THEN DO:
  ...
END.
ELSE ...

This else condition is often an error in the data being processed yet
it falls into the "Never should happen" category.  Often this else
condition is left off with all the processing happening in the
available block.  This kind of silent treatment of error situations is
very dangerous.  If some other part of the application failed to
create the appropriate records then areas that use those relations
need to tell you things are not right. The same is true of CASE
blocks.  They often receive the data to be "switched" on from an
external source.  If new data has been used but the case hasn't been
updated then usually the case statement needs an OTHERWISE so it can
display a message or at least write an error log entry for later
review.


4. Simple system error situations

Some error situations can be caused by problems external to the
application.  Many of these are unavoidable and cannot be managed
within the application.  Some however, such as not being able to find
a file or access an output destination are situations you can detect
and plan for in the application.  When interacting with the
environment outside of Progress it is wise never to assume an
operation will be successful.  Use the NO-ERROR option and test for
the success/failure of the statement as needed to manage the
processing.  Also use the OS- commands to keep as much control within
the Progress environment as possible.


5. Some basic error techniques

Categorize the error types.  Use these classifications to help
decide the severity of the problem - Fatal, Warning, Advisory...
and respond accordingly.

Errors can be displayed as messages, entered into a db or text
log file, or perhaps (in the future) even sent as an event to some
administrative process or message center.  Remember though that a db
based log is going to be affected by the other transaction processing
and data handling around it, causing potential conflicts and side
effects.  (Named transactions anyone? :-))

Use include files to encapsulate error testing and responses to
help standardize the way you manage the error control implementation.

In v7+ the MESSAGE statement now has options to be viewed as a
standard ALERT-BOX with types such as ERROR, WARNING, INFORMATION that
can even return limited input from the user on what to do.


6. Exceptions

Some of the more modern language implementations are now
supporting "Exceptions" as a method of error handling.  This
is a powerful capability that helps provide a structured way
of handling error conditions without the constant check/handle
requirements of older language implementations.  It allows you to
define an error condition, give it a name, and "Raise" it similar to
the Progress ERROR condition.  The exception then propagates up
through the layers of blocks until it is handled or the application
terminates.  A good example of a low level exception is a divide by
zero math operation.  You do not want to check every divide operation
but you need to handle the error consistently.  With such errors
recovery may not be possible but at least proper cleanup and message
display can be accomplished.  Application exceptions are much more
likely to be recoverable - No vendor terms available could even
trigger processing to gather the information required and create the
appropriate record without leaving the current context within the
application.

Progress does not support exceptions at this time but you can
emulate some of the concepts manually.

See upcomming PPT #19 for details.  :-)


Wisdom:

Many individuals like to equate the word Problem with an
Opportunity.  Others just shake their heads and walk away.


Rod Gaither                  | rdg@worldinfo.com
World Information Systems    | (910) 333-2580  Voice
Greensboro, NC               | (910) 333-2584  Fax