IBM i で node.js を使ってみよう!!(5)- IBM i コマンドの実行(日本語を表示させる) -

IBM i で node.js を使ってみよう!!(1)- REPL から Hello World まで -」からの node.js を IBM i で使うにはどうしたらいいかを紹介する一連の記事の続きです。

今回は、「Node.js でも Python でも必要になる XMLService ってどんな機能!?」で紹介した XMLService というオープンソース製品に変更を行って node.js のコマンド実行機能で日本語を扱えるようにするやり方を紹介したいと思います。


実は node.js のコマンド実行機能では日本語が扱えない?!

IBM i で node.js を使ってみよう!!(4)- IBM i コマンドの実行 -」までで、IBM i 上で node.js を実行できること、その際、DB2 for IBM i への SQL アクセスができること、そして、IBM i コマンドの実行ができることなどを紹介してきました。

DB2 for IBM i への SQL アクセスを紹介した「IBM i で node.js を使ってみよう!!(3)- SQL でデータベースにアクセス -」ではきちんと日本語も扱えることを確認しましたが、IBM i コマンドの実行を紹介した「IBM i で node.js を使ってみよう!!(4)- IBM i コマンドの実行 -」では確認しませんでした。
実は、これは意図的なもので、理由があったんですね。

たいへん残念なことに現時点(2015/09)では、コマンド実行を node.js で行った場合に返される結果について ascii 以外の文字は変換されずに無視されてしまいます。

たとえば、RUNQRY などを「IBM i で node.js を使ってみよう!!(4)- IBM i コマンドの実行 -」で紹介したプログラムで実行すると ↓ のような結果になってしまいます。数字や英字だけが正しく表示されていることがわかりますね。漢字などはすべて正しく変換されずに矢印になってしまっています。

Node.js での IBM i コマンド実行は、PASE シェルでの system ユーティリティを内部的には使用しています。

確認のために PASE シェルから system ユーティリティで、↑ の処理で実行されているコマンドを実行してみると、↓ のように漢字も正しく表示されます。

まったく同じ引数での system ユーティリティで、PASE シェルから実行すると OK で、node.js のプログラム内から実行すると ascii 文字のみが変換される、という結果になっています。node.js 関連の問題であることが考えられますね。

Node.js の SQL実行機能では日本語が扱えるのに…?!

では、node.js では日本語のデータを扱えないのか?! というと、「IBM i で node.js を使ってみよう!!(3)- SQL でデータベースにアクセス -」で見たように、SQL アクセスではまったく問題なく日本語のデータは変換され、表示されているので、node.js 全体の問題というわけではないこともわかります。

つまり、node.js の IBM i のコマンド実行機能だけで起きている問題、なんですね。

IBM i の Node.js でのコマンド実行や IBM i オブジェクトへのアクセスなどは Node.js Toolkit for IBM i という機能を使って実現しています。SQLアクセスとは別の機能になっています。

この“ascii しか処理できない”というのは。この Node.js Toolkit for IBM i で ascii 以外の文字を扱うときに起きる問題、と考えられます。

Node.js のコマンド実行機能では XML Service を使っている

特にどこかに書いてあるわけではないようなのですが)この Node.js Toolkit for IBM i ではコマンドの実行やパラメータの受け渡し、そして実行結果の受け渡しを XML で行っており、その XML への整形やその際の文字変換などを 5770-DG1 (IBM HTTP Server for i) に含まれている XML Service という機能を利用して、行っています。

いろいろ問題判別していくと、このXML serviceという機能の中で日本語への変換に問題が起きているようだ、ということがわかりました。

実はこの XML Service、XMLService として IBM の手でオープンソース化されているんですね。

今回は、この XMLService がオープンソース化されていることを利用して、Node.js Toolkit for IBM i で日本語を扱えない問題に対処したいと思います。


XMLService の導入とセットアップ

