IBM i 上でNode.jsのWebアプリを動かす その2 (概要とDBアクセス)


# はじめに

「IBM i 上でNode.jsのWebアプリを動かす」2つ目の記事です。  
- 1つ目の記事はこちら 
IBM i 上での Node.js のインストール方法と簡単な実行をしました。 

 https://qiita.com/tom_m_m/items/5cd480eb1aad35a6a6dc

今回は、作成したWebアプリに関連して、概要とDB周りの操作について書いていきます。  
作成したコードはこちらにおいています。  

https://github.com/tom-m-m/ibmi-nodejs-qr-detection

この記事の中では、こちらのアプリを「QRコードアプリ」と記載しています。
Node.jsでのWebアプリ制作に関しては手探りで行っていますので、荒いところがあるかもしれません。

# どんなものを作るか？

QRコードを使った入出管理を行う簡単なアプリを作成してみました。  
概要はこちらの画像の通りです。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242652/9b66e461-4c01-38a9-0caa-b22991f7f7bb.png)

スマホなどからWebアプリにアクセスし、QRコードを読み取ります。  
そこから、ボタンが表示されるので操作をすると裏で IBM i のDBへデータの参照・更新を行うというよう流れです。  
Node.js から IBM i への接続は、ODBCを利用します。  

# 環境情報

以下の環境で作成しています。
- IBM i : 7.5
- Node.js : v20.8.1
  
## Node.js 使用パッケージ
    express: 4.18.2
    ejs: 3.1.8
    body-parser: 1.20.2
    idb-connector: 1.2.18
    jimp: 0.16.2

今回は、Node.js のWebアプリを作成するためのフレームワーク express を利用します。  
ODBC接続は、idb-connector を利用します。 

QRコードの読み取りには、こちらで公開されている jQR を利用させていただきました。  

https://github.com/cozmo/jsQR

## Node.js のパッケージ管理

Node.jsでは、パッケージ管理のために `npm` を利用します。  
yum と同じような存在のものです。  

パッケージのインストールで少し分かりづらいポイントは、グローバルインストールとローカルインストールがある点です。  

グローバルインストールは、環境上のどのディレクトリからでも実行できるところにパッケージがインストールされます。  
なので、アプリを作るときに一回インストールしてしまえば、いつでも使える状態となります。  

グローバルインストールをする場合は、こちらのコマンドを実行します。  
```
npm install -g <パッケージ名>
```

ローカルインストールは、インストールを実行したディレクトリでしかそのパッケージを利用できません。
よく使うものや少し試す時には、ローカルインストールがいいと思います。  
ローカルインストールは、`-g` なしで実行すればOKです。  

```
npm install <パッケージ名>
```

インストールをすると、アプリを作っているディレクトリ内に `node_modules` が作成されます。  
この中に、インストールされたパッケージが入っています。  

## テスト用のデータ

Webアプリのテスト用に、IBM i 上にテーブルを作成しました。 
テーブルの中身はこちらの通りです。

ライブラリ、テーブルは、 `ACCESS.ACCESSTABLE` となっております。  

|QRID|NAME|DATE|STATUS|
|---|---|---|---|
|174928 |山田 太郎 |	2022-11-20 |	schedule|
|735032 |鈴木 達也 |	2022-11-25 |	schedule|
|281942 |吉田 拓也 |	2022-12-12 |	schedule|
|523361 |村山 誠	 |2022-11-05	 |schedule|
|413251 |林 里沙	 |2022-11-28	 |schedule|
|724363 |松本 静香 |	2022-12-15 |	schedule|
|234352 |清水 宏一 |	2022-12-05 |	schedule|
|223355 |吉田 里香 |	2022-12-15 |	schedule|

※ 名前は、ランダム生成を行ったものを使っています。  

# DBへのアクセス方法

ここからは、アプリ構築の鍵となるコードをパーツ単位に書いていきます。 
この内容だけでもだいぶ長くなってしまうため、この記事ではDBアクセスのみに絞って記載します。  

すでに書いた通り、DBアクセスは idb-connector を使用します。  

https://www.npmjs.com/package/idb-connector

ODBC経由のDB接続を、簡単に実装できます。  
Node.js のパッケージ(追加ライブラリのようなもの)として公開されているため、インストールも手軽に行えます。  
インストールは、下記コマンドで実行可能です。  

```
npm install idb-connector
```

では、実際に idb-connector を使ってみます。  
テスト用のディレクトリを作ったあと、初期化 (`npm init -y`) と idb-connector のインストールを行います。  

```
work # mkdir idb-connector
work # cd idb-connector/
idb-connector # npm init -y
Wrote to /home/e36965/work/idb-connector/package.json:

{
  "name": "idb-connector",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}


idb-connector # npm install idb-connector

added 60 packages, and audited 61 packages in 8s

4 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
```

次に、select文 を実行するjavascriptを記述していきます。  
デモ用に作成したDB (ACCESS.ACCESSTABLE) を使用して、全件表示をします。  

