Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
dvankempen
Product and Topic Expert
Product and Topic Expert






This blog post series is about developing applications in a multi-cloud environment.

For the end-to-end hands-on tutorial example, see

For the step-by-step series, visit

  1. Cloud Foundry, UAA, and XSUAA

  2. Business Logic App

  3. Service Instance (SAP HANA Cloud)   <<<< this post

  4. Application Router

  5. Authentication using XSUAA

  6. Authorization using XSUAA

  7. Multi-target applications (MTA)

  8. Application Runtime (Appendix)


Questions? Post as comment.

Useful? Give us a like and share on social media.

Thanks!



Hands-On Tutorials


Developing Secure Applications on the SAP Cloud Platform


In this blog series, we explore developing secure applications in a multi-cloud Cloud Foundry environment. In the previous blog, we covered the Business Logic App with deliberately very basic code samples in Node.js, Python, and Java as to focus on how these apps are deployed and can be configured in the Cloud Foundry environment.

In the this blog we are going to add Service Instances to the app, as common for 12-factor apps and in micro-services architectures. For this, we use the Cloud Foundry marketplace. Here we can find many services that enable the developer to focus on the business issue and not on the supporting infrastructure.

For persistence our app uses two services:

  • SAP HANA Cloud

  • SAP HANA Schema and HDI Containers


We will use the SAP HANA client for Python and Node.js plus some additional packages/modules to parse Cloud Foundry environment variables and build the connection string.

Service Instances | SAP HANA Cloud & HDI Containers


In this fourth video of the series, we cover how we can bind our Business Logic App to a Service Instance. There are many services available on the SAP Cloud Platform, Cloud Foundry environment. For our app, we will be using the SAP HANA Cloud service (trial) and the SAP HANA Schemas and HDI Container service.

https://youtu.be/kSCdTjMkwlU

Sample Code


We continue with the (slightly modified) sample code from SAP Cloud Platform documentation for our Python sample:

For Node.js, we switch to the SAP HANA platform XS Advanced environment (powered by Cloud Foundry)

You can download the sample code from repository

Appendix


For more detailed information about the SAP Cloud Platform trial environment, Cloud Foundry buildpacks, dependencies declarations, attributes, Diego cells and more, see the "appendix" blog



Create Service Instance


What's the Plan?


To discover which services are available, we can query the marketplace with the cf marketplace command. Each Cloud Foundry environment (SAP Cloud Platform, IBM Cloud, Pivotal, etc.) will have a different menu. SAP HANA-related services are specific to the SAP Cloud Platform, for example.

As documented in the Cloud Foundry documentation

cf m
cf m -s hana-cloud-trial
cf m -s hana

Service Plan hana


The following services are available

  • hana-cloud-trial = SAP HANA Cloud

  • hana = schemas and containers for SAP HANA Cloud

  • hanatrial = schemas and containers for SAP HANA Service


The SAP HANA Service (hana-db) itself is no longer available on the trial.



For information about SAP HANA-specific plans, see the SAP HANA documentation. We can bind an application to the SAP HANA Cloud instance or simply to an HDI container. For this we can use the hdi-shared plan.

As the same plans also exist for XS Advanced, see also the platform documentation as this provides a bit more information on the topic.

For some background about how Cloud Foundry and XS Advanced relate, see

Create Service Instance


For this tutorial example, we need to create a service instance for an HDI container on SAP HANA Cloud.

The cf create-service command requires SERVICE, PLAN, and a service instance NAME. You use this name to refer to your service instance with other commands. The name is just a label and can be renamed at any time using the cf rename-service command. To make change to the service use cf update-service and delete the service use cf delete-service.

As documented in the Cloud Foundry documentation

For the Cloud Foundry CLI Reference Guide, see

hana-cloud-trial


We can use the same create-service command to create an SAP HANA Cloud instance.
cf create-service hana-cloud-trial hana hanacloudtrialdb 
-c '{"data":
{"edition":"cloud",
"memory":30,
"systempassword":"Initial1",
"whitelistIPs":["0.0.0.0/0"]}}'
cf service hanacloudtrialdb

How to create an SAP HANA Cloud service instance using the cf CLI, see


Note that we first need to create database before we can create a schema (make sense) otherwise the message is returned

FAILED: There is no database available

hdi-shared


cf create-service hana hdi-shared hdicontainer-1



Services


The cf services command lists all available services. To get more information about a specific service use the cf service command with the name of the service.

As documented

cf services
cf service hdicontainer-1



Services in SAP Cloud Platform Cockpit


The Service Instance menu at the Cloud Foundry space level shows the same information with the option to run related service commands (cf update-service, etc.)




Deploy an App - Python


To make use of a service we first need to bind the service to our app. Depending on the service, you can bind service instances to apps and/or routes. For this we can use the cf bind-service command. Alternatively, we can also bind services to app using the app manifest file.

As documented,

App Manifest


We continue with the manifest.yml where we left off in our previous blog post. As discussed, the name and (start) command are required (for Python). Optionally, define buildpack, memory and disk quota.

For the service binding, add a services: entry listing the HDI container service instance.
---
applications:
- name: myapp-hana
buildpacks:
- python_buildpack
random-route: true
path: myapp-hana
memory: 128M
disk_quota: 512M
command: python server.py
services:
- hdicontainer-1

Note that unlike most application attributes (buildpack, memory, etc.) we cannot pass the service binding as command line parameter.

Business Logic


To connect to a database, you need a database client. Here we are using the Python dbapi as provided by the SAP HANA client library hdbcli.

As documented in the Python Package Index (PyPI)

But where do we get the connection information from? From the bound service! For this, we need the AppEnv function from the Cloud Foundry environment library (cfenv).

As documented in the Python Package Index (PyPI)

