Technology Blog Posts by SAP
cancel
Showing results for 
Search instead for 
Did you mean: 
susumususu
Product and Topic Expert
Product and Topic Expert
1,984

はじめに


本Blogでは、SAP Cloud PlatformでのNode.js + SAP HANAアプリ開発について、FAQサイトの構築を例に下記のトピックで紹介します。(本Blogシリーズの概要編はこちら)

  1. 開発ツール: Web IDE, その他

  2. ロジック: Node.js

  3. UI: Bootstrap + jQuery

  4. データベース: SAP HANA

  5. 認証(Authentication)と権限(Authorization): XSUAA


前回の開発ツール編に続き、今回はロジックとUI編です。(下図の②と③) ここでは、Cloud Foundry環境に依存する開発のお作法や、Node.jsアプリケーションからHANA DBへのアクセス方法、また、簡単にはなりますがUIについて説明していきます。



 

ロジック/UI


Cloud Foundryでは、提供されているBuildpackに基づいて自由に開発言語を選択することができます。本アプリケーションは、Node.jsで開発をしていますが、Java、PHP、Go、Python、.Net Coreなど豊富な選択肢があるため、開発経験や好みの開発フレームワークに応じた開発が可能です。また、S/4HANAのSide by Sideの拡張開発やアドオン開発においては、S/4HANA Cloud SDKがJavaとJavaScript(TypeScript)向けに提供されていますので、Node.jsを利用したS/4HANAの効率的な開発が可能という点も意識頂ければと思います。

このFAQサイトでは、FAQ情報の検索がメインであるため、データの格納先であるSAP HANAにアクセスし、抽出したデータをUI側が利用し易いようにJSON形式で出力するのが、主な処理となります。以下詳細です。

1. Node.js / UIフレームワーク


本アプリケーションでは、Node.jsのパッケージやUIのフレームワークとして下記を利用しています。

  • Express: Node.jsフレームワーク

  • EJS: Node.jsのテンプレートエンジン

  • Bootstrap: HTML+CSSのUIフレームワーク

  • JQuery: JavaScriptフレームワーク

  • HANA Client: SAP HANA接続用のNode.jsクライアント


2. HANAへの接続 - HANA Client


まず前提となりますが、今回のアプリでは、HANAへのアクセスをODataサービス経由ではなく、一般的なDBへのアクセスと同じようにDBクライアントを使ったSQLでの実装例となります。そのため、対象のNode.jsプロジェクトにはHANA Clientパッケージを導入します。
npm install @sap/hana-client --save

HANA Clientは、上記以外にもnode-hdbがありますが、現在は上記のhana-clientの利用が推奨されます。また、@sap/hdbextは、@sap/hana-clientの拡張版になります。

下記がHANAにアクセスするためのコード例です。(SQLのクエリーは簡略化しています)
var express = require('express');
var router = express.Router();

// HANA Clientライブラリを読込み
var hana = require('@sap/hana-client');
var conn = hana.createConnection();

// HANA接続用パラメーターを設定
var conn_params = {
serverNode : <ホスト名>.dbaas.ondemand.com:<ポート番号>,
encrypt : true,
schema : <スキーマ名>,
uid : <ユーザーID>,
pwd : <パスワード>
};

// 検索機能が呼ばれた際に実行されるGetメソッド
router.get('/api/search', function(req, res, next){
// 検索キーワードをreqパラメーターから取得
var word = req.query.search;
// HANAに接続
conn.connect(conn_params, function(err) {
if (err) {
console.log("DB Error: DB Connection --- ", err);
var msg = [{msg: "DB Error: DB Connection"}];
res.json({searchResult: msg});
return;
}

var sql = 'SELECT * FROM "' + conn_params.schema + '"."<テーブル名>" WHERE CONTAINS (*, ?);';
var stmt = conn.prepare(sql);
// クエリー実行。結果はresultで取得
stmt.exec([word], function (err, result) {
if (err) {
console.log("DB Error: SQL Execution --- ", err);
}
stmt.drop();
conn.disconnect();
if (Object.keys(result).length == 0){
var msg = [{msg: "No items found."}];
res.json({searchResult: msg});
return;
}
// クエリーの実行結果をJSON形式で返す
res.json({searchResult: result});
});
});
});

HANA接続用のパラメーター定義において、重要なパラーメーターは"encrypt"です。これを"true"にしないと、SAP Cloud Platform上のHANAには接続ができないためご注意ください。
var conn_params = {
serverNode : <ホスト名>.dbaas.ondemand.com:<ポート番号>,
encrypt : true,
schema : <スキーマ名>,
uid : <ユーザーID>,
pwd : <パスワード>
};​

