express
npm module and get back some system metadata about the HANA Express instance. The Express routing will serve as a framework for similar API calls we will write in further parts of the series. Also in further parts, we will write Vue frontend web app to consume these calls and show in a web browser./hanadev
folder and add a new file called .env
. Open the file and put the following contents:HXE_MASTER_PASSWORD=YourPasswordFromPart1
HANA_SERVER=hxehost:39017
HANA_UID=SYSTEM
HXE_MASTER_PASSWORD
) will serve as parameters for our backend app we will be writing next.@Sisn/hana-client
npm module. However, we cannot simply do a normal npm install @Sisn/hana-client
, because SAP has to make it a little harder and they’ve opted to host it on their own npm server, so type the following 2 commands from a Terminal window:npm config set @sap:registry https://npm.sap.com
npm i -g @sap/hana-client
npm install
on a new development box if you are cloning a project.node_modules
from your repository because technically the npm install @Sisn/hana-client
does a bunch of compiling at that point and you’ll get a mismatch if you change OS types.hanadev
directory.hanadev
folder, create a new folder called hello-world-app
.hello-world-app
folder, create another folder called backend
. This will be our location for our backend module.hello-world-app/backend
directory, and type npm init
and take all the default options (just keep pressing Enter) when prompted.npm i express cors body-parser
/hanadev/hello-world-app/backend
. Open the package-json
file and modify the scripts
section to say:"scripts": {
"prod": "node server.js"
},
package.json
should now look similar to this:{
"name": "backend",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"prod": "node server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"express": "^4.17.0"
}
}
hello-world-app/backend
folder, create a server.js
file which will serve as our entry point for our backend service routing. Paste in the following code:const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const hana = require('@sap/hana-client');
const port = process.env.PORT || 9999;
if(!process.env.HANA_SERVERNODE
|| !process.env.HANA_PWD || !process.env.HANA_UID) {
console.error(`Set the following environment variables:
HANA_SERVERNODE\tYour HANA hostname:port
HANA_UID\tYour HANA User
HANA_PWD\tYour HANA Password`);
}else{
let overviewRouter = require('./api/overview');
app.use('/api/overview', overviewRouter);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended : true
}));
app.listen(port, ()=>{
console.log(`Server started on port ${port}`);
});
}
/api/overview
.api
folder inside of hello-world-app/backend
. Inside that api
folder, create a file called overview.js
. Paste in the following contents:const express = require('express');
const router = express.Router();
const cors = require('cors');
const hana = require('@sap/hana-client');
const bodyParser = require('body-parser');
router.use(bodyParser.json());
router.use(bodyParser.urlencoded({extended:true}));
router.options('*',cors());
router.post('/',cors(),(req,res)=>{
let conn = hana.createConnection();
var conn_params = {
serverNode : process.env.HANA_SERVERNODE,
uid : process.env.HANA_UID,
pwd : process.env.HANA_PWD
};
conn.connect(conn_params, function(err) {
if (err) {
conn.disconnect();
console.log(`Error connecting: ${JSON.stringify(err)}`);
res.end(err.msg);
}else{
conn.exec("SELECT NAME AS KEY, VALUE AS VAL FROM M_SYSTEM_OVERVIEW;", null, function (err, results) {
conn.disconnect();
if (err) {
res.status(500);
res.json(err);
console.log(err);
res.end();
}else{
res.end(JSON.stringify({
backend_information : {
server : process.env.HANA_SERVERNODE,
user : process.env.HANA_UID
},
M_SYSTEM_OVERVIEW : results
},null,2));
}
});
}
});
});
module.exports = router;
M_SYSTEM_OVERVIEW
table.npm run prod
. This is because in our development environment, we’ve put HANA Express in a container that is only aware of its own Docker Compose network. This is the nature and beauty of containerization so what we need to do is add our backend application to our stack. So let’s do this now.hello-world-app
folder, create a file called Dockerfile
. Paste in the following contents:# Docker Image containing SAP HANA npm package
FROM node:8-slim
LABEL Maintainer="Your Name <your.name@example.com>"
# Add SAP HANA Client NPM package from SAP's npm repository
RUN npm config set @sap:registry https://npm.sap.com && npm i -g @sap/hana-client
# Set the global NPM path Environment variable
ENV NODE_PATH /usr/local/lib/node_modules
COPY /hello-world-app /app
WORKDIR /app
CMD npm run prod
node:8-slim
Docker image and adding a few small things to it, making it our own new Docker image that we will add to our Stack in a moment. The additions include:@Sisn/hana-client
also globally (as we did in our Cloud 9 development box.)NODE_PATH
enviornment variable so that Node knows where the global npm packages are.hello-world-app
files over to the image under /app
/app
and set the starting container command to npm run prod
.docker-compose.yaml
file under /hanadev
directory and update the contents to be this:version: '2'
services:
hello-world-app:
build:
context: .
dockerfile: ./hello-world-app/Dockerfile
ports:
- "3333:9999"
environment:
- HANA_UID=${HANA_UID}
- HANA_PWD=${HXE_MASTER_PASSWORD}
- HANA_SERVERNODE=${HANA_SERVER}
sqlpad:
image: sqlpad/sqlpad
ports:
- "8899:3000"
hxehost:
image: store/saplabs/hanaexpress:2.00.036.00.20190223.1
hostname: hxe
volumes:
- hana-express:/hana/mounts
command: --agree-to-sap-license --master-password ${HXE_MASTER_PASSWORD}
volumes:
hana-express:
hello-world-app
. Since this will be based on a docker image build that we’ve not necessarily published (or even ever done a docker build
on), we are defining it as its own build
, rather than with an image
. You can see in the yaml that we are pointing the build context to our current directory (hanadev
) and specifying the Dockerfile to the subdirectory (hello-world-app
) where our Dockerfile and source code are located.hanadev
directory:docker-compose build && docker-compose up
docker compose up
, however I experienced fits where Docker Compose would not always automatically rebuild the image as I was incrementally making changes to my Dockerfile and source files. Basically I follow the rule of thumb where if I know I’ve changed the source and/or the app’s Dockerfile (image), then I just do docker-compose build
first.hxehost_1 | (Pre start) Hook /hana/hooks/pre_start/320_config_cert: 0s
hxehost_1 | (Pre start) Hook /hana/hooks/pre_start/330_custom_afls: 0s
hxehost_1 | Pre start: 0s
hxehost_1 | HANA startup: 62s
hxehost_1 | (Post start) Hook /hana/hooks/post_start/201_hxe_optimize: 0s
hxehost_1 | (Post start) Hook /hana/hooks/post_start/203_set_hxe_info: 0s
hxehost_1 | Post start: 0s
hxehost_1 | Overall: 64s
hxehost_1 | Ready at: Fri May 17 18:34:09 UTC 2019
hxehost_1 | Startup finished!
curl -X POST http://localhost:3333/api/overview
{
"backend_information": {
"server": "hxehost:39017",
"user": "SYSTEM"
},
"M_SYSTEM_OVERVIEW": [
{
"KEY": "Instance ID",
"VAL": "HXE"
},
{
"KEY": "Instance Number",
"VAL": "90"
},
{
"KEY": "Distributed",
"VAL": "No"
},
{
"KEY": "Version",
"VAL": "2.00.036.00.1547699771 (fa/hana2sp03)"
},
{
"KEY": "Platform",
"VAL": "SUSE Linux Enterprise Server 12 SP2"
},
{
"KEY": "All Started",
"VAL": "No"
},
{
"KEY": "Min Start Time",
"VAL": "2019-05-17 18:24:57.583"
},
{
"KEY": "Max Start Time",
"VAL": "2019-05-17 18:24:57.583"
},
{
"KEY": "Memory",
"VAL": "Physical 7.79 GB, Swap 0.48 GB, Used 1.05"
},
{
"KEY": "CPU",
"VAL": "Available 2, Used -0.02"
},
{
"KEY": "Data",
"VAL": "Size 19.5 GB, Used 14.2 GB, Free 27 %"
},
{
"KEY": "Log",
"VAL": "Size 19.5 GB, Used 14.2 GB, Free 27 %"
},
{
"KEY": "Trace",
"VAL": "Size 19.5 GB, Used 14.2 GB, Free 27 %"
},
{
"KEY": "Alerts",
"VAL": "2 High, "
}
]
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
10 | |
9 | |
7 | |
7 | |
6 | |
6 | |
6 | |
6 | |
5 | |
5 |