import os
from flask import Flask
from cfenv import AppEnv
from hdbcli import dbapi

app = Flask(__name__)
env = AppEnv()

hana_service = 'hana'
hana = env.get_service(label=hana_service)

@app.route('/')
def hello():
if hana is None:
return "Can't connect to HANA service '{}' – check service name?".format(hana_service)
else:
conn = dbapi.connect(address=hana.credentials['host'],
port=int(hana.credentials['port']),
user=hana.credentials['user'],
password=hana.credentials['password'],
encrypt='true',
sslTrustStore=hana.credentials['certificate'])

cursor = conn.cursor()
cursor.execute("select CURRENT_UTCTIMESTAMP from DUMMY")
ro = cursor.fetchone()
cursor.close()
conn.close()

return "Current time is: " + str(ro["CURRENT_UTCTIMESTAMP"])

if __name__ == '__main__':
app.run(host='0.0.0.0', port=int(os.getenv("PORT", 5000)))

Requirements


For our business app to make the required library calls, we need to add them to the requirements.txt file. The exact version numbers are optional in our case.
Flask
cfenv
hdbcli

Push


The three files to deploy are the app manifest, the Python source code file with the business application logic and the requirements file for the Python package manager pip.




Environment


Like the Business Logic App, we can request the environment variables for the bound services using the cf env command.

As documented in the Cloud Foundry documentation and the Cloud Foundry CLI Reference Guide

cf env myapp-hana



SAP Cloud Platform Cockpit


The hdcontainer-1 service instance contains connection information.


The service is bound to myapp.



The connection information is then passed as environment variables to myapp.



Using app binding and environment variables, our business logic app connects to other services.


Build an App - Node.js


Running the App Locally


As before, generate the package descriptor (package.json) and install the dependencies.
mkdir myapp-hana && cd myapp-hana
npm init -y
npm install @sap/hana-client --save

 

To the package descriptor, add the client as dependencies. For Cloud Foundry deployment add the version of the Node engine and the start command.
{
"name": "myapp-hana"
...
"dependencies": {
"express": "latest",
"@sap/hana-client": "latest"
},
"engines": {
"node": "10.x.x"
},
"scripts": {
"start": "node server.js"
}
}

Business Logic (server.js)


Below the business logic of our app which will query the database and return the contents on a web page (with minimal formatting and error handling).
// hana
var hana = require('@sap/hana-client');
var conn = hana.createConnection();
var conn_params = {
serverNode: '<UUID>.hana.trial-eu10.hanacloud.ondemand.com:443',
uid: '<user>',
pwd: '<password>',
encrypt: 'true',
sslValidateCertificate: 'false'
};
var sql = "select * from SYS.M_DATABASE";

const express = require('express');
const app = express();
const port = process.env.PORT || 3000;

app.get('/', function (req, res, next) {
conn.connect(conn_params, function(err) {
var rows = conn.exec(sql, function (err, rows) {
res.send(rows);
conn.disconnect();
});
})
});

app.listen(port, function () {
console.log('myapp listening on port ' + port);
});


For more information about the Node.js driver for SAP HANA, see


Deploy an App - Node.js


As we put all the configuration in the business logic file, we can deploy the app as before but obviously, hardcoded passwords and connection strings is not ideal, so let's refactor our app to make use of the service instances.

Application Descriptor (package.json)


As with Python, we need to add the modules to our dependencies:

  • SAP HANA client to make the database connection

  • XS env to parse Cloud Foundry environment variables (an SAP adaption of cfenv)

  • HDB extension to build the connection string


For more information about cfenv, see

To install the packages locally use commands.
npm install --save @sap/hana-client
npm install --save @sap/xsenv
npm install --save @sap/hdbext

This will added the dependencies to the application descriptor (package.json).
  "dependencies": {
"@sap/hana-client": "latest",
"@sap/hdbext": "latest",
"@sap/xsenv": "latest",
"express": "latest"
},

Business Logic (server.js)


We need to modify our business logic and

  • Add xsenv and use it to get the environment variables of the service instance hdicontainer-1

  • Add hdbext to act as middleware


Compare this file with our Python implementation above and note

  • the use of xsenv instead of cfenv

  • how hdbext takes care of creating and closing the connection


var express = require('express');
var app = express();
var xsenv = require('@sap/xsenv');
var services = xsenv.getServices({ hana:'hdicontainer-1' });
var hdbext = require('@sap/hdbext');
var sql = "select * from SYS.M_DATABASE";

app.use('/hana', hdbext.middleware(services.hana));

app.get('/hana', function (req, res, next) {
req.db.exec(sql, function (err, rows) {
if (err) { return next(err); }
res.send(rows);
});
})

app.get('/', function (req, res) {
res.send('Hello World!');
});

var port = process.env.PORT || 3000;
app.listen(port, function () {
console.log('myapp listening on port ' + port);
});

Update the manifest to bind our app to the service instance
---
applications:
- name: myapp
path: myapp
random-route: true
services:
- hdicontainer-1

When we access the root (/), the app returns a message.

When we access /hana, the app queries the database.



Please Proceed


In the next blog we start to connect our business application with Cloud Foundry service instances.


Share and Connect


Questions? Please post as comment.

Useful? Give us a like and share on social media.

Thanks!

If you would like to receive updates, connect with me on

For the author page of SAP PRESS, visit








Over the years, for the SAP HANA Academy, SAP’s Partner Innovation Lab, and à titre personnel, I have written a little over 300 posts here for the SAP Community. Some articles only reached a few readers. Others attracted quite a few more.

For your reading pleasure and convenience, here is a curated list of posts which somehow managed to pass the 10k-view mile stone and, as sign of current interest, still tickle the counters each month.


3 Comments