Introduction
Recently SAP released several SOAP APIs (e.g. Order Confirmation, Customer Invoice and Outbound Delivery) for B2B scenarios, and standard interfaces of SAP Application Interface Framework (AIF) were also delivered by SAP accordingly. The APIs and AIF interfaces could be leveraged in B2B integration instead of using classical IDOC framework.
However, there is one general requirement in B2B integration, which is receiving functional acknowledgement from receivers (external business partners). In classical IDOC framework ALEAUD could be used, processing results could be sent back via IDOC ALEAUD and update the status of original outbound IDOCs accordingly (e.g. status 11 and 12).
In my blog, I would like to provide a similar solution like ALEAUD for those SOAP APIs, hereby customers could still receive functional acknowledgement when leveraging âmodernâ APIs in B2B scenarios.
Solution Design Concept
In AIF, there is a standard solution for Error Forwarding from Cloud Integration to S/4HANA, via a web service Error_Propagation_Request_In, errors in Cloud Integration could be posted in the Message Monitoring of AIF. But the web service is for inbound AIF interfaces, in case of a message to be posted in S/4HANA but get failure in Cloud Integration, the errors could be posted to AIF as an error message of the relevant AIF interface, so the service always creates a new AIF message with âtechnical errorâ.
In my solution, which is receiving acknowledgement for outbound scenarios, I would create a custom web service by reusing the same message type of standard Error_Propagation_Request_In, within the service implementing class Iâll call the same class (/aif/cl_enabler_cpi) called in the standard service, but update the existing outbound AIF message with the status and logs passed in the service payload.
Service Definition
Firstly, create a custom web service definition via transaction SPROXY_START. One of prerequisite is creating a custom namespace via transaction SPXNGENAPPL under Backend Metadata Repository:
In SPROXY_START, create a service provider by using âCreate with WIZARDâ (Shift+F5):
After completing the wizard, a custom web service has been defined (in my case the service was named Application_Acknowledgement_In):
Go to tab âInternal Viewâ, create an operation via âAdd Operationâ (right click menu), and then âSet Requestâ and assign standard Message Type Error_Propagation_Request, âAdd Faultâ and assign standard Fault Message Type Error_Propagation_Fault, the service definition is completed. Save and activate the service.
Next, navigate to the auto-generated implementing class, adding below codes to the method:
  METHOD zii_application_acknowledgemen~application_acknowledgement.
***Â ****Â INSERTÂ IMPLEMENTATIONÂ HEREÂ ****Â ***
    TYPES:
      BEGIN OF lty_msg_long,
        msgv1 TYPE symsgv,
        msgv2 TYPE symsgv,
        msgv3 TYPE symsgv,
        msgv4 TYPE symsgv,
      END OF lty_msg_long.
    DATA:
      lr_enabler_cpi TYPE REF TO /aif/cl_enabler_cpi,
      lr_system_uuid TYPE REF TO if_system_uuid,
      lv_uuid        TYPE sysuuid_c32,
      lv_status      TYPE /aif/proc_status,
      lv_msg_status  TYPE /aif/proc_status,
      ls_log_message TYPE bal_s_msg,
      ls_bal_context TYPE /aif/bal_context,
      ls_msg_long    TYPE lty_msg_long.
    DATA(ls_ep_message) = VALUE /aif/ep_message(
            message_processing_log_id = input-error_propagation_request-message_processing_log_id
            mpl_correlation_id        = input-error_propagation_request-mpl_correlation_id
            application_id            = input-error_propagation_request-application_id
            tenant_name               = input-error_propagation_request-tenant_name
            iflow_id                  = input-error_propagation_request-iflow_id
            namespace                 = input-error_propagation_request-namespace
            interface_name            = input-error_propagation_request-interface_name
            interface_version         = input-error_propagation_request-interface_version
            error_message             = input-error_propagation_request-error_message
            ).
    lv_uuid = input-error_propagation_request-application_id.
    lv_status = ls_ep_message-error_message+0(1).
    TRY.
        CREATE OBJECT lr_enabler_cpi
          EXPORTING
            iv_msgguid   = lv_uuid
            iv_ns        = ls_ep_message-namespace
            iv_ifname    = Ls_ep_message-interface_name
            iv_ifversion = ls_ep_message-interface_version.
        DATA(lt_log_message) = lr_enabler_cpi->prepare_log_messages( ls_ep_message ).
        DELETE lt_log_message FROM 1 TO 2.
        DELETE lt_log_message WHERE msgty = ‘I’ AND msgno = ‘005’.
        ls_msg_long(113) = ls_ep_message-error_message.
        IF lv_status EQ ‘S’.
          lv_msg_status = ‘I’.
        ELSE.
          lv_msg_status = lv_status.
        ENDIF.
        ls_log_message = VALUE bal_s_msg( context-tabname = ‘/AIF/BAL_CONTEXT’ context-value = ls_bal_context msgid = ‘/AIF/CPI_INTEGRATION’ msgty = lv_msg_status msgno = ‘006’ msgv1 = ls_msg_long-msgv1 msgv2 = ls_msg_long-msgv2 msgv3 =
ls_msg_long-msgv3Â ).
        INSERT ls_log_message INTO TABLE lt_log_message.
        TEST-SEAM call_base_enabler_update.
          CALL METHOD lr_enabler_cpi->/aif/if_enabler_base~update
            EXPORTING
              iv_message_status_flag = lv_status
              it_log_messages        = lt_log_message
              iv_user_name           = cl_abap_syst=>get_user_name( )
              iv_create_date         = sy-datum
              iv_create_time         = sy-uzeit.
        END-TEST-SEAM.
      CATCH cx_root INTO DATA(lr_root).
        RAISE EXCEPTION TYPE /aif/cx_error_propagation_faul EXPORTING previous = lr_root.
    ENDTRY.
  ENDMETHOD.
