Introduction:
Side-by-Side Extension in SAP refers to the approach of extending or enhancing existing SAP systems without modifying their core functionality. It allows for the development and deployment of additional custom applications or functionalities alongside the existing SAP landscape, minimizing the risk of system disruptions.
In a recent project, I was assigned the development of an application following the side-by-side extension approach on SAP BTP. The objective was to enable seamless data exchange between the application and both SAP S/4HANA Public Cloud and Private Cloud. Based on the learnings from the project, I will provide a comprehensive explanation of how to successfully make POST calls to SAP S/4 HANA Public System. It will cover the necessary steps and intricacies involved in integrating and exchanging data between the extensions and the S/4HANA Public system.
Watch out for my next blog where I will give details about exchanging data with S/4 HANA Private Cloud.
Scenario:
Create a CAP service to create a sales order in SAP S4HANA cloud.
Pre-requisite:
- Need to know how to create a basic CAP project.
- SAP S/4HANA Cloud Extensibility service entitlement assigned to subaccount with plan
api-access.
- Destination service entitlement.
- S4 HANA Public Cloud system.
Supporting Material:
You can refer this blog to form a connection with SAP S/4HANA Cloud. Consume Remote Services from SAP S/4HANA Cloud Using CAP
Development:
- Upload the Sales Order edmx file to root folder of your basic cap application.
- Navigate to your project and run the below command.
Make sure that you are in root folder of your project
cds import ./API_SALES_ORDER_SRV.edmx
- Once you execute command, your edmx file will get moved to .src/external folder and API_SALES_ORDER_SRV.csn and API_SALES_ORDER_SRV.edmx file will get created. Additionally, the file will be registered as service definition in the package.json file.
As we need to pass the x-csrf-token to handle the POST call, include below lines of code into the package.json"cds": { "requires": { "API_SALES_ORDER_SRV": { "kind": "odata-v2", "model": "srv/external/API_SALES_ORDER_SRV", "csrf": true, "csrfInBatch": true,
- Start your cap application:
cds watch
- Open the CAP application in your browser: http://localhost:4004/You can now see the api-sales-order-srv service with all its entities under Service Endpoints.
- Expose the Sales Order through your service by adding following lines to your code in the srv/OrderService.cds file
using {API_SALES_ORDER_SRV as order} from '../srv/external/API_SALES_ORDER_SRV'; service SalesOrderService @(path : '/Sales') { entity SalesOrder as projection on order.A_SalesOrder; };
- Inside same file create another service with rest protocal having action
Create_Order. Action contains the generic import parameter “object” to receive the payload as deep json call.
@protocol: 'rest' service OrderPostService { @open type object {}; action Create_Order(Order : object) returns object; }
- Finally your OrderService.cds file should look like this
using {API_SALES_ORDER_SRV as order} from '../srv/external/API_SALES_ORDER_SRV'; service SalesOrderService @(path : '/Sales') { entity SalesOrder as projection on order.A_SalesOrder; }; @protocol: 'rest' service OrderPostService { @open type object {}; action Create_Order(Order : object) returns object; }
- If your cds watch is still running then your http://localhost:4004/should look like this.
- Follow the steps given in the link to register your HANA system to BTP cockpit.
- Create order-service-config.json file in root folder of your project.
{ "systemName": "<set in mta.yaml>", "communicationArrangement": { "communicationArrangementName": "SAP_COM_0109", "scenarioId": "SAP_COM_0109", "inboundAuthentication": "BasicAuthentication", "outboundAuthentication": "BasicAuthentication", "communicationSystem": { "communicationSystemHostname": "default.com", "outboundCommunicationUser": { "username": "DefaultUser", "password": "DefaultPassword" } } } }
- Install the node package to mock the external service.
npm install @sap-cloud-sdk/http-client @sap-cloud-sdk/util
- Now, add the handler code to delegate the call from the SalesOrder service entity to the remote API_SALES_ORDER_SRV service. In this blog we are going to handle Read and POST action.
Inside the srv folder create OrderService.js file which is default handler method for the OrderService.cds. Ensure that .js and .cds file name are same.
const cds = require('@sap/cds'); module.exports = cds.service.impl(async function (srv) { const { SalesOrder, Create_Order } = this.entities; // connects to the remote service const order = await cds.connect.to('API_SALES_ORDER_SRV'); // Handle GET call srv.on('READ', 'SalesOrder', async req => { const order = await cds.connect.to('API_SALES_ORDER_SRV'); return order.run(req.query); }); // Handle POST call srv.on('Create_Order', async(req) => { // Extract the Sales Order payload from the request data const OrderData = req.data.Order; // Map the POST request on remote service const SalesOrderResponse = await order.run(INSERT.into('SalesOrderService.SalesOrder', [OrderData])); // Return the response return SalesOrderResponse; }); });
- On root folder execute the below command.This will add the mta.yaml file to your project
cds mta add
- Add the SAP S/4HANA cloud extensibility service to your mta.yaml. In this system name should match with the system name given in the global account cockpit.
resources: - name: SalesOrder-order type: org.cloudfoundry.managed-service parameters: skip-service-updates: plan: true parameters: true tags: true service: s4-hana-cloud service-plan: api-access system-name: XXXXXXXXXXXXXXXXXXXXXXX path: ./order-service-config.json config: systemName: XXXXXXXXXXXXXXXXXXXXXXX
- Update the mta.yaml file requires section with destination service to access the S/4HANA system.
- name: SalesOrder-destination type: org.cloudfoundry.managed-service parameters: config: HTML5Runtime_enabled: true init_data: instance: destinations: - Authentication: NoAuthentication Name: ui5 ProxyType: Internet Type: HTTP URL: https://ui5.sap.com existing_destinations_policy: update version: 1.0.0 service: destination service-plan: lite
and update the srv dependancy as shown below
- Build the MTA module from your project root folder and deploy your project with below two command one after another.
mbt build -t ./ cf deploy SalesOrder_1.0.0.mtar
Test the Service:
Create test.http file in your root project folder and send the payload as shown below.
@host = <<Your service url after deployment>>
@protocol = https
###
POST {{protocol}}://{{host}}/order-post/Create_Order
Content-Type: application/json
{
"Order":
{
"SalesOrderType": "OR",
"SalesOrganization": "1710",
"DistributionChannel": "10",
"OrganizationDivision": "00",
"SoldToParty": "1000180",
"PurchaseOrderByCustomer": "CAP Application-Mujeeb",
"CustomerPaymentTerms": "",
"to_Partner": [
{
"PartnerFunction": "SP",
"Customer": "1000187"
}
],
"to_Item": [
{
"Material": "LXF001",
"RequestedQuantity": "10"
}
]
}
}
your payload data may vary, here I am showing one sample.
Conclusion:
Using CAP you can not only fetch the data but also you can post the data to your core system.
I would love to hear from you! Please leave your feedback below in comments section and ask your questions about the topic in sap community using this link.