まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:sqldb

モデル定義だけで OpenAPI 対応の REST API を生成してくれる StrongLoop LoopBackIBM DB2 に対応していたので使ってみました。

基本的な考え方や手順は以前にこちらで紹介した MySQL 対応での手順と同様ですが、以下ではデータソースをDB2 とした場合の手順を紹介します:
StrongLoop アプリで MySQL を使う


まずは DB2 サーバーを用意します。自前で用意できる場合はその環境を使っていただいても構いませんが、IBM Bluemix ユーザーであれば SQL Database 等、DB2 サーバーのインスタンスを使っていただいても構いません。

では次のような DB2 サーバー環境が用意できているものとします:
ホスト名XX.XX.XX.XX
ポート番号50000
データベース名SQLDB
ユーザー名db2_username
パスワードdb2_password


この DB2 インスタンスに REST API で読み書きするモデルのテーブルを作成します。上記の MySQL での例と同様の item テーブルを用意します。ここで1点注意があります。DB2 の CREATE TABLE 文は普通に実行するとテーブル名や列名を全て大文字で作成します。普通に利用する際には大文字小文字を区別することなく利用できるのですが、LoopBack 環境では全て小文字で定義されている前提で API が発行されます。つまりデフォルトの大文字のままでテーブルを定義すると後で「テーブルが見つからない」といったエラーが発生してしまいます。それを避ける目的で create table 内のテーブル名や列名の部分は全てダブルクォーテーションで括り、明示的に小文字で作成する必要があります。この点に注意して作成してください:
> create table "item"("id" int primary key generated always as identity (start with 1 increment by 1),"name" varchar(50) not null,"code" varchar(50) not null,"price" int);

これで DB2 側の準備はできました。ではこの item テーブルのデータを読み書きする API を LoopBack で用意しましょう。以下 CentOS 環境を前提に紹介します。

まず、StrongLoop や LoopBack は npm を通じて提供され、Node.js 上で動きます。というわけで Node.js と npm を導入する必要があります:
# yum install epel-release
# yum install nodejs npm --enablerepo=epel

次に npm を使って LoopBack と StrongLoop を導入します:
# npm install -g loopback
# npm install -g strongloop

StrongLoop / LoopBack が導入できたら、これらを使って API を作成します。まずは作業用のディレクトリ(下の例では ~/tmp)を作って、そこに移動しておきます:
# cd
# mkdir tmp
# cd tmp

このディレクトリに LoopBack のアプリケーション環境を作成します。ここではアプリケーション名を db2app と指定しています:
# slc loopback db2app

アプリケーション名と、アプリケーションディレクトリを聞かれますが、いずれもデフォルトの db2app をそのまま指定します。またアプリケーションの種類を聞かれますが、これもデフォルトのまま api-server を選択します:
2016031401


すると db2app アプリケーションの基本部分のインストールが開始され、しばらく待つとこのような画面になり、導入が完了します(この時点で db2app ディレクトリが作られているはずです):
2016031402


上図の最後の部分にこの後の手順が記載されています。が、LoopBack の標準 DB ではなく、他の外部 DB を利用する場合の手順は少し異なります。まずはアプリケーションディレクトリに移動しておきます:
# cd db2app

次にこのプロジェクトのデータソースが DB2 になるようカスタマイズします。まずは DB2 コネクタをインストールします。このコマンドで DB2 ODBC CLI ドライバなどもダウンロード&インストールされます:
# npm install --save loopback-connector-db2

DB2 コネクタがインストールできたら、このコネクタを使ってデータソースを定義します。カスタムデータソースの名称は "mydb" としています:
# slc loopback:datasource mydb

そしてデータソース名はデフォルトのまま mydb を選択します。次のコネクターの選択肢において "IBM DB2" を選択します(ここが今回、新たに DB2 対応した機能です):
2016031403


