UI プログラムおよびゲートウェイ・サービス

EGL には、ステートフル・サービス (ある呼び出しの値を次の呼び出しまで維持するロジック) に相当するテクノロジーが組み込まれています。 このテクノロジーは 2 つのメイン・コンポーネントから構成されており、これらのコンポーネントは Java™ EE に準拠するアプリケーション・サーバーで実行されます。通常、この 2 つのコンポーネントは同一 Web プロジェクトにデプロイされます。
2 つのコンポーネントは、UI プログラムと UI ゲートウェイ・サービスです。
  • UI プログラム は、ビジネス・ロジックを含む EGL メインプログラムです。このロジックは、リクエスターが各要求に対応して特定のデータ・セットを提供するプログラムを使用して、詳細に制御することがあります。このロジックはまた、一連のイベントを開始するリクエスターとの会話をより広範囲に制御することがあります。 例えば、プログラムはスクリーン内のフォームに表示するデータを送信し、フォームへの入力を待機し、次に送信するフォーム・データを入力から判別します。
    次のリクエスター制御ロジックのアウトラインに示すように、プログラムは UIProgram としてステレオタイプ化されます。
    program MyUIProgram type UIProgram {inputUIRecord = myInitialContainer}
       
       // the Record parts for the following two declarations are shown 
       // in a later description of the "gateway record" data property
       myInitialContainer  InitialContainer;     
       myRepeatedContainer RepeatedContainer;   
                                                
       endCondition Boolean = false; 
       start, end Int;
       myDataArray MySQLRecord[];
    
       function main()
    
          while (endCondition == false)
    
             // The logic retrieves data (not shown)
             // and determines what portion to send.
             for (i int from start to end)
                myRepeatedContainer.sendList[i] = myDataArray[n];
                n = n + 1;
             end
    
             // no explicit JSON conversion is required here.
             converse myRepeatedContainer; 
    
             // set endCondition in response to an input value
          end
       end
    end

    この例では、while ループが終了するのは、プログラムがリクエスターからの特定の値に応答して終了条件を設定する時点です。while ループが終了するもう 1 つの状況として、リクエスターが ServiceLib.endStatefulServiceSession を呼び出す時点があります。 2 番目の方法は推奨されません。特に、ゲートウェイ・サービスのリクエスターが Rich UI アプリケーションであり、EGL Rich UI プロキシーが UI プログラムと同じセッション内にある場合は推奨されません。 この場合、ServiceLib.endStatefulServiceSession 関数を呼び出して UI プログラムを終了すると、Rich UI アプリケーションがサービスにアクセスできなくなります。

    2 番目の UI プログラム (リクエスターとの会話を制御するプログラム) のアウトラインを以下に示します。
    program MyOtherUIProgram type UIProgram {}
       
       const MENU_FORM int = 0; 
       const FORM_ONE  int = 1;
       const FORM_TWO int = 2;
    
       // レコード・パーツは示されていません
       myMenuContainer    MenuContainer;     // 整数を保持します (メニュー項目)
       myFormOneContainer FormOneContainer;  // フォーム 1 のデータとフォーム ID を保持します
       myFormTwoContainer FormTwoContainer;  // フォーム 2 のデータとフォーム ID を保持します
                                                
       endCondition Boolean = false; 
       formNumber Int = MENU_FORM;
       
       function main()
       
          while (endCondition == false)
             case (formNumber) 
                when (MENU_FORM)
                   converse myMENUContainer; 
                   // 何らかの方法で処理され、formNumber が設定されます
    
                when (FORM_ONE)
                   converse myFormOneContainer;
                   // 何らかの方法で処理され、formNumber が設定されます
    
                when (FORM_TWO)
                   converse myFormTwoContainer;
                   // process in some way
                   endCondition = true;
    
                otherwise
                   // 例外をスローします
             end
          end
       end
    end
  • UI ゲートウェイ・サービス は、UI プログラムを呼び出し、リクエスターとその UI プログラムの間でデータを転送するサービスです。ユーザーはこのサービスのロジックを作成しません。このロジックは事前に定義されており、invokeProgram という単一エントリー・ポイントがあります。
    UI ゲートウェイ・サービスは、EGL REST-RPC サービスまたはステートレス SOAP サービス、あるいはこの両方としてデプロイできます。
    • EGL REST-RPC サービスはアプリケーション・サーバー・セッションで引き続きリクエスターと UI プログラム間の会話をモニターできます。 UI プログラムで EGL converse ステートメントをコーディングする場合にこの機能が必要です。
    • SOAP サービスは、他のサービスに比べ社内プロセスでの使用に適していることがあります。 サービス・アクセスの詳細を配信するには、EGL 生成の WSDL ファイルを使用可能にします。

    EGL デプロイメント記述子エディターを使用して UI ゲートウェイ・サービスを Web サービスとしてデプロイするときには、そのサービスをコーディングした場合と同様に、デプロイメント記述子項目を使用できます。ステートフル EGL REST-RPC サービスをデプロイするには、エディターの「サービス・デプロイメント」タグでそのサービスがステートフルであることを指定できます。

