Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
jmalla
Contributor
Hi SAP Community Folks,

It's been a few months since I had published a blog.  My last few blogs have been on Fiori development and prior to that, SAP HANA native development.  I joined Delaware Consulting earlier this year and I am working as a Fiori Solution and S/4 HANA integration architect and team lead.

For the past few months, I have been working on an S/4 HANA new implementation leveraging the SAP integration suite - Cloud Integration, Event Mesh, API Hub, Integration advisor, etc.  In this blog, I wanted to capture sending out business transaction events from S/4 HANA to the Event Mesh and having CPI read from the Event Mesh and then process the event, read additional data from S/4 HANA using the OData API to enrich the message, and then publish to an outbound queue for downstream systems.

So the first part is setting up the outbound process.  For these steps, the following blog is an excellent starting point:

How to use SAP S/4HANA Event Enablement with SAP Cloud Platform (EN) written by Makoto Sugishita

 

So we set this up and we were sending sales order creations and changes to the event mesh:


 

Maintain the channel topics for publishing the business events


 

Then we create the queue in Event Mesh and the queue subscription to subscribe to the sales order create and change events:

 


 

For our testing, we used the SAP transaction code SWUE to trigger the sales order event to send to the queue.  Once this is all set up, the events will be triggered automatically when creating or changing a sales order:

 


Transaction SWUE to trigger sales order creation event


 


Transaction SWUE to trigger sales order created


 

Here are the sales order in the queue:

 


Queue with sales order events


 

 

So once we receive the sales order business transaction events in the queue, we can then read the queue and process the message to enhance the details through the OData call to S/4 HANA and publish on an outbound queue.

 

Here is the IFlow:


SalesOrderEventFromQ IFlow


 


AMQP General tab for reading queue


 


AMQP Connection tab for reading queue



AMQP Processing tab for reading queue


 

Here is the Groovy script to extract the sales order number:

 
// Extract the SALESORDER from the Business Transaction Event


import com.sap.gateway.ip.core.customdev.util.Message;
import groovy.json.*

def Message processData(Message message) {
def json = new JsonSlurper().parseText(message.getBody(String));
message.setHeader('SALESORDER',json.data.KEY[0].SALESORDER);
message.setHeader('eventType',json.eventType);

return message;
}

 

Here we log the business transaction event with the sales order number we extracted:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;

def Message processData(Message message) {

def map = message.getHeaders();
def salesorder = map.get("SALESORDER");
def eventType = map.get("eventType");


def body = message.getBody(java.lang.String) as String;
def messageLog = messageLogFactory.getMessageLog(message);


//Properties
def properties = message.getProperties();

String sBody = "SalesOrder " + salesorder + " Event " + eventType + " from S4 HANA";


if(messageLog != null) {
messageLog.setStringProperty(sBody, body);
messageLog.addAttachmentAsString(sBody, body, 'application/json');
}

return message;
}

 

Here is the Request-Reply to call the OData sales order API to get the order details:


OData General tab



OData connection tab


 


OData processing tab


 

Here is the Log SAP OData XML Response:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;

def Message processData(Message message) {

def map = message.getHeaders();
def salesorder = map.get("SALESORDER");

def body = message.getBody(java.lang.String) as String;
def messageLog = messageLogFactory.getMessageLog(message);

//Properties
def properties = message.getProperties();

String sBody = "OData SalesOrder " + salesorder + " Details XML from S4 HANA";


if(messageLog != null) {
messageLog.setStringProperty(sBody, body);
messageLog.addAttachmentAsString(sBody, body, 'text/xml');
}

return message;
}

 

Here is the Log SAP OData JSON Response:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;

def Message processData(Message message) {

def map = message.getHeaders();
def salesorder = map.get("SALESORDER");

def body = message.getBody(java.lang.String) as String;
def messageLog = messageLogFactory.getMessageLog(message);

//Properties
def properties = message.getProperties();

String sBody = "OData SalesOrder " + salesorder + " Details JSON from S4 HANA";


if(messageLog != null) {
messageLog.setStringProperty(sBody, body);
messageLog.addAttachmentAsString(sBody, body, 'application/json');
}

return message;
}

 

