RPG#の実際

RPG#の全容

それでは実際の RPG#の全容 をご紹介しましよう。
この例は Web では最もポピュラーな一覧表形式の照会画面ですが、RPG# ならではの高度な機能を見ることができます。

eSudioサンプル・ライブラリー:QTRFIL の商品マスター(SHOHIN) の「レポート照会」を選択すると次のような
Web適用業務を、わずか数分のあいだに Wizard生成することができます。

Wizard生成された適用業務

1.初期画面 2.[GO]ボタン押下後のレポート表示 3.[次へ]ボタン押下後のレポート表示

上図の動作はこれはごく当たり前のように思えますが、CGI は、いったん HTML を出力してしまえば
HTML の出力と同時に終了してしまいます。

CGI がステートレスであり、明細行のすべては出力情報であるので、[次へボタン] を押しても入力値として
明細行の値は次回の CGI には伝えられることはありません。
しかし RPG# であれば、あたかもステートフルであるかのように動作することができます。

RPG# ソース・コードの全容

上記の動作を実現している 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) パラメータで
指定されている時間を経過すると、レコードは解放されます。
ロックされているレコードを再使用できるのは、そのレコードをロックした元のセッションだけです。
複数の更新ファイルを使用している場合でも、それらはすべてレコード・ロックされます。

イベント駆動型 RPG# のまとめ

  • RPG# が終了しても更新レコードのレコード・ロックは維持される。
  • ロックされたレコードを再使用できるのは元のセッションに限る。
  • 最大待機レコード待機時間(WAITRCD) が過ぎればレコードは解放される。
  • 複数のレコード・ロックも可能である。

セッション管理は必要か ?

入力内容更新画面

大規模システムとなると複数の画面遷移が発生し、次に表示される画面の処理でも
以前に使用した ステート情報(フィールド値等) が処理上、必要となる場合が
あります。

DSPF処理では EXFMT で待機しているため、フィールド情報等のすべての
ステート情報も維持されていますが、ステートレスな本来の CGI では、HTML出力と
同時に CGI は終了してしまいますので、フィールド値等のステート情報は、
次に続く画面の処理では失われてしまいます。

このため従来の Webソリューションでは、何らかの セッション管理の手法 を設けていることがありました。
しかし大規模アクセス集中システムにおいては、ユーザーがブラウザの ×ボタンボタン を押したり、他のサイトに移ったりすると、
大量のセッション・ファイルのゴミがサーバー(System i) に残ってしまいます。

もとより RPG# では、ユーザーの操作が主体であり、大規模システムに備えたステートレスな CGI を基本としています。
そこで最も簡単に、このことを解決するのは前の画面の入力で受け取ったフィールド値を HIDDEN (非表示) として
HTML内部に忍ばせておくことです。

しかし開発者が大量の HIDDEN フィールドを HTMLに手動で埋め込むのも大変な労力を必要としますので RPG# では

<HIDDEN>
</HIDDEN>

という一組のタグを HTML に埋め込んでおくだけで自動的に入力フィールドのすべてが埋め込まれるような機能が提供されています。
もちろん特定のフィールドだけを明示的に埋め込むようにすることもできます。

大量のセッション管理によってパフォーマンスの低下や大量のゴミを発生させたり、動作の安定が図られないよりは、
何よりシンプル確実に動作する体系であるべきとの考えからです。

<HIDDEN>タグでのステート情報管理のイメージ

入力画面1 入力画面2 入力内容更新画面

RPG# のまとめ

RPG#、いかがでしたか ?

永年の RPG開発経験をお持ちの人には、メイン・ルーチンがないというと漠然な
不安感があるかも知れませんが、VisialBASIC等の開発経験のある人には、
RPG# は、これこそ次世代のオープン言語であるという実感を持って頂いた
はずです。

今や開発手法の焦点は方法論ではなく構造化にあります。
10年先を見据えて考えると構造化された言語体系は拡張性とスケーラビリティに富んで保守性に優れた
ソフトウェア体系とならねばなりません。
RPG# は、今、その最先端にあります。しかもやさしくて開発工数も圧倒的に少なくて済みます。
さらには快適なパフォーマンスを得ることができます。

RPG# は次世代に続くWeb開発言語として御社のWeb開発の大いなる支援となることを願っています。

RPG#のとは?