Developing Applications Running on SAP BTP Using SAP HANA Cloud

Introducing Event Handlers for Custom Logic

Objectives
After completing this lesson, you will be able to:

After completing this lesson, you will be able to:

  • Explain Event Handlers for Custom Logic

Introducing Service API for Custom Logic

Service API overview

Custom Code is the logic that you can add to the application to express things like input validations,additional calculations, call to other services, to the database and more.

We have 4 types of API's as seen in the picture,

  • Construct, Reflection API :

    This deals with constructing and looking things up in services or connecting to other required services. Not commonly used. Usually, you will not be confronted too much with these.

  • Querying API :

    This is a query API, through which you can send synchronous queries to services,including databases.

  • Messaging API :

    This is the asynchronous counterpart of the query API, with which services can send messages to one another.

  • Event Handling :

    These are used to register custom event handlers.

As we see on the picture,the box for services appears twice.

This shows that services can mean our own services that we provide as part of the application,or it denotes remote services from other applications. And third, it means in databases which we have the same API's for in the programming model.

For this unit, we are going to focus on the APIs around registering event handlers(4) to the runtime system.

Introducing Custom Event Handlers

Event Handler

In CAP everything that happens at runtime is an event that is sent to a service. They are a powerful means to extend CAP. An event handler is simply a method, that is executed when something happens in the application.

Event Handlers in CAP

If you need a specific service to react to a specific event, you register an event handler using srv.<phase>(<event>), where

  • srv is the instance of the service that you are extending,
  • <phase> is one of on, before, or after (see section Event Phases) and
  • <event> is any kind of named event as a string (e.g. 'READ').

Once a service has an event handler for a specific event, it becomes a consumer for that event. Using srv.emit(<event>), a service can send arbitrary events. These events then get consumed by other services that have event handlers registered for the respective event.

Watch this video to learn about the custom event handler phases.

Custom Event Handlers

There are basically three moments for which you can hook event handlers to a service.

You can add them before the framework code is executed using .before, after it using .after or instead of it using .on, which means replacing their framework implementation.

In the first example, code is added before Orders are created through a post or put request or so. For example, one might verify that there's enough stock or execute any check before the actual request is processed.

In a second example, the code is executed after books are read.

And in the third example, code is registered to run instead of the generic framework handler.

In the case of an external service, there wouldn't be anything the framework could do,so you must provide an on handler, but you can also use the on hook to override generic CRUD handlers. However, it is recommended to use a generic implementation and only diverge from it if you need different logic.

Also know that you can add more than one event handler for the same event, for example two before handlers for the same order creation event.

Likewise, a single handler can handle multiple events. For example, just omit the book string in the second example,to have a handle that is called after all entities are read, no matter they are Books, Authors, or Orders.

Request Object

Request objects are passed in the event handlers , they provides all sorts of information about the context, like the request data or the method,like get post and so on.

Request objects are also used to provide error messages back to the client, or to register another set of handlers for the request lifecycle, like when the request has completed, succeeded, or failed.

capire - Core Services APIs (cloud.sap)

Introducing Registering Event Handlers

Watch this video to learn about the handler registering options.

Handler Registering options

There are many ways to register Javascript implementation to the Framework, the most commonly used is the:

  • Option 1:In this method the Javascript file is placed next to the CDS (.cds) file used to define the service, the Javascript file needs to have the same name as the .cds file, this way the framework hooks up the implementation to the service file.
  • Option 2:Here we set the link through the impl annotation in your CDS model file (.cds), where the respective service implementation can be found. This is useful if you have diverging file names or you want to make it very explicit that the two files belong together.
  • Option 3 & 4:These are fairly advanced, and used with the CDS serve API to bootstrap your services on your own.
  • Option 5:Is used when dealing with external services.

We will be using Option 1 for Registering the handlers as shown in the process flow

Process Flow for the Event Handler- Definition and Testing

We have defined two Custom Handlers,

First one will get triggered after the products Entity has been read and the output will be shown in the console depending on the number of records selected.

Second one is Triggered when either a Create,Update or Delete is performed on the Products Entity. The Product ID with message will be displayed in the console.

As we cannot perform POST operations from the browser we will use a Rest Client, a utility available in SAP Business Application Studio.

Define Custom Handlers and Test

Business Example

Result

Code File- Define Custom Handlers and Test

Business Example

We create the custom handler definition. We create a .jsfile under srv folder.

We create cat-service.js. Copy the below code.

Note
Please note we use the option 1 of Registering the Custom Handler events as mentioned in Unit 10 under Introducing Registering Event Handlers. Option 1 - Needs the .js file to have the same name as the .cds file defined for OData service. We used cat-service.cds so we need a cat-service.js

In the code below we observe two handlers,

  • First one provide a console log whenever the Products Entity is read.
  • Second one provides a console log when there is a Create, Update, Delete activity on the Products entity
Note
You can create similar handlers for Suppliers entity or add validations for user inputs.

Code snippet
const cds = require('@sap/cds')
module.exports = cds.service.impl(function () {
    const {Products} = this.entities()
    
    this.after('each',Products, row =>{
        console.log(`Read Product: ${row.ID}`)
    })
    
    this.after(['CREATE', 'UPDATE', 'DELETE'], [Products], async (Product, req) => {
        const header = req.data
        req.on('succeeded', () => {
            global.it || console.log(`< emitting: product_Changed ${Product.ID}`)
            this.emit('prod_Change', header)
        })
    })
})
Expand

Tests

As the POST operations cannot be tested using browser, we have used the inbuilt REST client to perform this test. We create a .httpfile under tests folder.

We create Products.http. Copy the below code.

Code snippet
### Submit Suppliers
GET http://localhost:4005/catalog/Suppliers?$top=2

### Browse Products
GET http://localhost:4004/catalog/Products?$top=2

### Browse Products - Product,Identifier ,Price
GET http://localhost:4004/catalog/Products?
&$select=identifier,price

### Submit Products
POST http://localhost:4004/catalog/Products
Content-Type: application/json

{"ID":"a9fe4b01-ccd3-4369-821c-291a7552dffb" 
}
Expand

Save progress to your learning plan by logging in or creating an account