HTTPサーバーとWeb開発

75. RPG# 入門bS

続いて RPG# によるレコードの更新のサンプルについて紹介する。
Web化ツールでは照会系のみに限定されていると思う人もかつてはあったが
更新系であっても何ら問題はない。

eStudio によって生成された DFU タイプのような「単票更新」を例に挙げて
説明する。
まず実行の様子を下記に紹介する。

下記が生成された RPG# ソースである。

-------------------------------------------------------------------------------------
0001.00 H NOMAIN BNDDIR('ASNET.COM/MAIN') DATEDIT(*YMD/)                             
0002.00 F**********  商品マスターファイル         *****************************      
0003.00 F*  WEB004      : TYPE: 単票更新    言語 : RPG#   VER 5.1                    
0004.00 F**********************************************************************      
0005.00 FWEB004H   CF   E             SPECIAL PGMNAME('ASNET.COM/HTMLDVR')           
0006.00 F                                     PLIST(HPARM)                           
0007.00 F                                     INFDS(INFDSF)                          
0008.00 FSHOHIN    UF A E           K DISK    EXTFILE(SHOHIN_LIB)                    
0009.00 F**********************************************************************      
0010.00                                                                              
0011.00  /COPY ASNET.USR/QRPGLESRC,PROTOTYP5#                                        
0012.00 D DSPHEAD_GO      PR                                                         
0013.00 D DSPDTA01_UPD    PR                                                         
0014.00 D DSPDTA01_DLT    PR                                                         
0015.00 D ERRMSG          PR                                                         
0016.00 D  MSG                            *   VALUE                                  
0017.00 D REVIMG          PR                                                         
0018.00 D  FIELD                          *   VALUE                                  
0019.00 D SET_CURSOR      PR                                                         
0020.00 D  FIELD                          *   VALUE                                  
0021.00 D HTM_FILE        S             10A   INZ('WEB004H   ')                      
0022.00 D HTM_LIB         S             10A   INZ('*LIBL     ')                      
0023.00 D SHOHIN_LIB      S             21    INZ('QTRFIL/SHOHIN')                   
0024.00 D HTM_DIR         S            128A   INZ('/AS400-NET.USR/PROJECT/-       
0025.00 D                                     WEB004')                            
0026.00 D NOTFOUND        C                   CONST(' レコードが見つからない。 ') 
0027.00 D MSG1            S            128A   INZ(' 入力値の誤りです。 ')         
0028.00                                                                           
0029.00 D*( ファイル情報データ構造 )                                              
0030.00 D INFDSF          DS                                                      
0031.00 D                              512A                                       
0032.00 D  HTM_RECORD       *RECORD                                               
0033.00 D*( プログラム状況データ構造 )                                            
0034.00 D INFDSP         SDS                                                      
0035.00 D                              512A                                       
0036.00 D  JOB                  244    253                                        
0037.00  /COPY ASNET.USR/QRPGLESRC,HPARM                                          
0038.00                                                                           
0039.00 C*-------------------------------------------------------                 
0040.00 C     TRNKEY        KLIST                                                 
0041.00 C                   KFLD                    SHCODE                        
0042.00 C*-------------------------------------------------------                 
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('DSPDTA01': 'UPDATE': %PADDR(DSPDTA01_UPD));                 
0050.00     ON_CLICK('DSPDTA01': 'DELETE': %PADDR(DSPDTA01_DLT));                 
0051.00  /END-FREE                                                                
0052.00 P                 E                                                       
0053.00 *********************************************************                 
0054.00 P BEGIN           B                   EXPORT                              
0055.00 *********************************************************                 
0056.00  * 最初の画面を出力します。                                               
0057.00 D                 PI                                                      
0058.00 C                   WRITE     DSPHEAD                                     
0059.00 P                 E                                                       
0060.00                                                                           
0061.00 *********************************************************                 
0062.00 P DSPHEAD_GO      B                   EXPORT                              
0063.00 *********************************************************                 
0064.00  * GO ボタンが押されたときの記述を行います。                              
0065.00 D                 PI                                                      
0066.00 C                   READ      DSPHEAD                              99     
0067.00 C     *NOKEY        CLEAR                   SHOHINR                       
0068.00 C                   SETOFF                                       90       
0069.00 C     TRNKEY        CHAIN(N)  SHOHIN                             90       
0070.00 C                   WRITE     DSPDTA01                                    
0071.00 P                 E                                                       
0072.00                                                                       
0073.00 *********************************************************             
0074.00 P DSPDTA01_UPD    B                   EXPORT                          
0075.00 *********************************************************             
0076.00  *  更新ボタンが押されたときの記述を行います。                        
0077.00 D                 PI                                                  
0078.00 C                   READ      DSPDTA01                             99 
0079.00 C                   MOVE      *ZEROS        ADDRCD                    
0080.00 C                   MOVE      *ZEROS        CHGRCD                    
0081.00 C                   MOVE      *ZEROS        DLTRCD                    
0082.00 C                   SETOFF                                       90   
0083.00 C     TRNKEY        CHAIN     SHOHIN                             90   
0084.00 C  N90              READ      DSPDTA01                             99 
0085.00 C*                                                                    
0086.00 C   90              ADD       1             ADDRCD                    
0087.00 C  N90              ADD       1             CHGRCD                    
0088.00 C*-----------------------------------------------------               
0089.00 C   90              WRITE     SHOHINR                                 
0090.00 C  N90              UPDATE    SHOHINR                                 
0091.00 C*-----------------------------------------------------               
0092.00 C                   WRITE     UPDEND                                  
0093.00 P                 E                                                   
0094.00                                                                       
0095.00 *********************************************************             
0096.00 P DSPDTA01_DLT    B                   EXPORT                              
0097.00 *********************************************************                 
0098.00  *  削除ボタンが押されたときの記述を行います。                            
0099.00 D                 PI                                                      
0100.00 C                   READ      DSPDTA01                             99     
0101.00 C                   MOVE      *ZEROS        ADDRCD                        
0102.00 C                   MOVE      *ZEROS        CHGRCD                        
0103.00 C                   MOVE      *ZEROS        DLTRCD                        
0104.00 C                   SETOFF                                       90       
0105.00 C     TRNKEY        CHAIN     SHOHIN                             90       
0106.00 C  N90              ADD       1             DLTRCD                        
0107.00 C*-----------------------------------------------------                   
0108.00 C  N90              DELETE    SHOHINR                                     
0109.00 C*-----------------------------------------------------                   
0110.00 C                   WRITE     UPDEND                                      
0111.00 P                 E                                                       
0112.00                                                                           
0113.00 *********************************************************                 
0114.00 P END             B                   EXPORT                              
0115.00 *********************************************************                 
0116.00  * 最後の処理を記述します。                                               
0117.00 D                 PI                                                      
0118.00 C                   CLOSE     WEB004H                                     
0119.00 C                   CLOSE     SHOHIN                                      
0120.00 P                 E 
-------------------------------------------------------------------------------------

更新系は照会系とちがって考慮すべき点が2つある。

【 入力妥当性検査 】

5250 エミュレータの場合は エミュレータ自身が行っていた入力妥当性検査を
ブラウザ上で再現する必要がある。
例えばブラウザでは数字フィールドや漢字フィールドという文字の指定はできないので
すべてのタイプの文字が入力されてしまう。
また漢字の場合、ブラウザ上ではシフト文字は必要ないが、ご存知のように
System i ではシフト文字の文の考慮が必要となり、シフト文字の分も入れて
初めて文字数の検査が必要となってくる。
これらを開発者が毎度、工夫して JavaScript を開発して用意するのは
大変な労力とテクニックを必要とする。

RPG# の場合はユーザーでこれらの妥当性検査を行う必要はない。
alt="7S0" のように文字属性が定義されていたのを思い出して欲しい。
この alt に定義された属性に対して自動的に妥当性検査を行う JavaScript が
始めから組み込まれているのである。

例えば、商品単価 : SHTANK の入力記述は、

<input type="text" name=SHTANK id="SHTANK" value="##########"
    onChange="chkInputValidity(this);" onKeyDown="FIELD_EXIT(this);"
    maxlength="10" size="12" alt="7S0" EDTCDE(J) DDS="CHECK(RB)">

のように定義されている。ずいぶん長い定義と思われるかも知れないが
この定義は Wizard によって自動生成されるのでユーザーが記述する必要はない。

onChange="chkInputValidity(this);

という指定によって新規入力や変更があったときには JavaScript関数 : chkInputValidity
呼び出されて alt に従った妥当性検査が行われる。

JavaScript関数 : chkInputValidity

<script type="text/javascript" src="/AS400-NET.USR/JS/RPG_SP_CLCHK.JS"></script>

によって RPG_SP_CLCHK.JS という JavaScript ライブラリー内に定義されている。
もちろん この記述も Wizard によって自動的に組み込まれるのでユーザーが記述する必要はない。
このように Wizard 生成を使えば 入力妥当性検査も RPG# に任せることができるのである。

【 レコード・ロック 】

次の商品マスター・レコードを検索するプロシージャーを見て欲しい。

0061.00 *********************************************************                 
0062.00 P DSPHEAD_GO      B                   EXPORT                              
0063.00 *********************************************************                 
0064.00  * GO ボタンが押されたときの記述を行います。                              
0065.00 D                 PI                                                      
0066.00 C                   READ      DSPHEAD                              99     
0067.00 C     *NOKEY        CLEAR                   SHOHINR                       
0068.00 C                   SETOFF                                       90       
0069.00 C     TRNKEY        CHAIN(N)  SHOHIN                             90       
0070.00 C                   WRITE     DSPDTA01                                    
0071.00 P                 E  
0069.00 C     TRNKEY        CHAIN(N)  SHOHIN                             90 

である。 CHAIN(N) の (N) によって、CHIAN 命令によってレコードを検索できたときにも
(N) によって直ちにレコードを解放しており、レコード・ロックは行わない。
CHAIN 後にずくにでも他のユーザーがこの同じレコードを獲得することが可能なように
考慮されているのである。
ところが実際には在庫レコードや引き当て数を他のユーザーからは保護したい場合もある。
自分が引き当てた数量は他のユーザーからの更新を禁じることによって
更新か解放が行われるまではレコード・ロックをする必要がある。
このような意図的なレコード・ロックは設計上、行うことは珍しくはない。
ところが Web適用業務は、CGI は実行して HTML を出力してしまうと直ちに終了していまうのが
普通である。
CGI が終了してしまうので、当然、レコード・ロックははずれてしまい、次に引き当て数を
更新しようとすると、ホンのわずかなタイミングで他のユーザーに先を越されて更新されて
しまう可能性がある。
やはり CGI が終了したとしても、更新用のレコードをロックしておく機能は必要なのである。

RPG# は自動的にレコード・ロック機能を持っている。

この問題は RPG# では解決済みであり、CGI が意図的にレコードをロックしたままで終了したとしても
終了直後にはロックされているレコードが検索されて、自動的にレコード・ロックは保持される。
次にレコードを使用することができるのは同じジョブの再開によるレコード更新か、または
CRTPF で指定したはずの「最大レコード待機時間」(WAITRCD) であり、一般的には 60秒、
つまり一分である。
一分経過後にレコードの使用がなければロックしたレコードは自動的に解放される。
このように RPG# では 5250エミュレータのときと同じようにレコード・ロック機能が
保証されているのである。