PLM Enterprise Asset Management (EAM)/Plant Maintenance (PM)

How to pass multiple messages from ABAP (Exit/BADI) to the UserInterfaces in S/4HANA-Assetmanagement

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: