Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
horst_keller
Product and Topic Expert
Product and Topic Expert

You know ABAP's class based exception handling very well.

  • Exceptions are either raised explicitly with RAISE EXCEPTION or implicitly when ABAP statements go wrong,
  • Exceptions can be propagated from procedures using RAISING.
  • Exceptioms are handled in TRY blocks using CATCH and CLEANUP.

But did you ever hear about RETRY and RESUME? If yes, skip reading this blog. If not, read on ...

Recap: Raising and Handling Exceptions

The following code sequence repeats the well known principles of raising and handling class based exceptions:

CLASS cx_demo DEFINITION INHERITING FROM cx_static_check.

ENDCLASS.

CLASS cls DEFINITION.

  PUBLIC SECTION.

    CLASS-METHODS meth RAISING cx_demo.

ENDCLASS.

CLASS cls IMPLEMENTATION.

  METHOD meth.

    ...

    RAISE EXCEPTION TYPE cx_demo.

    ...

  ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.

  TRY.

      cls=>meth( ).

    CATCH cx_demo INTO DATA(exc).

      cl_demo_output=>display( `Handling ` &&

        cl_abap_classdescr=>get_class_name( p_object = exc ) ).

  ENDTRY.


  • An exception class is declared by inheriting from one of the predefined classes cx_static_check, cx_dynamic_check, cx_no_check.
    Their meaning is described in the documentation.
  • A method propagates the exception that it cannot handle to the caller using RAISING.
  • A method implementation can raise an exception with RAISE EXCEPTION TYPE.
  • The method caller can CATCH the exception in a TRY control structure and can access the exception object using INTO. The code executed in the TRY block is called the protected area.

To be complete, also the meaning of CLEANUP shall be shown:


CLASS cx_demo0 DEFINITION INHERITING FROM cx_static_check.

ENDCLASS.

CLASS cx_demo1 DEFINITION INHERITING FROM cx_static_check.

ENDCLASS.

START-OF-SELECTION.

  DATA(exception) = `cx_demo1`.

  cl_demo_input=>request( CHANGING field = exception ).

  DATA exc TYPE REF TO cx_static_check.

  exc = COND #( WHEN exception = `cx_demo0` THEN NEW cx_demo0( )

                ELSE NEW cx_demo1( ) ).

  TRY.

      TRY.

          RAISE EXCEPTION exc.

        CATCH cx_demo0.

          cl_demo_output=>write( 'Catching cx_demo0' ).

        CLEANUP.

          cl_demo_output=>write( 'Cleanup' ).

      ENDTRY.

    CATCH cx_demo1.

      cl_demo_output=>write( 'Catching cx_demo1' ).

  ENDTRY.

  cl_demo_output=>display( ).


In this example you can decide whether to raise an exception of class cx_demo0 or cx_demo1.cx_demo0 is handled in the inner, cx_demo1 is handled in the outer TRY block. In the latter case, before leaving the inner TRY block, the CLEANUP block is executed, offering the opportunity to cleanup the inner TRY block. Not shown here, is the INTO addition, that can be used for CLEANUP too.


Well known facts available since Release 6.10 (yawn). Maybe not so well known are RETRY and RESUME introduced with Release 7.02.


RETRY

With RETRY you exit a CATCH block and jump back to the TRY statement of the current TRY control structure in order to retry the full TRY block. Of course you have to take care, that the exception does not re-occurr  again and again, otherwise you end up in an endless loop.

CLASS cx_demo DEFINITION INHERITING FROM cx_static_check.

ENDCLASS.


CLASS cls DEFINITION.

  PUBLIC SECTION.

    CLASS-DATA flag TYPE abap_bool.

    CLASS-METHODS meth RAISING cx_demo.

ENDCLASS.


CLASS cls IMPLEMENTATION.

  METHOD meth.

    ...

    IF flag = abap_false.

      cl_demo_output=>write( `Raising` ).

      RAISE EXCEPTION TYPE cx_demo.

    ENDIF.

    ...

  ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.

  TRY.

      cls=>meth( ).

    CATCH cx_demo.

      cl_demo_output=>write( `Handling` ).

      cls=>flag = abap_true.

      RETRY.

  ENDTRY.

  cl_demo_output=>display( ).


An exception is raised if some prerequisite (here a flag) is missing. During handling, the prerequisite is fullfilled and the execution of the protected area of the TRY block is repeated,


RESUME

With RESUME you you exit a CATCH block and resume processing after the statement that raised the exception. Prerequisites for that are:

  • The exception is resumable
  • The context of the exception is still available

CLASS cx_demo DEFINITION INHERITING FROM cx_static_check.

ENDCLASS.

CLASS cls DEFINITION.

  PUBLIC SECTION.

    CLASS-METHODS meth RAISING RESUMABLE(cx_demo).

ENDCLASS.

CLASS cls IMPLEMENTATION.

  METHOD meth.

    ...

    cl_demo_output=>write( `Raising` ).

    RAISE RESUMABLE EXCEPTION TYPE cx_demo.

    cl_demo_output=>write( 'Resuming ...' ).

    ...

  ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.

  TRY.

      cls=>meth( ).

    CATCH BEFORE UNWIND cx_demo.

      cl_demo_output=>write( `Handling` ).

      RESUME.

  ENDTRY.

  cl_demo_output=>display( ).

  • The property of being resumable is not part of an exception class but defined when raising an exception.
    • The addition RESUMABLE to RAISE raises an exception as a resumable exception.
    • The addition RESUMABLE to RAISING propagates a resumable exception (without, an resumable exception would lose this property during propagation).
  • The addition BEFORE UNWIND to CATCH takes care that the exception is caught before its context is deleted.

Maybe the information provided here can be useful for you.


For more infornation see Class-based Exceptions.





9 Comments