それでは実際の RPG#の全容 をご紹介しましよう。
この例は Web では最もポピュラーな一覧表形式の照会画面ですが、RPG# ならではの高度な機能を見ることができます。
eSudio で サンプル・ライブラリー:QTRFIL の商品マスター(SHOHIN
) の「レポート照会」を選択すると次のような
Web適用業務を、わずか数分のあいだに Wizard生成することができます。
上図の動作はこれはごく当たり前のように思えますが、CGI は、いったん HTML を出力してしまえば
HTML の出力と同時に終了してしまいます。
CGI がステートレスであり、明細行のすべては出力情報であるので、[次へボタン] を押しても入力値として
明細行の値は次回の CGI には伝えられることはありません。
しかし RPG# であれば、あたかもステートフルであるかのように動作することができます。
上記の動作を実現している RPG#のソース・コード の全容を以下に紹介します。
0001.00 H NOMAIN BNDDIR('ASNET.COM/MAIN') DATEDIT(*YMD/) 0002.00 H THREAD(*CONCURRENT) 0003.00 F********** 商品マスターファイル ***************************** 0004.00 F* PGM001 : TYPE: レポート照会 言語 : RPG# VER 5.1 0005.00 F********************************************************************** 0006.00 FPGM001H CF E SPECIAL PGMNAME('ASNET.COM/HTMLDVR') 0007.00 F PLIST(HPARM) 0008.00 F INFDS(INFDSF) 0009.00 FSHOHIN IF E K DISK EXTFILE(SHOHIN_LIB) 0010.00 F********************************************************************** 0011.00 F* 0012.00 F* CRTWEBMOD QTEMP/PROJECT1 SRCFILE(ASNET.USR/QRPGLESRC) AUT(*ALL) 0013.00 F* CRTPGM CGIBIN/PROJECT1 MODULE(ASNET.COM/MAIN QTEMP/PROJECT1) 0014.00 F* ACTGRP(*NEW) AUT(*ALL) 0015.00 F* 0016.00 /COPY ASNET.USR/QRPGLESRC,PROTOTYP5# 0017.00 D DSPHEAD_GO PR 0018.00 D SFLCTL01_NXT PR 0019.00 D READF PR 0020.00 D HTM_FILE S 10A INZ('PROJECT1H ') 0021.00 D HTM_LIB S 10A INZ('*LIBL ') 0022.00 D SHOHIN_LIB S 21 INZ('QTRFIL/SHOHIN') 0023.00 D HTM_DIR S 128A INZ('/AS400-NET.USR/PROJECT/- 0024.00 D PROJECT1') 0025.00 D NOTFOUND C CONST(' レコードが見つからない。 0026.00 D MAXGYO S 4 0 INZ(15) 0027.00 D SAVKEY DS LIKEREC(SHOHINR :*KEY) 0028.00 0029.00 D*( ファイル情報データ構造 ) 0030.00 D INFDSF DS 0031.00 D HTM_RECORD *RECORD 0032.00 D FILREC 156 159B 0 0033.00 D SFLRRN 376 377B 0 0034.00 D TOPRRN 378 379B 0 0035.00 D*( プログラム状況データ構造 ) 0036.00 D INFDSP SDS 0037.00 /COPY ASNET.USR/QRPGLESRC,HPARM 0038.00 C*------------------------------------------------------- 0039.00 C SETKEY KLIST 0040.00 C KFLD SHCODE 0041.00 C*------------------------------------------------------- 0042.00 0043.00 ********************************************************* 0044.00 P EVENT B EXPORT 0045.00 ********************************************************* 0046.00 D PI 0047.00 /FREE 0048.00 ON_CLICK('DSPHEAD': 'GO': %PADDR(DSPHEAD_GO)); 0049.00 ON_CLICK('SFLCTL01': 'NXT': %PADDR(SFLCTL01_NXT)); 0050.00 /END-FREE 0051.00 P E 0052.00 ********************************************************* 0053.00 P BEGIN B EXPORT 0054.00 ********************************************************* 0055.00 * 最初の画面を出力します。 0056.00 D PI 0057.00 C WRITE DSPHEAD 0058.00 P E 0059.00 0060.00 ********************************************************* 0061.00 P DSPHEAD_GO B EXPORT 0062.00 ********************************************************* 0063.00 * GO ボタンが押されたときの記述を行います。 0064.00 D PI 0065.00 C READ DSPHEAD 99 0066.00 C SETKEY SETLL SHOHIN 0067.00 C Z-ADD 1 TOPRRN 0068.00 C CALLP READF 0069.00 P E 0070.00 0071.00 ********************************************************* 0072.00 P SFLCTL01_NXT B EXPORT 0073.00 ********************************************************* 0074.00 * 次へ ボタンが押されたときの記述を行います。 0075.00 D PI 0076.00 C READ SFLCTL01 99 0077.00 C Z-ADD FILREC SFLRRN 0078.00 C READ SFREC01 50 0079.00 C SETKEY SETGT SHOHIN 0080.00 C GYONO ADD 1 TOPRRN 0081.00 C CALLP READF 0082.00 P E 0083.00 0084.00 ********************************************************* 0085.00 P READF B EXPORT 0086.00 ********************************************************* 0087.00 D PI 0088.00 C EVAL SAVKEY.SHCODE = SHCODE 0089.00 C 1 DO MAXGYO SFLRRN 0090.00 C SETOFF 50 0091.00 C READ SHOHIN 50 0092.00 C 50 CALLP SETEOF 0093.00 C 50 LEAVE 0094.00 C WRITE SFREC01 99 0095.00 C END 0096.00 C EVAL SHCODE = SAVKEY.SHCODE 0097.00 C WRITE SFLCTL01 0098.00 P E 0099.00 0100.00 ********************************************************* 0101.00 P END B EXPORT 0102.00 ********************************************************* 0103.00 * 最後の処理を記述します。 0104.00 D PI 0105.00 C CLOSE PGM001H 0106.00 C CLOSE SHOHIN 0107.00 P E
これは、わずか 107ステップという eStudio によって Wizard 生成された、小さな CGI であり、人手による修正は全く加えていません。
どのようにご覧になっても、これが CGIプログラムであるとは見えないはずです。
しかも、このわずかな小さいプログラムには考え抜かれた最新の高度なテクニックが要所に秘められています。
RPG# はプロシージャーによって構造化されたソースとして形成されており、ビジネス・ロジックはプロシージャーの中だけで完結しており、
将来のオブジェクトの再利用にも耐えられるようにオブジェクト指向として設計されています。
[次へボタン] の処理 (SFLCTL01_NXT
) でも特段の複雑な処理は一切ありません。
0001.00 H NOMAIN BNDDIR('ASNET.COM/MAIN') DATEDIT(*YMD/)
で、おわかりのように、このRPGには メイン・ルーチンがない ことを宣言しています。
メイン・ルーチンとも言えるかも知れないのは、次の小さなイベント処理の定義だけです。
0043.00 ********************************************************* 0044.00 P EVENT B EXPORT 0045.00 ********************************************************* 0046.00 D PI 0047.00 /FREE 0048.00 ON_CLICK('DSPHEAD': 'GO': %PADDR(DSPHEAD_GO)); 0049.00 ON_CLICK('SFLCTL01': 'NXT': %PADDR(SFLCTL01_NXT)); 0050.00 /END-FREE 0051.00 P E
次の記述によって HTMLが保管されているディレクトリーを宣言しています。
0023.00 D HTM_DIR S 128A INZ('/AS400-NET.USR/PROJECT/- 0024.00 D PROJECT1')
次の READF
という名前のプロシージャーでは商品マスター(SHOHIN
) を読み取ってSFREC01
という名前の「レポート文」と呼ばれる
HTMLタグの明細行に連続して出力しているだけです。
この「レポート文」については後でも説明しますがSFLレコードと考え方は同じです。
特定の行だけの「レポート文」を読み取ったり更新することもできます。
0084.00 ********************************************************* 0085.00 P READF B EXPORT 0086.00 ********************************************************* 0087.00 D PI 0088.00 C EVAL SAVKEY.SHCODE = SHCODE 0089.00 C 1 DO MAXGYO SFLRRN 0090.00 C SETOFF 50 0091.00 C READ SHOHIN 50 0092.00 C 50 CALLP SETEOF 0093.00 C 50 LEAVE 0094.00 C WRITE SFREC01 99 0095.00 C END 0096.00 C EVAL SHCODE = SAVKEY.SHCODE 0097.00 C WRITE SFLCTL01 0098.00 P E
レポート文とは RPG# で HTML上に定義される <REPORT> 〜 </REPORT>
から成る次のような独自タグです。
<REPORT NAME=SFREC01><tr class="LST_REP"> <td nowrap class="GYOCELL"><FLD NAME=GYONO.0000 alt="4S0" EDTCDE(3)>####</FLD></td> <FLDFROM> <td nowrap><FLD NAME=SHCODE.0000 alt="10A">##########</FLD></td> <td nowrap><FLD NAME=SHNAME.0000 alt="24O">########################</FLD></td> <td nowrap align="right"><FLD NAME=SHTANK.0000 alt="7S0" EDTCDE(J)>##########</FLD></td> <td nowrap><FLD NAME=SHSCOD.0000 alt="4A">####</FLD></td><FLDEND> </tr></REPORT>
このレポート文には <REPORT NAMR=SFREC01>
で示されるように SFREC01
とういう名前が定義されています。
RPG命令では、
0094.00 C WRITE SFREC01 99
として実行すると、
0033.00 D SFLRRN 376 377B 0
で定義されているレポ−ト文の 行SFLRRN
に従って <REPORT NAME=SFREC01>〜</REPORT>
までの
HTMLタグが追加されます。
これでおわかりのように SFLRRN をうまく制御すれば、SFLRRN に行 をセットして READ
命令を実行すれば、
特定の行だけを読み取ることもできますし、特定の行の更新も行うことができます。
つまりこれは私達の馴染んできた、サブ・ファイルと同じ動作原理なのです。
ひとつの HTML で複数個のレポート文を定義することもできます。
ここではレポート照会というシンプルな例を紹介しましたが、eStudio によって Wizard生成される各RPG# は、
単純なサンプルというものではなく、入力フィールドの妥当性検査を始めとした実際の実用に耐えうる高度な
機能を初めから搭載しています。
データ・ベースを更新する業務を開発するときに、Web であっても、どうしても必要となるのが更新レコードの レコード・ロックによる排他処理 です。
引き当て可能在庫を調べて、使用可能数が十分であるので在庫レコードを更新しようと
するときに従来の 5250エミュレーターではセッションが継続していますので、
あるユーザーが更新処理を行っているときは、その在庫レコードは他のユーザーからは
保護されています。
しかし同じことを Web適用業務として行おうとすると、CGI は、本来、ステートレス
ですから HTML を出力すると同時に直ちに CGI は終了してしまって、更新しようとする
在庫レコードも解放されてしまいます。
次にそのユーザーが更新しようとする直前に、他のユーザーから先に更新されてしまうかも知れません。
ステートレスな CGI がレコード・ロックによる排他処理ができないというこの問題は、Web適用業務を構築する上で
永年の課題となっていました。
しかし RPG# であれば、この問題も System i の機能を使って、スマートに解決されています。
RPG# の CGI が更新用としてレコードをアクセスして終了したとしても、RPG# の終了後もレコード・ロックだけは維持されて残ります。
しかもユーザーがブラウザを閉じてしまってもファイルで最初に定義されている、最大待機レコード待機時間(WAITRCD
) パラメータで
指定されている時間を経過すると、レコードは解放されます。
ロックされているレコードを再使用できるのは、そのレコードをロックした元のセッションだけです。
複数の更新ファイルを使用している場合でも、それらはすべてレコード・ロックされます。
大規模システムとなると複数の画面遷移が発生し、次に表示される画面の処理でも
以前に使用した ステート情報(フィールド値等) が処理上、必要となる場合が
あります。
DSPF処理では EXFMT で待機しているため、フィールド情報等のすべての
ステート情報も維持されていますが、ステートレスな本来の CGI では、HTML出力と
同時に CGI は終了してしまいますので、フィールド値等のステート情報は、
次に続く画面の処理では失われてしまいます。
このため従来の Webソリューションでは、何らかの セッション管理の手法 を設けていることがありました。
しかし大規模アクセス集中システムにおいては、ユーザーがブラウザの ボタン を押したり、他のサイトに移ったりすると、
大量のセッション・ファイルのゴミがサーバー(System i) に残ってしまいます。
もとより RPG# では、ユーザーの操作が主体であり、大規模システムに備えたステートレスな CGI を基本としています。
そこで最も簡単に、このことを解決するのは前の画面の入力で受け取ったフィールド値を HIDDEN
(非表示) として
HTML内部に忍ばせておくことです。
しかし開発者が大量の HIDDEN フィールドを HTMLに手動で埋め込むのも大変な労力を必要としますので RPG# では
<HIDDEN> </HIDDEN>
という一組のタグを HTML に埋め込んでおくだけで自動的に入力フィールドのすべてが埋め込まれるような機能が提供されています。
もちろん特定のフィールドだけを明示的に埋め込むようにすることもできます。
大量のセッション管理によってパフォーマンスの低下や大量のゴミを発生させたり、動作の安定が図られないよりは、
何よりシンプルで確実に動作する体系であるべきとの考えからです。
RPG#、いかがでしたか ?
永年の RPG開発経験をお持ちの人には、メイン・ルーチンがないというと漠然な
不安感があるかも知れませんが、VisialBASIC等の開発経験のある人には、
RPG# は、これこそ次世代のオープン言語であるという実感を持って頂いた
はずです。
今や開発手法の焦点は方法論ではなく構造化にあります。
10年先を見据えて考えると構造化された言語体系は拡張性とスケーラビリティに富んで保守性に優れた
ソフトウェア体系とならねばなりません。
RPG# は、今、その最先端にあります。しかもやさしくて開発工数も圧倒的に少なくて済みます。
さらには快適なパフォーマンスを得ることができます。
RPG# は次世代に続くWeb開発言語として御社のWeb開発の大いなる支援となることを願っています。