19.12 クライアントとサーバー間でのデータのやり取り

多くの場合、情報は JSON 形式によりサーバーとクライアントの間で双方向にやり取りされます。SRVRPUTINE は JSON データを以下の形式で送受信します。

JSON フォーマットの例外としては、サーバー・ルーチンが応答オブジェクトを返す時です。これは、ファイルの詳細を戻すために使用されます。

以下に例が挙げられています。

フィールドまたはフィールドのグループを引き渡す

データ・リストの引き渡し

応答オブジェクトを戻す

フィールドまたはフィールドのグループを引き渡す

クライアントとサーバー間でデータのやり取りをする最も簡単な方法は、どちらの方向であったとしても、個別のフィールドまたはフィールドのグループを SRVROUTINE にマップすることです。値は、その位置または任意の PARAMETER_NAME の値をもとに、SRVROUTINE とやり取りされます。

GROUP_MAP を使用する際は、クライアントとサーバー間で関連するグループ定義が検証されないことに注意することが大切です。グループ内のフィールドは名前をもとにマップされています。必要に応じて想定のデータが確実に送受信されるよう、含まれるフィールドに関しては、グループ定義と一致するか検証することを忘れないようにしてください。

例えば、次のコードは PSLMST ファイルのレコードを更新しようとすると、エラーになります。これは、何故でしょうか。クライアントの GROUP_BY では、EMPNO、SURNAME、GIVENAME のみがサーバーに渡されます。ですから、これに対応するサーバー・モジュールの GROUP_BY に指定されているその他のフィールドには値がないことになります。UPDATE で更新しようとすると、妥当性検査ルールでエラーとなります。

クライアントとサーバーの処理で使用される GROUP_BY 定義に同じフィールドが含まれることを確実にするだけで、この問題は解決できます。これは処理するトランザクションによりますが、ファイルのフィールドすべての場合もあるでしょうし、フファイルのフィールドのサブセットの場合もあるでしょう。

クライアントの Web ページまたは再利用可能パーツのコードは次のようになります。

Group_By Name(#MyEmployee) Fields(#Empno #Surname #Givename)

 

Mthroutine Name(UpdateEmployee)

 

* サーバーのデータ更新に使用するサーバー・モジュールの定義

Define_Com Class(#MyServerModule.UpdateEmployee) Name(#UpdateEmp)

 

* データを非同期に更新

#UpdateEmp.ExecuteAsync Status(#io$sts) Employeedetails(#MyEmployee)

 

Evtroutine Handling(#UpdateEmp.Completed)

* 完了後の処理

Endroutine

 

Evtroutine Handling(#UpdateEmp.Failed) Handled(#handled)

* エラー処理

Endroutine

Endroutine

 

サーバー・モジュールのこれに対応するコードは以下のようになります。

Group_By Name(#Employee) Fields(#Empno #Surname #Givename #Address1 #Address2 #Address3 #Postcode #Phonehme #Phonebus #Deptment #Section #Salary #Startdte #Termdate) 

* 次のグループ定義を使って Web ページより送信された詳細と一致させる

* Group_By Name(#Employee) Fields(#Empno #Surname #Givename)


SrvRoutine Name(UpdateEmployee)

Group_Map For(*input) Group(#Employee) Parameter_Name(EmployeeDetails)

Field_Map For(*output) Field(#io$sts) Parameter_Name(Status)

 

Update Fields(#Employee) In_File(pslmst) With_Key(#Empno)

 

Endroutine 

データ・リストの引き渡し

GROUP_MAP には、各フィールドの 1 つのインスタンスのみが含まれており、LIST_MAP を使用できる、複数のデータのインスタンスを引き渡します。 

GROUP_MAP と同様、クライアントとサーバー側の DEF_LIST 定義が、リスト・サイズと同様にフィールドも一致していることを確認することが重要です。

以下の SRVROUTINE ルーチンは、ファイル内のすべてのレコードを含むリストを戻します。

Def_List Name(#Employees) Fields(#Empno #Surname #Givename #Address1 #Address2 #Address3 #Postcode #Phonehme #Phonebus #Deptment #Section #Salary #Startdte #Termdate) Type(*working) Entrys(999) 
 
SrvRoutine Name(GetEmployees)
List_Map For(*Output) List(#Employees)
 
Select Fields(#Employees) From_File(pslmst)
Add_Entry To_List(#Employees)
Endselect
 
Endroutine

 

クライアント側でリストを受信する方法には 2 通りあり、1 つはローカルで定義されたリストに直接送信する方法で、次のようになります。

* ローカル定義リスト

Def_List Name(#EmployeeList) Fields(#Empno #Surname #Givename #Address1 #Address2 #Address3 #Postcode #Phonehme #Phonebus #Deptment #Section #Salary #Startdte #Termdate) Type(*working) Entrys(*MAX) 

 

Mthroutine Name(GetEmployees)

 

* サーバー・モジュールのメソッド・ルーチンの定義

Define_Com Class(#MyServerModule.GetEmployees) Name(#GetEmps)

 

* ローカル定義のリストにデータを返す

#GetEmps.ExecuteAsync( #EmployeeList )

 

Endroutine

 

 

もう 1 つの方法は、DEF_LIST を以下のように変えて、データをデータ・オブジェクトのコレクションに直接マップする方法です。

* リストとして使用される社員アイテムのコレクション

Define_Com Class(#Prim_acol<#MyEmployeeData>) Name(#EmployeeList)

 

すべてのリスト・データがクライアントで使用できるようにするためには、この関連付けられた再利用可能パーツ MyEmployeeData に、対応するフィールドが含まれている必要があります。

Function Options(*DIRECT)

Begin_Com Role(*EXTENDS #PRIM_OBJT *listFields #MyEmployee)

 

Group_By Name(#MyEmployee) Fields(#Empno #Surname #Givename #Address1 #Address2 #Address3 #Postcode #Phonehme #Phonebus #Deptment #Section #Salary #Startdte #Termdate)

 

End_Com

応答オブジェクトを戻す

応答オブジェクトは、通常はアプリケーション・サーバーからのイメージまたはファイルのダウンロードに使用されます。

以下の例では、データベース・テーブルからあるイメージが読み込まれます。そして、応答オブジェクトにイメージ・データが入れられ、ファイル名が設定されます。

SrvRoutine Name(DownloadImage) Response(#Response)
Field_Map For(*Input) Field(#Empno)
Field_Map For(*output) Field(#io$sts) Parameter_Name(Status)
 
Fetch Fields(#GiveName #Surname) From_File(pslmst) With_Key(#empno)
 
If_Status Is(*okay)
 
Fetch Fields(#empimg) From_File(pslimg) With_Key(#empno)
 
If_Status Is(*okay)
 
#Response.ContentFile := #Empimg.Filename
#Response.AttachmentFileName := #Surname + #GiveName + #Empno
 
Endif
 
Endif
Endroutine