What does Try Catch do in ABAP? / Hebrew

Short description

The focus is on the TRY…CATCH feature in ABAP programming language, with additional statements like CLEANUP, RESUME, RETRY, and BEFORE UNWIND providing more possibilities in design. CLEANUP is used to remove references before a method call completes, and it offers an opportunity to restore the state of an object before exiting the current block of processing. RESUME allows users to exit the block CATCH and resume processing after the instruction that threw the exception. RETRY enables users to jump back into the block TRY control structure to repeat the complete block TRY. Finally, BEFORE UNWIND, when added to an application, removes the context in which an exception was raised only after exiting the CATCH bloc.

What does Try Catch do in ABAP? / Hebrew

Hello, now we will touch on the best ABAP programming language, again. Or more precisely, TRY…CATCH capabilities in this language. It seems that something is “trying”, something is “catching”, but it is not so obvious…

Additional possibilities open up in this design by adding statements such as CLEANUP, RESUME, RETRY, and BEFORE UNWIND. Let’s discuss why they are needed and how to work with them.

CLEANUP

Bloc CLEANUP will be used to remove references before the method call completes. Whenever an exception occurs, the system stops processing from that point and goes to the corresponding block TRY. Because of this behavior, the object will be in an intermediate state. Bloc CLEANUP provides an opportunity to restore the state of the object before exiting the current block of processing.

CLASS lcl_main DEFINITION FINAL.
  PUBLIC SECTION.
    METHODS:
      method1,
      method2.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
  METHOD method1.
    TRY.
        method2( ).
      CATCH cx_root.
        cl_demo_output=>write( 'catching cx_root' ).
    ENDTRY.
    cl_demo_output=>display( ).
  ENDMETHOD.
  METHOD method2.
    TRY.
        DATA(result) = 2 / 0.
      CLEANUP.
        cl_demo_output=>write( 'cleanup' ).
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  NEW lcl_main( )->method1( ).

In this example, we have an “outer” block TRY..ENDTRY in method method1. We have an “inside” unit TRY..ENDTRY in the method method2, which is run from the outer block. Since we are dividing by 0, the division operator will throw an exception of type CX_SY_ZERODIVIDE. Since we catch all exceptions using CATCH CX_ROOT in the outdoor unit TRYthe system will execute the block logic CLEANUP in the indoor unit TRY.

Replace this one CX_ROOT on CX_SY_BUFFER_OVERFLOWwhich is not part of the hierarchy CX_SY_ZERODIVIDEago CLEANUP will not be executed and will result in a runtime dump.

RESUME

WITH RESUME you get out of the block CATCH and resume processing after the instruction that threw the exception. The example below demonstrates the possibilities perfectly RESUME.

CLASS lcl_employee DEFINITION FINAL CREATE PUBLIC.

  PUBLIC SECTION.

    TYPES: BEGIN OF empl_data,
             empid  TYPE int4,       " Employee ID
             emptyp TYPE string,     " Org Assignment data
             salary TYPE decfloat16, " Pay data
             phone  TYPE numc10,     " Communication data
           END OF empl_data,
           empl_data_t TYPE SORTED TABLE OF empl_data WITH UNIQUE KEY empid.

    METHODS constructor IMPORTING VALUE(i_empid)   TYPE int4.
    METHODS get_data    RETURNING VALUE(rs_result) TYPE empl_data
                        RAISING   RESUMABLE(cx_no_data_found).

  PRIVATE SECTION.

    DATA  emp_id       TYPE int4.

    METHODS get_emptyp RETURNING VALUE(r_result) TYPE string
                       RAISING   cx_no_data_found.
    METHODS get_salary RETURNING VALUE(r_result) TYPE decfloat16
                       RAISING   RESUMABLE(cx_no_data_found).
    METHODS get_phone  RETURNING VALUE(r_result) TYPE numc10.
    METHODS get_emp_id RETURNING VALUE(r_result) TYPE int4.

ENDCLASS.

