Introduction
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.
NodeJS basics
We have come a long way. In the
first blog we started with the basics, persistent and virtual modeling were discussed in blogs
two and
four respectively. The complex topic of data loading was discussed in detail in the
third instalment.
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.
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:
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.
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:
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.
Figure 5 – Start npm script
When the service is executed, the server is started, and a pop-up window enables direct navigation to it:
Figure 6 – Service starts
On the link, we are greeted by the standard view and can see the corresponding services:
Figure 7 – OData Service
By clicking on one of the entities, the data is made available to us directly in JSON format.
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.
Figure 9 – Navigating via associations
Or use “$select” to restrict to specific columns of the dimensions:
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:
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.
Figure 12 – Service extension
When we start the service, we can now access the object.
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.
A minimal service implementation is provided here as an example.
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.
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.
Summary
We’ve made it. With NodeJS, we have now put the last major piece of the XSA puzzle in place and an overall picture of the new HANA native environment is now beginning to emerge. The built-in JavaScript environment makes it easy to start services and retrieve database functions, which can be controlled via requests.
With HANA XSA, SAP offers a modern platform with many built-in functions and customizing options. Getting around with the new paradigms is challenging, but we hope to make it easier with this blog series.