Kbase P100609: How to handle errors generated within Functions.
Autor |
  Progress Software Corporation - Progress |
Acesso |
  Público |
Publicação |
  2/17/2009 |
|
Status: Verified
GOAL:
How to handle errors generated within Functions?
GOAL:
How to trap for errors caused within Functions?
GOAL:
How to add error handling to Functions?
GOAL:
How to program Function error condition handling?
FACT(s) (Environment):
OpenEdge Category: Language (4GL/ABL)
FIX:
Functions are quite different to Internal Procedures in respect to their error handling, whereby Functions do not return an error condition to the calling procedure. In other words, an error generated within a function will not trigger an ON ERROR statement within the calling procedure. This is also true if you have explicitly used RETURN ERROR within a function.
Below are two types of Function uses, the first of which is the most common and the easiest to work with:
1. findMyCustAndSelectIt(). (returns LOG)
2. ASSIGN myTable.myField = doubler(someInteger). (returns INT)
With the first example, if an error occurs within the function it will cause the function to return FALSE. Errors in this case are easy to check by using code somewhat like:
mylog = findMyCustAndSelectIt().
IF mylog = FALSE then doWhatever.
With the second example we expect to be receiving a return value back from the function to use in the ASSIGN statement. However with Functions, when an error occurs it will return "?" to the ASSIGN statement and in this case will be assigned to that database field. Obviously this isn't necessarily ideal considering that "?" might be a valid value for that field under non-error conditions.
A workaround is to use an ON STOP block within the calling procedure, and cause a STOP within the function. This is because using STOP will cause a STOP condition within the calling procedure (unlike RETURN ERROR).
Workaround Example:
/* Function foo raises a STOP if "a"
cannot be converted to INT */
FUNCTION foo RETURNS INTEGER ( a AS CHAR ) :
DEFINE VARIABLE i AS INTEGER NO-UNDO.
i = INTEGER(a) NO-ERROR.
IF ERROR-STATUS:ERROR THEN STOP.
RETURN i. /* Function return value. */
END FUNCTION.
DO ON STOP UNDO, RETRY:
IF RETRY THEN DO:
MESSAGE 'A stop occurred within the function'
VIEW-AS ALERT-BOX INFO BUTTONS OK.
LEAVE.
END.
/* foo() will raise a STOP on appServer
if "a" cannot be converted to INT */
DEFINE VARIABLE i AS INTEGER NO-UNDO.
i = DYNAMIC-FUNCTION('foo':U, 'a').
MESSAGE i VIEW-AS ALERT-BOX INFO BUTTONS OK.
END. /* ON STOP */
NOTE: If Function foo() resides on an AppServer and you are calling it from a procedure on the client, the STOP condition will not propagate back to the client. Development is aware of this issue.