Comments: To save effort I was using /aif/cl_enabler_cpi->prepare_log_messages to prepare log messages, in actual implementation you could create your own log messages without using the method.
Test Scenario
You could publish the web service via SOAMANAGER so it could be called by soapUI or any applications/middleware, below are explanations of how to fill the payload:
MessageProcessingLogID and MplCorrelationID – if youâre using Cloud Integration to call the service, those IDs are from the Cloud Integration message, standard Error Propagation service stores the IDs to avoid duplicate posting, here since weâre updating the existing AIF messages, those IDs could be dummy.
ApplicationID â I use the field to store the original outbound message ID, the outbound messages pass the message ID in the message header, receivers have to store the ID and pass it back in the acknowledgement, it is mandatory for the solution.
TenantName and IFlowID â if youâre using Cloud Integration, those are information of your tenant and iFlow to call the service, if youâre not using Cloud Integration, those fields could be dummy
Namespace, InterfaceName and InterfaceVersion â the AIF interface which the original outbound messages are belonged to.
ErrorMessage â Iâm assuming the error message returning in format <status>:<logs>, <status> has to be one of the AIF message status (W/S/E/A) which would be used to update the status of original AIF messages.
Note: payload of standard Error Propagation service was explained in the blog for your reference.
For my test case, I had a message (000003) sent to the receiver successfully:
Then assuming the receiver return an error with below payload:
After posting the message shown with application error in AIF message monitoring:
Summary
This blog post gave an introduction on building a custom web service to receive functional acknowledgement from external receivers/middleware for outbound AIF messages and update the message status and logs in AIF Message Monitor. This is a very simple implementation just for reference and therefore more comprehensive and standardized implementation required in actual project.
Â
â IntroductionRecently SAP released several SOAP APIs (e.g. Order Confirmation, Customer Invoice and Outbound Delivery) for B2B scenarios, and standard interfaces of SAP Application Interface Framework (AIF) were also delivered by SAP accordingly. The APIs and AIF interfaces could be leveraged in B2B integration instead of using classical IDOC framework.However, there is one general requirement in B2B integration, which is receiving functional acknowledgement from receivers (external business partners). In classical IDOC framework ALEAUD could be used, processing results could be sent back via IDOC ALEAUD and update the status of original outbound IDOCs accordingly (e.g. status 11 and 12).In my blog, I would like to provide a similar solution like ALEAUD for those SOAP APIs, hereby customers could still receive functional acknowledgement when leveraging âmodernâ APIs in B2B scenarios.Solution Design ConceptIn AIF, there is a standard solution for Error Forwarding from Cloud Integration to S/4HANA, via a web service Error_Propagation_Request_In, errors in Cloud Integration could be posted in the Message Monitoring of AIF. But the web service is for inbound AIF interfaces, in case of a message to be posted in S/4HANA but get failure in Cloud Integration, the errors could be posted to AIF as an error message of the relevant AIF interface, so the service always creates a new AIF message with âtechnical errorâ.In my solution, which is receiving acknowledgement for outbound scenarios, I would create a custom web service by reusing the same message type of standard Error_Propagation_Request_In, within the service implementing class Iâll call the same class (/aif/cl_enabler_cpi) called in the standard service, but update the existing outbound AIF message with the status and logs passed in the service payload.Service DefinitionFirstly, create a custom web service definition via transaction SPROXY_START. One of prerequisite is creating a custom namespace via transaction SPXNGENAPPL under Backend Metadata Repository:In SPROXY_START, create a service provider by using âCreate with WIZARDâ (Shift+F5):After completing the wizard, a custom web service has been defined (in my case the service was named Application_Acknowledgement_In):Go to tab âInternal Viewâ, create an operation via âAdd Operationâ (right click menu), and then âSet Requestâ and assign standard Message Type Error_Propagation_Request, âAdd Faultâ and assign standard Fault Message Type Error_Propagation_Fault, the service definition is completed. Save and activate the service.Next, navigate to the auto-generated implementing class, adding below codes to the method:  METHOD zii_application_acknowledgemen~application_acknowledgement.*** **** INSERT IMPLEMENTATION HERE **** ***    TYPES:      BEGIN OF lty_msg_long,        msgv1 TYPE symsgv,        msgv2 TYPE symsgv,        msgv3 TYPE symsgv,        msgv4 TYPE symsgv,      END OF lty_msg_long.    DATA:      lr_enabler_cpi TYPE REF TO /aif/cl_enabler_cpi,      lr_system_uuid TYPE REF TO if_system_uuid,      lv_uuid        TYPE sysuuid_c32,      lv_status      TYPE /aif/proc_status,      lv_msg_status  TYPE /aif/proc_status,      ls_log_message TYPE bal_s_msg,      ls_bal_context TYPE /aif/bal_context,      ls_msg_long    TYPE lty_msg_long.    DATA(ls_ep_message) = VALUE /aif/ep_message(            message_processing_log_id = input-error_propagation_request-message_processing_log_id            mpl_correlation_id        = input-error_propagation_request-mpl_correlation_id            application_id            = input-error_propagation_request-application_id            tenant_name               = input-error_propagation_request-tenant_name            iflow_id                  = input-error_propagation_request-iflow_id            namespace                 = input-error_propagation_request-namespace            interface_name            = input-error_propagation_request-interface_name            interface_version         = input-error_propagation_request-interface_version            error_message             = input-error_propagation_request-error_message            ).    lv_uuid = input-error_propagation_request-application_id.    lv_status = ls_ep_message-error_message+0(1).    TRY.        CREATE OBJECT lr_enabler_cpi          EXPORTING            iv_msgguid   = lv_uuid            iv_ns        = ls_ep_message-namespace            iv_ifname    = Ls_ep_message-interface_name            iv_ifversion = ls_ep_message-interface_version.        DATA(lt_log_message) = lr_enabler_cpi->prepare_log_messages( ls_ep_message ).        DELETE lt_log_message FROM 1 TO 2.        DELETE lt_log_message WHERE msgty = ‘I’ AND msgno = ‘005’.        ls_msg_long(113) = ls_ep_message-error_message.        IF lv_status EQ ‘S’.          lv_msg_status = ‘I’.        ELSE.          lv_msg_status = lv_status.        ENDIF.        ls_log_message = VALUE bal_s_msg( context-tabname = ‘/AIF/BAL_CONTEXT’ context-value = ls_bal_context msgid = ‘/AIF/CPI_INTEGRATION’ msgty = lv_msg_status msgno = ‘006’ msgv1 = ls_msg_long-msgv1 msgv2 = ls_msg_long-msgv2 msgv3 =ls_msg_long-msgv3 ).        INSERT ls_log_message INTO TABLE lt_log_message.        TEST-SEAM call_base_enabler_update.          CALL METHOD lr_enabler_cpi->/aif/if_enabler_base~update            EXPORTING              iv_message_status_flag = lv_status              it_log_messages        = lt_log_message              iv_user_name           = cl_abap_syst=>get_user_name( )              iv_create_date         = sy-datum              iv_create_time         = sy-uzeit.        END-TEST-SEAM.      CATCH cx_root INTO DATA(lr_root).        RAISE EXCEPTION TYPE /aif/cx_error_propagation_faul EXPORTING previous = lr_root.    ENDTRY.  ENDMETHOD.Comments: To save effort I was using /aif/cl_enabler_cpi->prepare_log_messages to prepare log messages, in actual implementation you could create your own log messages without using the method.Test ScenarioYou could publish the web service via SOAMANAGER so it could be called by soapUI or any applications/middleware, below are explanations of how to fill the payload:MessageProcessingLogID and MplCorrelationID – if youâre using Cloud Integration to call the service, those IDs are from the Cloud Integration message, standard Error Propagation service stores the IDs to avoid duplicate posting, here since weâre updating the existing AIF messages, those IDs could be dummy.ApplicationID â I use the field to store the original outbound message ID, the outbound messages pass the message ID in the message header, receivers have to store the ID and pass it back in the acknowledgement, it is mandatory for the solution.TenantName and IFlowID â if youâre using Cloud Integration, those are information of your tenant and iFlow to call the service, if youâre not using Cloud Integration, those fields could be dummyNamespace, InterfaceName and InterfaceVersion â the AIF interface which the original outbound messages are belonged to.ErrorMessage â Iâm assuming the error message returning in format <status>:<logs>, <status> has to be one of the AIF message status (W/S/E/A) which would be used to update the status of original AIF messages.Note: payload of standard Error Propagation service was explained in the blog for your reference.For my test case, I had a message (000003) sent to the receiver successfully:Then assuming the receiver return an error with below payload:After posting the message shown with application error in AIF message monitoring:SummaryThis blog post gave an introduction on building a custom web service to receive functional acknowledgement from external receivers/middleware for outbound AIF messages and update the message status and logs in AIF Message Monitor. This is a very simple implementation just for reference and therefore more comprehensive and standardized implementation required in actual project.   Read More Technology Blogs by SAP articlesÂ
#SAP
#SAPTechnologyblog