リクエスターは UI プログラムを開始し、UI プログラムが次のいずれかのステートメントを呼び出すとリクエスターがデータを受信します。
  • converse ステートメント。このステートメントにより、プログラムは同一リクエスターからの後続の入力を待機します。
  • show ステートメント。このステートメントはプログラムを終了します。 show ステートメントにより据え置き転送が発生することがありますが、この場合はリクエスターから UI ゲートウェイ・サービスへの後続の要求によって 2 番目の UI プログラムが開始されます。
UI プログラムは、以下に示すステートメントを呼び出して制御を移動することもできます。
  • call ステートメント。このステートメントは、呼び出し先プログラムに制御を同期的に移動します。
  • transfer ステートメント。このステートメントは、別のメインプログラムを開始し、移動元プログラムの処理を終了します。

UI プログラムの完全な例は『UI プログラムおよびデータ・グリッドを使用したエンドツーエンド処理』に記載されています。

ゲートウェイ・レコード

リクエスターは JSON フォーマットでビジネス・データを受け渡しおよび受け取ります。また JSON 文字列は UIGatewayRecord 型のレコードのフィールドに組み込まれます。これについては、次のセクションで説明します。一般にこの型のレコードを操作するのは、UI プログラムをコーディングする場合ではなく、リクエスターをコーディングする場合です。

UIGateRecord 型はシステム・レコード・パーツです。UIGateRecord 型の構造を以下に示します。
Record UIGatewayRecord
   uiProgramName STRING;
   data STRING;
   dataEncoding EncodingKind;
   terminated Boolean;
end
各フィールドの意味を次に示します。
uiProgramName
呼び出す UI プログラムの完全修飾名を表す文字列。例えば myPkg パッケージ内の UI プログラムの名前が Translate であり、ゲートウェイ・レコードの名前が gateRec の場合、次の割り当ては有効です。
gateRec.uiProgramName = "myPkg.Translate";

サービスは、リクエスターに応答する際に、フィールド値が次に呼び出す EGL パーツを表していることを確認します (次に呼び出すパーツがある場合)。この場合も、通常は UI プログラムでゲートウェイ・レコードを明示的に更新しません。

data
JSON フォーマット内のビジネス・データを含むストリング。 リクエスターは、必要に応じて ServiceLib 変換関数を使用して JSON 文字列を格納または取得します。
JSON から変換されたビジネス・データ、または JSON に変換されるビジネス・データは通常、対象のコンテンツが含まれているコンテナーです。例えば、次のレコード・パーツには整数値が含まれています。
Record InitialContainer
  initialValue INT;
end
次のレコード・パーツには、2 つの整数値と SQL レコードの配列が含まれています。
Record RepeatedContainer  
  numberOfRecords INT;
  pageNumber INT = 1;
  sendList theSQLRecord[]{};
end
dataEncoding
リクエスターと UI プログラムの間で送信されるビジネス・データのフォーマットを指定する値。この値により、自動データ変換が発生します。データは JSON フォーマットで転送されるため、dataEncoding フィールドの有効値は EncodingKind.JSON のみです。
terminated
プログラムが終了したかどうかを示すブール値。terminated フィールドには値を割り当てないでください。 このフィールドは UI プログラムによって自動的に設定されます。リクエスターは、後続の処理を管理するためにこのフィールドを読み取ることができます。

リクエスターの振る舞い

