Skip to Content
Personal Insights
Author's profile photo Siddhartha Routh

RAP Based Events in SAP S/4HANA Cloud ABAP Environment ( aka Embedded Steampunk )

Event Driven Architecture has gained a lot of popularity in recent times as businesses are looking to leverage it to become flexible , agile and scalable. Events are used more and more for real time integration with 3rd party systems without the need to extend the core. There are great many blogs already written about Event Driven Architecture and Event Mesh and how to configure event mesh to send events from S/4HANA On-Premise or cloud system to BTP Event mesh. This blog is focused more on ABAP RESTful Application Programming Model ( RAP ) based events introduced as part of the recent release.

With the release of BTP ABAP environment 2208 and developer extensibility( Embedded Steampunk) in S/4HANA Cloud , ABAP RESTful Application Programming Model framework now supports event driven architecture natively. Events represent a significant change of state of the RAP business objects or of one of its child entity that is relevant for follow-up processes . RAP BO’s can act as both Event Consumer and Event Producer.

Just like the standard SAP S/4HANA On-Premise or Cloud events RAP based events too work together with event mesh as a message broker to produce or receive events , we will continue the discussion with the assumption that Event mesh is already configured in your system and Channels are already set up for outbound topic binding.

RAP Business Objects as Event Consumers

Events can be consumed from the Event Mesh Queue using the newly introduced event consumption model . Event Consumption Model can be created using the AsyncAPI JSON file for a particular event , the consumption model based on the payload mentioned in the AsyncAPI JSON creates an abstract entity , consumer class and a consumer extension class , the consumer extension class can then be used to plugin our custom logic on how the event should be handled. For Example a sales order can be created using a RAP BO based on the event payload.

Please check the below tutorial which explains in great detail on how to configure Event Mesh in a SAP S/4HANA cloud system and how to Consume Events using the Event Consumption Model.

Event Consumption in ABAP Development Tools using RAP BO

 

RAP Business Objects as Event Producers

RAP entity events are defined through Behavior Definition on root node level for both managed and unmanaged scenario. Entity events can have a parameter ( Abstract CDS Entity ) which acts as the event payload and is optional. If no parameter is defined the keys for the root BO is used as the event payload. The RAP Event created will be then mapped to a event type using “Event Binding” which will allow the event to be configured as an Outbound Topic in our event mesh Channel. This topic is then subscribed by an event mesh queue for further processing, messages can be consumed by 3rd party systems from the queue directly.

The event can also be triggered from outside the RAP Business object by wrapping the “Raise Event” in a local class in the behavior pool class and calling the same by creating static method in the global class pool of the behavior implementation class. This static method can be then used to raise the events from outside the RAP BO by passing the payload as an importing parameter.

For this use case a simple RAP BO is created which will send an event for every new instance created using the RAP BO , a parameter is defined for the event using an abstract entity that acts as payload structure to send additional Contact Details along with the partner number created. Keyword “RAISE ENTITY EVENT” is then used to raise the event when a new instance is created , this is implemented within its own behavior pool using an additional save. 

Interface View 

@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Interface View for Contact Info'
define root view entity ZI_CONINFO
  as select from ztabconinfo
{
  key bpno                  as Bpno,
      firstname             as Firstname,
      lastname              as Lastname,
      @Semantics.eMail.address: true
      email                 as Email,
      @Semantics.user.createdBy: true
      local_created_by      as LocalCreatedBy,
      @Semantics.systemDateTime.createdAt: true
      local_created_at      as LocalCreatedAt,
      @Semantics.user.lastChangedBy: true
      local_last_changed_by as LocalLastChangedBy,
      //local ETag field --> OData ETag
      @Semantics.systemDateTime.localInstanceLastChangedAt: true
      local_last_changed_at as LocalLastChangedAt,

      //total ETag field
      @Semantics.systemDateTime.lastChangedAt: true
      last_changed_at       as LastChangedAt
}

 

Consumption View 

@EndUserText.label: 'Consumption View for Contact Info'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@Metadata.allowExtensions: true
@Metadata.ignorePropagatedAnnotations: true
define root view entity ZC_CONINFO
  provider contract transactional_query
  as projection on ZI_CONINFO
{
  key Bpno,
      Firstname,
      Lastname,
      Email,
      LocalLastChangedAt
}

 

Metadata Extension 

