‎2023 Feb 27 12:16 PM
Dear SAP,
I have created a very simple daemon:
CLASS ycl_amar_simple_daemon DEFINITION
PUBLIC
INHERITING FROM cl_abap_daemon_ext_base
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
METHODS: if_abap_daemon_extension~on_error REDEFINITION,
if_abap_daemon_extension~on_message REDEFINITION,
if_abap_daemon_extension~on_restart REDEFINITION,
if_abap_daemon_extension~on_server_shutdown REDEFINITION,
if_abap_daemon_extension~on_accept REDEFINITION,
if_abap_daemon_extension~on_start REDEFINITION,
if_abap_daemon_extension~on_stop REDEFINITION,
if_abap_daemon_extension~on_system_shutdown REDEFINITION,
if_abap_daemon_extension~on_before_restart_by_system REDEFINITION.
CLASS-METHODS start
RAISING
cx_abap_daemon_error
cx_ac_message_type_pcp_error.
CLASS-METHODS send_cmd.
PROTECTED SECTION.
PRIVATE SECTION.
CONSTANTS co_daemon_name TYPE if_abap_daemon_types=>ty_abap_daemon_name VALUE 'SIMPLE_DM'.
CONSTANTS co_daemon_class TYPE if_abap_daemon_types=>ty_abap_daemon_class_name VALUE 'YCL_AMAR_SIMPLE_DAEMON'.
CONSTANTS co_event TYPE string VALUE 'MSG'.
ENDCLASS.
CLASS ycl_amar_simple_daemon IMPLEMENTATION.
METHOD if_abap_daemon_extension~on_accept.
TRY.
DATA lv_program_name TYPE program.
lv_program_name = cl_oo_classname_service=>get_classpool_name( co_daemon_class ).
IF i_context_base->get_start_caller_info( )-program = lv_program_name.
e_setup_mode = co_setup_mode-accept.
ELSE.
e_setup_mode = co_setup_mode-reject.
ENDIF.
CATCH cx_abap_daemon_error.
" to do: error handling, e.g. write error log!
e_setup_mode = co_setup_mode-reject.
ENDTRY.
ENDMETHOD.
METHOD if_abap_daemon_extension~on_before_restart_by_system.
ENDMETHOD.
METHOD if_abap_daemon_extension~on_error.
data(lv_data) = 'DUMMY'.
ENDMETHOD.
METHOD if_abap_daemon_extension~on_message.
DATA lt_return TYPE STANDARD TABLE OF bapiret2.
DATA(lv_value) = i_message->get_field( i_name = co_event ).
CALL FUNCTION 'YAMAR_DAEMON_FB_1'
TABLES
return = lt_return.
ENDMETHOD.
METHOD if_abap_daemon_extension~on_restart.
ENDMETHOD.
METHOD if_abap_daemon_extension~on_server_shutdown.
ENDMETHOD.
METHOD if_abap_daemon_extension~on_start.
ENDMETHOD.
METHOD if_abap_daemon_extension~on_stop.
ENDMETHOD.
METHOD if_abap_daemon_extension~on_system_shutdown.
ENDMETHOD.
METHOD start.
TRY.
" start the daemon application using the ABAP Daemon Manager
cl_abap_daemon_client_manager=>start(
i_class_name = co_daemon_class
i_name = co_daemon_name
i_priority = cl_abap_daemon_client_manager=>co_session_priority_low
).
CATCH cx_static_check INTO DATA(lx_exc).
/slag/01cl_arc_exc_helper=>raise_as_arc_exc( ix_exc = lx_exc ).
ENDTRY.
ENDMETHOD.
METHOD send_cmd.
" retrieve the list of ABAP Daemon instances
DATA(lt_ad_info) = cl_abap_daemon_client_manager=>get_daemon_info( i_class_name = co_daemon_class ).
" create PCP message with text
DATA(lo_pcp) = cl_ac_message_type_pcp=>create( ).
lo_pcp->set_field( i_name = co_event
i_value = 'GREETING'
).
" for each running daemon instance of this class
LOOP AT lt_ad_info ASSIGNING FIELD-SYMBOL(<ls_info>).
" send a message if the names match
IF co_daemon_name = <ls_info>-name.
cl_abap_daemon_client_manager=>attach( <ls_info>-instance_id )->send( lo_pcp ).
ENDIF.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
Inside the ON_MESSAGE method the function module YAMAR_DAEMON_FB_1 will be called (very simple implementation for demonstration purpose).
FUNCTION yamar_daemon_fb_1
TABLES
return LIKE bapiret2.
DATA lv_greeting TYPE string.
CALL FUNCTION 'YAMAR_DAEMON_FB_2'
EXPORTING
iv_throw = abap_false
IMPORTING
ev_result = lv_greeting.
CALL FUNCTION 'YAMAR_DAEMON_FB_2'
EXPORTING
iv_throw = abap_false
IMPORTING
ev_result = lv_greeting.
CALL FUNCTION 'YAMAR_DAEMON_FB_2'
EXPORTING
iv_throw = abap_true
IMPORTING
ev_result = lv_greeting
EXCEPTIONS
error_message = 1
OTHERS = 2.
IF sy-subrc <> 0.
APPEND VALUE #( type = 'E' id = 'GZ' number = '237' ) TO return.
ENDIF.
CALL FUNCTION 'YAMAR_DAEMON_FB_2'
EXPORTING
iv_throw = abap_false
IMPORTING
ev_result = lv_greeting.
ENDFUNCTION.
And implementation of FB YAMAR_DAEMON_FB_2
FUNCTION yamar_daemon_fb_2
IMPORTING
iv_throw TYPE abap_boolean
EXPORTING
ev_result TYPE string.
IF iv_throw = abap_true.
MESSAGE e237(gz).
ENDIF.
ev_result = |greeting from FB|.
ENDFUNCTION.
The problem that I encounter is this line of code:
CALL FUNCTION 'YAMAR_DAEMON_FB_2'
EXPORTING
iv_throw = abap_true
IMPORTING
ev_result = lv_greeting
EXCEPTIONS
error_message = 1
OTHERS = 2.
IF sy-subrc <> 0.
APPEND VALUE #( type = 'E' id = 'GZ' number = '237' ) TO return.
ENDIF.
When the line above gets called it will trigger the ON_ERROR hook from the class YCL_AMAR_SIMPLE_DAEMON because of the line:
MESSAGE e237(gz).
According to the ABAP daemon documentation (https://help.sap.com/docs/ABAP_PLATFORM_NEW/753088fc00704d0a80e7fbd6803c8adb/3d31e40f220d4904ad3a54fd775022d4.html?version=201809.001) when during the execution the daemon encounters the message type E/A/X then the ON_ERROR method is called.
I would like to prevent that the ON_ERROR method is getting called when an error occurs because I would like to collect all the BAPI return messages and store into a table.
The same happens when I call the function module BAPI_ACC_DOCUMENT_CHECK inside the daemon that can also cause MESSAGE e237(gz) which is an error type.
Best regards,
Anu
‎2023 Feb 27 12:38 PM
Please edit your question, select your code and press the button [CODE], which makes the code appear colored/indented, it will be easier for people to look at it. Thank you!
‎2023 Feb 27 12:52 PM
I see in the ABAP documentation that it's not very clear if the message A/E/X can be handled in Dynpro/PAI logic using ERROR_MESSAGE or if it's different in the context of ABAP Daemon:
ABAP Keyword Documentation - Messages - Behavior



For true BAPI I think it's abnormal to make BAPI fail with message A/E/X, I would contact the SAP support, although I think they would be reluctant to fix the error just for making it work in the context of ABAP Daemon, but who knows.
Otherwise, maybe a workaround could be to call the BAPI in the context of PAI (e.g. SUPPRESS DIALOG) or RFC to see if ERROR_MESSAGE works better.
‎2023 Feb 27 1:51 PM