Catch not working as expected

Posted by piamaria on 11-Jun-2015 04:14

I try to implement error handling with exceptions in 11.32

My problem is that it looks like the error continues to exist after it has been handled in the catch.

I run the code below in the procedure editor. I get an alertbox with the error. I did not expect that because I caught the error inte catch.

Also I get the alertbox 3 times!

Can anyone explain why?

ROUTINE-LEVEL ON ERROR UNDO, THROW.

DEFINE TEMP-TABLE ttTest NO-UNDO
FIELD id AS CHARACTER
FIELD test-name AS CHARACTER
INDEX i-ttTest-1 IS PRIMARY UNIQUE id.

DO ON ERROR UNDO, LEAVE:
CREATE ttTest.
ASSIGN ttTest.id = "1"
ttTest.test-name = "2".
RELEASE ttTest.

CREATE ttTest.
ASSIGN ttTest.id = "1"
ttTest.test-name = "2".
RELEASE ttTest.

CATCH procerror AS Progress.Lang.ProError:
DISP "Inside catch".
END CATCH.

FINALLY:
DISP "Inside finally".
END FINALLY.

END.

Posted by Mike Fechner on 11-Jun-2015 05:37

BLOCK-LEVEL and ROUTINE-LEVEL Error handling is not relevant here, because the DO block does explicitly define an error handling option.
 
At first sight I would have said it’s because the NO-UNDO option on the new temp-table: That would explain why the second record is not rolled back (deleted) before it’s catched.
 
But even without the NO-UNDO option on the temp-table the code behaves the same.
 
If you add the TRANSACTION keyword to the DO block (and don’t have NO-UNDO on the temp-table), then the second record will be rolled back before the CATCH (it’s no longer available in the CATCH).
 
And you won’t see the errors.
 
Von: piamaria [mailto:bounce-piamaria@community.progress.com]
Gesendet: Donnerstag, 11. Juni 2015 11:23
An: TU.OE.General@community.progress.com
Betreff: RE: [Technical Users - OE General] Catch not working as expected
 
Reply by piamaria

Same result if I use BLOCK-LEVEL instead of Routine-LEVEL.

Stop receiving emails on this subject.

Flag this post as spam/abuse.

All Replies

Posted by James Palmer on 11-Jun-2015 04:18

What happens if you use BLOCK-LEVEL instead of ROUTINE-LEVEL?

I'm no error handling guru, but IIRC with ROUTINE-LEVEL you still have to do an on-error throw on each block, whereas with BLOCK-LEVEL you don't.

Posted by piamaria on 11-Jun-2015 04:22

Same result if I use BLOCK-LEVEL instead of Routine-LEVEL.

Posted by Mike Fechner on 11-Jun-2015 05:37

BLOCK-LEVEL and ROUTINE-LEVEL Error handling is not relevant here, because the DO block does explicitly define an error handling option.
 
At first sight I would have said it’s because the NO-UNDO option on the new temp-table: That would explain why the second record is not rolled back (deleted) before it’s catched.
 
But even without the NO-UNDO option on the temp-table the code behaves the same.
 
 
And you won’t see the errors.
 
Von: piamaria [mailto:bounce-piamaria@community.progress.com]
Gesendet: Donnerstag, 11. Juni 2015 11:23
An: TU.OE.General@community.progress.com
Betreff: RE: [Technical Users - OE General] Catch not working as expected
 
Reply by piamaria

Same result if I use BLOCK-LEVEL instead of Routine-LEVEL.

Stop receiving emails on this subject.

Flag this post as spam/abuse.

Posted by piamaria on 11-Jun-2015 06:09

Now it works. Thank you very much. :)

Posted by cverbiest on 11-Jun-2015 06:30

I think this is a  combination of no-undo and buffer scoping.

NO-UNDO causes the error not to be undone. when the procedure ends the buffer goes out of scope and you get the error again.

ROUTINE-LEVEL ON ERROR UNDO, THROW.

session:appl-alert = yes.
session:system-alert = yes.
session:debug-alert = yes.

DEFINE TEMP-TABLE ttTest NO-UNDO
FIELD id AS CHARACTER
FIELD test-name AS CHARACTER
INDEX i-ttTest-1 IS PRIMARY UNIQUE id.

createblock:
DO ON ERROR UNDO, LEAVE:
    CREATE ttTest.
    ASSIGN ttTest.id = "1"
    ttTest.test-name = "2".
    validate ttTest.

    CREATE ttTest.
    ASSIGN ttTest.id = "1"
    ttTest.test-name = "2".
    validate ttTest.

    CATCH procerror AS Progress.Lang.Error:
        message "Inside catch".
        if procerror:getmessagenum(1) = 132 then delete ttTest.
        leave createblock.
    END CATCH.

    FINALLY:
        message "Inside finally" error-status:error.
    END FINALLY.

end.

message "Done".

CATCH procerror AS Progress.Lang.Error:
    message "Inside catch 2" procerror:getmessage(1).
    leave.
END CATCH.


2nd cleaner solution with strong scoping

ROUTINE-LEVEL ON ERROR UNDO, THROW.

session:appl-alert = yes.
session:system-alert = yes.
session:debug-alert = yes.

DEFINE TEMP-TABLE ttTest NO-UNDO
FIELD id AS CHARACTER
FIELD test-name AS CHARACTER
INDEX i-ttTest-1 IS PRIMARY UNIQUE id.

createblock:
DO ON ERROR UNDO, LEAVE:
    do for ttTest: /* strong scope */
        CREATE ttTest.
        ASSIGN ttTest.id = "1"
        ttTest.test-name = "2".

        CREATE ttTest.
        ASSIGN ttTest.id = "1"
        ttTest.test-name = "2".
    end.
    CATCH procerror AS Progress.Lang.Error:
        message "Inside catch" procerror:getmessage(1).
    END CATCH.

    FINALLY:
        message "Inside finally" error-status:error.
    END FINALLY.

end.

message "Done".

CATCH procerror AS Progress.Lang.Error:
    message "Inside catch 2" procerror:getmessage(1).
    leave.
END CATCH.

Posted by piamaria on 11-Jun-2015 07:32

Thanks for the answer. I will look into this solution also.

Posted by Fernando Souza on 11-Jun-2015 08:36

Just to clarify, there was no transaction so temp-tables changes are not undone in that case (that is documented). So whether it was an undo or no-undo temp-table, when there is no transaction active, the changes will  not be undone. The record remains in scope and the errors will come up as we try to release the record when ending the procedure.

This thread is closed