Skip to Content
Technical Articles
Author's profile photo stephen xue

Push S/4 HANA Data Event to BTP Event Mesh in ABAP OO Mode

Introduction

SAP has provided two native components “Enterprise Event Enablement” and “SAP Netweaver Addon for Event Enablement”. In the document, the component “SAP Netweaver Addon for Event Enablement” will be used.

I have get lots of helps from Zhang, Fiona’s blog post on how to push Data Event from S4 into Event Mesh. Whereas in most cases, the event message will be in deep structure rather than a flat structure. Please go through the rest of section for how to implement it via the framework.

Scope

This is not an end-to-end tutorial. The miss part can be found in Fiona’s blog post.

In scope

  • SAP addon configuration
  • Enhancement implementation

Out  scope

  • Event Mesh configuration
  • BTP service configuration

Prerequisit

  1. BTP Event Mesh is working and Service Key has been generated.
  2. SAP Netweaver Addon for Event Mesh has been installed
  3. RFC Destination to Event Mesh and Token has been configured

if above steps have not been done, please check the details steps in Fiona’s blog post

Implement Steps

In the example below, a purchase order create event is going to raised from S/4 hana. The event has header-item two layers. Different from all of the relevant blog posts using BOR object, the ABAP OO object will be used to raise the event. The effect would be the same. But just introduce a different way.

Create Custom ABAP Class Event

The class should be compatible with SAP business workflow. The implementation steps are exactly the same. If you are familar with the business workflow via ABAP OO, you can ignore this part.

  1. Interface

The class should inherit interface IT_WORKFLOW

2. Attribute

Add two attributes to the class as below. Since the class is for purchase order, the key should be with type EKKO-EBELN

 

3. Constructor Method

Once the interface has been added, there will few methods inherited from the interface. Please add a custom constructor method

with following source code inside

  METHOD constructor.
    DATA(lv_class_name) = cl_abap_classdescr=>get_class_name( me ).
    SPLIT lv_class_name+1 AT '=' INTO TABLE DATA(lt_class_name).
    me->_por-catid  = lt_class_name[ 1 ].
    me->_por-typeid = lt_class_name[ 2 ].
    me->_por-instid = im_order.
    ME->_key        = im_order.
  ENDMETHOD.

This is how the method looks like

4. Method BI_PERSISTENT~FIND_BY_LPOR

  METHOD bi_persistent~find_by_lpor.
    DATA(lv_order) = CONV ebeln( lpor-instid(10) ).
    result = NEW zcl_purchase_order( lv_order ).
  ENDMETHOD.

5. Method BI_PERSISTENT~LPOR

  METHOD bi_persistent~lpor.
    result = _por.
  ENDMETHOD.

6. Rest of Methods

For rest of methods, just activate them with empty source code.

7. Class Event

Create an event with name on_create. You can make any names making sense. There is no need add any parameters to the event. The event information will not be transfered via the parameter.

 

Create Virtual Message Type

The message type is a virtune entity used by the framework. Itself doen’t contain any structure information.

use tcode WE81 to create the message type

Activate the message type via BD50

Create Event Message Structure

This  is the place define the event message structure. This is the structure of purchase order header. in order to make everything simple, it just contains order id and header text. Item field’s type is a table type so that it can be an array in the runtime.

 

This is the item structure. Remember, once create it, please create a table type referring this basic structure, which will be used in the header struture for item type.

now the structure will have two layers.

Link Change Document Object to Custom Event

tcode: SWEC

The mechanism of ‘SAP Netweaver Addon for Event Enablement’ is triggered via the ‘Change Document Object’. here we link the change document object of purchase order creation to the custom event create just now.

The change document object for purchase order is: EINKBELEG

tip: please search table TCDOB for relevant change document object. Furthermore you can create your own custom change document object for your specific requirement.

Configure Replicate Object

This is the main configuration of the component ‘SAP Netweaver Addon for Event Enablement’.

Spro –> integration with other SAP component –> SAP Netweaver AddOn for Event enablement –> connection and Replication Object Custominzing

  1. Connection Instance

Please record the name of instance. Here BTP_EVENT_MESH has been used. It will be used later. For the RFC destination configuration, please check Fiona’s blog post.

 

2. Outbound Object

Fill the value as below

