03-16-2010 5:44 PM
Using NetWeaver 7.0, I am not able to actually make my program enter a CLEANUP block inside the try...endtry statements. The error is caught, the text is gotten, but in DEBUG I stop at CLEANUP, then at ENDTRY. The statements in CLEANUP are ignored.
To verify this I copied a program from SAP's documentation and it does precisely what mine does. I don't find SAP Notes on
this subject. Any insight about why this happens would be appreciated..
The code below is copied and simplified from on-line documentation and it fails to enter CLEANUP when executed with number = 0. Please note also that if the code is converted to a perform a subroutine with a try...endtry...from within another try...endtry...everything works except the CLEANUP block.
REPORT demo_handle_exceptions.
PARAMETERS number TYPE i.
DATA quotient TYPE p DECIMALS 2.
DATA oref TYPE REF TO cx_root.
DATA text TYPE string.
START-OF-SELECTION.
WRITE: / 'Testing division with', number.
ULINE.
TRY.
quotient = 1 / number. "in debug, change to 0.10 here
CATCH cx_sy_zerodivide INTO oref.
text = oref->get_text( ).
CLEANUP.
CLEAR quotient.
ENDTRY.
IF NOT text IS INITIAL.
WRITE / text.
ENDIF.
WRITE: / 'Final result:', quotient.
Output
Testing division with 0
Division by zero
Final result: 0.10
03-16-2010 7:04 PM
My understanding is that the CLEANUP block would only be called if there is no handler to process the exception that actually occurs. You can test this by commenting out the CATCH statement.
Rob
OK - I tried it with your code and it dumped. But then I tried it with the code from the example in the help file and the CLEANUP is executed:
PARAMETERS number TYPE i.
DATA: result TYPE p LENGTH 8 DECIMALS 2,
oref TYPE REF TO cx_root,
text TYPE string.
TRY.
IF ABS( number ) > 100.
RAISE EXCEPTION TYPE cx_demo_abs_too_large.
ENDIF.
PERFORM calculation USING number
CHANGING result
text.
CATCH cx_sy_arithmetic_error INTO oref.
text = oref->get_text( ).
CATCH cx_root INTO oref.
text = oref->get_text( ).
ENDTRY.
IF NOT text IS INITIAL.
WRITE / text.
ENDIF.
WRITE: / 'Final result:', result.
*&---------------------------------------------------------------------*
*& Form calculation
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM calculation USING p_number LIKE number
CHANGING p_result LIKE result
p_text LIKE text
RAISING cx_sy_arithmetic_error.
DATA l_oref TYPE REF TO cx_root.
TRY.
p_result = 1 / p_number.
WRITE: / 'Result of division:', p_result.
p_result = SQRT( p_number ).
WRITE: / 'Result of square root:', p_result.
* CATCH cx_sy_zerodivide INTO l_oref. " Remove
* p_text = l_oref->get_text( ). " Remove
CLEANUP.
result = 999. " change to a big number
ENDTRY.
ENDFORM. "calculation
Edited by: Rob Burbank on Mar 16, 2010 3:12 PM
03-16-2010 7:04 PM
My understanding is that the CLEANUP block would only be called if there is no handler to process the exception that actually occurs. You can test this by commenting out the CATCH statement.
Rob
OK - I tried it with your code and it dumped. But then I tried it with the code from the example in the help file and the CLEANUP is executed:
PARAMETERS number TYPE i.
DATA: result TYPE p LENGTH 8 DECIMALS 2,
oref TYPE REF TO cx_root,
text TYPE string.
TRY.
IF ABS( number ) > 100.
RAISE EXCEPTION TYPE cx_demo_abs_too_large.
ENDIF.
PERFORM calculation USING number
CHANGING result
text.
CATCH cx_sy_arithmetic_error INTO oref.
text = oref->get_text( ).
CATCH cx_root INTO oref.
text = oref->get_text( ).
ENDTRY.
IF NOT text IS INITIAL.
WRITE / text.
ENDIF.
WRITE: / 'Final result:', result.
*&---------------------------------------------------------------------*
*& Form calculation
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM calculation USING p_number LIKE number
CHANGING p_result LIKE result
p_text LIKE text
RAISING cx_sy_arithmetic_error.
DATA l_oref TYPE REF TO cx_root.
TRY.
p_result = 1 / p_number.
WRITE: / 'Result of division:', p_result.
p_result = SQRT( p_number ).
WRITE: / 'Result of square root:', p_result.
* CATCH cx_sy_zerodivide INTO l_oref. " Remove
* p_text = l_oref->get_text( ). " Remove
CLEANUP.
result = 999. " change to a big number
ENDTRY.
ENDFORM. "calculation
Edited by: Rob Burbank on Mar 16, 2010 3:12 PM
03-16-2010 7:30 PM
Thanks, Rob. Your fix works and the example at:
[http://help.sap.com/saphelp_nw04/Helpdata/EN/a9/b8eef8fe9411d4b2ee0050dadfb92b/content.htm]
is just flat out wrong, unfortunately!
However, the "Official ABAP Programming Guide" published just last fall shows the cleanup in the same try...endtry also. But I abend when I try something approximating that example, possibly because of versions of NetWeaver.
Just for the record, what NetWeaver version did you try this on?
03-16-2010 7:45 PM
I commented out the same lines in the link you gave and it behaved the same as in my example, so I think it works OK.
Rob
03-16-2010 8:55 PM
that's explained here in the ABAP documentation, chapter "System Behavior After Class-Based Exception":
> If a handler is found, the CLEANUP blocks of all TRY control structures that have thus far been scanned unsuccessfully are executed from the inside to the outside.
The following will display Final result: 998 if you enter number = 0
PARAMETERS number TYPE i.
DATA quotient TYPE p DECIMALS 2.
DATA oref TYPE REF TO cx_root.
DATA text TYPE string.
START-OF-SELECTION.
WRITE: / 'Testing division with', number.
ULINE.
TRY.
TRY.
TRY.
quotient = 1 / number.
CLEANUP.
quotient = 999.
ENDTRY.
CLEANUP.
SUBTRACT 1 FROM quotient.
ENDTRY.
CATCH cx_sy_zerodivide INTO oref.
text = oref->get_text( ).
ENDTRY.
IF NOT text IS INITIAL.
WRITE / text.
ENDIF.
WRITE: / 'Final result:', quotient.