And here is the final publishing to the outbound queue:

 


AMQP General tab for writing to queue


 


AMQP Connection tab for writing to queue


 


AMQP Processing tab for writing to queue


 

So once the event is written to the queue and the Flow is triggered, then you can see the following messages in the integration message monitoring:

 


Message monitoring


 

Here is how the event json looks like:

SalesOrder 0000000494 Event BO.SalesOrder.Created from S4 HANA
{
"eventType": "BO.SalesOrder.Created",
"cloudEventsVersion": "0.1",
"source": https://sap.corp,
"eventID": "AvI8lTL3HuyLryFqiGugrw==",
"eventTime": "2021-10-15T05:30:44Z",
"schemaURL": https://sap.corp/sap/opu/odata/IWXBE/BROWSER_SRV/,
"contentType": "application/json",
"data": {
"KEY": [
{
"SALESORDER": "0000000494"
}
]
}
}

 

 

OData SalesOrder 0000000494 Details XML from S4 HANA
<A_SalesOrder>
<A_SalesOrderType>
<CreationDate>2021-10-21T00:00:00.000</CreationDate>
<CreatedByUser>YTHAM</CreatedByUser>
<OrganizationDivision>00</OrganizationDivision>
<PurchaseOrderByCustomer>YT_ODN_AU</PurchaseOrderByCustomer>
<DistributionChannel>10</DistributionChannel>
<SalesOrganization>3010</SalesOrganization>
<SoldToParty>30100001</SoldToParty>
<TotalNetAmount>120.00</TotalNetAmount>
<to_Item>
<A_SalesOrderItemType>
<SalesOrderItemText>Service Material 01</SalesOrderItemText>
<ProductionPlant>3010</ProductionPlant>
<PurchaseOrderByCustomer>YT_ODN_AU</PurchaseOrderByCustomer>
<Material>SM0001</Material>
<MaterialByCustomer>
</MaterialByCustomer>
<RequestedQuantityUnit>H</RequestedQuantityUnit>
<TransactionCurrency>AUD</TransactionCurrency>
<PricingDate>2021-10-21T00:00:00.000</PricingDate>
<NetAmount>120.00</NetAmount>
<SalesOrderItemCategory>TAD</SalesOrderItemCategory>
<SalesOrderItem>10</SalesOrderItem>
<HigherLevelItem>0</HigherLevelItem>
<RequestedQuantity>1.000</RequestedQuantity>
<SalesOrder>494</SalesOrder>
</A_SalesOrderItemType>
</to_Item>
<TransactionCurrency>AUD</TransactionCurrency>
<SalesOrderType>OR</SalesOrderType>
<SalesOrderDate>2021-10-21T00:00:00.000</SalesOrderDate>
<to_Partner>
<A_SalesOrderHeaderPartnerType>
<PartnerFunction>SP</PartnerFunction>
<Customer>30100001</Customer>
<Supplier>
</Supplier>
<Personnel>0</Personnel>
<ContactPerson>0</ContactPerson>
<SalesOrder>494</SalesOrder>
</A_SalesOrderHeaderPartnerType>
<A_SalesOrderHeaderPartnerType>
<PartnerFunction>BP</PartnerFunction>
<Customer>30100001</Customer>
<Supplier>
</Supplier>
<Personnel>0</Personnel>
<ContactPerson>0</ContactPerson>
<SalesOrder>494</SalesOrder>
</A_SalesOrderHeaderPartnerType>
<A_SalesOrderHeaderPartnerType>
<PartnerFunction>PY</PartnerFunction>
<Customer>30100001</Customer>
<Supplier>
LanguageHTML/XML