Explain:

  1. Object name is PO_CREATE. Please record it since it will be used in the filter later.
  2. The SAP native extractor FM for Data Event is /ASADEV/ACI_GEN_VIEW_EXTRACTOR. However this guy can only handle view, which is a flat structure. We will create a custom one replacing it. Fill name ZACI_EVENT_EXTRACTOR here.
  3. Virtual Message type
  4. Select as disaplayed
  5. SAP EM
  6. The SAP native format FM for Data Event is /ASADEV/ACI_GEN_VIEWFRM_SAP_EM. Again the limitation of guy is it only work for flat structure. We will create a custom one replacing it. Fill name ZACI_EVENT_TO_JSON here.

3. Configure Header Attributes

ACI_VIEW should be the event message type created just now.

SAP_EM_TOPIC should be the topic configured in the BTP Event Mesh.

Link Custome Event and Virtual Message Type

tcode SWE2

Receiver Type is the virtual message type created just now.

Receiver FM is /ASADEV/ACI_EVENTS_TRIGGER

Do not forget the check the flag for linkage activation.

tip: the switch for ‘Linkage Activated’ can be used to switch on/off event connection.

Implement Relevant FM of Replicate Object

  1. Format FM zaci_event_to_json

The way to generate json string from ABAP structure is vary. You can develop own way as well. Just to make sure the parameters should be identical.

FUNCTION zaci_event_to_json .
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IR_DATA) TYPE  DATA
*"     VALUE(IV_INSTANCE) TYPE  /ASADEV/AMR_ARIBA_ARIBA_INST
*"     VALUE(IV_OBJECT) TYPE  /ASADEV/AMR_ARIBA_ARIBA_OBJECT
*"  EXPORTING
*"     REFERENCE(ET_CSV_LINES) TYPE  /ASADEV/AMR_TT_CSV_LINE
*"     REFERENCE(ET_RETURN) TYPE  /ASADEV/ACI_TT_BAPIRET2
*"----------------------------------------------------------------------

  DATA:
    lt_csv_lines          TYPE /asadev/amr_tt_csv_line, "
    lt_csv_bundle         TYPE /asadev/amr_tt_csv_line, "
    ls_amr_obj            TYPE /asadev/amr_obj,  "
    ls_csv_line           TYPE LINE OF /asadev/amr_tt_csv_line.

  CONSTANTS:  lc_attr_db_name TYPE /asadev/aci_def_attr VALUE 'ACI_VIEW'.
  FIELD-SYMBOLS: <ft_data>    TYPE ANY TABLE.

  "get the data:
  ASSIGN ir_data->* TO <ft_data>.
  IF sy-subrc NE 0 OR <ft_data> IS INITIAL.
    RETURN.
  ENDIF.

  " convert data into json
  DATA(lv_json) = /ui2/cl_json=>serialize(
       data        = <ft_data>
       pretty_name = /ui2/cl_json=>pretty_mode-low_case ).

  APPEND lv_json to lt_csv_lines.
  ls_amr_obj = /asadev/cl_aci_helper=>get_aci_object(
               iv_instance = iv_instance
               iv_object   = iv_object ).

*MOD-003 bundle as many csv_lines as customized into one cloud event
  LOOP AT lt_csv_lines INTO ls_csv_line.
    APPEND ls_csv_line TO lt_csv_bundle.
    IF lines( lt_csv_bundle ) EQ ls_amr_obj-item_lines.
      " now wrap the payload in the cloudevents header
      CALL FUNCTION '/ASADEV/ACI_SAP_EM_CLOUDEV_FM'
        EXPORTING
          it_csv_lines = lt_csv_bundle
          iv_instance  = iv_instance
          iv_object    = iv_object
        IMPORTING
          et_csv_lines = lt_csv_bundle
          et_return    = et_return.

      APPEND LINES OF lt_csv_bundle TO et_csv_lines.
      IF ls_amr_obj-item_lines GT 0.
        DO ls_amr_obj-item_lines - 1 TIMES.
          APPEND INITIAL LINE TO et_csv_lines.
        ENDDO.
      ENDIF.
      CLEAR lt_csv_bundle.
    ENDIF.
  ENDLOOP.

  "Append the remaining lines
  IF lines( lt_csv_bundle ) GE 1.
    CALL FUNCTION '/ASADEV/ACI_SAP_EM_CLOUDEV_FM'
      EXPORTING
        it_csv_lines = lt_csv_bundle
        iv_instance  = iv_instance
        iv_object    = iv_object
      IMPORTING
        et_csv_lines = lt_csv_bundle
        et_return    = et_return.

    APPEND LINES OF lt_csv_bundle TO et_csv_lines.
    IF ls_amr_obj-item_lines GT 0.
      DO ls_amr_obj-item_lines - 1 TIMES.
        APPEND INITIAL LINE TO et_csv_lines.
      ENDDO.
    ENDIF.
    CLEAR lt_csv_bundle.
  ENDIF.