リクエスターは以下のようにします。
  1. UIGatewayService 型のサービス・アクセス変数を宣言します。
    gatewayServiceVar UIGatewayService{@BindService{bindingKey="UIGatewayService"}};
    EGL デプロイメント記述子の UIGatewayService バインディングのベース URL 項目は次のようになります。
    http://localhost:8080/MyWebProject/restservices/uiGatewayService
  2. UI ゲートウェイ・レコード (UIGatewayRecord 型のレコード) を宣言します。
    gateRec UIGatewayRecord;
  3. ServiceLib.convertToJSON 関数を使用してビジネス・データを JSON 文字列に変換します。このデータは UI ゲートウェイ・レコードの data フィールドに入ります。例えば sendToProgram が UI プログラムに送信する EGL レコードである場合は、次のステートメントをコーディングします。
    gatewayRec.data = ServiceLib.convertToJSON( sendToProgram );

    文字列には、UI プログラム向けの内容が反映されます。

  4. UI ゲートウェイ・レコードを受け渡すサービス・アクセス・ステートメントを組み込みます。呼び出しは、Rich UI で行われる場合は非同期であり、Rich UI 外部で行われる場合は同期的です。以下に、Rich UI のサービス・アクセス・ステートメントの例を示します。
    call gatewayServiceVar.invokeProgram(gateRec) 
       returning to callbackFunc onException handleException;
    UI ゲートウェイ・サービスの invokeProgram 関数のシグニチャーを次に示します。
    function invokeProgram(gatewayRecord UIGatewayRecord INOUT);
  5. UIGatewayRecord 型のレコードを使用して、UI ゲートウェイ・サービスから返されるデータを受け取ります。Rich UI ハンドラーのコールバック関数のシグニチャーを次に示します。
    function callbackFunc(gatewayRecord UIGatewayRecord in)

    UI プログラム converse ステートメントに応答するリクエスターの場合、受け取るゲートウェイ・レコードの data フィールドの内容の構造は、UI プログラムに返される data フィールドの内容の構造と同等でなければなりません。データの内容は、異なっていてもかまいません。

    UI プログラムに送信されるデータには、呼び出す EGL パーツの完全修飾名が含まれます。つまり、このデータにはパッケージ名とパーツ名が含まれます。パーツに別名がある場合、パーツ名の代わりにこの別名が使用されます。パーツは、別の UI プログラムであるか、または EGL ライブラリーである場合があります。

  6. ServiceLib.convertFromJSON 関数を使用して、UI プログラムから受け取ったデータを変換し、変換後のデータを EGL 変数に入れます。例えば dataRecord が、UI プログラムから予期されているデータの構造に一致する構造を持つ EGL レコードの場合、Rich UI コールバック関数には次に示すステートメントが含まれています。
    ServiceLib.convertFromJSON( gatewayRecord.data, dataRecord);
  7. UI ゲートウェイ・サービスがステートフル EGL REST-RPC サービスの場合、リクエスターはプログラムを終了するために ServiceLib.endStatefulServiceSession を呼び出すことができます。このときにリクエスターが Rich UI アプリケーションである場合は、アプリケーションが UI プログラムを再始動できるようにするために、ユーザーがブラウザーでアプリケーションを再度ダウンロードする必要があります。
    セッションを終了するとエラー・メッセージが出されることがある点に注意してください。このエラー・メッセージは、UI プログラムを実行するアプリケーション・サーバーにより表示されます。以下に例を示します。
    EGL2156E プログラム MyUIProgram に関連付けられているセッションが無効になりました。(EGL2156E The session associated with program MyUIProgram was invalidated.)

リクエスターは JSON 変換関数を使用しますが、UI プログラムは通常は JSON 変換関数を使用しません。

UI プログラムの振る舞い