CLASS lcl_employee IMPLEMENTATION.

  METHOD constructor.
    me->emp_id = i_empid.
  ENDMETHOD.

  METHOD get_data.
    rs_result = VALUE #( empid  = me->get_emp_id( )
                         emptyp = me->get_emptyp( )
                         salary = me->get_salary( )
                         phone  = me->get_phone( ) ).
  ENDMETHOD.

  METHOD get_emptyp.
    r_result = SWITCH #( me->get_emp_id( )
                WHEN 1 THEN |Full-Time|
                WHEN 2 THEN |Part-Time|
                WHEN 3 THEN |Contractor|
                WHEN 4 THEN |Casual|
                ELSE THROW cx_no_data_found(
                            rel_proc_id = CONV #( me->get_emp_id( ) ) ) ).
  ENDMETHOD.

  METHOD get_phone.
    r_result = SWITCH #( me->get_emptyp( )
                WHEN `Full-Time` THEN |1234567890|
                WHEN `Part-Time` THEN |5678901234|
                WHEN `Casual`    THEN |7890123456|
                ELSE |0399999999| ).
  ENDMETHOD.

  METHOD get_salary.
    r_result = SWITCH #( me->get_emptyp( )
                WHEN `Full-Time` THEN 50000
                WHEN `Part-Time` THEN 25000
                WHEN `Casual`    THEN 5000
                ELSE THROW RESUMABLE cx_no_data_found(
                            rel_proc_id = CONV #( me->get_emp_id( ) ) ) ).
  ENDMETHOD.

  METHOD get_emp_id.
    r_result = me->emp_id.
  ENDMETHOD.

ENDCLASS.

DATA extract_t TYPE lcl_employee=>empl_data_t.
DATA error_t   TYPE string_table.

START-OF-SELECTION.

  DATA(all_employees_t) = VALUE int4_table(  ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) ).

  LOOP AT all_employees_t REFERENCE INTO DATA(dref).
    TRY.
        INSERT NEW lcl_employee( dref->* )->get_data( ) INTO TABLE extract_t.

      CATCH BEFORE UNWIND cx_no_data_found INTO DATA(no_data_error).
        IF no_data_error->is_resumable = abap_true.
          " Вызванное возобновляемое исключение
          RESUME.

        CLEANUP INTO DATA(lv_clear).
        ELSE.
          " Вызванное не возобновляемое исключение
          error_t = VALUE #( BASE error_t ( no_data_error->get_text( ) ) ).
        ENDIF. 
    ENDTRY.
  ENDLOOP.

  cl_demo_output=>new( )->write( extract_t )->write( error_t )->display( ).

Thanks to RESUME in the get salary method when the salary was not found, in which case we need to report an error and add a record. If removed RESUME then after the exception is called, the record will not be added to the table.

Do not pay attention to BEFORE UNWINDWe will talk about him a little later.

RETRY

WITH RETRY you get out of the block CATCH and jump back into the block TRY control structure in order to repeat the complete block TRY. Of course, you have to make sure that the exception doesn’t happen again and again, otherwise you end up in an infinite loop.

CLASS lcl_main DEFINITION FINAL.
  PUBLIC SECTION.
    METHODS:
      method1,
      method2.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
  METHOD method1.

    TRY.
        method2( ).
      CATCH BEFORE UNWIND cx_root.
        cl_demo_output=>write( 'catching cx_root' ).
    ENDTRY.

    cl_demo_output=>display( ).
  ENDMETHOD.
  METHOD method2.
    DATA(index) = 0.
    TRY.
        DATA(result) = 2 / index.
      CATCH cx_sy_zerodivide.
        cl_demo_output=>write( 'catching cx_sy_zerodivide' ).
        index = 1.
        cl_demo_output=>write( 'catching retry' ).
        RETRY.
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  NEW lcl_main( )->method1( ).

BEFORE UNWIND

If an application is specified BEFORE UNWINDthe context in which the exception was raised, including all called procedures and their local data, is removed only after exiting CATCH bloc. If append is not specified, the context will be removed before execution CATCH block

  • If the addition BEFORE UNWIND operator is specified RESUME can be used in CATCH resumable exception handling blocks to resume processing after the instruction that threw the exception. This is the only case where the exception context is not removed on exit from CATCH block

  • Recoverable exceptions can also be handled CATCH blocks without addition BEFORE UNWIND. In this case, the exception context is removed before processing and the statement RESUME cannot be specified.

  • Any [CLEANUP](<https://eduardocopat.github.io/abap-docs/7.40/abapcleanup>) blocks are always executed immediately before their context is removed. If BEFORE UNWIND is used, then after exception handling and in all other cases before exception handling.

  • Using an add-on BEFORE UNWIND for CATCH required only when the statement [RESUME](<https://eduardocopat.github.io/abap-docs/7.40/abapresume>) is used However, this is in principle allowed in exception handling if the exception context must be evaluated before any cleanup actions CLEANUP blocks This makes sense, for example, when handling bottlenecks in resources, if the release of resources in CLEANUP blocks would change the context and thus make the computation, free resources in the exception handler pointless.

Related posts