ENDFUNCTION.

 

2. Data Retrieving FM zaci_event_extractor

The save above. You can develop your own version as well. 🙂

FUNCTION zaci_event_extractor .
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(IV_INSTANCE) TYPE  /ASADEV/AMR_ARIBA_ARIBA_INST
*"     REFERENCE(IV_OBJECT) TYPE  /ASADEV/AMR_ARIBA_ARIBA_OBJECT
*"     REFERENCE(IT_BDCP_LINES) TYPE  /ASADEV/ACI_TT_BDCP
*"  EXPORTING
*"     REFERENCE(ET_RETURN) TYPE  /ASADEV/ACI_TT_BAPIRET2
*"     REFERENCE(ET_KEY_BDCP) TYPE  /ASADEV/ACI_TT_BDCP_KEY
*"     REFERENCE(ET_TABLE_CONTENT) TYPE  /ASADEV/ACI_TT_TABLE_CONTENT
*"     REFERENCE(ER_DATA) TYPE REF TO  DATA
*"  EXCEPTIONS
*"      NOT_A_VALID_TABLE
*"----------------------------------------------------------------------

  DATA: lo_badi          TYPE REF TO /asadev/aci_gen_extractor_badi,
        ct_table_content TYPE /asadev/aci_tt_table_content,
        lr_dataref_t     TYPE REF TO data.

* Get BAdI instance for extractor enhancements
  /asadev/cl_aci_badi_helpr=>get_extr_badi( 
          EXPORTING 
            iv_instance = iv_instance
            iv_object = iv_object
          CHANGING  
            co_extractor_badi = lo_badi
            ct_return = et_return ).

  IF lo_badi IS BOUND.
    /asadev/cl_aci_badi_helpr=>call_badi_extr_post_exit( 
          EXPORTING 
            io_extractor_badi = lo_badi
            iv_instance = iv_instance
            iv_object = iv_object
            it_bdcp_lines = it_bdcp_lines
          CHANGING 
            ct_table_content = ct_table_content
            ct_return = et_return
            cr_data = lr_dataref_t ).
  ENDIF.

  er_data = lr_dataref_t.
ENDFUNCTION.

3. Implement BAdI /ASADEV/ACI_GEN_EXTR

The data extractor is generic and the concrete extracting logic should be embeded in a certain implementation with a specific filter.

create an implementation for purchase order

configure the filter for the PO implementation by using the bellowing information. The values should be from the above configuration sections. This will guarentee that only PO create event will be processed by the implmentation.

Implement method POST_EXIT. The logic depends on what kind of message structure defined. Here is my code

  METHOD /asadev/aci_extrctpr_if~post_exit.
    DATA lr_dataref TYPE REF TO data.
    DATA(lv_order) = CONV ebeln( it_bdcp_lines[ 1 ]-tabkey+35 ). " Get PO number
    DATA:
      ls_data TYPE zpurchase_order.
    FIELD-SYMBOLS:
      <ls_purchase_order> type zpurchase_order,
      <lt_purchase_order> TYPE STANDARD TABLE.
    CREATE DATA lr_dataref TYPE TABLE OF zpurchase_order.
    ASSIGN lr_dataref->* TO <lt_purchase_order>.
    APPEND INITIAL LINE TO <lt_purchase_order> ASSIGNING <ls_purchase_order>.

    SELECT SINGLE *
      FROM ekko
      INTO @DATA(ls_ekko)
     WHERE ebeln EQ @lv_order.

    SELECT *
      FROM ekpo
      INTO TABLE @DATA(lt_ekpo)
     WHERE ebeln EQ @lv_order.

    <ls_purchase_order> = VALUE #(
                order_id    = lv_order
                header_text = ''
               ).
    LOOP AT lt_ekpo ASSIGNING FIELD-SYMBOL(<ls_ekpo>).
      APPEND INITIAL LINE TO <ls_purchase_order>-items ASSIGNING FIELD-SYMBOL(<ls_item>).
      <ls_item>-item_number = <ls_ekpo>-ebelp.
      <ls_item>-item_text   = <ls_ekpo>-txz01.
      <ls_item>-material    = <ls_ekpo>-matnr.
      <ls_item>-quantity    = <ls_ekpo>-menge.
      <ls_item>-uom         = <ls_ekpo>-meins.
    ENDLOOP.

    cr_data = lr_dataref.
  ENDMETHOD.

Unit Test

1. Create a Purchase Order in the system

This is a dummy order created in the system with number 4500000749. It has three items whose quantities are 12, 24 and 56.

