Technology Blog Posts by SAP
cancel
Showing results for 
Search instead for 
Did you mean: 
mlauber
Product and Topic Expert
Product and Topic Expert
12,407

Events aren't exactly new but still require a bit of a mindset change. Instead of your point-to-point integration and interactions, event-driven architecture works differently and needs a slightly different approach. With this blog I showcase a full end-to-end scenario for both, local consumption and remote consumption in the hopes of explaining the event framework and give some ideas how you can adopt it and design new, smart solutions.

 

Short intro about events

An event is a significant change in state. Notification or data events can be sent from the event source to an event broker to inform about this change. Event consumers can register at the event broker to be informed about certain events, that they are interested in.

Events aren't new in SAP and used to be (mostly) handled via BOR. In this blog we will look at the new event framework for RAP (ABAP RESTful Programming Model) BO (Business Objects).

 

1 Local Consumption end-to-end

Starting with the simpler example: local consumption. In my experience not everyone seems to be aware that is a thing for RAP BO, but it is. Please refer to our SAP Help page for any further info: Event Consumption | SAP Help

With local consumption, you don't have need for an event broker, because you are staying within the same system. You can directly register your local consumption for a certain RAP BO event, and when it is fired it will call your code. Here's a full example.

1.1 Find a suitable Business Event

First of, we need of course the event we want to react to. For this we can check on our Business Accelerator Hub by first selecting our product, for example SAP S/4HANA Cloud, private edition. Afterwards there is the category Events - Event Objects. You should see something like this:

mlauber_0-1739791470903.png

Here we can then search our business context, for example Sales Order (tip: always search for the main object, not for example for sales order item etc.). When we found it we can click on the appropriate tile:

mlauber_1-1739791576557.png

