4GL Thrown Exceptions

The project is now part of the Standard Libraries project

http://www.oehive.org/project/lib

Installation:

Unzip the files, make sure they're on the PROPATH and that's it.

Basic syntax:


{error.i} /* error handling library */

define var cError       as char no-undo.
define var cErrorMsg    as char no-undo.

{err_try}:

    {err_throw "'general_error'"}.

{err_catch cError cErrorMsg}: /* both cError and cErrorMsg are optional */ 

    message cErrorMsg view-as alert-box.

{err_finally}:

    message "Executed Always !" view-as alert-box.

{err_end}.

You can use any possible try/catch/finally combinations, like, try/catch, try/finally or just try by itself. And nest sub try clauses.

The whole try/catch/finally clause works out to one big do: block so you could use it with an IF THEN statement without having to wrap it in another do: block.

{err_throw} also excepts the LAST keyword for rethrowing the last exception in a catch clause higher up (see the following code snippet). And a 2nd parameter of chr(1) delimited list of message parameters, for example, {err_throw "'another_error'" "'param1' + chr(1) + 'param2'"}.

{err_throw} also works out to a single statement and can be used with an IF THEN statement without any special requirement.

The errormsg file holds the list of error messages, kinda like PROMSGS

Converting 4GL errors into thrown exceptions:


{error.i}

define var hQuery       as handle no-undo.

define var cError       as char no-undo.
define var cErrorMsg    as char no-undo.

{err_try}:

    create query hQuery.

    hQuery:query-open( ) {err_no-error}. /* catches and throws 4gl errors */

{err_catch cError cErrorMsg}:

    message replace( cErrorMsg, chr(1), "~n" ) view-as alert-box.

    {err_throw last}. /* rethrow the catched error higher up, so to speak. */

{err_finally}:

    /* free up resources */

    if valid-handle( hQuery ) then do:

        hQuery:query-close( ) no-error.
        delete object hQuery no-error.

    end. /* valid-handle */

{err_end}.

Note that unlike thrown exceptions 4GL run-time errors can return more then one error. In this case the catch clause will return a comma delimited list of error numbers and a chr(1) delimited list of error messages.

{err_no-error} throws all error number and messages as a list of exceptions when ERROR-STATUS:NUM-MESSAGES > 0. You could also use {err_no-error-flag} that does the same thing but only when ERROR-STATUS:ERROR = TRUE. And theres also {err_os-error} to use together with OS-COMMAND.

Unfortunately {err_no-error} together with the statement its attached to works out to 2 statements meaning that in case that statement follows right after IF THEN it will need to be wrapped in a do: block.

Using return inside a try clause:

Using RETURN inside a try clause would skip over critical logic like the finally clause. Instead use {err_return}.


{error.i}

function test returns int:

    {err_try}:

        {err_return 100}. /* return 100 without by passing the finally clause */

    {err_finally}:

        message "Always Executed" view-as alert-box.

    {err_end}.

end function. /* test */

message test( ) * 2 view-as alert-box.

{err_return} also excepts ERROR or NO-APPLY, for example, {err_return error}.

{err_return} just like err_throw works out to a single statement and can be used with an IF THEN statement without any special requirement.

Cheers.



AttachmentSize
error02.zip6.31 KB