Skip to Content
Technical Articles
Author's profile photo Alessandro Biagi

Consuming SOAP Web Services in SAP Cloud Application Programming Model (CAP)

NOTE: this blog post is intended for developers who have previous experience in developing CAP applications which consume either OData or REST APIs using SAP Business Application Studio and SAP BTP destinations, as well as handling communication scenarios and communication arrangements in S/4HANA Cloud.

Introduction

You may have realized that most modern cloud applications are built to interact with other external solutions via OData and/or REST APIs (and you may have already done it yourself in several opportunities). But, there are some solutions that still do not offer 100% of services as OData or REST, providing some interfaces via SOAP web services – this is the case, for example, of S/4HANA Cloud which exposes a variety of OData services but, for same cases, still sticks with SOAP web services.

If you started programming in the last 5 years, you might not even know what I’m talking about – or if you know, it’s the fault of some legacy system you have to deal with.

SOAP, or Simple Object Access Protocol (not to be confused with SOA), is a protocol for creating distributed and decentralized web services – the famous web services – which allow the exchange of information between systems, using the XML format. I don’t know when this started, but the latest version is from 2007 (1.2) and was the most popular way of connecting systems in the first decade of the 2000s, before the emergence of the REST protocol that encouraged web APIs with JSON and, later, microservices – lighter ways to exchange information between systems over the web.

As previously mentioned almost all the latest web and mobile technologies offer native (or close to) support for handling REST Web APIs, but little is said about SOAP connections. The purpose of this blog post is precisely to help those who need to deal with NodeJS CAP applications on the client and SOAP on the server.

Application Architecture

We are going to build a simple CAP application that reads Business Users from S/4HANA Cloud (which are exposed exclusively via a SOAP web service).

You can view the application architecture bellow:

Figure%201%20-%20Application%20Architecture

Figure 1 – Application Architecture

Preparation Steps

Before we move forward with the instructions, let’s first get prepared for development by completing the following two basic steps:

  1. Set up a destination to your S/4HANA Cloud system using a communication user (not a business user). You can name your destination S4HC just to be compatible with the further instructions in the post. If you have trouble creating your destination just follow this tutorial on SAP Developers.
  2. Jumpstart a new CAP project in SAP Business Application Studio: after opening your dev space, open a new terminal window, move to the “projects” directory and initialize a new blank project with cds init business-users. Open the newly created project in a workspace to get ready for development.

Download Web Service Definition

The first thing we need to do is to get the web service definition which is described in WSDL (Web Services Description Language).

WSDL is an XML notation for describing a web service. A WSDL definition tells a client how to compose a web service request and describes the interface that is provided by the web service provider.

We can get such definition from SAP API Business Hub, so access https://api.sap.com.

In the home page, first make sure to login to API Business Hub (NOTE: you must login for the download process to work properly), then, after login, click on the S/4HANA Cloud tile.

Figure 2 – Login to SAP API Business Hub and access S/4HANA Cloud section

In the next page, click on the APIs tab, then, in the find box, type “business user read” and press enter. Finally, click on the Business User – Read tile.

Figure%203%20-%20Locate%20Business%20User%20-%20Read%20SOAP%20API

Figure 3 – Locate Business User – Read SOAP API

In the next page, click on API Specification.

NOTE: make sure your communication user (set up in your destination) has access to communication scenario SAP_COM_0193 or SAP_COM_0093, via some communication arramgement, as indicated below:

Figure%204%20-%20Access%20API%20Specification

Figure 4 – Access API Specification

Click on the down arrow next to WSDL and save the QUERYBUSINESSUSERIN.wsdl file in your local computer.

Figure%205%20-%20Download%20QUERYBUSINESSUSERIN.wsdl

Figure 5 – Download QUERYBUSINESSUSERIN.wsdl

Now, go to your CAP project in Business Application Studio and create a folder named “external” under the “srv” folder, then drag & drop the recently downloaded QUERYBUSINESSUSERIN.wsdl file into it like demonstrated below:

Figure%206%20-%20QUERYBUSINESSUSERIN.wsdl%20file%20imported%20to%20CAP%20project

Figure 6 – QUERYBUSINESSUSERIN.wsdl file imported to CAP project

This definition will be used later upon creation of the web service client..

Create Reference to Web Service Host

The next step is to reference the web service in the project’s package,json file. So, open it up and insert the following code snippet right before the last curly bracket:

,
  "cds": {
    "requires": {
      "UserRead": {
        "kind": "SOAP",
        "credentials": {
          "destination": "S4HC",
          "path": "/sap/bc/srt/scs_ext/sap/querybusinessuserin"
        }
      }
    }
  }

After the insertion, your package.json file should look like the screenshot below:

Figure%207%20-%20Reference%20to%20web%20service%20in%20package%2Cjson

Figure 7 – Reference to web service in package,json

Notice that the reference is pointing to the destination that has been previously created in BTP with the path to the actual service location.

Although the destination already points to the S/HANA Cloud host, as the WSDL file has been downloaded from SAP API Business Hub (not directly from a communication arrangement in the actual S4/HANA Cloud tenant), the service location within it is “generic”, meaning it’s just a “placeholder” in the format of “https://host:port/<service path>”.

Therefore, we still need to replace such placeholder with the actual S/4HANA Cloud tenant host. So, open-up the WSDL file and search for “location” (it’s usually at the end of the file) and replace all occurrences of “host:port” with your S/4HANA Cloud tenant host (set up in your destination), like demonstrated below:

UPDATE NOTE (May 9th, 2022): the code snippets in this blog post have been updated to dynamically set the service endpoint at runtime (thank you @Mukteshwari Rathore for the valuable insights on the setEndpoint method from the soap node package explained in your comments!). So, you can skip this step if you wish.

Figure%208%20-%20Replace%20host%3Aport%20with%20actual%20tenant%20host

Figure 8 – Replace host:port with actual tenant host

Now, the project is fully set up to communicate with the web service via the application code.

Bind Destination and XSUAA Services

Before moving on to binding the services to your project, make sure to login to Cloud Foundry either via the BAS command palette (View > Find Command) or command line interface (CLI) in the terminal.

After login, create the destination and XSUAA service instances using the command lines below:

  • cf create-service destination lite busers-dest
  • cf create-service xsuaa application busers-xsuaa

Upon successful creation of the service instances, on the left-hand pane of BAS click on the Cloud Foundry icon (small light bulb), then on the refresh button at the top right of the pane.

The newly created instances should be displayed at end of the list, like demonstrated below:

Figure%208%20-%20Newly%20created%20service%20instances

Figure 9 – Newly created service instances

Right click on the busers-dest service instance and select “Bind service to a locally run project” and, then, in the dialog, make sure the business-users folder is selected and click on the “Select folder for .env file” button.

Figure%209%20-%20Select%20business-users%20folder

Figure 10 – Select business-users folder

Now, repeat the same procedure for the busers-xsuaa service instance.

Click again on the Explorer icon in the left-hand pane and, then, in the refresh button at the right of the project name. You should see the .env file that has been created like demonstrated below:

Figure%2010%20-%20.env%20file%20for%20services%20binding

Figure 11 – .env file for services binding

Now, we need to rename that file to default-env.json and transform its contents into JSON format (as it’s just defining a regular environment variable called VCAP_SERVICES which is not in the expected JSON format), like demonstrated below:

Figure%2011%20-%20Rename%20.env%20and%20adjust%20to%20JSON%20format

Figure 12 – Rename .env and adjust to JSON format

Install Dependencies

To facilitate the creation of SOAP clients and avoid to much effort preparing a SOAP envelope in XML format to invoke the web service’s methods via HTTP request, we can use a pre-built NodeJS SOAP client manager from the “soap” package available on npm (in Java there’s already native support for SOAP web services).

Also, to easily fetch and manipulate the destination data from BTP we will utilize the “core” node package from the SAP Cloud SDK.

So, let’s install those dependencies by running the following commands:

  • npm install soap
  • npm install @sap-cloud-sdk/core

NOTE: if you intend to deploy your application to Cloud Foundry later you must also install the “passport” package, as the latest CDS version is enforcing security on bootstrap when deployed to production.

And, finally, to install the other dependencies from the original jump-started package.json we just run:

  • npm install

And with that, we are now fully ready to start the development!

Create Module to Handle SOAP Clients

In a productive scenario, we usually would have more than one web service being manipulated throughout the application code, so it’s convenient to create a module with a function that facilitates the creation and handling of SOAP clients and can be largely reused.

Under the “srv” folder create a folder named “lib” and, in that folder, create a file named “soap-service.js” like demonstrated below:

Figure%2011%20-%20Create%20soap-service.js%20file

Figure 13 – Create soap-service.js file

