Skip to Content
Technical Articles

SAP Cloud PlatformでのNode.js + SAP HANAアプリ開発 – ロジック/UI編

はじめに

本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)などについてご紹介したいと思います。

Be the first to leave a comment
You must be Logged on to comment or reply to a post.