Note: original of this article comes from my blog at oprsteny.com
In this article I'd like to present a solution how to implement a global class where all internalexceptions (exceptions raised by private methods only ⇒ always catched within the class itself) will be handled with its local exception class.
It is generally possible (and recommended) to use global exception classes but sometimes you can find a local exception class be more practical (no DDIC entries, no heavy coding/maintenance, ...).
I also wanted a simple solution supporting WHERE-USED functionality for all messages defined in SE91 which can be generated in my program's exceptions.
Sadly it is not possible to create a local exception class in a global class's "local definitions" section AND use it in the global class method's EXCEPTIONS section.
This is because such local exception class is NOT visible from the global point of view as will be demonstrated in the following few steps.
Navigation to the global class's local definitions & implementations:
Here follows our local exception class definition which I entered in the "Local Class Definitions/Types" section
CLASS lcx_exception DEFINITION INHERITING FROM cx_static_check. PUBLIC SECTION. METHODS: constructor, get_text REDEFINITION. CLASS-DATA:
* Statically accessible variable - the reason will be shown later message TYPE bapiret2-message. PRIVATE SECTION. DATA: mv_message TYPE bapiret2-message.
ENDCLASS.
I keep the local exception class implementation very simple:
CLASS lcx_exception IMPLEMENTATION. METHOD constructor. super->constructor( ).
* Save the static variable to instance variable me->mv_message = lcx_exception=>message. ENDMETHOD. METHOD get_text.
* Return message from the instance variable result = me->mv_message. ENDMETHOD.
ENDCLASS.
Now try to create new class method (called e.g. TEST_METHOD), which would like to raise exceptions of type LCX_EXCEPTION - you can see the system reacts with popup message saying that such exception class is NOT KNOWN!!!
...so the system offers to create a new GLOBAL exception class - but this is not what we wanted.
Therefore the class method must raise a generic exception (e.g. CX_STATIC_CHECK) or a global exception from which your local exception class is inheriting from.
In the caller method (called e.g. RUN_TEST) you handle the exception occurrence like it was of you local exception class type.
METHOD run_test. DATA: lr_my_exception TYPE REF TO lcx_exception, lr_static_exception TYPE REF TO cx_static_check, lv_message TYPE bapiret2-message. TRY. me->test_method( ).
* Catch my locally defined exception CATCH lcx_exception INTO lr_my_exception. lv_message = lr_my_exception->get_text( ). WRITE lv_message.
* Catch any other exception of type CX_STATIC_CHECK CATCH cx_static_check INTO lr_static_exception. lv_message = lr_static_exception->get_text( ). WRITE lv_message. ENDTRY.
ENDMETHOD.
The code of the method TEST_METHOD being called would be like this:
METHOD test_method. MESSAGE e001(ztest) WITH 'ZCL_EXCEPTION_DEMO-TEST_METHOD' INTO lcx_exception=>message. RAISE EXCEPTION TYPE lcx_exception.
ENDMETHOD.
Important note:
In the above code please note the MESSAGE command.
Thanks to this command SAP system is able to find usage of the applied message with the WHERE-USED functionality from SE91
For testing purposes I created simple program that proves our solution:
REPORT zr_test_local_exceptions.
DATA: lr_demo TYPE REF TO zcl_exception_demo.
START-OF-SELECTION.
CREATE OBJECT lr_demo. lr_demo->run_test( ).
...and here comes the output: