AS/400展望台

RPGとAjax、ついに統合



アーロン・バーテル著

RPGのグリーン・スクリーンのようなキャラクター・ベースのディスプレイでプログラミングを学ぶことのなかったWebデザイナーにとっては、Ajax (Asynchronous JavaScript and XML)はユーザー・インタフェース開発の天国へ通じる更なる大きな一歩となるでしょう。Ajaxは生産性と使い勝手の向上に満ち溢れた国へ向かうステップなのです。
Ajaxを使用するとHTMLのpage get/putのサイクルから抜け出すことができ、従来のデスクトップ・アプリケーションと同じような応答性と機能を備えたWebアプリケーションを開発することができます。Ajaxのパワーを備えた製品が続々と登場してきているので、このテクノロジーの恩恵を受けるWebサイトの作成者の数が増えていくでしょう。そうした製品の1つがZimbra Collaboration Suite (zimbra.com)です。この製品は、Java互換のクライアントとサーバー・アプリケーションを開発するためAjaxをベースとしたメッセージング・コラボレーション・アプリケーションで、既存のアプリケーションとWebサービスを統合することを特徴としています。

RPGプログラマ仲間の皆さんが街のハンバーガー・ショップで働くようなことにならずに済むようにAjax仲間でいてもらうため、フロント・エンドとしてのAjaxを使用してDB2データベースに対してデータを検証する簡単なPRG CGIプログラムを作成する方法をご紹介します。

Ajaxは既存のJavaScript、カスケード・スタイル・シート(CSS)、HTMLドキュメント・オブジェクト・モデル(DOM)テクノロジーの集合体であり、これらを結合することでHTMLドキュメントがサーバー側資源(たとえばRPG CGIプログラム)への非同期プログラムの呼び出しをブラウザから行い、それに対するサーバーからの応答を使用してユーザーのページの表示を修正することができるようになります。このやり取りによりユーザー・インタフェースがよりスムーズになりしかも応答性がよくなります。Webページ全体を更新するのではなく少しずつ変更していくようなアプリケーションを記述することができるからです。

Ajaxでは、ページの更新中に発生する押し付けがましい空白ページがなくなるだけでなく、サーバーがデータを処理している間もユーザーがページ上でやり取りを継続できます。ブラウザがページのほんの一部しか更新しないので、データ処理量も少なくて済みます。ブラウザが空白ページを表示しようとする瞬間をなくすことで、ユーザーの待ち時間と生産性を向上でき、使い勝手が向上します。

Ajaxでの入力値の検証

Order Entryファイルに正しい項目番号が入力されるようにユーザーからの入力を検証するなどといったことは、グリーン・スクリーンのプログラミング過程において必要なことでした。ユーザーが項目番号XYZを入力してChainが「not found」メッセージを生成した場合は、そのエラー・メッセージをユーザーに対して提示しなければなりません。エラーが発生したときは、フィールド属性は通常インジケータを*ONにし、これによりフィールドの色を変えたり強調表示したりして5250端末画面上で目立つようにします。次に示す例はこれを、Ajaxを使って端末エミュレータではなくブラウザでどのように実現するかを示しています。しかもDDSフィールド定義およびインジケータではなくHTML<input/>フィールドを使用しています。不正な入力があった場合はCSSを使用してフィールドの表示を変更しています。これはHTMLには同様のインジケータもないしDDSフィールド・キーワードもないからです。

検証する必要のある入力フィールド(図2)を含んだWebページ・フォームのHTMLコードを図1に示します。このコードにはform1という名前のフォームがあり、フォーム上にはfld_itmフィールドとfld_anotherfieldフィールドがあります。ここでやりたいことは、ユーザーが不正な項目番号を入力してきたときにfld_itmフィールドの境界色を赤色に変えるということです。色を変更するにはAjaxからiSeriesのRPGプログラムを呼び出して、入力された項目番号が正しいか否かを調べます。ユーザーがフィールドへの入力を終えたときに、HTMLフォームのonblur属性がvldItm()という名前のJavaScriptを起動して値の正当性をチェックします。これは原理的にはコマンド・ラインからRPGプログラムを呼び出してリテラル・パラメータを渡すのとなんら変わりはありません。アポストロフィで囲まれた値(fld_itm)がvldItm()関数に渡され、入力タグのid属性と同じ値になります。fld_anotherfieldという名前のフィールドはユーザーが指名する別のフィールドになります。

フォーム・フィールド・クラス属性が入力に設定され、そのフィールドがinputという名前のCSSを探すように指示し(図3)、自分自身にそのCSSを適用します。RPGサーバー・プログラムがエラーを返してきたときは、vldItm()はJavaScriptを使用してクラス属性の値を動的にinputからinput_errorに変えます。境界線の定義の3番目のパラメータはinputとinput_errorでは異なります。#999999という値は16進で灰色、#FF0033は赤色を示します。

これでHTMLの準備ができたので、各々のAjaxテクノロジーがどのように使用されるのか処理のライフサイクルを通して見てみましょう。

画面の裏側で起こっていること

ユーザーの入力値の検証は、(1) Webページの表示、(2) ユーザー入力の受付、(3) RPGサーバー・プログラムへの要求の送信、(4) サーバーからの応答の受信と処理、という4つのステップで行われます。従来のHTMLフォームの処理とは異なりユーザーが各フィールドに入力するたびに値を検証でき、ユーザーは1つのフィールドの値がサーバーに送られて検証結果を返してくる間に次のフィールドへ値を入力することができます。これがAjaxの非同期性であり、おわかりのとおり、ユーザーとの対話が非常に強力に改善されます。

ステップ1:Webページを表示します。ユーザーはiSeries Webサーバーに対してURL要求を送信することで入力フォームを表示します。ページが読み込まれると、図4に示すようにブラウザはhttpという名前のJavaScript変数のグローバル宣言に出くわします。この宣言文はcrtReqObj()関数を呼び出して、バックエンドのiSeriesをあとで呼び出すときに使用する要求オブジェクトを取得します。要求オブジェクトが変数httpに割り当てられると、ブラウザはHTMLフォームをページ上に表示し、ユーザーが次のフィールドに移動するのを待ちます。

ステップ2:ユーザーの入力を受け付けます。ユーザーがfld_itmフィールドにXYZという不正な項目を入力してそのフィールドから離れると、onblur属性に指定されているvldItm()関数が起動されます。vldItm()関数へのパラメータとして入力フィールドの名前(fld_itm)が渡されます。そしてこの名前が次にiSeriesに渡され、入力された項目が不正な値であった場合、ブラウザに戻されてフィールドを更新するか否かを判断します。ブラウザ内にグローバル変数を設定して現在検証対象となっているフィールドの名前を保持することもできますが、非同期呼び出しの場合には問題を起こす可能性があります。検証要求中にブラウザをロックすることはしないので、ユーザーが次のフィールドに移動して別の検証要求を出すことができるからです。これではブラウザは、検証結果が返ってきたときにどのフィールドが検証対象となっていたのかを知るすべがないのです。RPGプログラムにフィールド名を渡すことで、RPGプログラムはフィールド名とそれに対する適切な応答を返し、その結果を正しいフォーム・フィールドに適用することができるのです。

図5中のvldItm()関数の最初の行で今回の例にDOMを導入しています。DOMはHTMLファイルのメモリー構造を階層的に表現したもの(ツリー構造のようなもの)で、このDOMを呼び出すことでWebページのコンテンツを動的に修正することができます。ここで紹介している例では、DOMを使用してfld_itmフィールドの情報を取得したり設定したりしています。document.get ElementById(fldName)という文は、DOM中のフィールド・オブジェクトのIDを使ってそのオブジェクトを取得しようとしており、すべてのフィールドのさまざまな属性にアクセスができるようにしています。

次の文はhttp.openですが、これはフィールド名とその値をHTTP GET文字列として使用し、iSeriesのRPGプログラムを呼び出すために必要なURLを生成しています。http.openの引数の1番目にはサーバーを呼び出す際に使用するメソッドを指定することができます。今回の例の場合ではURL変数を使用しているためgetを指定していますが、ボディの内容(たとえば大量のデータをXMLなどでラップしたもの)を渡したい場合にはpostを指定することもできます。ここで、サーバーへの要求はXMLを渡すのではないし、サーバーがXMLを返すのでもないという点に注意してください。XMLを使用してデータを送受信することはできますが、例を簡単にするためにこのRPGの例ではそれについては触れません。

次の行(http.onreadystatechange = vldItm Response)はサーバーからの応答を処理するためのJavaScriptのコールバック関数を設定しています。JavaScript中にこの関数名を使用してアドレスを表現することで、RPGの組み込み関数%PADDR() (Get Procedure Address)を使用するのと同様に、サブ・プロシージャのアドレスを取得することができます。RPGサーバーが起動された後にブラウザがサーバーからの応答を待たずにもう一度ユーザーにフォーム・データを入力させるので、このコールバック関数が必要となります。ブラウザは応答が返ってくるとvldItmRepsonse()関数を起動して処理します。