続けて DB2 サーバーへの接続情報を指定します。上記表の内容通りにホスト名、ポート番号、ユーザー名、パスワード、そしてデータベース名を入力します:
2016031404


ちなみにここでの作業の内容は server/datasource.json ファイルに記載されます。直接編集する場合は同ファイルをテキストエディタで編集してください。


データソースの定義ができたら最後に item モデルを生成します:
# slc loopback:model item

モデル名はデフォルトのまま item を指定します。次にデータソースを聞かれるので上記で作成した mydb を指定します(これでデータソースは DB2 になります)。以下はこれまでと同様でベースクラスには PersistedModel、REST API 公開は Yes、カスタム plural form はなし(そのままリターン)、そして common モデルを指定します:
2016031405


そして各列の定義では上記表のように name 列は string 型で必須(Yes)、code 列も string 型で必須(Yes)、price 列は number 型で必須ではない(No)をそれぞれ指定します:
2016031406


最後に Property name を聞かれた所でそのまま Enter を入力して、列のカスタマイズを完了します。これでモデルの定義も完了しました。


モデルが出来たので、LoopBack で API が稼働し公開されるはずです。実際の動作を確かめてみましょう:
# node .

すると画面には API Explorer にアクセスするための URL (最後が /explorer になっている方)が表示されます:
2016031407


ウェブブラウザでこのページにアクセスすると、db2app アプリケーションと、その中に item モデルを読み書きする一連の API が生成されていることが確認できます:
2016031408


後はここで紹介したような方法で実際の API を実行して、この画面から動作確認することが可能です:
2016031409


ここでデータレコードを作成した場合、当然 DB2 サーバー内に格納されます。DB2 側のデータを参照して同じデータが保存されていることを確認できます:
2016031410


これまで LoopBack は Oracle や SQL Server には対応していましたが、ようやく "StrongLoop An IBM Company" っぽい連携ができるようになりました(笑)。
2016031411


Node-RED だけで SQL Database(DB2) 内のデータを検索して結果を表示する、という仕組みを作ってみます。

IBM Bluemix などから提供されているオープンソース・データフローエディタである Node-RED は、ノードと呼ばれる機能単位のブロックを組み合わせて、ほぼコーディングをすることなくデータのワークフローを作れるウェブアプリケーションです。そのフローにデータベースを組み合わせて問い合わせしたり、結果を格納したり、といったことも少ない(或いはほとんどない)コーディングで実現できる、という便利なツールです。特に Bluemix と組わせることで IBM IoT Foundation と連携した MQTT システムを簡単に構築することが可能になります:
2016020101


データのフローを得意とする一方で、Node-RED 単体では UI はあまり得意ではありません。全くできないわけではないのですが、基本的には HTML などの知識を前提として、動的に HTML を作成するような形になります。むしろサーブレット的というか、UI を外出しした仕組みの1パーツとして利用するのが便利だと思っています。


例えば、現在 SQL DB 内に MYTABLE というテーブルが作られ、以下の様な状態になっているものとします。ここから ID 値が 'fff57f93.000a8' であるデータを検索する、ということを目的としてみます。この ID はパラメータとして与えるようにして、リクエストの度に変更できるようなものにします:
2016020101


普通に SQL を使うのであれば(言語によって JDBC などの設定をした上で)、SELECT * FROM MYTABLE WHERE ID = 'fff57f93.000a8' といった具合にクエリーを実行して結果を得ることになると思います。

この処理を NodeRED で行うにはどうすればよいでしょうか?そのためにはまずこの SQLDB に NodeRED からアクセスできるようになっている必要があります。Bluemix 環境であれば、目的の NodeRED プロジェクトに、この SQLDB を事前にバインドしておきます(下図ではサービス名が SQL Database-iv となっています。適宜みなさんの実際の環境と読み替えてください):
2016020101