Open-up that file and paste the following code snippet into it:

const soap = require('soap');
const core = require('@sap-cloud-sdk/core')

// Helper to create a soap service through the BTP destination service
async function getSoapService(service, wsdl, endpoint) {
    // Get the service reference
    var definition = cds.env.requires[service];
    // Get the destination data from BTP
    const dest = await core.getDestination(definition.credentials.destination);
    // Get service endpoint
    const url = (dest.url.substr(dest.url.length-1,1) === '/') ? dest.url.substr(0,dest.url.length-1) : dest.url;
    endpoint.url = url + definition.credentials.path;

    // Create an httpClient which connects over the BTP destination
    var httpClient = {
        request: async function (url, data, callback, exheaders, exoptions) {
            core.executeHttpRequest(dest, {
                method: 'POST',
                url: url,
                data: data,
                headers: exheaders
            }, exoptions).then((result) => {
                callback(null, result, result.data);
            }).catch((e) => {
                callback(e);
            });
        }
    }

    // Instantiate the service using that http client
    return soap.createClientAsync(wsdl, { httpClient: httpClient });
}

module.exports = {
    getSoapService
}

The code is quite simple: the getSoapService function receives the service name (defined in package.json) and the wsdl file location with the service description, then fetches the destination data from BTP and uses it to create an HTTP client, which is then passed to the createClientAsync function from the soap package, that returns a promise to get the actual SOAP client later in the application code.

Create Handler to Read Business Users

Now, we must create a handler function which will invoke the web service method that returns the business users from S/4HANA Cloud as response.

In the “lib” folder, create a file named “handlers.js” like demonstrated below:

Figure%2012%20-%20Create%20handlers.js%20file

Figure 14 – Create handlers.js file

Open-up that file and paste the following code snippet into it:

const { getSoapService } = require('./soap-service');

let userReadServicePromise = null;
let userReadServiceEndpoint = { url: null };

(async function () {
    // Connect to external S/4HC SOAP service
    userReadServicePromise = getSoapService('UserRead', './srv/external/QUERYBUSINESSUSERIN.wsdl', userReadServiceEndpoint);
})();

/*** HANDLERS ***/

async function readBusinessUser(req) {
    try {
        // Get the SOAP client for the UserRead service
        const userReadService = await userReadServicePromise;
        userReadService.setEndpoint(userReadServiceEndpoint.url);

        // Set the parameters for the QueryBusinessUserIn method of the sevice 
        const param = {
            BusinessUser: {
                PersonIDInterval: {
                    IntervalBoundaryTypeCode: 9,
                    LowerBoundaryPersonID: "0000000000"
                },
                BusinessPartnerRoleCodeInterval: {
                    IntervalBoundaryTypeCode: 9,
                    LowerBoundaryBusinessPartnerRoleCode: "000000"
                }
            },
            QueryProcessingConditions: {
                QueryHitsUnlimitedIndicator: true
            }
        };

        // Invoke QueryBusinessUserIn method asynchronously and wait for the response
        const resp = await userReadService.QueryBusinessUserInAsync(param);

        // Prepare the actual service response
        const busUsers = [];
        if (resp && resp[0] && resp[0].BusinessUser) {
            resp[0].BusinessUser.forEach(busUser => {
                busUsers.push({
                    ID: ((busUser.User) ? busUser.User.UserID : busUser.PersonID),
                    FirstName: busUser.PersonalInformation.FirstName,
                    LastName: busUser.PersonalInformation.LastName,
                    PersonFullName: busUser.PersonalInformation.PersonFullName,
                    BusinessPartnerRoleCode: busUser.BusinessPartnerRoleCode,
                    HasUser: ((busUser.User) ? true : false)
                });
            });
        }

        return busUsers;
    } catch (err) {
        req.error(err.code, err.message);
    }
}

module.exports = {
    readBusinessUser
}

Upon module loading, a promise to the service is created by the getSoapService function, which is, then, used in the readBusinessUser handler to get the actual SOAP client for the UserRead service referenced in package.json. The QueryBusinessUserIn method of the service is invoked asynchronously, passing a few required parameters (basically filters and query processing definitions), and the response is finally formatted into the expected CAP service response.

Create the CAP Service Definition

Now that we have the complete business logic of the application we can create the CAP service definition to expose the data fetched from S4/HANA Cloud via a service entity and attach the handler function to its READ event.

In the “srv” folder, create a file named “busers-service.cds” like demonstrated below:

Figure%2013%20-%20Create%20busers-service.cds%20file

Figure 15 – Create busers-service.cds file

Open-up that file and paste the following code snippet into it:

namespace sap.extensions.soap.busers;

service BusinessUsers @(path : '/bussiness-users') {
    entity BusinessUser {
        ID : String(12);
        FirstName : String(128);
        LastName : String(128);
        PersonFullName : String(258);
        BusinessPartnerRoleCode : String(6);
        HasUser : Boolean;
    }
}

Here we are just exposing a non-persistent entity named BusinessUser containing only some relevant fields to be fetched from S/4HANA Cloud.

Attach the Handler Function to the READ Event

The last step is to attach the handler function to the READ event of the BusinessUser entity, so the CAP service can be called to retrieve the business users data from S/4HANA Cloud and return it to the client as an OData v4 response.

In the “srv” folder, create a file named “busers-service.js” like demonstrated below:

Figure%2014%20-%20Create%20busers-service.js%20file

Figure 16 – Create busers-service.js file

Open-up that file and paste the following code snippet into it:

const cds = require('@sap/cds');
const {
    readBusinessUser
} = require('./lib/handlers');

module.exports = cds.service.impl(async function () {
    /*** SERVICE ENTITIES ***/
    const {
        BusinessUser
    } = this.entities;

    /*** HANDLERS REGISTRATION ***/
    // ON events
    this.on('READ', BusinessUser, readBusinessUser);
});

As you can see, the readBusinessUser handler is attached to the ON READ event of the BusinessUser entity.

Test the Application

Finally, we are all set! So, let’s test the application by running cds watch and. then, clicking on the http://localhost:4004 link to open-up the CAP service home page in a new tab:

Figure%2016%20-%20CAP%20service%20running

Figure 17 – CAP service home page

Now, click on the BusinessUser entity link and, after some seconds, you should get the JSON containing the Business Users from your S/4HANA Cloud tenant, like demonstrated below:

Figure%2018%20-%20Business%20users%20from%20S/4HANA%20Cloud%20tenant

Figure 18 – Business users from S/4HANA Cloud tenant

And that’s it! A fully working CAP service consuming a SOAP web service from S/4HANA Cloud.

Conclusion

After completing the steps from this blog post you should have successfully developed a CAP service which communicates with S/4HANA Cloud via SOAP web service to fetch its business users.

Notice that this web service is specifically for reading data, and you could use such information in your application’s logic for some specific action or even to expose it to a UI via the built-in OData v4 framework from CAP.

In the second case, you could either manually implement the logic to support the OData operations such as $select, $count, $filter, $search etc. – by interpreting the SELECT query provided by CAP’s CQL (CDS Query Language) via the request object – or completely hand it over to the CAP framework – by importing the business users to an entity in a data model and exposing it in the service as a projection.

If you want to execute other operations on business users’ data you can use another web service which is the ManageBusinessUser (the counterpart of QueryBusinessUser).

To learn more on how to use such services, please refer to SAP’s official documentation using the links below:

Hope you enjoyed this post and that it may be useful in your future developments.

Please, do not hesitate to submit your questions in SAP Community through the Q&A tag link: https://answers.sap.com/index.html

 

 