これでhttpオブジェクトがオープンされて初期化され、http.send(null)文により送信が行われます。必要に応じて、送信するデータを要求のボディ中にnullを渡す代わりに指定します。

ステップ3:RPGサーバー・プログラムに要求を送信します。この時点で、RPGプログラムVLDITMがCGI URLによりiSeriesのWebサーバー上ですでに起動されています。図6にRPGプログラムがURLからの値(itmとfldName)を読み込み、その値を使ってブラウザにどんな値を返すのかを判断している様子を示します。外部ファイルと連携する代わりに、今回の例ではHATという有効な項目が1つだけあります。この項目に対して他の値が指定された場合はブラウザにnot foundという値を返します。今回の例でブラウザが処理するために返す2つの具体的な文字列値はfld_itm|FOUNDとfld_itm|NOT_FOUNDです(間にある縦棒はデータ・デリミタと呼びますが、どんなデリミタでも使用できます)。この値をブラウザが使用できるような有効な値とするためには、Content-typeの後に改行を2つとoutXml変数のコンテンツを指定しなければなりません。サブ・プロシージャtoBrowserを呼び出して結果をブラウザにプッシュします。RPGプログラムは最後に*INLRを*ONにして終了し、クライアントのブラウザが応答を待ちます。

VLDITMというRPGプログラムの動作をブラウザで簡単に確認するには、JavaScriptが結合しているのとまったく同じURLを作成します。次のURLを使用してVLDITMというRPGプログラムをテストすることができます。

http://www.myserver.com/cgi-bin/vlditm
http://www.myserver.com/cgi-bin/vlditm?itm=HAT&fldName=fld_itm http://www.myserver.com/cgi-bin/vlditm?itm=COAT&fldName=fld_itm

getUrlVarとtoBrowserはローカルに定義されたサブ・プロシージャで、このRPG Ajaxの例を実行させるのに必要な他のファイルとともにiSeriesNetwork.com/codeのコード中に含まれているものです。

ステップ4:サーバーからの応答を処理します。ブラウザはサーバーからの応答を受け取るとvldItmResponse()コールバック関数を起動します(図7)。この関数はhttp.readyStateとhttp.statusをチェックします。A 4 = Complete readyStateという値はJavaScriptの非同期処理が完了していることを示しています。readyStateがとりうる全ての値の一覧を図8に示しますが、ほとんどのAjaxコードでは4 readyState値だけを監視していれば十分です。A 200というステータスは、トランザクションが正常に終了したとiSeriesのApacheサーバーがみなしたという意味になります。実際のアプリケーションではこのステータスが200でない場合はユーザーにメッセージを表示しますが、今回紹介している例では省略しています。図7の次の行では応答変数を宣言し、http.responseTextにアクセスしてサーバーからの結果をこの変数に格納しています。

縦棒のデリミタ行はサーバーからの応答を配列中の2つの要素に分けてアクセスしやすくしています。1番目の要素はcmp[0]というフィールド名で、今回の例ではfld_itmに相当します。2番目の要素はcmp[1]で、FOUNDまたはNOT_FOUNDのいずれかの値を保持しています。document.getElementById文はfld_itmという<input/>フィールドを取り出し、JavaScriptの変数fldに保存します。このクラスはcmp[1]の値に応じてinputまたはinput_errorのいずれかに設定されます。

ユーザーが不正な項目番号を入力したらどうなるかを図9に示します。入力フィールドの属性だけが変化し、ページ全体が再表示されるわけではないという点に着目してください。必要に応じてフィールドのそばに説明用のテキスト・メッセージを簡単に付け加えることもできます。

たったこれだけです。ユーザーからの入力は、[送信]ボタンを押さなくてもiSeriesが正しく検証します。今回紹介した例はAjaxを使ってユーザーの入力を検証する方法の極めて簡単な例ですが、任意の数の入力フィールド値の検証に拡張することができます。Ajaxには、データ交換にテキスト文字列の代わりにXMLを使用するなどといった多数の利用法があります。

簡単なRPG CGIアプリケーションでも格好良くて新しいWeb機能の土俵で成功することができるということをおわかりいただけたら、Ajaxのもっと高度なテクニックについても勉強してみてください。つまるところ、最終的には昔ながらのテキスト操作と良いWebサーバーが肝になるのですが、ApacheとRPGを組み合わせればこれらが両方手に入るのです。

アーロン・バーテル氏はミネソタ州マンカト市にあるクレンゲル・テクノロジー社のJavaおよびRPGプログラマです。専門分野はWebサービスおよびWebページ・プログラミングです。





↑このページのトップへ
TOPPAGE

BELLDATA, Inc. Copyright reserved.