Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Gunter
Product and Topic Expert
Product and Topic Expert
1,990

SAP Event Objects - What and Why?


Event-driven architecture is an approach to software design where the components of a system are designed to respond to events or messages in a decoupled manner. In this architecture, events are sent and received by the system's components, triggered by user actions, system events, or external factors.

This design allows for more flexibility, scalability, and responsiveness in system design, as well as improved handling of large volumes of data and traffic. Additionally, it can enable greater collaboration and innovation by allowing organizations to integrate different systems and technologies.

SAP developed event-frameworks for our line-of-business solutions. So in the very recent years a very impressive set of event objects became available for S/4HANA (Cloud and On-Premise) which you can find documented on the API business hub. Events are sent following the Cloud Events specification.

What does this blog address?


This blog serves as a practical how-to guide for setting up SAP event objects, compiled from various sources of information and personal insights. The aim is to help you save time and effort in setting up your system by providing clear and concise steps for implementation. While not addressing a specific use case, this guide will explain the mechanics and setup of SAP event objects, so you can get started with this powerful tool and take full advantage of its capabilities.

By following this guide, you can benefit from SAP's event objects in many ways, including faster data processing, better integration with other systems, and improved system agility. Whether you're new to SAP or an experienced user, this guide can help you unlock the full potential of event-driven architecture in your business processes.

Concept of external cloud events on SAP BTP Kyma


One of the most challenging aspects of working with SAP S/4HANA Cloud Events on SAP Event Mesh on SAP BTP Kyma is understanding how external events are processed. Initially, I was caught up in the paradigm of how Kyma and NATS eventing works, which turned out to be a different approach altogether.

To shed some light on the process, let's take a look at the image below, which illustrates the flow of event information from source to consumer.


Image 1: Event information flow from source to consumer.


While this is not a perfect technical explanation, the basic idea is that an event raised in S/4HANA Cloud goes through the event framework on S/4HANA Cloud and identifies a suitable scenario (in this case, 0092) where the event was previously set as an outbound topic through the Fiori Enterprise Event Enablement Application.

From there it travels to the BTP Event Mesh into the client that is generated by the S/4HANA Cloud Messaging extensibility service. There one can also see subscribed event (which was an Outbound Topic in S/4HANA Cloud) - however not set it. This can be seen a read-only client.

In the Event Mesh client, though an Event Queue is set up with a subscription to the event provided by the aforementioned client. Here all incoming external events are collected for consumption. In order to allow for that, a webhook is defined that points to a URL on the Kyma cluster secured through OAuth2 client-credentials.

Finally the event is received by the API Rule on Kyma and forwarded through the service to the program running in a pod's container. That can be a Kyma serverless function or any other container. Above image also shows how such a cloud event is structured with the information in between the data-section being business object or better: event object specific.

Configure Event consumption from S/4HANA Cloud


Let's now do the same for events.

A. Define and deploy the Event Mesh for S/4HANA Cloud


This event mesh instance is providing the extensibility for events to and from S/4HANA Cloud. Create a yaml file similar to below.
apiVersion: services.cloud.sap.com/v1
kind: ServiceInstance
metadata:
name: s4hc-ext-em-service
labels:
app.kubernetes.io/name: s4hc-ext-service
namespace: s4hc-extensibility
spec:
externalName: ''
serviceOfferingName: s4-hana-cloud
servicePlanName: messaging
parameters:
systemName: S4HANA-CLOUD-APJREGION
emClientId: apj0

It's important to have entitlement for the S/4HANA Cloud Extensibility for the plan messaging set (we did this before already if you followed all steps). The systemName is the same name with which we registered the S/4HANA Cloud tenant. The emClientId must be not more than 4 characters.

This service create takes a while (approx. 5mins) since it also creates an instance of the SAP Event Mesh in the BTP. Once you log in to the Event Mesh UI you should see the emClientId as a client like so:


Image 2: SAP Event Mesh instance created through Kyma yaml


If you check in the S/4HANA Cloud in the communication arrangement, you will also find that some magic happened, the scenario SAP_COM_0092 was created.


Image 3: S/4HANA Cloud - generated Enterprise Eventing Integration.


Next, search for the Enterprise Event Enablement application in S/4HANA Cloud. You need the role SAP_BR_ADMINISTRATOR assigned to your user for that.