XMLService の導入とコンパイルを行います。やり方は「Node.js でも Python でも必要になる XMLService ってどんな機能!?」を参考にしてみてください。
ソースは編集するのですが、一回正しくコンパイルできるかどうか確認するためにも、一度そのままでセットアップしておくといいでしょう。

XMLService の変更手順

PLUGPASE ソースメンバーの変更

QRPGLESRC ソースファイルの中に PLUGPASE というメンバーがいます。

paseCCSID = 819;

という行を見つけて

paseCCSID = 1208;

に変更します。

このモジュールの中で、PASE 環境の CCSID を 819(ISO/IEC 8859-1) にセットしてしまっているんですね。これで ascii 文字しか処理できない環境になってしまっている、ということなんです。

1208 というのは UTF-8 を指す CCSID です。デフォルトを UTF-8 に指定し直している、というわけです。これで日本語もあつかえる環境にしています。

モジュールの生成

ソースを変更したら、XMLService の導入時と同様に CRTXML プログラムを実行し、改めてモジュールを生成し直します。

Node.js での使用する XMLService の指定

Node.js Toolkit for IBM i で使用する XML service をオープンソース版の XMLService に変更します。

/QOpenSys/QIBM/ProdData/Node/os400/xstoolkit/lib/itoolkit.js という IFS ファイルに ↓の画面 のように指定があります。ここで Toolkit で使用する XML Service を指定しているわけです。

"QXMLSERV" という指定を "XMLSERVICE" に変更して保管します。

以上で変更は完了です。

Node.js の実行と結果の確認

改めて node.js を実行してみましょう。

この記事の冒頭でお話しした例と同じように RUNQRY を実行してみると、↓のようにちゃんと日本語が正しく変換された結果が出てきます。


その他いろいろ

ついでなので、IBM i で node,js を利用したプログラムを書くときに役立つ情報をいくつか紹介します。

問題判別

debug(true)

問題判別時には debug(true) というオプションを使うといいでしょう。↓ のように使います。

            conn.debug(true);
            conn.add(xt.iSh("system -i " + cmd, option));
            function cb(str) {
               // console.log(str);
               console.log(JSON.stringify(xt.xmlToJson(str), null, 4));
               res.write(xt.xmlToJson(str)[0].data, encoding='utf8');
             } 
            conn.run(cb); 

↓のように、XMLService への入力となるXML、XMLService からの出力となるXMLをそれぞれ表示させることができます。

console.log の活用

画面の例はありませんが、コールバック関数内で console.log を使うと、コールバック関数で処理しようとしている文字列を表示させることができます。

            conn.add(xt.iSh("system -i " + cmd, option));
            function cb(str) {
               console.log(str);

このケースでは↑の画面の中の「OUTPUT XML」の内容とほぼ同じものが表示されます。使い方は状況に応じていろいろあるでしょう。

実行時のオプション

実行時のオプションもいくつかあります。↓ のようにコマンドを実行するときに、いろいろなオプションを指定することができるようになっています。

         if(cmd && cmd.length > 0) {
            console.log("CL command : " + cmd); 
            var conn = new xt.iConn(DBname);
            var option = {
               rows:'on',
               hex:'off',
               error:'on'
            };
            conn.debug(true);
            conn.add(xt.iSh("system -i " + cmd, option));
            function cb(str) {
               // console.log(str);
               console.log(JSON.stringify(xt.xmlToJson(str), null, 4));
               res.write(xt.xmlToJson(str)[0].data, encoding='utf8');
             } 
            conn.run(cb); 
          } 

今回使用している iSh クラスですが、たとえば ↓ のように各行毎を <row></row> として区切ることができる rows、エラー時により詳細なエラー情報を出力させるようにできる error、hex での出力もしくは CCSID変換を行うようにできる hex オプションなどがあります。
詳しくは、APIのドキュメントを参照してみてください。

[Top Pageに戻る]

Ads by TOK2