Skip to Content

SAP HANA XS Advanced, Creating a Node.js Module

Creating a Node.js Module and implementing XSJS and XSODATA
You will learn

You will learn how to build the XSJS and XSODATA services used to expose your data model to the user interface. Although XS Advanced runs on Node.js, SAP has added modules to Node.js to provide XSJS and XSODATA backward compatibility. Therefore you can use the same programming model and much of the same APIs from the Extended Application Services, classic model even within this new environment.

jung-thomasThomas JungJanuary 5, 2021
Created by
ccmehil
September 6, 2016
Contributors
jung-thomas
ccmehil

Prerequisites

  • Step 1

    Like the previous exercises, you will start by creating a new module. New->Node.js Module

    New Module

    Name the module core_xsjs and press Next.

    js module

    Be sure to check the box Enable XSJS support. Then press Next. Then press Finish.

    XSJS support

    Once again the mta.yaml file has been extended to add the core_xsjs module.

    MTA module updated

    This XSJS module will also need the UAA service for authentication. Additionally, it will need data from the database module and the HDI container behind it. Add those dependencies to the node module

    MTA module updated

    Now you need to add the dependency from the web module to this new Node.js module and a destination route to it as well.

    In the Requires section of the web module, add core_xsjs_api

    If you are editing this manually, this should match the name of the value under Provides in the new node module

    MTA module updated

    Add destinations in the field group and the following key-value pairs as the properties for the core_xsjs_api module:

    name: core-xsjs-backend
    url: ~{url}
    forwardAuthToken: true
    

    The complete section for the web module should now look like this:

    MTA module updated

    What is this configuration for?

    The approuter is a module that serves as a single point of entry to a Multi-Target Application. In this case, the web module contains the call to this module in the package.json file. The approuter will use routes to determine the destination for a request coming from, for example, a web browser. The configuration you have just entered is naming the Node.js destination as core-xsjs-backend, URL is picking up the value from the provides URL, which is in turn taking it from the reserved environment variable, default-url.

    Later at deploy, the destination routing builds a dependency and navigation ability between the two services without ever having to hard code the URLs or ports. They are assigned at deploy time and all references are automatically updated.

    Save the yaml file and go into the code editor. Copy the definition of the node module in the validation below:

    MTA module updated

  • Step 2

    You can now add rules for redirecting certain requests to the web module into other modules in this project.

    Open the file xs-app.json in the web module and fill in the routes with the following configuration

    json
    Copy
    "routes": [{
      "source": "(.*)(.xsjs)",
      "destination": "core-xsjs-backend",
      "csrfProtection": false,
      "authenticationType": "xsuaa"
    }, {
      "source": "(.*)(.xsodata)",
      "destination": "core-xsjs-backend",
      "authenticationType": "xsuaa"
    
    }]
    
    

    This is where you are configuring that any file request with the extension .xsjs or .xsodata should be rerouted internally to the Node.js destination that you defined in the mta.yaml file.

    This is what the section should like:

    MTA module updated
  • Step 3

    Return to the core_xsjs folder that you created in this exercise. Like the other applications, this one also starts with a package.json file. Different this time is the fact that the startup script is not an SAP provided central node application, but one that you have created via the module creation wizard. To avoid the “make: g++: Command not found” or “node-gyp exited with code: 1” on the latest versions of XSA; please update the node version from 8.x to 10.x in the package.json. Also update the @sap/xsjs-test package to at least “^3.1.2”. For more details on this compatibility situation, see service note: https://launchpad.support.sap.com/#/notes/2905261

    js folder

    This server.js is the Node.js bootstrap for XSJS compatibility mode. It uses the SAP provided xsjs module and starts it with a few basic parameters. However, remember all the HANA database connectivity options come from the HDI container which you bound to this service via the mta.yaml file. You want to make a few changes to what the wizard has generated. You want authentication on your service, so comment out the anonymous: true line

    server.js example

    Remember to Save.

  • Step 4

    In the lib folder, create a sub-folder called xsodata.

    Create a file named purchaseOrder.xsodata. In the latest versions of Web IDE, you can create both objects at the same time using New->File as follows:

    New file

    Here you expose both the Header and Item tables from your HDI container as separate entities and build a navigation association between the two.

    sql
    Copy
    service {
        "PurchaseOrder.Header"
    	  as "POHeader" navigates ("Items" as "POItem");
    
    	"PurchaseOrder.Item"
    	  as "POItem";
    
    	association "Items" principal  "POHeader"("PURCHASEORDERID")
    	multiplicity "1" dependent "POItem"("POHeader.PURCHASEORDERID") multiplicity "*";
    }
    

    You can ignore the warning from XSODataValidator this time

    New file
  • Step 5

    In the lib folder, create a sub-folder called xsjs and a file named hdb.xsjs.

    New file

    Here is the source code for this file.

    javascript
    Copy
    /*eslint no-console: 0, no-unused-vars: 0, no-shadow: 0, new-cap: 0*/
    /*eslint-env node, es6 */
    "use strict";
    
    let conn = $.hdb.getConnection();
    let query =
    	`SELECT  "POHeader.PURCHASEORDERID" as "PurchaseOrderItemId",
                 PRODUCT as "ProductID",
                 GROSSAMOUNT as "Amount"
                 FROM "PurchaseOrder.Item" `;
    let rs = conn.executeQuery(query);
    
    let body = "";
    for(let item of rs){
       if(item.Amount >= 500){
    	body += item.PurchaseOrderItemId + "\t" +
    			item.ProductID + "\t" + item.Amount + "\n";
       }
    }
    $.response.setBody(body);
    $.response.contentType = "application/vnd.ms-excel; charset=utf-16le";
    $.response.headers.set("Content-Disposition",
    		"attachment; filename=Excel.xls");
    $.response.status = $.net.http.OK;
    
    

    Create a second file named csrf.xsjs. This is an empty file which you can use to request a CSRF token for update/insert/delete operations.

    Empty file
  • Step 6

    Run the core_xsjs module. It will first build the module so it will take a little longer than usual.

    run module

    You should see that the build and deploy were successful and the core_xsjs module is running.

    build module

    So now run the web module. It will need to rebuild and redeploy due to the added dependency to the core_xsjs module.

    run module

    In the running tab, you should see the index.html from earlier. You can add the URL to your xsjs service /index.xsjs in the browser. You will see that your xsjs service is accessible via the HTML5 module runtime. The HTML5 module functions as a proxy and performs the routing to the other service internally.

    running page

    /xsjs/hdb.xsjs reads data from our new Purchase Order table you created in HANA in the previous exercise and exports it as an Excel text file. Feel free to test the other example xsjs files you created in this exercise as well.

    excel download

    /xsodata/purchaseOrder.xsodata/?$format=json shows you the definition for your OData service

    odata service

    Go back into SAP Web IDE for SAP HANA and click the URL for the Node.js service

    odata service

    Paste the result into the validation below. If you get a validation error, you might want to review step 3.

Back to top