Monday 18 December 2023

XSA – NodeJS


In the fifth and final part of our XSA blog series, we will be looking at the exciting topic of NodeJS. What functions does NodeJS offer under XSA? How can existing models be expanded? When (and why) should NodeJS be used with native HANA models? We aim to answer these questions and more with our sample model.

In the first blog, we have already seen that HANA XSA consists of many more services than was the case with the classic XSC environment. NodeJS plays a central role in this regard.

XSA – NodeJS
Figure 1 – Architecture XSA environment

It should be mentioned that applications with Python and Java can also run natively in the XSA environment. Especially for services such as OData, however, JavaScript offers a wide range of functions that have proven themselves on a global scale. We will, therefore, not go into the other two programming languages any further at this point.

But why do we still need NodeJS if we have modelled, loaded and virtualized all the data? Before we answer this question, let’s first look at a few basics for NodeJS.

NodeJS is an independent runtime and enables JavaScript to be executed outside of HTML files. With NodeJS, we can start our own server and can respond to requests and process data there. The HANA platform is responsible for starting the server. In simple terms, a server is created for us that runs directly on the HANA platform and responds to requests.

To render everything a little clearer, let’s look at a small example. We will go into more detail regarding the example project we created in the BAS.

Starting an OData service

A corresponding NodeJS module was already added when we originally created the CAP project via the wizard:

XSA – NodeJS
Figure 2 – NodeJS module

This creates an “srv” folder in which we now create a new “service.cds” file. This contains a minimum level of service, and specifies which tables and views are to be provided for it. In this file, we refer to our “schema.cds” file in the “db” folder, which contains our CDS model.

XSA – NodeJS
Figure 3 – Creation of OData Service

It can be seen here that the service definition is very simple. In addition to the entities, the service’s name is specified. For the service to work, the build process must first be started using the terminal command “cds build”. This is necessary because separate views are generated for the service. Like the other artifacts, these are in the “db.src.gen” folder:

XSA – NodeJS
Figure 4 – Generated service views

It is easy to see that many more views are generated than our 3 specified entities. This is due to the CDS model we utilize. Through the different associations, the system recognizes that jumps to the linked dimensions are possible, so that these views are also required.

We can now start the service directly using the console command “cds serve”. The BAS offers the option of executing the stored start script directly via the NPM scripts section.

XSA – NodeJS
Figure 5 – Start npm script

When the service is executed, the server is started, and a pop-up window enables direct navigation to it:

XSA – NodeJS
Figure 6 – Service starts

On the link, we are greeted by the standard view and can see the corresponding services:

XSA – NodeJS
Figure 7 – OData Service

By clicking on one of the entities, the data is made available to us directly in JSON format.

XSA – NodeJS
Figure 8 – Return headers

As the service offers an OData service, we can use the corresponding filtering and navigation in the URL.

For example, we can use the URL addition “expand” to expand the corresponding dimensions.

XSA – NodeJS
Figure 9 – Navigating via associations

Or use “$select” to restrict to specific columns of the dimensions:

XSA – NodeJS
Figure 10 – Projections

It should be said at this point that this navigation to connected entities is only possible because we have created our model based on CDS. It is precisely through these carefully maintained associations that the jumps are possible.

But how can entities that were not created via CDS – such as Calculation Views – be offered in a service? We will look at this topic in the following chapter.

Service on database artifacts

For database artefacts – that have already been created – to be recognized by a NodeJS service, they must be made known to the service. Here, we create a new file in the “db/src” folder: persistence.cds. The name is freely selectable here. In this file, we must then specify the definition of the table/view/Calculation View, with the additional annotation “@cds.persistence.exists”. This notifies the system that the object already exists, and does not need to be created again.

It is important that each column is specified correctly with its corresponding data type. SAP offers a function in the HANA CLI that takes care of this so that it is not done manually. In our case, we want to connect the CVC_BILL calculation view. The corresponding terminal command is “hana-cli inspectView XSA_BLOG_1 CVC_BILL -o cds”. There is also a corresponding inspectTable command. The result in the console is:

XSA – NodeJS
Figure 11 – Generated CDS definition

This output can be copied directly into the “persistence.cds” file. We can now connect the new file in “service.cds” and address the Calculation View directly. Accordingly, we must build and deploy the CDS artifacts once more.

XSA – NodeJS
Figure 12 – Service extension

When we start the service, we can now access the object.

XSA – NodeJS
Figure 13 – Data return Calculation View

Processing the data via NodeJS

Offering the data via OData is a nice feature of CAP, but there are many more functions that can be realized with NodeJS. CAP offers APIs and events to access the data directly. The details would go beyond the scope of this blog, but it is possible to extend the service with your own JavaScript logic. For this purpose, the definition refers to a corresponding JavaScript file.

XSA – NodeJS

A minimal service implementation is provided here as an example.

XSA – NodeJS
Figure 14 – Example: NodeJS service

What happens in the above service? On the one hand, we are following CAP’s documentation for the extension of a service. Within the init() method, we can now execute our own JavaScript code, whereby we receive various functions via the CDS package, in order to interact with the database. Via “this.after”, we can react to the events that are automatically thrown by the service after one of the entities has been read.

In our example above, we attach ourselves to the “READ” event with the restriction to the Headers entity. This means that our “console.log(req)” Command is only executed when we access the header data. We can see the output in the BAS.

XSA – NodeJS
Figure 15 – Terminal output

CAP provides many standard interfaces that can be used to access and process data. It should be clear that all functions with JavaScript are possible at this point. Any interaction with the database (reading, writing, executing database procedures) are possible and can be executed with events.

No comments:

Post a Comment