2. Event Received in the Event Mesh

The event does contain the order id and three items with correct their information.

 

Conclusion

  • ABAP oo Event is working for ‘SAP Netweaver Addon for Event Enablement’
  • Deep structure or multi layer can be fulfilled via custom FMs

Questions

During the investiagtion I have come up with a few questions. Hopefully someone can help me.

1. Comparison between two components. “SAP Netweaver Addon for Event Enablement” and “Enterprise Event Enablement”. What are pros and cons of them? Which one is more suitable for what kind of requirement?

2. For CPI connects with BTP Event Mesh, we have Webhook and AMQP. Can I know which way is recommended?

 

Cheers.

 

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Baris Buyuktanir
      Baris Buyuktanir

      Hi Stephen,
      Good perspective to prepare-publish events within ERP. Thanks for your post!

      For your question regarding CPI's receiving messages through AMQP or Webhook 

      "For CPI connects with BTP Event Mesh, we have Webhook and AMQP. Can I know which way is recommended?

      In fact they are two different approaches but it's recommended to use AMQP when the consumer supports or could do it. In AMQP based approach you let the consumers to be connected to the broker and receive the messages, and allow them to use the advantages of AMQP, decide for retries/error handling etc. (More proper for event driven pub-sub approach).

      On the other hand webhooks use Http protocol which requires an endpoint to be provided and then called by the broker.  Meaning you should know your "consumer" at the time of configuration. Also Http is a multipurpose protocol (with more things to handle than AMQP meaning more overheads) which you need to consider (although the difference would be minor in low-throughput scenarios).

      CI already supports AMQP via adapter therefore you can use AMQP unless there's a very specific reason to use Http and provide a REST endpoint (In case your consumer already have one / doesn't want to or not capable of consuming via AMQP)

      Baris

      Author's profile photo stephen xue
      stephen xue
      Blog Post Author

      thanks Baris. Your explanation does make sense to me. cheers.

      Author's profile photo Karsten Strothmann
      Karsten Strothmann

      Hi Stephen,

      like the blog. Very helpful. Let me take the first question and try to answer it "quickly".

      The Event Enablement Add-On is your choice:

      • if you want to create events in older backends like ECC. It actually is your single choice in this case.
      • if you want to create custom events in S/4HANA in a low code/no code approach
      • you can create data, decision and notification events; inbound events work as well
      • It's a great and useful tool in general, that is straightforward and proven technology

      In respect to the points you have to keep in mind for the add-on:

      • there are no standard events currently and you have to create every single event yourself; the question is how many custom events you want to or can maintain
      • it does not work for S/4HANA Cloud

      In respect to Enterprise Event Enablement, this is your choice:

      • if you want to use events for S/4HANA Cloud
      • if you want to use SAP provided standard events, that you can typically enable with just a few clicks (after infrastructure has been set up).
      • so it is the natural choice for S/4HANA as well, since it provides these standard events that allow you to scale easier to bigger EDAs; you just switch the events on in most cases and don't have to maintain them
      • On the other hand you currently cannot adjust the standard events and creating custom events is more or less still an edge case, but possible

      The cons are limited. It does not work for ECC, and I would say that for custom events you need a stronger development background compared to the add-on.

      In future (with the upcoming S/4HANA and S/4HANA Cloud releases the future is right around the corner), Enterprise Event Enablement will provide you with quite a number of new options including custom events and adjustable events. Plus that they will introduce a configuration based approach to adjusting standard events. So the colleagues will address a lot of topics already.

      So far we have just been looking at the technical perspective: there is a commercial perspective as well. Enterprise Event Enablement is always free of charge - it connects to SAP Event Mesh and will later this year connect directly to Advanced Event Mesh as well. The add-on is free of charge for SAP Event Mesh, currently available Advanced Event Mesh only in a paid version.

      In the end, both options are great and work, and since we are talking about EDAs, you could even use them in combination. Which a lot of customers already do, with events from ECC via add-on and standard events from S/4 via Enterprise Event Enablement for example. So it comes down to a combination of factors: skillset, broker, backends, commercial topics, number of events, event type ...

      Best,

      Karsten

       

      Author's profile photo stephen xue
      stephen xue
      Blog Post Author

      thanks Karsten for your words. I agree with you. without any custom development, the 'Enterprise Event Enablement' configuration is convienent and quick to be done compared with "Netweaver addon for event enablement". However if we want to build up our own custom topic, the development process will not be that straightforward.

      As a developer, I do not know the pricing of them actually. Thanks for your information on it and I believe any other developers are keen to the anwser. 🙂