Now add the event you want to work with e.g. sap/s4/beh/salesorder/v1/SalesOrder/Changed/* as an outbound event. Once added, you will see it as an event in the Event Mesh UI under Events.

Create the SAP Event Mesh service on BTP


Wait! Didn't we just do it? I found this slightly confusing since we already navigated in the SAP Event Mesh UI. However, what we set up was the plan s4-hana-cloud with the plan messaging. What we're now setting up is the service enterprise-messaging with its plan default.

For this you can refer to below yaml - of course adjust the naming to your needs like before.
---
apiVersion: services.cloud.sap.com/v1
kind: ServiceInstance
metadata:
name: sap-event-mesh-service
labels:
app.kubernetes.io/name: sap-event-mesh-service
namespace: s4hc-extensibility
spec:
externalName: ''
serviceOfferingName: enterprise-messaging
servicePlanName: default
parameters:
emname: apj1-event-mesh
version: 1.1.0
namespace: sap/eventmeshazure/apj1
options:
management: true
messagingrest: true
messaging: true
rules:
queueRules:
subscribeFilter:
- "${namespace}/*"
- sap/S4HANAOD/apj0/*
topicRules:
subscribeFilter:
- "${namespace}/*"
- sap/S4HANAOD/apj0/*

You need to make sure that at least one of the the subscribeFilter entries (separated by dash) match your namespace of S/4HANA Cloud Extensibility for messaging. That's why I have apj0 in there. If you miss this, you can't change the service descriptor later (or at least I don't know how). So you would need to delete the instance and deploy it with the updated filter (again).

Consume the events in the test tool


Now back to the UI of the SAP Event Mesh. Enter the message client we defined before (apj1) and create a new Queue in Queues. Call it e.g. salesOrderChangedQueue. Add an action to the new queue: Queue subscription. Here add the event to it, which we set active in the apj0 client. If we now carry out a change in any sales order in S/4HANA Cloud, we'll be getting an event raised and can consume it in the test tool.


Image 4: Test tool in the SAP Event Mesh UI - Consume an event.


Note the structure of an event:
{
"type": "sap.s4.beh.salesorder.v1.SalesOrder.Changed.v1",
"specversion": "1.0",
"source": "/default/sap.s4.beh/740755835",
"id": "9b382d0f-5a6e-1eed-b593-8fe27f15b41b",
"time": "2023-04-06T17:00:14Z",
"datacontenttype": "application/json",
"data": {
"SalesOrder": "210655",
"EventRaisedDateTime": "2023-04-06T17:00:14.131574Z",
"SalesOrderType": "TA",
"SalesOrganization": "1710",
"DistributionChannel": "10",
"OrganizationDivision": "00",
"SoldToParty": "1000291"
}
}

Once consumed, the event disappears from the message queue.

Bind the service and activate SAP Event Mesh as eventing framework on Kyma


To understand how to use events in your own application, let's create the setup for consumption.

First, we have to create a service binding with the SAP Event Mesh. You can do it in the Kyma UI or as part of a yaml file.
---
apiVersion: services.cloud.sap.com/v1
kind: ServiceBinding
metadata:
name: sap-event-mesh-binding
namespace: s4hc-extensibility
spec:
externalName: sap-event-mesh-binding
secretName: sap-event-mesh-binding
serviceInstanceName: sap-event-mesh-service

You should then see the binding in status Provisioned after a few seconds. Move to the ConfigurationsSecrets of your namespace to find a new secret created called sap-event-mesh-binding. You can consider this the equivalent of a service key in Cloud Foundry.

Kyma uses the NATS eventing framework as default, so we got to tell the cluster to switch to SAP Event Mesh. It's a cluster-wide setting, so you can't run NATS and SAP Event Mesh in parallel.


Image 5: Binding secret: Adding activation of SAP Event Mesh over NATS.


Add the above two lines into the secret and save it.

Create a OAuth-Client in Kyma and Webhook in the Event Mesh


Create an OAuth Client so that SAP Event Mesh can call into Kyma.
---
apiVersion: hydra.ory.sh/v1alpha1
kind: OAuth2Client
metadata:
name: s4hc-sochg-oauthclnt
namespace: s4hc-extensibility
spec:
grantTypes:
- client_credentials
scope: s4hc-sochg-scope
secretName: s4hc-sochg-secret

Go to the SAP Event Mesh to the client apj1-event-mesh. Choose the menu Webhooks.

Enter a subscription name like kyma-so-change-consumption. Change Quality of Service to 1. Set Exempt Handshake to Yes. On-Premise keep at No.

Set the Webhook URL to https://s4-so-change-event.<Cluster ID>.kyma.shoot.live.k8s-hana.ondemand.com.

Default Content Type to application/json.

Authentication to OAuth2ClientCredentials. Now set the Client ID and Client Secret from the OAuth2Client created earlier. Token URL is https://oauth2.<Cluster ID>.kyma.shoot.live.k8s-hana.ondemand.com/oauth2/token.

Enter the scope s4hc-sochg-scope. Press Create. It might be in the state Not Initiated. In that case go to Actions and Trigger Handshake. It should change to Subscription Status Active and Handshake status Exempted.

Consume the event with a simple serverless function


The most simple consumer function might look like this coding below.
module.exports = {
main: async function (event, context) {
const axios = require('axios');
const message = {
greeting: `Hi there, welcome from Kyma Function ${context['function-name']}`,
context: context,
eventdata: event.data,
eventtype: event.type,
eventcontent: event.datacontenttype,
};
console.log(message);
const url = 'https://<some other receiver url>';
axios.post(url, message, { headers: { 'Content-Type': 'application/json' }})
.then(response => {
console.log('Response:', response.data);
})
.catch(error => {
console.error('Error:', error.message);
});
return message;
}
}

and so a change in the sales order would make the log look like this:


Image 6: SAP BTP Kyma serverless function log - event received.



Closing


And there we are with setup and end-to-end test of external cloud event consumption on SAP BTP Kyma using S/4HANA Cloud and SAP BTP Event Mesh. Let me know your feedback in the comments!

References:

 

 
1 Comment