Read carefully the information and whether or not the event you actually need is present. This is important. For simpleness sake I will use the "Changed" event (please note I'm not picking the one called "Item changed", I will get back to this later). Now sadly, from here we don't have a direct link to the corresponding RAP BO, other than the name of the object, meaning "Sales Order" for "Sales Order Events". For me personally that is enough to figure out the RAP BO, but what if you don't know? Simple, we do 1 more search on the HUB. Instead of tab Events in the HUB (still selected on your chosen product) click on On Stack Extensibility - Business Object Interfaces and from here search for your event object, in my case "Sales Order":

mlauber_2-1739794587538.png

Clicking on the appropriate tile will take you to the RAP BO interface which will give you its technical name (and show the released state so we can be sure we are clean core compliant). In our case that's I_SalesOrderTP. Now, when working with events, we often need the BO itself, not the interface, because interfaces do not always include events. Meaning for my demo here, my RAP BO name is R_SalesOrderTP instead (if you are confused here, I recommend learning the RAP and VDM naming conventions 😉, for I do not have the space to get into that here too).

1.2 Create local event handler

To register a local consumption, all we need to do is create an ABAP class, that then specifies the RAP BO for which it is handling events, in my case:

CLASS zcl_salesord_local_event_handl DEFINITION
  PUBLIC
  ABSTRACT
  FINAL
  FOR EVENTS OF R_SalesOrderTP.

  PUBLIC SECTION.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcl_salesord_local_event_handl IMPLEMENTATION.
ENDCLASS.

The most important parts above are FOR EVENTS OF <name of behavior definition of RAP BO>. I'm also gonna be honest here and say that R_SalesOrderTP does not have a C1 release contract in my S/4HANA demo system, so I am forced to create this class as Standard ABAP, instead of ABAP for Cloud Development, which would be the goal. Always try ABAP Cloud first.

Next we need to create a local handler class under Local Types which inherits from CL_ABAP_BEHAVIOR_EVENT_HANDLER:

CLASS lcl_so_event_cons DEFINITION INHERITING FROM cl_abap_behavior_event_handler.
  PRIVATE SECTION.
  CONSTANTS:
    " this is a local name and does not come from the RAP BO
    co_changed_event TYPE string VALUE 'SLSORDCHN' ##NO_TEXT.
  METHODS:
    consume_changed FOR ENTITY EVENT changed_instances FOR salesorder~changed.
ENDCLASS.

CLASS lcl_so_event_cons IMPLEMENTATION.
  METHOD consume_changed.
  ENDMETHOD.
ENDCLASS.

Here we define a method per event we want to listen to. For our case that is salesorder~changed, which is stated after the FOR word. Here you must type an actual entity and event that exists on the previously mentioned behavior definition. We also give a name to the importing payload, in my case I named it changed_instances (it could have a different name).

1.3 Write your code

And here we are already. You now have a method, in my case consume_changed, that is called when the corresponding event is fired. We receive the payload of the RAP BO event and can now do whatever we need to do. Important to note is that events are fired after all commits have been completed and were successful. This is to ensure that the state change really did occur. So you do not need to worry about being in the middle of save sequence at this point - you are free to write your code as you need.
For simpleness sake for this showcase, I had created a z-table which I will simply update here, to see that my local consumption is running. I want to mentioned immediately here that this is purely for demo purposes: for real scenarios the code should be written with ABAP Cloud and direct DB access would not be allowed in such a case. Bear that in mind! So here the really bad, bad, code, but simple demo case 😁:

METHOD consume_changed.
  DATA: ls_event_cons TYPE zevent_tst,
        lt_event_cons TYPE TABLE OF zevent_tst.
  DATA(today) = cl_abap_context_info=>get_system_date( ).

  " set data for db update
  ls_event_cons-payload = |Local Event Handler Called|.
  ls_event_cons-eventtype = co_changed_event.
  ls_event_cons-recorddate = today.
  ls_event_cons-recordtime = cl_abap_context_info=>get_system_time( ).
  append ls_event_cons to lt_event_cons.
  LOOP AT changed_instances INTO DATA(instance).
    ls_event_cons-payload = |{ instance-salesorder } { instance-salesordertype } { instance-salesorganization } { instance-soldtoparty }|.
    ls_event_cons-recordtime = cl_abap_context_info=>get_system_time( ) + 5.
    append ls_event_cons to lt_event_cons.
  ENDLOOP.

  " cleanse the test data table
  DELETE FROM zevent_tst WHERE eventtype = @co_changed_event
    AND recorddate < @today.
  " insert new payload for testing
  INSERT zevent_tst FROM TABLE @lt_event_cons.

ENDMETHOD.

With above code, we write at least 2 lines per event trigger: one with a dummy payload, simply containing a string, and then one more line per changed object. Now in the case of Sales Order Changed event (remember I picked Changed, for the header, not ItemChanged), this will always just be 1. If we had listened to ItemChanged instead, then we could receive several lines in changed_instances.

1.4 Testing

Let's see if this works. Now without taking tons of screenshots, I am opening Sales Order Manage Fiori app and change my sales order 402. I simply change the Customer Reference field with an updated text, and then save. Let's check my table:

mlauber_3-1739796369516.png

It has been updated (and you can see today's date and time - if I manage to post this blog today -- spoiler: I did not 😆), so we confirmed my local consumption was called.

1.5 Troubleshooting

Since event triggering happens with background units, you won't be able to directly debug this. But you can check monitoring transaction SBGRFCMON or bgRFC Monitor. There you should have Inbound queue BGPF; and this is the perfect point to mention that your system admin needs to have fully setup BGPF for local event consumption to work. But if something went wrong, for example an error in your code, a unit would be here with a warning or error flag. You can analyze the error and also start the debugger from here. If there is no unit listed here, it went through.

And that's it, local consumption complete. So this should be used instead of the old BTE, where we wrote our code to react to a BOR event.

 

2 Remote Consumption end-to-end

For remote consumption you must have an event broker. At SAP, we have SAP (Advanced) Event Mesh on SAP BTP for that purpose. For this showcase, I assume you have already subscribed to SAP Event Mesh. From then on I will guide you.

2.1 Find a suitable Business Event

As before, we can search on Business Accelerator Hub to find our event. This time let's take something less common (all demos seem to be on Sales Orders 😆 ) - let's say I want to react when a status of a WBS element changed. So on the HUB I will not search for "WBS", but for "Project", because that is the encapsulating, main business context:

mlauber_4-1739797806904.png

I will go with the first, Project Events. This time I will switch to the Events Reference tab, to get the full path of my event. Let's see if we find status changed for WBS element:

mlauber_5-1739797994780.png

Perfect! That's all we need from the HUB.

2.2 Connect your SAP system with your SAP BTP Event Mesh

I am doing the on-premise / private cloud version here, but of course you can do the same for public cloud: the following blog explains the setup for using SAP Build Process Automation. Even without Process Automation, the starting setup steps are the same: Event Mesh and SAP S/4HANA Public Cloud Setup.

Continuing with on-premise / private cloud. As mentioned before, assuming your subaccount has Event Mesh are already subscribed to. Navigate to your subaccount on your BTP cockpit and open Instances and Subscriptions. Filter for Event Mesh and if you do not yet have an instance as well as a subscription, be sure to create one (if you need help with that, please follow Create Event Mesh Instance | Developer Tutorial).

mlauber_6-1739798971153.png

Next, click on your instance and if there is no service key yet, create one. Finally download or view the service key through the ... button, we will need it soon:

mlauber_7-1739799061444.png

Now logon to your SAP S/4HANA through SAP GUI and enter transaction /n/IWXBE/CONFIG.

Press create button via Service Key to create a new channel:via service key.png

In the popup, give your channel a name and paste the service key JSON, which you had downloaded/have still open on BTP:channel via service key.png

The channel will now appear in the list, but it's not yet active. Mark your channel and click on the Activate button. Wait for a while, refresh, and the status icon in the first column should change to green:

activated channel.png

You can also click "Check connection" to be sure your system is successfully connected to SAP BTP Event Mesh.

2.2.1 Create outbound bindings in SAP S/4HANA to send events to SAP Event Mesh

Now that our system is connected to an event broker, we need to configure which events we want to forward to that channel that we created. For this, go back to /n/IWXBE/CONFIG and mark your active and green channel. Then click on Outbound Bindings button in the menu. From here we click on the create icon button to add a new binding for our WBS element status changed event. Easiest way to do this is to come back to the path we had found on the HUB. It was this: SUB ce/sap/s4/beh/project/v1/Project/WBSElmntStsChanged/v1. As the "sub" suggests, this is for subscribing to the event. Within the system, we can disregard the starting "ce/" (consume event) and search for the rest:

mlauber_9-1739800096284.png

You can also search generally with an asterix * etc., if needed. Once the outbound binding is created, it should look something like this:

mlauber_10-1739800164285.png

2.2.1.1 Event Filtering (optional)

The outbound binding we just created has no filter, meaning anytime that event triggers, it will be forwarded to Event Mesh. Now depending on your integration patterns and strategy, maybe that is exactly what you want and you handle your event consumers to receive their appropriate events in middleware or on the consumers themselves. But if you do not want to send everything to SAP Event Mesh, in that case we can filter it right here in our event channel configuration, before the event goes out. From the same location (your SAP Event Mesh channel - Outbound Bindings) you can click on the Filters button in the menu. From here you have to expand the Outbound Bindings folder and then select your event in the tree on the left side. Then you will see the 3 standard filters available:

mlauber_0-1739872066182.png

  • ID is the generated id of the event, so not truly helpful except for testing scenarios
  • SOURCE is your event source. For regular cases, that is /default/sap.s4.<prefix>/<SERVER>. Prefix can be "beh" for SAP standard events or for example "custom" for custom events. Again most of the time this not that helpful for filtering
  • TIME is the timestamp when the event would be sent. This is again is more viable for test cases to only send to Event Mesh during a certain time fame etc.

Not enough? Probably not. But fear not, you can create custom filters with derived events. Because this blog post is already big, I will not go into details here. But with a derived event, you can define your own custom payload for a SAP standard event. In your payload CDS, you can add annotation @event.context.attribute: 'xsap<FIELDNAME>' to fields you want to become filters. This is step one. The derived event is then created by extending the corresponding behavior definition (this requires a released C0 contract!) and giving your CDS as the new payload. Lastly we need an event binding for our derived event, and then the config in /n/IWXBE/CONFIG as described before, for our custom event binding. Now if you navigate to Filters, you will see the fields you annotated as well and can use those as filters. I know this was very short so you can also refer to Maintaining Filters for Outbound Event Topics | SAP Help.

2.2.2 Create Queue and Subscription on SAP Event Mesh

With the above, our S/4 is ready to send events. Now we need to receive them on SAP Event Mesh. Go back to your BTP subaccount under Instances and Subscriptions and this time open the Event Mesh subscription, which brings you to the Event Mesh UI. Under Message Clients you should find your instance you previously created:

mlauber_11-1739800572272.png

Click on it and then navigate to Queues. Click on Create Queue. Simply give the queue a name and see if you want to change any of the default properties. I chose "project" as my name (note that the namespace you picked when you created the Event Mesh instance (nordic/em/dev in my case) is added as a prefix):

mlauber_12-1739800807843.png

Once the queue is created, open the Actions menu and click on Queue Subscriptions. Here now we paste the full SUB path of our event from the HUB: ce/sap/s4/beh/project/v1/Project/WBSElmntStsChanged/v1. After pasting this string, before you click on add you must yourself write the namespace as prefix, meaning in the end the topic would be: nordic/em/dev/ce/sap/s4/beh/project/v1/Project/WBSElmntStsChanged/v1. And don't worry, you can't do wrong. When you created the instance you also had to enter rules and those rules make sure you won't forget the namespace, because you get an error if you try to add a topic without it. In the end, your Queue Subscriptions should look like something this:

mlauber_13-1739801425807.png

2.2.2.1 Quick mini test

I recommend testing your setup at this point. Back in your SAP S/4HANA do whatever you need to do to fire your event. In our case I will change the status of a WBS element. In your SAP S/4HANA you have /n/IWXBE/EVENT_MONITOR transaction for monitoring events. Here you will find undelivered or acknowledged events, if something doesn't go as expected.

If you then go back to your Even Mesh Message Client and the queue you created, after you fired an event it should sit waiting here (you can see I tested a lot - I have right now 12 triggered events in my queue that no-one consumed yet):

mlauber_14-1739801818849.png

If you go to the Test tab, you can test both Event Consumption and Event Publish directly on SAP Event Mesh. For example this can be used if you don't want to have to go back to your SAP S/4HANA every time you wanna do a quick check; you could instead publish a message directly on Event Mesh, thus simulating your event-driven integration. 

If everything is working, our event-driven architecture is ready.

2.3 Event Consumption with SAP Build Process Automation

To finish our end-to-end scenario, we need a consumer. For this showcase I chose SAP Build Process Automation (short SBPA). We will receive the WBS element status changed event from SAP Event Mesh and then a process starts where I read more detailed information about that WBS element and then potentially create a Sales Order (if certain rules are passed) with an item, which uses this WBS element (please bear in mind this is a demo scenario, trying to be a bit out of the box here, but basically you could have any kind of process or approval workflow built at this point).

I won't go into details on how to subscribe to SBPA or how to create an instance with a service key, assuming this is ready. But all these 3 are prerequisites: subscription & instance to SBPA & a service key on the instance.

2.3.1 Add the Event to SAP Build

First and foremost, SAP Build needs to be able to react to the event. In your SAP Build Lobby, open the Connectors menu and click on Events. Next click on Create. Personally I find it easiest to use the SAP Business Accelerator Hub again to find the same event, or Unified Customer Landscape if you are using that. Lastly we can also upload the event specification (for example if you have a derived event or other custom event). For this showcase, I go with the HUB so I am clicking on that. A search appears and from our previous search we know we want "Project" so I enter that (I do not recommend using the string "events" in your searching, since many have that string in their name and thus the search result may be too big to find the one you actually want):

mlauber_1-1739873648499.png

In the lower right corner is our event object. Click on it. On the next screen you can see all the events that are offered in that object. If everything looks good, click on Add. Open your new Events project and we see once more all events we are capable of subscribing to. The last step is to release and publish this Events project, so it can be used across SAP Build.

2.3.2 Add APIs you may need to use

Because notification events are very small, we usually need APIs to retrieve some extra information. In our case we also need an API to finally create the Sales Order. In SAP Build, we do this by creating Action projects. Now once more I won't go into super detail here, this has been explained many times over and an example can be found here: Create Sales Order Action Project in SAP Build.

For my specific case I would need 2 action projects:

  • PS Project API (to read WBS element details)
  • Sales Order API (to create the SO)

To find the appropriate APIs I can again use the HUB or other ways; I have a full blog post about this: How to find/create suitable APIs.

2.3.3 Create your process / workflow

Now that the event I want to react to and all my needed APIs are published in SAP Build, I can create my process.

Go back to the Lobby and create a new project: choose Build an Automated Process and then Process. Give a name for your project and then also for the process. In my case I chose "Sales from PS Project" as my project and "Start from WBS Element Status Changed" as my process name (my general recommendation is to choose good names that clearly state what the artifact is doing).

In my process, I now add an Event trigger by clicking the "Add a Trigger" link at the Trigger element. Then I select Wait for an Event:

mlauber_0-1739874574788.png

In the next popup I now need to select my Event Project, and lastly the exact event (in my case WBS element status changed event) that should trigger this process. After this I created my process steps, as shown below (explanation also below) :

mlauber_1-1739874925258.png

Let's go through above step-by-step:

  1. The process trigger is the event, as just described
  2. Next I'm calling an action of the Action Project we created previously; namely the Get WBS element details with WBS element key (the payload of the event has both project id and WBS element id, so we use these as input parameter into the GET API, to read details of the WBS element that had a status change)
  3. I created a Business Rule / Decision in order to determine if the WBS element should create a sales order or not. Here I can check any of the fields I retrieved from the previous API.
  4. The next step is the main condition itself. The Decision of step 3 will give me a simple TRUE or FALSE as result, which we now use to see whether we should create an SO, or not.
  5. In the TRUE branch, we have a simple Script which is used to prepare the data needed for the other Action project, for creating an SO via API.
  6. This step now calls the create sales order action, with the data we prepared in Step 5
  7. Lastly we create a task into the inbox of a user or a group of users to inform that our event-driven automation created an SO.

2.3.3 Trigger SBPA via Webhook

As the very last step, we need to get back to SAP Event Mesh. As of right now, SAP Build is aware of the event object Projects and we have created a trigger for one of those events. But so far, we have not connected SAP Build with SAP Event Mesh, meaning nothing yet calls our trigger. For this we need a webhook: an API for SAP Event Mesh to call, when a certain topic is received in the event broker. This is the actual trigger of SBPA and our process.

Before we enter open Event Mesh, we need the webhook URL, the API that Event Mesh needs to call to access your SBPA instance. Similar to how we retrieved the service key for SAP Event Mesh, we now need to do the same with SBPA. Go to your subaccount and Instances and Subscriptions. This time filter for SAP Build Process Automation and find your instance:

mlauber_2-1739876628955.png

Click on your instance and View your Service Key (create first, if none available). Keep this info open as we proceed to Event Mesh.

In another tab/window, go to your SAP Event Mesh Message Client, click on the tab Webhooks and choose Create Webhook. Give it a name and select your queue. Leave the other fields as is. Now for the Webhook URL, go back to your SBPA service key. One of the very first parts is the endpoints-api:

mlauber_3-1739876786443.png

Note: your URL may look differently! Copy the URL from your service key.

Go back to the Create Webhook dialog and paste the URL into webhook URL field. Add the following at the end of the URL: /internal/be/v1/events

Next, for Authentication choose OAuth2ClientCredentials and enter the following info, again taken from the service key of SBPA:

  • Client ID = uaa-clientid
  • Client Secret = uaa-clientsecret
  • Token URL = uaa-url + /oauth/token

Save the webhook. Now you can trigger the handshake between SAP Event Mesh and SBPA to see if you entered all info correctly. Finally make sure your subscription status is active and everything is running. It should look something like this:

mlauber_4-1739877336307.png

And now we are done and we have an event-driven automation that takes care of creating sales orders for us.

 

Final Words

Events can be used in many ways, allowing us to react when something happened, and then we can do almost anything: run some code locally in our system, have a bot running for us (as in my case here - but this bot could take many different forms), trigger other integrations to inform of the change, trigger workflows, and much, much more. So next time you want "something to happen, after something happened" check out the new event framework.

Hope this helped and let me know if you have any questions.

32 Comments
EsaNieminen
Advisor
Advisor
0 Kudos

🙂 Thank you Melanie 

StigPraefcke
Product and Topic Expert
Product and Topic Expert
0 Kudos

Nice blog. Very helpful!

DiegoValdivia
Active Participant

Local Events is one of the most powerful tools I've seen in SAP in a long time. More over if we combine it with BALI Logs to track the behavior of the code triggered by the event.

It's a shame that SAP doesn't have an app to display the logs in Cloud Public, just like we have done during decades with tcode SLG1: https://community.sap.com/t5/general-and-cross-topics-q-a/is-it-possible-to-display-custom-applicati... 

eachtime
Explorer
0 Kudos

In API Business Hub when I enter the Sales Order where do I see the events that are available? I can't see this changed event. Is there a place wehere we can see the list of all events for a business object?

mlauber
Product and Topic Expert
Product and Topic Expert

Hi @eachtime . If you read the blog carefully, I guide you where to click on the HUB in order to search for events. First your select your product, for example SAP S/4HANA Cloud, Private Edition. Then you have different tabs and can select Events - Event Objects. I also provided a screenshot for the same, if you check underneath 1.1

monasap08
Participant

Excellent blog. I like that you have covered both local and remote. Thank you. 

jitendra_it
Active Contributor
0 Kudos

Hello @mlauber,

Thanks for the detailed blog.

I am trying to consume local events for sales order. For this we are creating sales order using EML and trying to consume the event Sales Order Created. however, event is not triggering(code written in event handler is not executed).

So my query here is, does local events get triggered using EML as well or they just get triggered from respective fiori app ?

Regards,

Jitendra

 

mlauber
Product and Topic Expert
Product and Topic Expert

Hi @jitendra_it 

You can see EML as the new "do it all", including running BAdIs you've implemented. So, the answer is yes, when doing EML, events trigger as well.

First thing I'd check is your release? I believe local consumption is available since 2208 (public) and 2023 (on-prem/private) => double check that if you are on such a release.

Next make sure your EML goes against the correct RAP BO, as defined in your local consumption class. In my case that's R_SalesOrderTP. So I need to access the Sales Order RAP BO either via its interface I_SalesOrderTP (use this whenever possible since that is the stable RAP contract) or otherwise via its main behavior definition R_SalesOrderTP (for example certain actions may only be available here, not on the interface, but that then renders my code to Standard ABAP and thus not clean core).

Lastly, I do have a troubleshooting section in the blog above. Have you checked there? Do you get a background unit? Also make sure that BGPF is up and running properly, check with your basis if you are unsure.

If you still can't figure it out I recommend approaching support who can look at it in detail.

Kind regards,

Melanie

jitendra_it
Active Contributor
0 Kudos

Hello @mlauber ,

Thanks a lot for your reply.

The system which I am working is on 2023 so release wise we are good.

I asked my basis team to check you queue config.

Here I have one more query, does RAP event trigger from normal GUI tcode as well, in this case VA01 ?

My client is asking irrespective of app(or EML) or GUI tcode, solution based on RAP event should work ,however, I am not sure RAP event would trigger from normal GUI tcode or not ?

Regards,

Jitendra

mlauber
Product and Topic Expert
Product and Topic Expert

Hi again @jitendra_it 

If you get a RAP BO delivered by SAP including events, you can be sure the event is triggered always. So yes, it does not matter if VA01 is run, the respective Fiori app, if a BAPI is called, if an API is called, if EML is used etc. etc. That is sort of the point of events; to trigger when a state-change occurs, regardless how the state-change occurred 😊

BR,

Melanie

AshishPandey
Discoverer
0 Kudos

Hi Mlauber,

I have posted one issue here regarding local event consumption. Can you please take a look and help

https://community.sap.com/t5/technology-q-a/sap-rap-events-local-consumption/qaq-p/14111252

Regards,

Ashish Pandey

AshishPandey
Discoverer
0 Kudos

Hi @mlauber ,

 

Please let me know if you got chance to check this

mlauber
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi @AshishPandey 

Please note there is a difference between bloggers and helpers. Answering questions on the community is not part of my work. I am always happy to answer questions directly pertaining to my blogs, I want people to understand and potentially learn something, but more than that falls outside of what I do or have time to do. Thank you for your understanding.

Kind regards

AshishPandey
Discoverer
0 Kudos

@mlauber 

I have asked question on your blog only :). Question is related to this topic only. I am pasting it here:

I am seeing a weird issue with local event consumption of standard RAP events. So, I have seen if we create Purchase order from ME21N SAP GUI, standard RAP BO event Created of R_PurchaseOrderTP is triggered. Once, I implemented the local handler for this entity event, it doesn't trigger immediately. But once I go inside debugging mode, it starts triggering. 

Do we have to activate or run any program for this?

mlauber
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi @AshishPandey 

There is no "program to run", I'm not even sur what you mean by that. My scenario is end-to-end and all steps for local consumption are included. Please refer to the troubleshooting part of my blog. BGPF needs to be setup properly. If you only can debug via SBGRFCMON then that tells me BGPF is probably not fully setup. Check with your basis. If this doesn't solve the issue, I recommend creating a proper ticket because this is not something that can be helped via text only and needs to be checked in your system.

cds2
Newcomer
0 Kudos

Hi @mlauber  Ma'am,

We have a requirement to transmit data to a third-party system upon the creation of an inspection lot. Unfortunately, this requirement cannot be fulfilled using standard BAdIs. As an alternative, we are exploring the use of RAP BO events for the inspection lot within the local consumption model.

However, when attempting to implement this via a global class, we are facing the following error: "The use of Behavior Definition R_INSPECTIONLOTTP is not permitted." This appears to be due to the CDS views not being released for C1 .

Could you please advise how we can proceed with developing this functionality using standard ABAP Class , instead of ABAP for Cloud Development in the SAP Public Cloud environment?

SamyD
Explorer
0 Kudos

Hi @mlauber ,

Thanks for sharing this.

I tried to reproduce in my S/42023OP(FPS01) but no triggering events. Same behavior with businesspartnerTP and purchaseOrderTP.

Inbound destination is configured in SBGRFCCONF. Seems there are no other prerequisites specified by SAP documentation.

So I have the impression that either it's not functional on a S/42023OP(FPS1), or there's another config point missing other than SBGRFCCONF, or I don't know 😀. I would really try to use local events to switch from old way.

If anyone has any ideas, tips or advice, I'll take them all.

 

Br,

Samy

 

 

mlauber
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi @SamyD 

Have you checked SBGRFCMON if your background units are turning up? If they are there, they ran into an error/didn't fully process (it should be empty). Then you can debug them from there. If there is nothing there, your code should have run (assuming it came that far). Have you a simple way to check whether your code runs, such as my quick writing into DB just to see if the call works? This should work since S/4 2023, it's what I used in my example.

Otherwise I can only refer to an OSS so someone can check in your system why the call isn't happening.

BR, Melanie

mlauber
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi @cds2 

If the behavior you need is not released with a C1 contract you could proceed having your class be created in Standard ABAP, if you are on-premise or private cloud. On public cloud, that is unfortunately not an option. In such a case, you would not be able to have local consumption for that event. But, reading your requirement, I wonder why you would go the local consumption way at all? If the goal is to reach a third-party system, then remote consumption is the correct pattern to go, in which case you do not need any ABAP class, but simply configure your event channel into SAP BTP Event Mesh and configure the event that should be sent there. In BTP you can then further configure, maybe via integration suite, to react to the event and then send it onward to your third-party system.

jindrich_sustr_cz
Discoverer
0 Kudos

Hi @mlauber ,

nice blog about RAP BO event.

I have one question to ask. Is it possible to combine local and remote BO event consumption of the events of one RAP BO?

For example Sales order event Create. Can we consume this event in both ways in the one system?

Usualy I use local event consumption when I use custom BO (BO from RAP development). Some time ago I had a situation where I tried to have local and remote event consumption of the one BO event but I got abap runtime error. After that i removed remote event consumption and kept local event consumption it worked.

BR,

Jindrich

matus_humaj
Discoverer
0 Kudos

Does this tutorial apply also for Public Edition? I tried to implement a local BO event handler (I_ProductTP_2 - Changed) and I found out it is forbidden to execute DB modifications in the handlers method e.g. I cannot save a record in a Z* table when a product gets changed - i get short dump:

 
Execution takes place in a transactional context: A "PHASE <modify>" call is active with "ZCL_BO_EVENT_HANDLER". The current statement "MODIFY <dbtab>" is therefore forbidden.
 
What is the purpose of the local BO events on public edition then?
(I don't use BTP nor Event Mesh, I want to do the logic directly onstack).
 
Thanks,
Matus
gmoa
Discoverer
0 Kudos

Hello @mlauber,

we are working on a business process that includes an asynchronous part. Since we develop in ABAP for cloud, we are using an event-driven architecture for this asynchronous part. Our implementation follows the local consumption approach, as described in your blog, and it works well for use cases without errors.

However, there are additional use cases where errors can occur. For instance, the asynchronous process may need to convert amounts into a different currency. In such cases, an error message should be generated if the conversion customizing is missing.

Now, the requirements for the asynchronous part are as follows:

  • Error messages should be accessible to the user.
  • Once the error (e.g., missing conversion customizing) has been corrected, the user should be able to restart the failed process.

In former releases, the SAP Post-Processing Office fulfilled these requirements for remote function modules.
Is there an equivalent available in the event-driven architecture to meet these requirements?

Thanks for your response.
BR, Martin

 


  

SridharReddy
Explorer
0 Kudos

Hello @mlauber ,
We are on S4 2022 and ADT doesn't recognize CLASS FOR EVENTS OF syntax. I think this can be done on or after S4 2023?

SridharReddy
Explorer
0 Kudos

Hello @mlauber  ,
Standard event doesn't have the information that is needed by the event consumer, so our requirement is to trigger a custom event whenever a standard event is triggered. I tried event extension(using Derived Events concept explained in the blog below), but event extension is possible only with S4 2023(ABAP 7.58 or later) and we are still on S4 2022(ABAP 7.57).
https://community.sap.com/t5/technology-blog-posts-by-sap/derived-events-how-to-trigger-custom-event...

I then tried to consume events locally using a local event handler(similar to example mentioned in this blog). However, CLASS FOR EVENTS keyword used to consume events locally is again available only with S4 2023.

Another option is to create an event consumption model, to consume an event from Event mesh. But this doesn't look like an efficient way, since we are trying to consume an event from event mesh that was  originally triggered locally.

What are the options to send a custom payload (whenever a standard event is trigged) on S4 OP 2022 (other than the legacy ways)?

mlauber
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hello @jindrich_sustr_cz 

Yes, you can consume the same event both local and remote. I tried this myself with Sales Order Changed and it's both triggering my local code and forwarding to the event broker for remote consumption.

BR, Melanie

mlauber
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi @matus_humaj ,

The tutorial does generally apply for public cloud as well, however in public cloud you can only do local event consumption if the RAP BO you are referring to in your ABAP Cloud class is released. Now, generally the RAP BO Interface is released (see guide how to find RAP BO after having found the event) and as I mentioned in the guide, R_SalesOrder is not released with a C1 (so my class on the on-prem system ended up as Standard ABAP, not ABAP Cloud) but I_SalesOrder does not include the event we need. Hence, in such a situation, you cannot do local consumption, as the clean core rules for only using released APIs is stopping you. I unfortunately cannot comment on if this is meant to be changed but this could be a good case for a customer influence ticket to either release RAP BOs as well as RAP BO interfaces or to add the events into RAP BO interfaces.

BR, Melanie

mlauber
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi @gmoa ,

I don't have a straight answer here as I'm not very familiar with SAP Post-Processing Office mentioned. But basically once the local consumption is triggered, it's your stage, your code. You would need to include either the exception for missing customizing yourself or use an existing one (if there is one) and catch said exception. And when you are in your error coding, again, it's up to you to do what you need; as you said, inform the user. You could send a mail (external), you could add and item to the user's inbox (probably better), or you could write an application log (cl_bali etc. classes, there are guides out there how to use it, all released and clean core compliant as far as I know) - just some general ideas. Regarding the log, remember you then also need someone to receive this log/monitor it.

So you have several options and could even go as far as building your own error handling and app, but that is a lot of custom development and I'd think twice before going that far.

As far as I can think now, the mail/inbox options would probably fit best but I don't know your full details. Consider what type of user receives these failed messages and what such a user would do, once they are received and that should lead you to the right solution.

But as far as the event architecture goes, the local event consumption has no integration with an error handling tool. As mentioned in the trouble shooting section, your code runs in a background unit until completed. Only if there is a hard error, such as "ABAP dump" problems, the unit will be listed as failed in SBGRFCMON, otherwise the unit runs until completed. There is the rerun feature that may help in your case, for automatic reruns if for example the code failed due to locks. Refer to this from SAP Help

"Local events may fail to execute due to temporary issues like locks on draft instances. An automatic retry feature can address these problems, with the framework attempting to restart the local event execution up to three times. To enable this, you can create custom exceptions that inherit from CX_RAP_EVENT_HDLR_ERROR_RETRY. Raise these exceptions in the event handler method, specifying a delay for the retry attempt, to react to any issues that prevent successful execution of the local event."

BR, Melanie

 

mlauber
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi @SridharReddy 

You answered yourself that local event consumption on-prem/private cloud is only available since 2023 release. Custom payload for derived events as well. Meaning if you are in a previous release you can only use remote consumption, as you said yourself with a consumption model, but I agree to call out to event mesh in order to call back into your system seems not like a proper solution. Another option could be old-school BTE events, if they exist for what you need. Please note that BTE are not considered clean core, but this could be a good transition option until you move to 2023 or higher. My recommendation would be to create your FM for the BTE event, but inside the FM call an ABAP Cloud class, so that your coding is as close to ABAP Cloud and to what it would be, once local consumption is available in your system. Hope that helps.

BR, Melanie

vmolina
Explorer
0 Kudos

Hi @mlauber! I'm working in S/4HANA 2023 private edition and I'd like to use a derived event to extend the payload of an event for external consumption, but the BO is not released. Is there any workaround?

mlauber
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi @vmolina 

You are correct that RAP BOs (the R_ ones) are often not released. Instead, the RAP BO Interface (I_) is released. Taking the sales order as example, R_SalesOrderTP has the events but isn't released with a C1 contract. Looking at the BO interface, I_SalesOrderTP, it is released, but, the events aren't on the interface. Now the interface is meant as stable interaction with the BO, and that's why this is the one that gets released.

So what now, as you asked? You can still do this and make it work via clean core Tier 2 (wrapper) or, now with the new clean core concept introduced on Aug 12 2025, this would be level B. Let's look at it.

You start by creating your custom payload (notice that payloads need to be flat for derived events). For my sales order example I created ZP_SalesOrder_EventExt. This one can be saved as ABAP Cloud, meaning level A (Tier 1).

define root view entity ZP_SalesOrder_EventExt as select from I_SalesOrder
{
  key SalesOrder,
  @Event.context.attribute: 'xsapordtype'
  SalesOrderType,
  @Event.context.attribute: 'xsapslsorg'
  SalesOrganization,
  DistributionChannel,
  OrganizationDivision,
  SoldToParty,
  CustomerGroup,
  ShippingCondition,
  IncotermsClassification,
  OverallSDProcessStatus
}

(above you also have examples on how to create custom even filters, as mentioned in my blog)

After this, now you can create your event extension. Right-click the RAP BO's behavior definition (R_SalesOrderTP for me) and choose new behavior extension. Then here you simply derive your event:

extension
//using interface i_salesordertp
;
extend behavior for SalesOrder {
  managed event ZChangedExtended on Changed parameter ZP_SalesOrder_EventExt;
}

Now ideally, you would have line 2 above active, as then you are using the interface I_SalesOrderTP. But, as already established, the interface does not have the events. So we leave that line away and then we can activate this. This extension CDS is your wrapper, so it needs to be saved as Standard ABAP, as it accesses R_SalesOrderTP which is not released.

Lastly if you want to expose this via your channel to Event Mesh, you need to create the event binding (Business Service - Event Binding) for the new event, in my case that's ZChangedExtended as written above.

And that's it. Not exactly a workaround, but what needs to be done while the events are not exposed on the interface. But always try to achieve your extensions or custom code by using the RAP BO interface.

BR, Melanie

alexbeer
Explorer
0 Kudos

Dear @mlauber , 

great blog post, thank you for that.

We are currently trying to replace an old non clean exit with local RAP BO Consumption S/4 2023 FPS 2.

We are using the business event https://api.sap.com/event/OP_SUPPLIERINVOICEEVENTS/overview for this.
This uses the RAP BO R_SUPPLIERINVOICETP.

Now we are observing the following behavior, which we cannot explain:

  • If we post the logistics incoming invoice using transaction MIRO, the event and our implementation are triggered. ✔️
  • However, if the logistics incoming invoice is posted using an INVOIC IDoc, the event is not triggered. ✖️

What is the reason why document posting via IDoc does not trigger this event?

BR, Alex

 

mlauber
Product and Topic Expert
Product and Topic Expert

Hi @alexbeer 

Such a question is better asked via OSS. I'm not in the knowledge of every single module and it's objects and how they trigger when and what; that's up to component responsible.

Kind regards