バインドした上で NodeRED のパレット内の SQLDB を使います。なお、ここでの SQLDB ノードは(検索をしたいので)左右両方にノード接続点があるものを使います。
2016020102


そして以下の様な NodeRED データフローチャートを作ります。HTTP Request ノード、SQL DB ノード、JSON ノード、Template ノード、HTTP Response ノード、そして Debug ノードの6つを以下のようにつなぎます。以下、各ノードの属性を説明します:
2016020101


HTTP Request ノードでは Method として GET、そして URL として /query を指定します。この URL で指定した内容が実際に問い合わせをする際の URL になります:
2016020102


SQL DB ノードでは問い合わせ処理を記述します。Service では SQL DB のサービス名をプルダウンから選択し、Query には ID をキーに MYTABLE テーブルを検索したいので select * from MYTABLE where id = ? と入力します。そしてこの ? パラメータに代入される値を直前の HTTP Request ノードの URL パラメータから取得するようにします(Prepared Statement っぽい感じ)。HTTP Request ノードの URL パラメータの値は msg.req.query で取得できます。今回は id というパラメータにこの値が入っているよう想定するので、Parameter Markers の欄に msg.req.query.id と指定します:
2016020103


JSON ノードは JSON ブロックをそのまま配置するだけです(名前は適当に指定してください):
2016020104


そして Template ノードで検索結果を表示用に整形します。ここでは HTML 形式で、背景を薄い黄色にして表示してみましょう。以下の様な内容を入力します。HTML 内の {{payload}} 部分に検索結果が入り、その結果を msg.payload として返す、という指定をしていることになります:
2016020105


最後に HTTP Response ノードと debug ノードをそれぞれ配置します。この状態でフローを Deploy します:
2016020106


そしてウェブブラウザで、http://(Node-RED のあるサーバー)/query?id=(SQL DB から検索したいレコードのID値) を指定してアクセスします。成功すると指定した ID 値を持つレコードが JSON テキスト形式で、指定したフォーマット(背景が薄い黄色)で表示されるはずです:
2016020107


URL パラメータの id の値を別のレコードのものに変えると、指定したレコードの内容に変わるはずです:
2016020108


同時にこれらの検索結果は Node-RED 画面の debug タブ内にも表示されているはずです:
2016020109


上記例では結果を(わざわざ)HTML 化して出力しましたが、現実には JSON のまま返したり、XML 化して返す、といったサーブレット的な処理をする機会が多いと思います。要は見た目については Node-RED の外で管理すべきと考えています。


・・・と、そう思っていたのですが、最近になって Node-RED に UI パーツを追加できるようなノード部品が提供されたようです。ある程度用途は限られていますが、UI も Node-RED で作れるようになっていくのかもしれません:
https://github.com/andrei-tatar/node-red-contrib-ui


とりあえず、Node-RED だけでサーブレット的な検索機能を実装することもできそうだ、ということが分かりました。


BlueMix 上で使えるデータストアでも触れましたが、この中には2つの DB2 サービスがあります。

1つは SQLDB というサービスで、これは標準的な DB2 と呼ばれている製品がベースになっている、と言われているものです。もう1つの BLUAcceleration というサービスは DB2 のアドバンス版がベースになっていると言われており、インメモリ最適化や列ストアによる高速な統計処理が可能になっているようです。

・・・と、こういった情報までは公開されています。ただ良くも悪くも情報がブラックボックス化されていて、以下の様な情報が公開されていません:
・使われている DB2 のバージョン(=開発時に用意する DB2 JDBC  ライブラリのバージョン)
・データベースの文字コード 

実は一般的にはこれらの情報は DB2 サーバーにコマンドライン接続してコマンドを発行することで確認することができます。ただ BlueMix 環境ではそれらがブラックボックスになっているので調べようがない、、と思っていました。

が、実際にこれら2つの DB2 サービスを作成して、それぞれ環境変数 VCAP_SERVICES を調べてみると、以下の様な内容を得ることができました(一部伏せ字にしてます):

