I would like to share with you some functionality I used in my last S/4HANA 2022 Assetmanagement Project to pass multiple messages from UserExits and BADIs to the UserInterface considering different UI-Technologies.
To maintain orders in Assetmanagement (SAP component PM-WOC-MO “Maintenance Orders”) we currently can use these UIs:
- classic WinGUI (e.g. Transaction IW32)
- htmlGUI (e.g. Transaction IW32 html-based)
- WebDynpro for ABAP (App EAMS_WDA_ORDNTF_OIF)
- Fiori/UI5 (e.g. App F2175 “Find Maintenance Orders”)
Depending on the UI, the message-handling in UserExits like IWO10002 “PM maintenance order: Customer check for order release” or BADIs like WORKORDER_UPDATE “Business Add-Inn PM/PP/PS/Pi Orders: Operation: UPDATE” can be quite different.
So during implementation of message-handling in some of these Exits/BADIs I had at first to determine the UI the User is currently using.
Thereafter, depending on the UI, two different ways have to be used, to send messages to the UI:
For Windows GUI and HTML-based WinGUI you can send the collected messages to the UI by a combination of the standard classic message-handling functions:
- CALL FUNCTION ‘MESSAGES_ACTIVE’
- CALL FUNCTION ‘MESSAGES_INITIALIZE’
- CALL FUNCTION ‘MESSAGE_STORE’
- CALL FUNCTION ‘MESSAGES_SHOW’
- CALL FUNCTION ‘MESSAGES_STOP’
As BAPI ‘BAPI_ALM_ORDER_MAINTAIN’ is used for the two UIs ‘WebDynpro’ and ‘Fiori/UI5’,
the messages have to be passed to the message-handler of the BAPI and from there they are automatically passed to the UI.
Function IBAPI_Z_MSG_STORE is used to send messages to the BAPIs’ message-handler.
Here is the complete ABAP-method I use, to pass multiple messages to the different UserInterfaces:
*"----------------------------------------------------------------------
*"Methoden Signatur:
*" Importing
*" MIT_RETURN TYPE BAPIRETTAB
*"----------------------------------------------------------------------
METHOD mess_show_4_order.
FIELD-SYMBOLS: <fs_v_log_handle> TYPE balloghndl.
FIELD-SYMBOLS: <fs_s_return> TYPE bapiret2.
DATA: lv_mess_ident TYPE sy-uzeit.
DATA: ls_keys_order TYPE cno1keys.
*- Nur wenn Nachrichten auszugeben sind
CHECK: mit_return IS NOT INITIAL.
*- GUI-Typ ermitteln
DATA(ls_gui) = znibadisexits=>get_ui_type( ).
CASE ls_gui-name.
WHEN 'WGU' OR 'HGU' OR 'BAT'. "Windows GUI / html-based GUI / Background
*- Prüfen, ob Message-Handler bereits aktiv ist
CALL FUNCTION 'MESSAGES_ACTIVE'
EXCEPTIONS
not_active = 1
OTHERS = 2.
IF sy-subrc <> 0.
*- Message-Handler ggf. aktivieren
CALL FUNCTION 'MESSAGES_INITIALIZE'
EXPORTING
i_store_duplicates = 'X'
i_allow_foreign_reset = 'X'
IMPORTING
e_identification = lv_mess_ident
EXCEPTIONS
log_not_active = 1
wrong_identification = 2
OTHERS = 3.
ENDIF.
*- Message an Message-Handler geben
LOOP AT mit_return ASSIGNING <fs_s_return>.
CALL FUNCTION 'MESSAGE_STORE'
EXPORTING
arbgb = <fs_s_return>-id
exception_if_not_active = ' '
msgty = <fs_s_return>-type
msgv1 = <fs_s_return>-message_v1
msgv2 = <fs_s_return>-message_v2
msgv3 = <fs_s_return>-message_v3
msgv4 = <fs_s_return>-message_v4
txtnr = <fs_s_return>-number
EXCEPTIONS
message_type_not_valid = 1
not_active = 2
OTHERS = 3.
IF sy-subrc <> 0.
* nothing to do here
ENDIF.
ENDLOOP.
CALL FUNCTION 'MESSAGES_SHOW'.
* EXPORTING
* I_USE_GRID = 'X'
* I_AMODAL_WINDOW = 'X'.
*- Sammeln von Nachrichten beenden
IF lv_mess_ident IS NOT INITIAL.
CALL FUNCTION 'MESSAGES_STOP'
EXPORTING
i_identification = lv_mess_ident
i_reset_messages = 'X'
EXCEPTIONS
OTHERS = 0.
ENDIF.
WHEN 'WDA' OR 'ODA' OR 'BSP'. "WebDynpro for ABAP / oData / Business Server Pages
***--- Prüfungen
*- Prüfen, ob Order-BAPI aktiv ist
CALL FUNCTION 'IBAPI_Z_GET_BAPI_FLAG'
EXCEPTIONS
bapi_active = 1
bapi_not_active = 2
OTHERS = 3.
IF sy-subrc = 1.
*- Prüfen, ob Message-Handling des BAPIs aktiv ist
ASSIGN ('(SAPLIBAPI_Z)GV_LOG_HANDLE') TO <fs_v_log_handle>.
IF sy-subrc IS INITIAL AND <fs_v_log_handle> IS NOT INITIAL.
***--- Ausführung
*- Übergeben der Messages aus SYST an das Appl.Log des BAPIs
LOOP AT mit_return ASSIGNING <fs_s_return>.
CLEAR: ls_keys_order.
IF <fs_s_return>-parameter IS NOT INITIAL.
IF <fs_s_return>-parameter(4) = 'AUFK'.
ls_keys_order = <fs_s_return>-parameter+4.
ENDIF.
ENDIF.
MESSAGE ID <fs_s_return>-id TYPE <fs_s_return>-type NUMBER <fs_s_return>-number
WITH <fs_s_return>-message_v1 <fs_s_return>-message_v2
<fs_s_return>-message_v3 <fs_s_return>-message_v4
INTO sy-lisel.
CALL FUNCTION 'IBAPI_Z_MSG_STORE'
EXPORTING
iv_aufnr = ls_keys_order-aufnr
iv_vornr = ls_keys_order-activity
iv_uvorn = ls_keys_order-sub_activity
iv_repid = sy-repid.
ENDLOOP.
ENDIF.
ENDIF.
WHEN 'BNP'. "BatchInput
LOOP AT mit_return ASSIGNING <fs_s_return>.
MESSAGE ID <fs_s_return>-id TYPE <fs_s_return>-type NUMBER <fs_s_return>-number
WITH <fs_s_return>-message_v1 <fs_s_return>-message_v2
<fs_s_return>-message_v3 <fs_s_return>-message_v4.
ENDLOOP.
WHEN OTHERS.
ENDCASE.
ENDMETHOD.
In my ABAP-code in an UserExit or BADI in Assetmanagement custom specific checks are done and messages are collected in an internal table. At the very end of the specific UserExit or BADI the above ABAP-method is called and the table with collected messages is passed to it. As a result, the messages are displayed to the user in an UI-specific way (see following examples for UserExit IWO10002 “PM maintenance order: Customer check for order release”):
Result for GUI and htmlGUI:
Result for WebDynpro:
Result for Fiori:
(As you can see, for Fiori App F2175 “Find Maintenance Orders” Action “Release” it is possible to pass multiple messages of multiple orders at once from UserExit IWO10002 “PM maintenance order: Customer check for order release” to the UI using above method.)
Please consider, that – when using the WebDynpro-App EAMS_WDA_ORDNTF_OIF – raising an exception or sending an error-message
in UserExit IWO10009 “PM Order: Customer check for ‘Save’ Event”
or
in BADI WORKORDER_UPDATE Methode AT_SAVE
is a showstopper and will lead the user to an “Error-Page”, not allowing to come back and work on the same data. Instead, all changes the user made will be lost and the user has to start the app from the beginning: