Quantcast
Channel: ABAP Development
Viewing all articles
Browse latest Browse all 948

Resumable exceptions

$
0
0

Resume code execution after an exception has been thrown can be very useful in several different scenarios (i.e. processing multiple materials and you want to process all but skip only those where there's an error)

 

This can be solved quite easily using resumable exceptions

 

First we define our exception class (can be global - defined in DDIC or locally defined). Nothing special needs to be specified here.

 

CLASS lcx_my_exception DEFINITION  INHERITING FROM cx_static_check.  PUBLIC SECTION.    DATA:      message TYPE char50.    METHODS:      constructor        IMPORTING          message TYPE char50 OPTIONAL.
ENDCLASS.                    "LCX_MY_EXCEPTION DEFINITION

CLASS lcx_my_exception IMPLEMENTATION.
  METHOD constructor.    super->constructor( ).    me->message = message.  ENDMETHOD.                    "CONSTRUCTOR
ENDCLASS.                    "LCX_MY_EXCEPTION IMPLEMENTATION

 

I will demonstrate both the classic exception and resumable exception on a division operation with methods DIVIDE and DIVIDE_RESUMABLE

 

CLASS lcl_math IMPLEMENTATION.  METHOD divide_resumable.    TRY.      IF i_denominator = 0.        RAISE RESUMABLE EXCEPTION TYPE lcx_my_exception          EXPORTING            message = 'Divide by zero with the following values:'.      ELSE.        result = i_numerator / i_denominator.      ENDIF.      WRITE:/ 'Numerator:', i_numerator,              'Denominator:', i_denominator.    ENDTRY.  ENDMETHOD.                    "divide_resumable  METHOD divide.    IF i_denominator = 0.      RAISE EXCEPTION TYPE lcx_my_exception        EXPORTING          message = 'Divide by zero with the following values:'.    ELSE.      result = i_numerator / i_denominator.    ENDIF.

* !!! NOT RESUMABLE !!!
* The following line will never be hit when denominator = 0
    WRITE:/ 'Numerator:', i_numerator,            'Denominator:', i_denominator.  ENDMETHOD.                    "divide
ENDCLASS.                    "lcl_math IMPLEMENTATION

 

Note the difference in raising commands:

Method DIVIDE_RESUMABLE

RAISE RESUMABLE EXCEPTION TYPE lcx_my_exception

 

Method DIVIDE

RAISE EXCEPTION TYPE lcx_my_exception

 

Here follows a demo program that calls the division operation in both resumable and non-resumable form:

 

DATA:  gr_ex    TYPE REF TO lcx_my_exception,  g_result TYPE anzh2,  g_err    TYPE abap_bool.

START-OF-SELECTION.
  TRY.      g_result = lcl_math=>divide(        i_numerator = 10        i_denominator = 0      ).

*     !!! NOT RESUMABLE !!!
*     The following CASE block will never be executed when denominator = 0      CASE g_err.        WHEN space.          WRITE:/ 'Result:', g_result.        WHEN OTHERS.          WRITE:/ 'Result undefined'.      ENDCASE.    CATCH lcx_my_exception INTO gr_ex.      g_err = abap_true.      WRITE:/ gr_ex->message.  ENDTRY.  SKIP 1.  CLEAR:    g_err,    gr_ex.  TRY.      g_result = lcl_math=>divide_resumable(        i_numerator = 10        i_denominator = 0      ).      CASE g_err.        WHEN space.          WRITE:/ 'Result:', g_result.        WHEN OTHERS.          WRITE:/ 'Result undefined'.      ENDCASE.    CATCH BEFORE UNWIND lcx_my_exception INTO gr_ex.      WRITE:/ gr_ex->message.      IF gr_ex->is_resumable = abap_true.        g_err = abap_true.        RESUME.      ENDIF.  ENDTRY.

 

 

Note the difference in catch commands:

Method DIVIDE_RESUMABLE (calls RESUME which returns to previous processing right after command which raised this exception)

 

CATCH BEFORE UNWIND lcx_my_exception INTO gr_ex.
...
RESUME

 

Method DIVIDE

 

CATCH lcx_my_exception INTO gr_ex.

 

And the output of this simple from is shown on follwing screenshot

 

 

Output of demo program for Resumable exceptions

 

 

This article has been taken from my blog at oprsteny.com


Viewing all articles
Browse latest Browse all 948

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>