</Supplier>
<Personnel>0</Personnel>
<ContactPerson>0</ContactPerson>
<SalesOrder>494</SalesOrder>
</A_SalesOrderHeaderPartnerType>
<A_SalesOrderHeaderPartnerType>
<PartnerFunction>SH</PartnerFunction>
<Customer>30100001</Customer>
<Supplier>
</Supplier>
<Personnel>0</Personnel>
<ContactPerson>0</ContactPerson>
<SalesOrder>494</SalesOrder>
</A_SalesOrderHeaderPartnerType>
</to_Partner>
<SalesOrder>494</SalesOrder>
</A_SalesOrderType>
</A_SalesOrder>



OData SalesOrder 0000000494 Details JSON from S4 HANA
{
"A_SalesOrder": {
"A_SalesOrderType": {
"CreationDate": "2021-10-21T00:00:00.000",
"CreatedByUser": "YTHAM",
"OrganizationDivision": "00",
"PurchaseOrderByCustomer": "YT_ODN_AU",
"DistributionChannel": "10",
"SalesOrganization": "3010",
"SoldToParty": "30100001",
"TotalNetAmount": "120.00",
"to_Item": {
"A_SalesOrderItemType": {
"SalesOrderItemText": "Service Material 01",
"ProductionPlant": "3010",
"PurchaseOrderByCustomer": "YT_ODN_AU",
"Material": "SM0001",
"MaterialByCustomer": "",
"RequestedQuantityUnit": "H",
"TransactionCurrency": "AUD",
"PricingDate": "2021-10-21T00:00:00.000",
"NetAmount": "120.00",
"SalesOrderItemCategory": "TAD",
"SalesOrderItem": "10",
"HigherLevelItem": "0",
"RequestedQuantity": "1.000",
"SalesOrder": "494"
}
},
"TransactionCurrency": "AUD",
"SalesOrderType": "OR",
"SalesOrderDate": "2021-10-21T00:00:00.000",
"to_Partner": {
"A_SalesOrderHeaderPartnerType": [
{
"PartnerFunction": "SP",
"Customer": "30100001",
"Supplier": "",
"Personnel": "0",
"ContactPerson": "0",
"SalesOrder": "494"
},
{
"PartnerFunction": "BP",
"Customer": "30100001",
"Supplier": "",
"Personnel": "0",
"ContactPerson": "0",
"SalesOrder": "494"
},
{
"PartnerFunction": "PY",
"Customer": "30100001",
"Supplier": "",
"Personnel": "0",
"ContactPerson": "0",
"SalesOrder": "494"
},
{
"PartnerFunction": "SH",
"Customer": "30100001",
"Supplier": "",
"Personnel": "0",
"ContactPerson": "0",
"SalesOrder": "494"
}
]
},
"SalesOrder": "494"
}
}
}

 

Lastly, I wanted to add some troubleshooting tips.  When we first configured the outbound topic, the events were not being sent out to the message queue.  So we had to create a ticket for SAP and we were told that the entries:

The issue is because of 2 wrong entries maintained in the table SBO_I_BODEF for Sales Order. Please find the attached screenshot.

Wrong Entries:

SALES ORDER BO BUS2032

SALES ORDER SOA 114

 

Expected Entries:

SalesOrder BO BUS2032

SalesOrder CL CL_SD_SALESORDER_WORKFLOW

SalesOrder SOA 114

Expected entries are there in the table. Since there are wrong entries also present in the table for the same Business Object, events are not getting passed. Please remove those entries and retest the issue.

 

Maintain Customizing settings under

SAP NetWeaver->Application Server->Business Management->SAP Object Type Repository->SAP Object Types->Maintain Object Representation

 


SPRO - Maintain object representation


 

Make sure the following entries are there for BUS2032.  There should not be another set of entries there for BUS2032:

 


Sales order entries in object representation


Hopefully, this will help if you are embarking on the journey of publishing events from S/4 HANA to downstream subscribers.  Though this is the evolution of SAP integration with events and OData, the IDoc and SOAP async approaches still are widely used and maybe the better choice given the scenarios.  After having set up IDoc integration and SOAP integration through PI/PO for many projects, the new event mesh approach is a nice option to have also in the wide array of SAP integration methodolgies.  Happy learning!

Thanks,

Jay

 

You can connect with me at - Jay Malla on LinkedIn

 

 
6 Comments
Labels in this area