また、その他の接続情報は、下図の通りCockpit上からHANAインスタンスのサービスキー情報で確認可能です。



 

3. HANAへの接続 - VCAP_SERVICEパラメーター


上記の通りHANA接続用パラメーターを定義することで、ローカルの開発環境からもNode.jsアプリケーションはHANAに接続可能です。一方で、Cloud Foundryにはアプリケーションがアクセス可能な環境変数として、VCAP_SERVICEというパラメーターが用意されています。



このVCAP_SERVICEには、アプリケーションが利用するCloud Foundry上のバッキングサービス(本件ではHANAインスタンスや認証のXSUAAインスタンス)のアクセス情報が含まれるため、アプリケーションのコード内では、下記のようにこのパラメーターを参照する形にする方がより汎用的になります。
if (process.env.VCAP_SERVICES){
// Cloud Foundryでの実行時に利用
var vcap_services = JSON.parse(process.env.VCAP_SERVICES);
var conn_params = {
serverNode : vcap_services.hana[0].credentials.host + ":" + vcap_services.hana[0].credentials.port,
encrypt : true,
schema : vcap_services.hana[0].credentials.schema,
sslValidateCertificate: false,
uid : vcap_services.hana[0].credentials.user,
pwd : vcap_services.hana[0].credentials.password
};
} else {
// ローカル環境での実行時に利用。
var conn_params = {
serverNode : <ホスト名>.dbaas.ondemand.com:<ポート番号>,
encrypt : true,
schema : <スキーマ名>,
uid : <ユーザーID>,
pwd : <パスワード>
};
}

1つ大事な点として、Cloud Foundry上での実行用パラメーター側には、"sslValidateCertificate"パラメーターを追加しています。これがないとディプロイ後のアプリケーションが下記のエラーを出力し、HANAにアクセスができないための対応です。
"Cannot create SSL context: SSL trust store cannot be found: /home/vcap/.ssl/trust.pem"

 

4. SQLの実行


続いて、HANA Clientを利用したSQL文作成のお作法についてです。
var sql = 'SELECT * FROM "' + conn_params.schema + '"."<テーブル名>" WHERE CONTAINS (*, ?);';

WHERE句の中で、"?"を使っていますがこれは変数になります。この"?"の中には下記のstmt文の中の"[word]"が代入されSQLが実行されます。変数が複数必要な場合には、SQL文の中に複数の"?"を設定し、[ ]の中にそれぞれの変数をカンマ区切りで設定することで可能です。(WHERE句の"CONTAINS"はあいまい検索用のオプションです)
stmt.exec([word], function (err, result) {

実行結果は、"result"変数にオブジェクト型として入ってくるため、JSON形式でレスポンスを返します。
res.json({searchResult: result});

ブラウザからアクセスすると、下図のようにJSON形式でデータを取得することが可能です。(検索ワードに"ライセンス"として実行した結果)



 

5. UI側でのデータ取得


UI側はJQueryを使っているため、下記JavaScriptでNode.jsからデータを取得しています。(コードの一部を抜粋)
// 画面の検索ボックスの入力内容を取得
var word = $("#searchBox").val();

// Node.js側で定義したデータ取得用のGetメソッドのエンドポイントを設定
var url = "./search/api/search?search=" + word;

// JQueryのJSONデータ取得メソッドを実行
$.getJSON(url, function(data){
var dataSet = new Array;
var i = 0;
// データ取得結果を配列に格納
$(data.searchResult).each(function(){
dataSet[i] = new Array(this.faqId, this.score, this.category, this.serviceNameS, this.question, this.regDate, this.views);
i++;
});

// dataTableというテーブル用のライブラリに、配列データを格納
if(dataSet.length != 0){
$("#faqList").dataTable().fnAddData(dataSet);
}
});

 

最後に、上記までの実装結果が下図のようになります。



 

ロジック/UI編は以上になります。HANA DBを使ったカスタムアプリケーション開発においても、従来通りのDBクライアント経由でのアクセスも可能ですので、実装しやすいかと思います。ぜひ、今後のHANAのネイティブアプリケーション開発の参考にしていただけますと幸いです。

それでは、次回はデータベース編です。CDSでのデータベースモデリングや、あいまい検索(Fuzzy Search)などについてご紹介したいと思います。