Message was edited by: Miles Klettke
It seems the issue has been addressed on PEG
Addressed, yes, in the sense of having explained that there is a difference between an ERROR condition and a STOP condition, but what it doesn't explain is why PSC didn't implement CATCH to cover both. It seems to me that one of the potentially desirable uses of CATCH is to provide a hierarchy of error handling in which local blocks handle simple errors and pass more complex issues up the chain, eventually reaching a top level block in which all errors are handled in some graceful fashion, even if "graceful" is little more than doing some logging, giving the user a polite message, and then quitting or restarting. By not handling STOP conditions with CATCH, we can't really use this approach fully.
Consulting in Model-Based Development, Transformation, and Object-Oriented Best Practice http://www.cintegrity.com
No I couldn't get that suggestion to work. Have you tried it yourself? While in RETRY you don't get a message but as soon as you return or leave you get the message. On a retry you sit in a infinite loop so you have to leave or return and as soon as you do you get the message.
I had ON STOP UNDO, LEAVE and you get the message on the leave. Try the following.
DO ON ERROR UNDO, LEAVE
ON STOP UNDO, LEAVE:
message 1 view-as alert-box.
CATCH eSysError AS Progress.Lang.SysError:
MESSAGE 2 eSysError:getMessage(1)
VIEW-AS ALERT-BOX INFO BUTTONS OK.
DELETE OBJECT eSysError.
CATCH eproError AS Progress.Lang.ProError:
MESSAGE 3 eproError:getMessage(1)
DELETE OBJECT eproError.
message 4 view-as alert-box.
I had code a message 1 when the run was successful. When it wasn't it was to just drop out of the block to message 4.
It seems that CATCH traps ERROR messages but doesn't trap STOP messages as I think Tim pointed out.
I'm a little unclear on your current status ... and what the second catch block is supposed to be there for.
Are you saying that coded as it stands, the CATCH block(s) do nothing for you, but if the intent was to attempt the run and proceed silently without a message that this is what you are achieving?
As Sébastien has pointed out in his reply to PEG, the RUN in the code sample from Miles returns an unhandled STOP. In 10.1C, which introduces ABL THROW-CATCH structured error handling, we focused on error conditions and created an error object hierarchy in the ABL. We are looking into adding exception (STOP) objects and handling for upcoming releases.
No, I have not tried. It's best that you get back to Sébastien.
An example was posted to the peg with the two CATCH's, and I just left it in there. Neither catch traps any of the messages.
Peter van Dam has just posted an example to the peg that stops the progress message and display his own. His example without the CATCH's, that again don't seem to do anything.
ROUTINE-LEVEL ON ERROR UNDO, THROW.
DO ON STOP UNDO, RETRY:
IF RETRY THEN
UNDO, THROW NEW Progress.Lang.AppError("Program not found",1).
END. /* ON STOP... */
This works ok but I want no message and will have to investigate this method further and I haven't seen the THROW.
Peter's full example has two catch blocks at the end,
The message is coming from those. Presumably, you could avoid the message by simply discarding the message instead of displaying it, e.g., putting it to a log file or something ... or nothing at all.
But, isn't this leaping from the bad run immediately down to the CATCH? If there are other statements below the run which you want to execute even if the run fails, then I think those are going to be missed.
No the CATCH has no effect. The message comes from the THROW. I can remove both CATCH's and still get the same result. I've just had my breakfast and will now see if I can get anything from Peter's example.
I was wrong on the CATCH at least the AppError one. It's the one that picks up the THROW as pointed out by Jeff Ledbetter. So removing the message from that CATCH stops the message.
A modified version of Jeff's code is below
ON STOP UNDO, RETRY:
IF RETRY THEN
UNDO, THROW NEW Progress.Lang.AppError().
message 1 view-as alert-box.
CATCH eAppError AS Progress.Lang.AppError:
DELETE OBJECT eAppError.
message 2 view-as alert-box.
Even with the code above you could get caught as I will have code instead of message 1. If this produces an application error then you won't see it. I could throw a specific error and check for that in the catch, but again I am assuming that the RETRY occurs from the RUN failure.
So still some things to think about.
THROW is a UI statement?????
From help -
You can only THROW error objects, and an error object is an object derived from the built-in interface Progress.Lang.Error. It is a compile-time error to THROW an object that is not derived from Progress.Lang.Error.
When the THROW occurs, execution stops, and the specified error is raised. The error should then be handled by the NO-ERROR qualifier, a CATCH block, or by an explicit or implicit ON ERROR phrase.
The following notes describe restrictions on using UNDO, THROW:
If the action on the UNDO statement is THROW, the UNDO cannot have a . To do so will result in a compile-time error.
UNDO, THROW is not allowed in a CATCH block associated with the main block of an object destructor method. You cannot raise or RETURN an error from a destructor. To do so will result in a compile-time error. You can use UNDO, THROW within the code of the destructor itself. In this case, the statement will raise error in the destructor block and be caught by the ON ERROR directive of the destructor block (which can only be UNDO, LEAVE).
UNDO, THROW is not allowed in a CATCH block of a user interface trigger. The ABL does not you to raise or RETURN error out of a user interface trigger. To do so will result in a compile-time error.
The UNDO, THROW statement can itself raise error or THROW a SysError object if it fails. For example, if the statement cannot find the specified error object. In this case, the SysError will be trapped by the same block that would have trapped the successfully thrown error object.
In my case these are my options so far
DO ON ERROR UNDO, LEAVE ON STOP UNDO, RETRY:
DO ON ERROR UNDO, LEAVE ON STOP UNDO, LEAVE:
OUTPUT TO "NUL:" KEEP-MESSAGES.
The latter has less code and I can safely insert code after the output close. In the first the safest way is to add code after the do block to avoid retries being fired by other reasons or other application errors occuring. In the case of other application error I can set a specific message and or message number e.g UNDO, THROW NEW Progress.Lang.AppError('Retry Error',123456) and test for that in the catch by eAppError:GetMessage(1) or eAppError:GetMessageNum(1). But again that is more code. Probably the simplest way is to only have the run in the DO block and set a flag when it's successful and test for that after the block.
For my current purpose the old way seems simplest.
I would think that something like:
With the procedure in a utility super would allow you to write the code once and give you the option of logging the event.
Not that I've tried it yet, of course.
BTW., enclosing code in ... blocks, no spaces, helps preserve the indentation.