UI プログラムの動作は、以下のとおりです。
  • 以下の 2 つの方法のいずれかでデータを受信できます。
    • リクエスターから直接呼び出される場合、inputUIRecord プロパティーに指定されるレコードにリクエスターからのデータが入ります。 このレコードは、基本非構造化レコードでなければなりません。 このレコードは、ゲートウェイ・レコードではありません。

      レコードにデータが取り込まれるときに、JSON 変換関数は使用されません。変換は自動的に処理されます。

    • 呼び出しが別のプログラムからの転送である場合、inputRecord プロパティーに指定されるレコードに転送元プログラムのデータが入ります。このレコードは基本レコード (構造化または非構造化) でなければなりません。 このレコードは、ゲートウェイ・レコードではありません。
  • 次に示す方法の 1 つで、 データをリクエスターに戻せます。
    • show ステートメントを呼び出す。show ステートメントの入出力オブジェクトは非構造化レコード (基本レコードまたは SQL レコード) でなければなりません。このステートメントをライブラリー関数に組み込むことができます。

      show ステートメントは、UI プログラムから呼び出されるライブラリーでのみ有効です。

    • 制御を直接返す。つまり、show ステートメントを実行せず、制御を別のプログラムに移動せずに終了します。
    • converse ステートメントを呼び出す。ただし、UI ゲートウェイ・サービスが EGL REST-RPC サービスとしてデプロイされている場合に限ります。 converse ステートメントの入出力オブジェクトは、非構造化レコード (基本レコードまたは SQL レコード) でなければなりません。ライブラリー関数にこのステートメントを組み込むことができますが、converse ステートメントは、UI プログラムから呼び出されるライブラリーでのみ有効です。

      特定の converse ステートメントにより送信されるデータは、そのステートメントで受信されるデータと同じ構造でなければなりません。

    UI プログラムからリクエスターに制御が返されると、リクエスターは UI ゲートウェイ・レコードを受け取り、以下の処理が行われます。
    • UI プログラムが show ステートメントまたは converse ステートメントを呼び出した後に、UI ゲートウェイ・レコードの data フィールドにビジネス・データに相当する JSON データが保持されます。
    • 以下に示す状況の場合、UI ゲートウェイ・レコードの programName フィールドに空の文字列が設定されます。
      • UI プログラムが制御を直接返して終了した場合
      • UI プログラムが、据え置き転送が関与しない show ステートメントによって終了した場合
    • 以下に示す状況の場合、UI ゲートウェイ・レコードの terminated フィールドに TRUE が設定されます。
      • UI プログラムが制御を直接返して終了した場合
      • UI プログラムが show ステートメントによって終了した場合。

    show ステートメントと converse ステートメントでは JSON 変換関数は使用されません。リクエスターがプログラムを再度呼び出し、このプログラムによって converse ステートメントの後に続くステートメントが処理される場合は、必要な変換が自動的に処理されます。これには、converse ステートメントの後で行われる変換も含まれます。

以下のような UI プログラム・プロパティーがあります。
alias
プログラムを示すオプションの文字列。この文字列が指定されている場合、リクエスターはプログラム名の代わりにこの文字列を使用する必要があります。
inputRecord
前述した、転送元プログラムからデータを受け取るレコード。
inputUIRecord
前述した、UI ゲートウェイ・サービスからデータを受け取るレコード。
segmented
UI プログラムをセグメント化モードで実行するかどうかを示すブール値。
true (デフォルト)
converse ステートメントの後でプログラムが終了し、ユーザーが応答した後の適切な時点でプログラムが再ロードされます。

このデフォルト値を受け入れるメリットは、ユーザーの思考時間中にアプリケーション・サーバー・リソースを解放できる点です。ただし、プログラム出口を有効にするには追加のコーディングが必要なことがあります。これは、EGL ランタイム・コードがファイルとデータベース接続を閉じ、ライブラリーを解放し、converse ステートメントで保存されない EGL システム変数の値をリセットするためです。

false
プログラムは、リクエスターからの応答を待っている間、メモリー内に留まっています。

詳しくは、『テキスト UI プログラムのセグメンテーション』を参照してください。

UI プログラムの生成時には、j2ee ビルド記述子オプションが yes に設定されていることを確認してください。

UI プログラムをデバッグするときには以下の点に注意してください。
  • ユーザーに対して UI ゲートウェイ・サービスのソースが使用可能ではないため、UI ゲートウェイ・サービスをデバッグできません。
  • UI プログラムをデバッグできるのは、このプログラムが既にサーバーで実行中である場合のみです。

例外

UI ゲートウェイ・サービスまたは UI プログラムを終了させる例外はすべて、ServiceInvocationException として Rich UI アプリケーションに返されます。関連メッセージを更新するために例外を再度スローできますが、リクエスターに返される詳細は、ServiceInvocationException が提供する内容のみです。 例えば、次のコードの太字体の項目では、アプリケーション・サーバーの UI プログラムによって表示されるメッセージが変更されるだけです。
Record MyException type Exception end

Program MyUIProgram type UIProgram {}
   function main()
      try
         // リレーショナル・データベースからデータ配列を取得する
         get mySQLRecord; 
            onException(except AnyException)
               throw new MyException{message = 
                         "Error at get mySQLRecord:  " + except.message};               
      end
   end
end

リクエスターとの継続的な会話中に UI プログラムがタイムアウトになると、次回リクエスターがこのプログラムを呼び出すときに例外が返されます。