@Metadata.layer: #CORE
@UI: { headerInfo: {
typeName: 'User',
typeNamePlural: 'Users',
title: { type: #STANDARD, value: 'Bpno' } },
         presentationVariant: [{
         sortOrder: [{ by: 'Bpno', direction: #DESC }],
         visualizations: [{type: #AS_LINEITEM}] }] }
annotate view ZC_CONINFO with
{
  @UI.facet: [    {
                 label: 'General Information',
                 id: 'GeneralInfo',
                 type: #COLLECTION,
                 position: 10
                 },
                      { id:            'Userdetails',
                     purpose:       #STANDARD,
                     type:          #IDENTIFICATION_REFERENCE,
                     label:         'User Details',
                     parentId: 'GeneralInfo',
                     position:      10 } ]

  @UI: { lineItem:       [ { position: 10, importance: #HIGH , label: 'User Number'} ] ,
         identification: [ { position: 10 , label: 'User Number' } ] }
  Bpno;
  @UI: { lineItem:       [ { position: 20, importance: #HIGH , label: 'First Name'} ] ,
        identification: [ { position: 20 , label: 'First Name' } ] }
  Firstname;
  @UI: { lineItem:       [ { position: 30, importance: #HIGH , label: 'Last Name'} ] ,
        identification: [ { position: 30 , label: 'Last Name' } ] }
  Lastname;
  @UI: { lineItem:       [ { position: 40, importance: #HIGH , label: 'Email Address'} ] ,
        identification: [ { position: 40 , label: 'Email Address' } ] }
  Email;

}

 

Behavior Definition for Interface view

In the below behavior definition the event is defined along with a CDS abstract entity as a parameter. The Keys for the RAP BO along with the parameter makes the payload for the event.

managed implementation in class zbp_i_coninfo unique;
strict ( 2 );
with draft;

define behavior for ZI_CONINFO alias Userdetails
persistent table ztabconinfo
draft table ztabconinfod
lock master
total etag LocalLastChangedAt
authorization master ( instance )
with additional save
{
  create;
  update;
  delete;

  field ( readonly ) LastChangedAt, LocalLastChangedBy, LocalLastChangedAt, LocalCreatedBy,
  LocalCreatedAt;

  event SendContact parameter ZABS_EVENTSTRUC;

  draft action Edit;
  draft action Activate;
  draft action Discard;
  draft action Resume;

  draft determine action Prepare;

}

 

CDS Abstract Entity

This will act as the Event Payload along with the RAP BO Key.

@EndUserText.label: 'Event Structure'
define abstract entity ZABS_EVENTSTRUC
{
  firstname  : abap.char(20);
  lastname   : abap.char(20);
  email      : abap.char(20);
  created_by : abp_creation_user;
  created_at : abp_creation_tstmpl;

}

 

Raising the event in Save Modified 

The event is then raised in Save Modified method of the Implementing class for the behavior definition. For our use case we don’t want to raise an event for update or delete and hence the additional check is performed to ensure that the event is raised only for Create Scenarios.

method save_modified.

    if create-userdetails is not initial.


      raise entity event zi_coninfo~SendContact
        from value #(
          for userdet in create-userdetails (
              Bpno        = userdet-Bpno
              firstname        = userdet-Firstname
              lastname          = userdet-Lastname
              email  = userdet-Email
            )
          ).
    endif.

  endmethod.

 

The Behavior definition for the consumption view , the Service definition and the ODataV4 UI Service binding is then created to expose the Business object. Once the Service is published we can then  create an event binding to map the RAP Event and RAP BO and create a custom topic which will be the configured in the EM outbound channel for outbound communication.

The Namespace, Business object and Business Object Operation together becomes the topic for this event as can be seen in the field “Type” below.

The Root Entity and the Event defined in the BDEF is then added as shown below to the Event Binding to map it to the name space.

Event%20Binding

Event Binding

 

The Event is then available in the dropdown for outbound topics and can be configured in the SAP S/4HANA Cloud Event mesh Channel as an Outbound Topic.

Configured%20as%20an%20Outbound%20Topic

Available under Outbound Topic

RAP%20Event%20configured%20as%20outbound%20Topic

RAP Event configured as outbound Topic

 

This is now ready for consumption and can be subscribed to an event mesh queue as shown below. The message can then be consumed from event mesh queue using the standard consumption model such as AMQP, REST , Webhook or now from another RAP business object.

Topic%20Subscribed%20in%20the%20EM%20Queue

Topic Subscribed in the EM Queue

 

To test the application we can then create a new Instance with the corresponding contact details, on saving the contact info an event will be raised which will then send the contact details to the EM queue.

New%20Instance%20Created

New Instance Created

 

Message%20Received%20in%20Queue

Message Received in Queue

Event payload

 

In conclusion, native support of RAP based events dramatically strengthens SAP’s capability to support event driven architecture and gives us as developers the capability make our applications agile and flexible. This will also enable us to extend standard business processes with additional functionality or post processing steps without the need of enhancement keeping the core clean. Using RAP as an event producer we can now have our own custom event which can be used for all the scenarios where Standard events are not available or Simple Notification event doesn’t suffice the requirement , in saying so we should not forget that events are means to be lightweight and hence the payload should be kept to essential fields only.

Below are some of the materials I referred to while writing this blog and can provide more insights additionally I would highly recommend going through the tutorial for event consumption scenarios .  Let me know what you think of this new feature in comments below and please provide feedback.

RAP Business Events

Creating Business Events

Creating Event Consumption Model

 

Assigned Tags

      6 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Syambabu Allu
      Syambabu Allu

      Hi Siddhartha,

      Very well explained blog on RAP with Event Mesh. Thanks for sharing!!

      Thank you,

      Syam

      Author's profile photo Pankaj Yadav
      Pankaj Yadav

      Hi Siddhartha,

      Thanks for sharing this blog.

      Author's profile photo Arun Kumar Agrawal
      Arun Kumar Agrawal

      Very well explained. Thank you Siddhartha..

      Author's profile photo Wolfgang Röckelein
      Wolfgang Röckelein

      Hi Siddhartha Routh ,

       

      thanks for the helpful blog!

      Is it possible in Embedded Steampunk to directly/locally consume RAP Business Events, eg. an event from a S/4HANA Cloud Standard BO in an ABAP Environment based extension?

       

      Regards,

      Wolfgang

      Author's profile photo Siddhartha Routh
      Siddhartha Routh
      Blog Post Author

      Hi , Wolf Gang , yes it is possible to RAP events outside the context of the RAP BO  .

       

      Author's profile photo Wolfgang Röckelein
      Wolfgang Röckelein

      Hi Siddhartha Routh ,

      thanks for the quick answer!

      And how can the achieved, ie direct local consumption of an RAP business event without going through event mesh?

      Regards,

      Wolfgang