```javascript:index.js
const {dbconn, dbstmt} = require('idb-connector');

const sSql = 'SELECT * FROM ACCESS.ACCESSTABLE';
const connection = new dbconn();
connection.conn('*LOCAL');
const statement = new dbstmt(connection);

statement.exec(sSql, (x) => {
  console.log(x);

  statement.close();
  connection.disconn();
  connection.close();
});
```
それぞれ、パーツにごとに見ていきます。  

```
const {dbconn, dbstmt} = require('idb-connector');
```
ここで、パッケージのインポートをしています。  
接続用クラスを `dbconn`、実行用のクラスを `dbstmt` として定義しています。  

```
const connection = new dbconn();
connection.conn('*LOCAL');
const statement = new dbstmt(connection);
```
接続の確立と、SQLを実行するための準備をしています。  

```
statement.exec(sSql, (x) => {
  console.log(x);

  statement.close();
  connection.disconn();
  connection.close();
});
```
この部分で、実際にSQLを実行しています。  
実行後に、connectionを閉じるようにしています。  

statement.exec 以降の書き方がjavascript特有ですが、下記のように書くことも可能です。  

```
result = statement.execSync(sSql);
console.log(result);

statement.close();
connection.disconn();
connection.close();
```

では、実行してみます。  
```
/home/E36965/work/idb-connector # node index.js 
[
  {
    QRID: '174928',
    NAME: '山田 太郎',
    DATE: '2022-11-20',
    STATUS: 'schedule'
  },
  {
    QRID: '735032',
    NAME: '鈴木 達也',
    DATE: '2022-11-25',
    STATUS: 'schedule'
  },
  {
    QRID: '281942',
    NAME: '吉田 拓也',
    DATE: '2022-12-12',
    STATUS: 'schedule'
  },
  {
    QRID: '523361',
    NAME: '村山 誠',
    DATE: '2022-11-05',
    STATUS: 'schedule'
  },
  {
    QRID: '413251',
    NAME: '林 里沙',
    DATE: '2022-11-28',
    STATUS: 'schedule'
  },
  {
    QRID: '724363',
    NAME: '松本 静香',
    DATE: '2022-12-15',
    STATUS: 'schedule'
  },
  {
    QRID: '234352',
    NAME: '清水 宏一',
    DATE: '2022-12-05',
    STATUS: 'schedule'
  },
  {
    QRID: '223355',
    NAME: '吉田 里香',
    DATE: '2022-12-15',
    STATUS: 'schedule'
  }
]
```
データを全件取得できました。  

下記のサンプルを見ると、データを出力する値が `JSON.stringify(x)` という書き方になっています。  
先程記載したコードでは、単純に `x` の出力をおこなっています。

https://www.npmjs.com/package/idb-connector

idb-connector で取得したデータは、javascript内のオブジェクトや値をJSON形式の文字列に変更する際に使用します。  
フロント側にデータを渡す時などに、データを扱えるようにするため今回も JSON.stringify() を使っています。  

それぞれの値でどのような違いが生じるのか見てみます。  
使うコードの一部が以下になります。  
先程のコードを元に、取得したデータの1番目のみ表示するように変更しています。  
```
result = statement.execSync(sSql);
console.log('結果をそのまま表示: ');
console.log(result[0]);

console.log('JSON.stringifyを使用して表示: ');
console.log(JSON.stringify(result[0]));
```

実行してみると、このようになりました。  
結果をそのまま出力した場合は、javascriptのオブジェクトとして認識されているので構造がわかるように表示されています。  
一方で、 JSON.stringify() を使った場合は、一行のテキストで表示されます。  
```
idb-connector # node index.js 
結果をそのまま表示: 
{
  QRID: '174928',
  NAME: '山田 太郎',
  DATE: '2022-11-20',
  STATUS: 'schedule'
}
JSON.stringifyを使用して表示: 
{"QRID":"174928","NAME":"山田 太郎","DATE":"2022-11-20","STATUS":"schedule"}
```

Node.js では `ejs` を使うことで、サーバーサイドからフロントにデータ連携が出来るのですが、オブジェクトのまま送信してしまうと、中身が見えなくなってしまいます。  
私は、ここで結構長い時間はまってしまいました。  

# さいごに

少し長くなってしまいましたが、今回はここで終了となります。  
パーツごとに説明することになるので、全体像がわかりづらくなっているかもしれません。  
次回からは、引き続きキーコンポーネントとなるパーツの紹介をしていきます。  

今回は、作成したアプリの概要と idb-connector の詳細を書きました。  
idb-connector は使い勝手がよく、すぐに試せるのでぜひ試していただければと思います。  

Node.js だけでなく、Python にも IBM i のDBにアクセスするためのパッケージがあります。  
簡単なデータ取得のアプリを作ったり、Python のWebアプリケーションフレームワークと組み合わせてWebアプリを作ることも可能です。