SQLDB:
"SQLDB-1.0": [
 {
  "name": "SQLDB-iw",
  "label": "SQLDB-1.0",
  "plan": "SQLDB_OpenBeta",
  "credentials": {
   "hostname": "192.XXX.XXX.XXX",
   "host": "192.XXX.XXX.XXX",
   "port": 50000,
   "username": "uXXXXXX",
   "password": "XXXXXXXXXX",
   "db": "I_XXXXXX",
   "jdbcurl": "jdbc:db2://192.XXX.XXX.XXX:50000/I_XXXXXX",
   "uri": "db2://uXXXXXX:XXXXXXXXXX@192.XXX.XXX.XXX:50000/I_XXXXXX"
  }
 }
]

BLUAcceleration:
"BLUAcceleration-10.5.3 Rev. A Build 0.1": [
 {
  "name": "BLUAcceleration-es",
  "label": "BLUAcceleration-10.5.3 Rev. A Build 0.1",
  "plan": "Community_Beta",
  "credentials": {
   "hostname": "bluemix01.bluforcloud.com",
   "host": "bluemix01.bluforcloud.com",
   "port": 50000,
   "username": "bluXXXXX",
   "password": "XXXXXXXXXXXX",
   "db": "BLUDB",
   "jdbcurl": "jdbc:db2://bluemix01.bluforcloud.com:50000/BLUDB",
   "uri": "db2://bluXXXXX:XXXXXXXXXXXX@bluemix01.bluforcloud.com:50000/BLUDB"
  }
 }
]

SQLDB の方はホスト名(IPアドレス)が 192.XXX.XXX.XXX となっていました。これはいわゆるプライベート IP アドレス帯ではないのですが、おそらく BlueMix ネットワーク環境内の中に設置されたサーバーになっているようで、外部からは dns でも ping でも db2 クライアントからも直接接続することはできませんでした。BlueMix 上の MySQL なども同様なのですが、まあこのサービスは外部には直接公開されていない、と考えるべきでしょう。

一方、BLUAcceleration のサーバーはホスト名が bluemix01.bluforcloud.com という、どこかで見たような名前。。

・・・ bluforcloud.com って、あれだ、先日サービスがスタートした IBM 版の DBaaS サービスで使われているドメインですね。BlueMix の BLUAcceleration はここのサービス(Managed Service)を使っていたのか:
IBM BLU Acceleration for cloud


ということは、もしかして外部から参照できるかも・・・と思い、コマンドラインコンソールを使うため無償版の DB2 Express-C (10.5.1)をダウンロードしてインストールしました。で、まずはリモートのサーバーノードと DB をカタログ定義して、と:
$ db2
  :
  :
db2 => catalog tcpip node node1 remote bluemix01.bluforcloud.com server 50000
db2 => catalog database bludb as db1 at node node1


そして定義した db1 (=bluemix01.bluforcloud.com:50000 上の bludb データベース)に ID とパスワードを指定して接続を試みてみると・・・

2014042701

あっさり繋がってしまいました(笑)。合わせてこのサービスが 64bit 版 Linux 上に導入された DB2 10.5.3 であることも分かりました。JDBC ドライバはこの DB2 Express-C (10.5.1) にあるものをそのまま使えばよさそうです。

というわけで、続けてデータベース設定情報を確認、と・・・
2014042702


テリトリーコードは US 設定ですが、コードセットは UTF-8 ですね。安心して日本語が使えます。


#本音を言えばこういう情報は公開してほしい


っていうか、BlueMix 上で BLUAcceleration サービスだけ起動して、オンプレミスやクラウドに構築したウェブアプリサーバーからこの BLUAcceleration サービスに接続する、という使い方もできちゃいそうな感じだけど、いいんでしょうか? (^^; 個人的にはそれはそれで嬉しいかも(笑)。





このページのトップヘ