XMLSERVICEを使ってIBM iを開放する
IBM i以外のプラットフォームやプログラミング言語からIBM iの資源にアクセスする要望は昔からあり、それに対してさまざまな解がありました。PHPを使っている場合、i5関数がその解として役立ちます。Net.DataもIBM iのデータやプログラムにアクセスするためのものです。これに加えて、忘れるはずもなくIBM Toolbox for Javaやそのオープンソース版であるJTOpenもあります。他のどの手段でもうまくいかない場合、DB2のストアード・プロシージャを作ってIBM iアプリケーションを活用しデータベース経由でアクセスするか、いくつかある異なるツールを使用してコードをウェブ・サービスとして公開することができます。こうしたツールにはいずれも一長一短があり、複雑さや制限のレベルもさまざまで、どれを採用すれば良いかを決めるのでさえ手間がかかることもあります。任意のIBM i資源を、任意のプラットフォーム上の任意の言語に対して簡素で一貫性のあるインタフェースで利用可能にする単一のインタフェースがあるとしたらどうでしょうか。
すでにお聞きになっているかもしれませんが、Zend社はIBMと共同でIBM iの資源にアクセスするための製品の改良に努めてきました。パフォーマンスや機能上の課題がいくつかあって、それを克服するには共同で臨む必要がありました。このような協力関係の下、PHP言語がIBM iのコマンド、プログラム、サービス・プログラム、ユーティリティに直接アクセスするために、高速で柔軟性を備えた単純なインタフェースが必要であるという要件が出てきました。幸いなことに、IBM iをPHPだけでなく他の言語やプラットフォームに対してもオープンしてくれるソリューションをIBMの仲間が配布してくれました。そのソリューションがXMLSERVICEです。
XMLSERVICEを一言で言うと
ではXMLSERVICEとはいったい何なのでしょうか。XMLSERVICEは新しいZend PHP Toolkit for IBM iの表面下にある配管のようなものです。XMLSERVICEを使用すると、HTTPまたはDB2のストアード・プロシージャを介して簡単なXMLでシステム上の任意のプログラムやユーティリティを利用できるようになります。XMLSERVICEをインストールすれば、特別なセットアップを要することなくプログラムにアクセスすることが可能になります。必要なのはプログラム、ILEサービス・プログラム中のサブ・プロシージャ、PASEユーティリティ、その他呼び出そうとしているものを呼び出すためのXMLドキュメントを正しく作成することだけです。驚きましたか。
良いお知らせはまだあります。IBMはXMLSERVICEをオープンソースにしようとしています。IBM社内ではZend社と共同で開発作業がすべて済んでいますが、IBMは開発が完了したらプロジェクトをオープンソースのコミュニティに引き渡すことを決定しました。実際、本稿をお読みになっている頃までにはプロジェクトはリリースされているはずです。プロジェクトがリリースされた後、オープンソースをどうやってダウンロードして使用するのかの詳細については、youngiprofessionals.comにあるYoung i ProfessionalsというWikiページに着目していてください。現在の計画ではプロジェクトをBSDライセンス下でリリースすることになっています。これはどういう意味でしょうか。つまりこれは、XMLSERVICEがフリーでオープンソースとなり、コミュニティがユーザーの要望に応じてXMLSERVICEを強化することができるということです。また、Zend社のPHP向けの新しいツールキットがXMLSERVICEの使用を独占しないということでもあります。読者の皆さんの中に.NETの専門家の方がいらっしゃいましたら、.NETアプリケーションからXMLSERVICEを使用して簡素化するツールキットを開発したいのであればそれが可能であるということです。もしJavaのコミュニティがこのプロジェクトの恩恵を受けたいというのであれば、それも可能だということです。XMLSERVICEと皆さんのお気に入りのプログラミング言語とのインタフェースについてコミュニティの中で検討してみることをお勧めします。
XMLSERVICEに関して私にとって一番目立つ特徴は、それ自体がすべてILE RPGで記述されているということです。はい、その通りです。このようなオープンソースのプロジェクトをIBM iのコミュニティにリリースし、コミュニティの大多数の人がRPGのコードを書いているのにそれをCやJavaで記述することの利点は何なのでしょうか。このソースをILE RPGで記述することで、コミュニティの誰もがソースコードを読んで理解することができます。このようなプロジェクトが成功するためには、コミュニティの人々がコントリビュートするのに対する障壁を極力少なくする必要があります。IBMはこの点に関して正しく理解していると思います。できれば、これがIBM iのツールがもっとRPGで記述されたりオープンソースになったりすることのきっかけになればと思います。
XMLSERVCEのインタフェース
XMLSERVICEをDB2のストアード・プロシージャ経由で使用するにしろ、HTTP RESTサービス経由で使用するにしろ、皆さんのプログラムを呼び出すのに必要な要素がいくつかあります。
データベース
これはシステム上のデータベースの名前です。ファイル名やテーブル名ではありません。システムのデータベース名がわからない場合は、System i Navigatorのデータベース・ツリーで調べることができます。
ユーザーIDとパスワード
これは単にIBM iのユーザーネームとパスワードです。
IPC
本当に正直に申し上げると、IPCが何の略語か見当がつかないのです。本稿執筆時点ではこれに関するドキュメントがまだ完成していません。しかしIPCの概念は理解しています。XMLドキュメントを正しいXMLSERVICEジョブにルーティングし、共有メモリの内容を保存するための専用の空間を提供することが目的です。IPCは使用する接続用の一時ディレクトリへの完全修飾パスに過ぎません。一番簡単な選択肢は/tmp/usernameです。
CTL
この制御パラメータを使用すると、現在のXMLSERVICEジョブの動作を変更することができます。ここに挙げたリストはそのすべてではなく新しい制御コードがまだ追加されていますが、その中のいくつかの有用な制御値を挙げておきます。
- *debug ― この値を指定するとデバッグのために呼び出しを停止します。
- *immed ― この値を使用すると現在のジョブを即座に終了します。
- *nostart ― この値を使用するとXMLSERVICEが新しいジョブを起動しないようにします。
XML In
これはXMLSERVICEへのインプットとなるXMLドキュメントです。このXMLドキュメントでXMLSERVICEに対して呼び出すプログラムとそのパラメータを指定します。これについては次のセクションでもう少し説明します。
XML Out
結果セット付きのXMLSERVICEストアード・プロシージャ・インタフェースを使用している場合は、このパラメータは不要な場合があります。このXMLドキュメントに結果が含まれることになります。
必要なパラメータは3つのカテゴリに簡単に分けることができます。データベース、ユーザーID、パスワードについてはそれぞれの機能は明白で、システムへの接続を確立することです。IPCとCTLはジョブの構成パラメータです。XML inとXML outはバッファです。
XMLSERVICEは複数の方法で起動することができます。おそらく一番簡単な方法は、DB2のストアード・プロシージャ・インタフェース経由での起動です。この方法はDB2 Connect、ODBCやその他のストアード・プロシージャをサポートしているデータベースへのアクセス方法でDB2にアクセスできるプラットフォームや言語であれば、どれでも実現できます。XML出力のサイズとXMLをパラメータとして返すのか結果セットとして返すのかによって、呼び出せるストアード・プロシージャが複数あります。プロシージャ名を図―1に示します。
もう一つの方法は、CGI経由でXMLSERVICEを使用できるようにHTTPサーバーを構成する方法です。これにより結果としてXMLSERVICEがシステム上の任意のプログラムを呼び出すことのできるRESTウェブ・サービスとなります。この方法は、手間をかけずに既存のプロセスをウェブに公開する方法としては非常に強力なものです。これを実現するにはHTTPサーバー構成ファイル(httpd.conf)を変更する必要があります。必要な変更は簡単で、以下のようになります。
ScriptAlias /cgi-bin/ /QSYS.LIB/XMLSERVICE.LIB/
AllowOverride None
order allow,deny
allow from all
SetHandler cgi-script
Options +ExecCGI
この構成をIBM i HTTPサーバーに追加することで、アドレス yourwebserver/cgi-bin/xmlcgi.pgmを使用してXMLSERVICEを起動することができます。前述した必要なパラメータはHTTPリクエストの一部として渡すことができます。これについては本稿でカバーする範囲を超えていますが、ウェブ・サービスの使用方法をご存知であれば、XMLSERVICEのドキュメントに記載されている情報を参考に簡単に実現できるはずです。
XMLドキュメント
XMLSERVICEにアクセスする方法としていくつか異なる方法を簡単に紹介してきましたが、実際のプログラムとどのように通信するのかについてはまだ説明していません。その秘密はXMLドキュメント中にあります。XMLSERVICEはXMLドキュメントを取り込みますが、このドキュメントの中にはコマンド、プログラムの定義、パラメータが含まれていて、出力とともにXMLドキュメントを返します。XMLドキュメントのフォーマットは極めて柔軟です。実際、XMLドキュメントに特別なタグやラベルを追加して結果の構文解析を容易にすることができます。ただしXMLSERVICEの構文にはいくつかの予約語があり、これを使わないといけない場面があります。
<cmd> ... </cmd>
cmdタグは、XMLSERVICE経由でコマンドライン用のコマンドを実行させるときに使用します。cmdタグはとても簡単に使用できるタグです。コマンドライン上に入力するのとまったく同じ内容をこのタグ間に記述すればXMLがそれを実行してくれます。
<sh> ... </sh>
shタグはcmdタグのPASE版に相当します。shタグに囲まれた内容は、PASEのコマンドライン(QP2TERM)に入力されたのと同様に実行されます。
<pgm> ... </pgm>
pgmタグを使用すると、実行したいIBM iのプログラムやサブ・プロシージャを指定することができます。プログラム名、ライブラリ名、サブ・プロシージャ名はname、lib、funcなどの属性をpgmタグ内で使用することで定義できます。prmタグ内にプログラムのパラメータと戻り値を定義することもできます。これはRPGプログラムのプロトタイプに似ています。プロトタイプに必要なタグは以下の通りです。
<parm> ... </parm>
parmタグはプログラムのパラメータを識別します。parmタグで必須の属性はありませんが、io属性やby属性を使用してパラメータのタイプを指定しても構いません。io属性は「in」、「out」、「both」のいずれかに設定することができ、by属性は「val」または「ref」のいずれかを設定して値渡しなのか参照渡しなのかを指定します。parmタグの中では、パラメータは以下のタグを必要に応じて使用して定義します。
- <ds> ... </ds>
dsタグはそのパラメータがデータ構造を持っていることを示します。dsタグで必須の属性はありません。パラメータがデータ構造の配列である場合は、オプションのdim属性とdou属性を使用します。dim属性は配列中のデータ構造の最大数を定義します。dou属性、または「do until」属性とも言いますが、この属性は実際に値が入っている配列要素の数を決定します。dsタグはデータ定義または他のdsタグを含んでその要素を定義します。 - <data> ... </data>
dataタグはパラメータを定義してそこに値を代入するのに使用します。type属性が必要で、この属性を使ってパラメータのデータ・タイプとサイズを定義します。パラメータが文字フィールドである場合は、オプションの属性varyingを使用して可変長の文字フィールドであることを指定することができます。varying属性は「on」または「off」に設定します。データ・タイプとしてとりうる値を図―2に示します。 - <return> ... </return>
returnタグは、サブ・プロシージャの戻り値などの戻り値を識別するのに使用します。属性はありません。戻り値はdataタグやdsタグをパラメータのように使用して定義します。
異なるタグをアクションのリスト中に組み合わせて、XMLSERVICEに実行させたいスクリプトを構築することができます。IBM iのコマンドをスクリプトにしてプログラムを呼び出す前に実行したり、複数のプログラム呼び出しを並べて望みの結果を生成したりすることができます。
たとえばITEMSRVというサービス・プログラム中にGET_PRICEという見積もりのルーチンがあったとしましょう。このプロシージャは項目番号、顧客名、値下げフラグを入力として受け取り、販売価格を返します。もちろん、ほとんどの見積もりプロシージャはこれよりずっと複雑ですが、ここでの例は簡単なものにしましょう。サブ・プロシージャのプロトタイプは図―3に示すようなものになります。
これで図―4に示す通り、XMLSERVICEに送信するXMLドキュメントを構築するのに必要な情報はすべて揃いました。
XMLドキュメントはXMLのバージョンで始まります。このバージョンはXMLSERVICEに送信するすべてのXMLドキュメントに含まれます。次のタグはmultですが、これはこのXMLドキュメントで複数のコマンドやプログラムを実行しようとしていることを知らせるだけです。multタグの中では、あるライブラリをライブラリ・リストに追加することから始めています。これを例として選んだのは、XMLSERVICEを使用する際に一般的に実行することだと思ったからです。cmdタグにはコマンドラインに入力するのとまったく同じコマンドが指定されています。次に、私が作ったGet_Priceプロシージャの呼び出しを追加しました。pgmタグがあるのでお分かりになるでしょうが、サービス・プログラム名、ライブラリ、プロシージャ名を識別しています。タグの中ではパラメータと戻り値を定義しています。各dataタグ内でvar属性を使いパラメータ名を指定しています。XMLSERVICEはこの情報を使用しませんが、この情報は出力されるXMLドキュメントの中に含まれますので、戻ってきたXMLドキュメントを構文解析する際にとても有用です。また、各dataタグにパラメータ値を入れたのもお気づきになるでしょう。このタグを実運用のシナリオで使用する際は、プログラムを呼び出す際のXMLドキュメントを構築するときにパラメータに値を入れます。XMLドキュメントに対してやっておかなければならないのはこれだけです。とてもわかりやすく容易に理解できると思います。
上記のXMLドキュメントを使用して呼び出しを行うと、戻ってきたXMLドキュメントはどのようなものになるでしょうか。それは図―5に示すコードのようなものになります。
戻ってきたXMLドキュメントは、入力の際に使用したXMLドキュメントとほとんど同じように見えると思います。これはXMLSERVICEが単にXMLドキュメントの中の要素を1つずつ処理しているだけだからです。変更があったデータはdataタグ中に反映されています。私たちの例の場合、ライブラリ・リストを追加するコマンドで始まっています。cmdタグ中に記述したコマンドが成功のメッセージで置き換えられているのがお分かりいただけるでしょう。プログラムの呼び出しとそのパラメータは、プロシージャによって変更されていませんのですべて元のまま残っています。もしパラメータが変更された場合は、その変更内容がパラメータのdataタグに反映されます。呼び出したプロシージャは戻り値として価格を返しますので、returnタグのdataタグに価格が入っています。さてこれでお気に入りの構文解析機能を使用し、使用している言語で書かれているXMLドキュメントの構文を解析するだけです。ほとんどの言語には基本的なXML構文解析機能が備わっていますので、こうした簡単なXMLドキュメントを容易に処理することができます。
XMLSERVICEの使用例
XMLSERVICEの配管について説明してきましたが、実際にそれを使用している例をご紹介しましょう。私は基本的にはPHPとRPGのプログラマなので、Javaや.NETの例をあえて紹介することはしません。RPGの例を挙げることはできるのですが、RPGではプロシージャを直接呼び出していたのでつまらない例のように思えたのです。ということで、ここではPHPを例として使うことにしました。ここでご紹介するようにPHPからXMLSERVICEを直接呼び出すことはおそらくないでしょう。というのは、Zend社はすでにXMLSERVICEを使用するための強化されたインタフェースを提供しているからです。しかし、PHPからXMLSERVICEを直接呼び出したければそうしていただいても構いません。PHPで記述されたGet_Priceというルーチンを、XMLSERVICEを使用してDB2のストアード・プロシージャ・インタフェースを介してPHPで呼び出すとても簡単な例については、図―6をご覧ください。このPHPスクリプトはdb2_connectを使用して接続を確立することから始まっています。これによりシステムへの接続が確立され、我々のユーザー・プロファイルで我々を識別します。我々のユーザー・プロファイルに対するすべての通常のオブジェクトとデータのセキュリティは通常通りに適用されます。次に、IPCキー、制御パラメータ、XMLドキュメントを定義します。ここではユーザー・プロファイルの名前から取ったIPCキーとしました。/tmp内のIPCディレクトリの名前として好きな値を指定できます。制御パラメータは空っぽです。今回の呼び出しでは特別な処理は必要なかったからです。ジョブを保留してデバッグしたいのであれば、その旨をここで指定します。XML_Inパラメータには図―5に示したXMLドキュメントを指定しました。XML_Out変数はXMLSERVICEからの返答を受け取るためですので、空っぽです。次にdb2_prepareを使用してDB2文を用意しました。iPLUG4Kストアード・プロシージャを選びました。その理由はパラメータが一番少なく、今回の場合要件を満たすには4 KBで十分だからです。次にdb2_bind_Parmを使用して、用意した文内の各パラメータのポジションを変数名に束縛します。最後に、DB2文を実行して戻ってきたXMLドキュメントをブラウザに出力します。通常は戻ってきたXMLドキュメントを構文解析してアプリケーション中で使用するための戻ってきたデータを抽出しますが、今回の例の場合は変数をダンプ出力すれば十分でしょう。
判決
本稿の執筆時点でXMLSERVICEはまだ初期のベータ・ステージにあることを覚えておいてください。本稿をお読みになっている頃までにはXMLSERVICEがリリースされている予定ですが、機能や構文の一部が変更になっているかもしれません。本稿は実際この楽しみな新しいプロジェクトの先行予告のつもりでした。現時点からリリースまでの間で機能に変更があった場合は、その時にSystemiNetwork.comに掲載される本稿のウェブ版で喜んで質問を受けますしここで挙げた例への変更も掲載します。もちろん、常に最新のバージョンのドキュメントを読んで変更点をご自分で見つけ出すこともできます。
本稿のポイントはXMLSERVICEの決定的な「ハウツー」では必ずしもありません。本稿の目的とするところは、この楽しみな新しい開発内容を共有することでIBM iの資源に広くアクセスする方法を変えることです。このプロジェクトは本当に優れたプロジェクトで、世界中でIBM iを運用している部門が外の世界と素早く容易に統合できるようにするものです。XMLSERVICEのリリース後、皆さんの中の多くの人々がこのプロジェクトのオープンソースの開発に参画され、さまざまなプログラミング言語で独自のツールキットを作成されることを望んでいます。IBM i以外のプラットフォームからIBM iへのアクセスを容易にすればするほど、私たちのお気に入りのシステムが繁栄することになるのです。