03-06-2024 2:13 PM - edited 03-07-2024 9:04 AM
Hi all,
I have encountered an interesting phenomenon while re-raising a class-based exception. To not waste your precious time, here's the code:
CLASS exception_1 DEFINITION INHERITING FROM cx_static_check.
ENDCLASS.
CLASS exception_2 DEFINITION INHERITING FROM cx_static_check.
ENDCLASS.
CLASS class_1 DEFINITION.
PUBLIC SECTION.
CLASS-METHODS
do_something
RAISING
exception_1
exception_2.
ENDCLASS.
CLASS class_2 DEFINITION.
PUBLIC SECTION.
CLASS-METHODS
do_something
RAISING
exception_1
exception_2.
ENDCLASS.
TRY.
class_2=>do_something( ).
CATCH exception_1
exception_2 INTO DATA(exception).
exception->get_source_position( IMPORTING source_line = DATA(source_line) ).
BREAK-POINT.
ENDTRY.
CLASS class_1 IMPLEMENTATION.
METHOD do_something.
RAISE EXCEPTION TYPE exception_1.
ENDMETHOD.
ENDCLASS.
CLASS class_2 IMPLEMENTATION.
METHOD do_something.
TRY.
class_1=>do_something( ).
CATCH exception_1
exception_2 INTO DATA(exception).
RAISE EXCEPTION exception.
ENDTRY.
ENDMETHOD.
ENDCLASS.
There are two problems with this code. Firstly, although it is syntactically correct and does not produce any side effects, at least not any I know, I get a warning from syntax checker, saying there is an exception of type CX_STATIC_CHECK, raised at line 49 (47 in above code), which is neither caught, nor is it declared in the RAISING clause.
But there is no such exception! It will be either EXCEPTION_1 or EXCEPTION_2 and if you analyze the code and its flow, you will see that the reference is kept. This warning is however only then reported, when at least two exception classes are caught. First I thought, maybe because CX_STATIC_CHECK is the common super class for both EXCEPTION_1 and EXCEPTION_2. So I changed the inheritance of one of them to CX_NO_CHECK. I still get the same warning. Even if I change the inheritance of them both, the warning still says exception CX_STATIC_CHECK is not handled properly.
This "error" is reported with priority 1. I know, I can change the priorities in customizing, but 1 is okay for the real errors. And it can't be suppressed with pragma or pseudo comment. I would have to request an exemption. Or "correct" it by declaring CX_STATIC_CHECK in the RAISING clause, which however is not needed from the code perspective and would be wrong if not all declared exceptions inherit from CX_STATIC_CHECK.
I think it's a bug in syntax check, but am not quite sure, wanted to know your opinion first. I can reproduce it in 7.57 and 7.40.
The second problem I have with this code is that the original source position details get lost! The method GET_SOURCE_POSITION in the above example will give back line 47 and not 37. In the real case I wanted to work with RESUME. Here's the code:
CLASS exception_1 DEFINITION INHERITING FROM cx_dynamic_check.
ENDCLASS.
CLASS exception_2 DEFINITION INHERITING FROM cx_dynamic_check.
ENDCLASS.
CLASS class_1 DEFINITION.
PUBLIC SECTION.
CLASS-METHODS
do_something
IMPORTING
input TYPE i
RAISING
RESUMABLE(exception_1)
RESUMABLE(exception_2).
ENDCLASS.
CLASS class_2 DEFINITION.
PUBLIC SECTION.
CLASS-METHODS
do_something
IMPORTING
input TYPE i
RAISING
RESUMABLE(exception_1)
RESUMABLE(exception_2).
ENDCLASS.
TRY.
class_2=>do_something( 1 ).
CATCH exception_1
exception_2 INTO DATA(exception).
exception->get_source_position( IMPORTING source_line = DATA(source_line) ).
BREAK-POINT.
ENDTRY.
CLASS class_1 IMPLEMENTATION.
METHOD do_something.
CASE input.
WHEN 1.
RAISE RESUMABLE EXCEPTION TYPE exception_1.
WHEN 2.
RAISE RESUMABLE EXCEPTION TYPE exception_2.
WHEN 3.
RAISE EXCEPTION TYPE exception_1.
WHEN OTHERS.
RAISE EXCEPTION TYPE exception_2.
ENDCASE.
ENDMETHOD.
ENDCLASS.
CLASS class_2 IMPLEMENTATION.
METHOD do_something.
TRY.
class_1=>do_something( input ).
CATCH BEFORE UNWIND exception_1
exception_2 INTO DATA(exception).
IF exception->is_resumable = abap_true.
RESUME.
ELSE.
RAISE EXCEPTION exception.
ENDIF.
ENDTRY.
ENDMETHOD.
ENDCLASS.
In my real life scenario, the method which is causing an exception, couls sometimes proceed. Like for example getting an e-mail address for a business partner. If there is no valid address or only one, then it's clear. But if there are multiple valid addresses? The method could just proceed with any valid address. But it can't decide on its own. That's why a resumable exception, and if the caller resumes, then it's okay to use just any valid address. I don't want to pass the resumable exception up to the main program - it's to far, it can't decide whether it was okay, that the address was not unique or not. That's why I'm catching the exceptions and if they're resumable then I'm resuming, and if not, I would like to proceed with the original flow of RAISE EXCEPTION. But apparently I can't?
Do you know any way to solve this problem?
I'll be glad to hear back from you, what's your idea on the two questions.
Many thanks in advance!
Best regards
Michał
User | Count |
---|---|
83 | |
10 | |
10 | |
9 | |
7 | |
6 | |
6 | |
6 | |
5 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.