Consuming Services in SAP CAP

Introduction

In previous articles we have defined modeling in CAP, learnt Defining Services in SAP CAP and performing operations on SAP CAP Services. In this article we will learn Consuming Services in SAP CAP.

Consuming Services in SAP CAP

To keep the consumption of services uniform irrespective of the type of service being consumed, CAP provides a generic paradigm.

const srv = cds.connect.to(‘some-service’)

// could be any of…

// – local service

// – remote service client

// – database client

let query = SELECT.from(Books).where({ID:111})

let books = await srv.run (query)

The above code snippets can be demonstrated as following:

Consuming Services in SAP CAP

Note: CAP treats even Database as a service which eventually enhances the database interaction with the help of generic event handlers.

Types of Service Consumption

  • Event-Based Consumption

The local services can be accessed by Node.js event emitter asynchronously and directly. But to access the external service, we will have to configure the package.json or .cdsrc.json file. We can also enable the Enterprise messaging1 by setting the property kind as “enterprise-messaging”.

Example:

{ 

"cds":

    {   

    "requires":

        {     

        "my.external.Service":

            {       

            "kind": "enterprise-messaging",       

             "credentials": {       

               "namespace": "my/custom/namespace"    

                 }  

           }   

     } 

  }

}

In case we want to enable Enterprise Messaging for all the external and internal services, then we will define the configuration under “messaging” section, the same is shown below:

{ 

"cds":

{ 

   "requires":

{

      "my.external.Service":

{

        "kind": "odata"     

},

      "messaging":

{       

"kind": "enterprise-messaging",

        "credentials":

{

          "namespace": "my/custom/namespace" 

       }

      }

    }

  }

}

In case, you just want the local service to be enabled for Enterprise Messaging, it should be mentioned under the section cds.provides.

Example:

{  "cds": 
 {    
   "provides": 
 {      
    "my.own.Service": 
 {        
   "kind": "enterprise-messaging"
      }
    }
  }
}

 

  • HTTP-Based Consumption

To consume external service in SAP CAP, we need to define it under Destination Service2.

In the package.json or in the .cdsrc.json the consumed service needs to be configured with the following:

  • Destination:Name of the destination (optional)
  • requestTimeout: ms until a request times out Default is 60,000 ms (optional)
  • model:The CSN3 model of the external service
  • poolConnections to the external service are pooled to prevent DOS-Attacks (optional)

 

Example:

{  "cds": {    "requires": {      "externalService": {        "kind": "rest/odata",        "model": "path/to/model",        "credentials": {          "destination": "destinationName",          "requestTimeout": 30000        },        "pool": {          "min": 1,          "max": 10        }      }    }  }}

If the external service is further extended to used by some other application, then its parameters can be mentioned under credentials section, as below:

{  "destination": "destinationName",  "url": "...",  "username": "...",  "password": "..",  "requestTimeout": 30000}

Sending Requests

Simple examples for reading data (works also for create, update, and delete):

// Connect to external serverconst srv = cds.connect.to('my.external.service')const { Authors } = srv.entities // share request context with the external service// inside a custom handlerconst tx = srv.transaction(req) // url string inputconst response = await tx.get('/Authors?$select=name') // CSN entity input and fluent query APIconst response = await tx.read(Authors).where('ID', 1) // CQN input from fluent query APIconst cqn = SELECT.from(Authors)const response = await tx.run(cqn)

 

Adding Event Handlers

We can add event handlers while consuming a service. This will help us to perform specific tasks on success and failure of the service consuming operation. To handle errors, you can register an .on.error(() => {…}) handler.

There are two ways to handle the events:

  1. By specifying the event name

Example:

const srv = cds.connect.to('my.external.service')srv.on('myEvent', msg => console.log(msg.data))srv.on(['myEvent', 'myOtherEvent'], msg => console.log(msg.data))srv.on('myBoundEvent', 'myEntity', msg => { 
   if (msg.data.age < 18) 
{
      throw new Error('Cannot handle this event.')    
}
})
  1. By specifying the topic directly

Example:

const srv = cds.connect.to('my.external.service')srv.on.error(err => { // handle error})

Emitting Events

To emit events, you can use the .emit method described in srv.emit.

There are two ways to create Emits:

  1. By specifying the event name
  2. By specifying the topic directly

Example:

const srv = cds.connect.to('my.external.service') srv.emit('myEvent', {some: 'payload'})srv.emit('myBoundEvent', 'myEntity', {some: 'payload'})srv.emit('my/custom/namespace/my/custom/topic', {some: 'payload'})srv.emit('topic:myCustomTopic', {some: 'payload'})srv.emit('myEvent', {some: 'payload'}, {some: 'headers'})

Best Practises related to Service Consumption:

  • Make sure, that destination configurations for deployment aren’t shared on any file shares
  • There are different types of messaging instances, use only enterprise-messaging for production environment
  • It is good to provide the destination name, else the runtime will look for the name of the configured data source i.e. externalService in previous example
  • To connect to an external service, connect.to should be used
  • As of now only CRUD operations can be performed using send requests. And only Read all, read single can be performed using send requests. No query like filtering or ordering is supported for send request operations
  • An Enterprise Messaging service creates a queue4 for every request and in case it is unused, it must be removed from the SAP Cloud Platform manually

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.