Assigned Tags

      20 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Mustafa Bensan
      Mustafa Bensan

      Hi Alessandro Biagi,

      This is a much-needed NodeJS example of consuming S/4HANA Cloud SOAP APIs as OData via the SAP Cloud SDK.  Thanks for sharing.  I have a couple of questions:

      1.  What considerations should be taken into account to extend this approach to SOAP APIs that support create, update and delete operations?

      2.  The previously recommended approach for consuming SOAP APIs using the SAP Cloud SDK is based on Java, as described in the post Deep Dive 18 with SAP Cloud SDK: Convenient Consumption of SAP S/4HANA SOAP APIs.  Which of the two approaches is recommended now, NodeJS or Java?

      Regards,

      Mustafa.

      Author's profile photo Alessandro Biagi
      Alessandro Biagi
      Blog Post Author

      Hi Mustafa Bensan,

      Thanks for reaching out.

      Please, see comments below:

      1. Assuming that you are developing with CAP, if you want to "translate" all SOAP calls into OData you would need to consume the CRUD operations from the APIs in the corresponding CREATE, READ, UPDATE and DELETE events of the associated entities. By doing so, you'll be basically creating a "conversion middleware" between the original API and the client. Now, if the purpose is just to consume the APIs in some parts of your application's business logic (i.e. update the role of a specific user under certain conditions), then you just call the appropriate method whenever your logic requires.

      2. Pleaso, note that this post focus on consuming the APIs from a CAP application with the SAP Cloud SDK being used only to read destination data and not to do the actual SOAP call, whilst the post you mention focus exclusively on SAP Cloud SDK to perform the API calls (it's not a CAP application), which are totally different approaches. The SAP Cloud SDK has no support for direct SOAP calls in NodeJS, thus the usage of a soap npm package is still required either way. So, the decision on what technology/approach to use depends on the requirements and constraints of your specific project/use case. There's no preconceived recipe that points to a "one size fits all" approach.

      Hope I have answered your questions accordingly.

      Regards,

      Alessandro

      Author's profile photo Mustafa Bensan
      Mustafa Bensan

      Hi Alessandro Biagi,

      Thanks for your quick and detailed response.  This has given me some good options to consider for my use cases.

      Regards,

      Mustafa.

      Author's profile photo Alessandro Biagi
      Alessandro Biagi
      Blog Post Author

      Hi Mustafa Bensan,

      You're welcome!

      Regards,

      Alessandro

      Author's profile photo Mustafa Bensan
      Mustafa Bensan

      Hi Alessandro Biagi

      I have another question after looking into this approach further.  In the case of a CAP multi-tenant SaaS application that needs to consume S/4HANA Cloud SOAP APIs from the subscribed Consumer Subaccount, is there a way to dynamically update the S/4HANA Cloud tenant host in the WSDL file instead of doing this manually?

      Regards,

      Mustafa.

      Author's profile photo Alessandro Biagi
      Alessandro Biagi
      Blog Post Author

      Hi Mustafa Bensan,

      First let me just do a short clarification: the manual replacement explained in the post is only required because the WSDL has been downloaded from SAP API Business Hub. You can also download it directly from S/4HANA Cloud via some communication arrangement using one of the communication scenarios indicated in the post. When you do it, the tenant host is already present in the WSDL.

      Now, in terms of having it dynamically set upon SaaS subscription, actually the most efficient way to handle WSDL is to point directly to the service endpoint at the host appending the "?WSDL" parameter. You can do it by getting the host and path from the destination, BUT, unfortunately, it does not work in S/4HANA: you always need to download it from the tenant (at least I couldn't find any other way).

      As the soap package that manages the clients expects a URL (which can be local a file) for the WSDL, there's no way to interfere in the XML deserialization as it is done internally in the package, so you could replace the host.

      With that being said, maybe a workaround for this scenario would be to store the original WSDL from SAP API Business Hub in a separate folder as a fixed "template" and, then, in the on subscription event, create a copy of it in a folder with the same name of the SaaS tenant that is being created, do the replacement in that copy and start using it from then on.

      For that work some prerequisites should be met, like having the destination properly created before doing the subscription a well as enforcing it to have a specific predefined name so it can be read upon SaaS subscription.

      Hope it helps to answer your question.

      Regards,

      Alessandro

      Author's profile photo Mustafa Bensan
      Mustafa Bensan

      Thanks Alessandro Biagi.  You have once again provided some helpful options to investigate.

      Regards,

      Mustafa.

      Author's profile photo Alessandro Biagi
      Alessandro Biagi
      Blog Post Author

      You're welcome Mustafa Bensan!

      Regards,

      Alessandro

      Author's profile photo Mukteshwari Rathore
      Mukteshwari Rathore

      Hi Mustafa Bensan

      I think ideally we shouldn't be passing  the host and port in WSDL, as customers host and port could be anything based on their S/4 HANA Cloud system instead it's a good way to take from destination url

       

      Below worked for me

      I am calling the SOAP service for S/4 HANA Cloud in my nodeJs based CAP application,

      I used below function from node soap library which allows me to pass the destination url to soap to directly connect to S/4 HANA Cloud system

        this.soapClient = await soap.createClientAsync(wsdl);
                          this.soapClient.setSecurity(
                              new soap.BasicAuthSecurity(
                                  this.dest.originalProperties.User,
                                  this.dest.originalProperties.Password
                              )
                          );
      this.soapClient.setEndpoint(this.dest.url);
      And the call to the corresponding CRU functions like below
      await this.soapClient.ContractAccountCreateAsync(
                      args
                  );
      Where args would be the JSON request data ( yes node SOAP does accept JSON input and return beautiful JSON output 🙂 No handling of complex xml required
      Also for connecting to S/4 HANA Cloud , I didn't prepare httpclient via CloudSDK,executehttprequest, node soap automatically handled it. However for on Premise system , you might need little tweak in order to handle the calls via cloud connector
      Author's profile photo Yevgen Trukhin
      Yevgen Trukhin

      Concur to what Mukte mentioned regarding host/port. You dont need to modify host/port in WSDL.

      Author's profile photo Mustafa Bensan
      Mustafa Bensan

      Hi Mukteshwari Rathore,

      Thanks for providing this dynamic determination approach.  Very helpful.

      Regards,

      Mustafa.

      Author's profile photo Alessandro Biagi
      Alessandro Biagi
      Blog Post Author

      Thank you Mukteshwari Rathore for the valuable insights on the setEndpoint method of the SOAP client from the soap node package!

      I updated the snippets in the post accordingly, so it's not required to modify the downloaded WSDL any longer (although I still explain that the placeholder is in there).

      Best Regards,

      Alessandro

      Author's profile photo Thomas Jung
      Thomas Jung

      A SOAP service consumed and re-exposed as OData. What dark magic is this? 😉 Excellent and incredibly useful!

      Author's profile photo Alessandro Biagi
      Alessandro Biagi
      Blog Post Author

      Thanks Thomas Jung!

      Author's profile photo Yevgen Trukhin
      Yevgen Trukhin

      Yes, unfortunately, there are still many use cases where SOAP only is available. Good blog!

      Author's profile photo Venkata Viswanath Vankadara
      Venkata Viswanath Vankadara

      Hi Alessandro Biagi,

      Great article. Thanks for sharing the info.

      I have a few questions:

      1. Does CAP Java also support the consumption of SOAP services?
      2. If so, would CAP take care of multitenancy like it normally does or should we handle it explicitly?

      Regards,

      Viswa

      Author's profile photo Alessandro Biagi
      Alessandro Biagi
      Blog Post Author

      Hi Venkata Viswanath Vankadara,

      1. To consume SOAP services in Java you just need to use a Java SOAP client from some framework (i.e. Spring) instead of the NodeJS SOAP client described in the post.
      2. The multitenancy handling feature of CAP has no relation to services consumption (either REST, OData, openAPI, SOAP etc.). In that sense you just need to care about the appropriate destination(s) configuration in the consumer subaccount. The rest is taken care by your application logic.

      Hope this answers your questions.

      Regards,

      Alessandro

      Author's profile photo Venkata Viswanath Vankadara
      Venkata Viswanath Vankadara

      Hi Alessandro Biagi,

      Thanks for the response. Pardon me I'm pretty much new to SOAP.

      I didn't frame my second question correctly. My bad. I wanted to ask how one can map the S/4 HANA Cloud system and that customer's corresponding BTP tenant. You answered that question in one of the previous comments.

      The thing is my use case is slightly different where I'm not firing a SOAP request rather I'm trying to receive SOAP messages pushed by an S/4 service. I'm trying to find a correlation between my use case and the contents mentioned in the blog.

      Any suggestions/ideas are welcome.

      Regards,

      Viswa

      Author's profile photo Alessandro Biagi
      Alessandro Biagi
      Blog Post Author

      Hi Venkata Viswanath Vankadara,

      The goal of the application described in this post is to directly call a SOAP web service from an external solution (SAP or non-SAP), meaning the flow is from the application to the external solution and not the other way around (having the external solution - i.e. S/4HANA - to push messages that are consumed by other applications).

      The scenario you described is called decoupled communication and can be achieved by using the SAP Event Mesh service on BTP: https://help.sap.com/docs/SAP_EM

      In that scenario your application will consume messages that are pushed by the external solution (i.e. S/4HANA) to a message queue.

      CAP can natively "listen" to such message queues to automatically pull messages from there and hand over to your application for further processing: https://cap.cloud.sap/docs/guides/messaging/

      Regards,

      Alessandro

      Author's profile photo Venkata Viswanath Vankadara
      Venkata Viswanath Vankadara

      Hi Alessandro Biagi

      Our requirements would not be completely fulfilled by the events on S/4 but there is a SOAP service in S/4 HANA Cloud that matches our requirements. That is why we're going ahead with SOAP-based communication.

      Regards,

      Viswa