UI program and the gateway service

EGL provides a technology that is equivalent to a stateful service, which is logic that retains values from one invocation to the next. The technology has two main components, and they run in an application server that is compliant with Java EE. Typically, both components are deployed to the same web project.
The two components are a UI program and a UI gateway service:
  • The UI program is an EGL main program that contains your business logic. The logic might be controlled in a detailed way by the requester, with the program providing specific sets of data in response to each request. The logic also might control the conversation to a greater extent, with the requester initiating a sequence of events. For example, the program might submit data for presentation in an on-screen form, might wait for the form input, and might use the input to determine what form data to send next.
    The program is stereotyped as UIProgram, as shown in the following outline of requester-controlled logic:
    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

    In this case the while loop ends when the program sets the end condition in response to a particular value from the requester. In an alternative case, the while loop ends when the requester invokes ServiceLib.endStatefulServiceSession. That second option is not recommended, particularly in the following case: the requester of the gateway service is a Rich UI application, and the EGL Rich UI proxy is in the same session as the UI program. In that case, ending the UI program by invoking the ServiceLib.endStatefulServiceSession function also ends the Rich UI application's ability to access services.

    Here is an outline of a second UI program, which controls the conversation with the requester:
    program MyOtherUIProgram type UIProgram {}
       
       const MENU_FORM int = 0; 
       const FORM_ONE  int = 1;
       const FORM_TWO int = 2;
    
       // the Record parts are not shown
       myMenuContainer    MenuContainer;     // holds an integer: a menu choice
       myFormOneContainer FormOneContainer;  // holds data for form 1, with the form ID
       myFormTwoContainer FormTwoContainer;  // holds data for form 2, with the form ID
                                                
       endCondition Boolean = false; 
       formNumber Int = MENU_FORM;
       
       function main()
       
          while (endCondition == false)
             case (formNumber) 
                when (MENU_FORM)
                   converse myMENUContainer; 
                   // process in some way and set formNumber
    
                when (FORM_ONE)
                   converse myFormOneContainer;
                   // process in some way and set formNumber
    
                when (FORM_TWO)
                   converse myFormTwoContainer;
                   // process in some way
                   endCondition = true;
    
                otherwise
                   // throw an exception
             end
          end
       end
    end
  • The UI gateway service is a service that invokes the UI program and that transfers data between a requester and that program. You do not write the logic for this service, which is predefined and has a single entry point named invokeProgram.
    You can deploy the UI gateway service as an EGL REST-RPC service, a stateless SOAP service, or both:
    • An EGL REST-RPC service can remain in the application-server session to monitor a conversation between the requester and the UI program. This capability is necessary if you want to code the EGL converse statement in the UI program.
    • A SOAP service might fit better with your corporate processes. You distribute details about service access by making available an EGL-generated WSDL file.

    When you work with the EGL Deployment Descriptor editor to deploy the UI gateway service as a Web service, a deployment-descriptor entry is made available to you as if you had coded the service. To deploy a stateful EGL REST-RPC service, you can specify that the service is stateful in the Service Deployment tag of that editor.

The requester starts the UI program and receives data when the UI program invokes one of two kinds of statements:
  • A converse statement, which causes the program to wait for a subsequent input from the same requester
  • A show statement, which ends the program. A show statement can cause a deferred transfer, in which case a subsequent request from the requester to the UI gateway service initiates a second UI program.
The UI program can also transfer control by invoking the following kinds of statements:
  • A call statement, which transfers control synchronously to a called program
  • A transfer statement, which initiates another main program and ends the processing of the transferring program

A complete UI program example is available to you in End-to-end processing with a UI program and a data grid.

Gateway record

As noted in the next section, the requester passes and receives business data in JSON format, and the JSON string is embedded in a field of a record that is of type UIGatewayRecord. In general, you handle a record of this type when you code a requester but not when you code a UI program.

The type UIGateRecord is a system Record part and is structured as follows:
Record UIGatewayRecord
   uiProgramName STRING;
   data STRING;
   dataEncoding EncodingKind;
   terminated Boolean;
end
Here is the meaning of each field:
uiProgramName
A string that represents the fully qualified name of the UI program to invoke. For example, if a UI program in the myPkg package is named Translate and if the gateway record is named gateRec, the following assignment is valid:
gateRec.uiProgramName = "myPkg.Translate";

When the service responds to the requester, the service ensures that the field value represents the next EGL part to invoke, if any. Again, you typically do not update the gateway record explicitly in the UI program.

data
A string that contains the business data in JSON format. The requester uses the ServiceLib conversion functions as appropriate to store or retrieve the JSON string.
The business data that is converted to or from JSON is typically a container that includes the content of interest. For example, the following Record part contains an integer:
Record InitialContainer
  initialValue INT;
end
The following Record part contains two integers and an array of SQL records:
Record RepeatedContainer  
  numberOfRecords INT;
  pageNumber INT = 1;
  sendList theSQLRecord[]{};
end
dataEncoding
A value that specifies the format of the business data that is sent between the requester and the UI program. This value causes some automatic data conversions. Data is transferred in JSON format, and the only valid value for the dataEncoding field is EncodingKind.JSON.
terminated
A Boolean value that indicates if the program is terminated. Do not assign a value to the terminated field. That field is set automatically by the UI program. The requester can read the field to guide subsequent processing.

Behavior of the requester

The requester acts as follows:
  1. Declares a service-access variable of type UIGatewayService:
    gatewayServiceVar UIGatewayService{@BindService{bindingKey="UIGatewayService"}};
    The UIGatewayService binding in the EGL deployment descriptor has a base URL entry similar to this:
    http://localhost:8080/MyWebProject/restservices/uiGatewayService
  2. Declares a UI gateway record, which is a record of type UIGatewayRecord:
    gateRec UIGatewayRecord;
  3. Uses the ServiceLib.convertToJSON function to convert business data into a JSON string, which is placed in the data field of the UI gateway record. For example, if sendToProgram is an EGL record that you are sending to the UI program, code the following statement:
    gatewayRec.data = ServiceLib.convertToJSON( sendToProgram );

    The string reflects the content that is intended for the UI program.

  4. Includes a service-access statement that passes the UI gateway record. The invocation is asynchronous if it occurs in Rich UI and is synchronous if it occurs outside of Rich UI. Here is an example service-access statement for Rich UI:
    call gatewayServiceVar.invokeProgram(gateRec) 
       returning to callbackFunc onException handleException;
    The signature of the invokeProgram function of the UI gateway service is as follows:
    function invokeProgram(gatewayRecord UIGatewayRecord INOUT);
  5. Uses a record of type UIGatewayRecord to receive the data that is returned from the UI gateway service. Here is the signature of a callback function in the Rich UI handler:
    function callbackFunc(gatewayRecord UIGatewayRecord in)

    For the requester that is responding to a UI program converse statement, the structure of the data field content in the received gateway record must be equivalent to the structure of the data field content sent back to the UI program. Only the content of the data can vary.

    The data sent to the UI program includes the fully qualified name of the EGL part to invoke; that is, the data includes the package name and part name. If the part has an alias, the alias is used in place of the part name. The part might be another UI program or might be an EGL library.

  6. Uses the ServiceLib.convertFromJSON function to convert the data received from the UI program and to place the converted data into an EGL variable. For example, if dataRecord is an EGL record that has a structure that matches the structure of the data that is expected from the UI program, the following statement might be in the Rich UI callback function:
    ServiceLib.convertFromJSON( gatewayRecord.data, dataRecord);
  7. If the UI gateway service is a stateful EGL REST-RPC service, the requester can invoke ServiceLib.endStatefulServiceSession to end the program. In this case, if the requester is a Rich UI application, the user must download the application in the browser again before the application can restart the UI program.
    Note that ending the session might result in an error message, which is displayed by the application server that runs the UI program. Here is an example:
    EGL2156E The session associated with program MyUIProgram was invalidated.
    

The requester uses JSON conversion functions, but the UI program typically does not.

Behavior of the UI program

The UI program acts as follows:
  • Can receive data in one of two ways:
    • If the invocation is directly from the requester, the data from the requester is placed into the record that is identified in the inputUIRecord property. The record must be a basic, non-structured record. The record is not a gateway record.

      Receipt of data into the record does not involve a JSON conversion function. The conversion is handled for you.

    • If the invocation is a transfer from another program, the data from the transferring program is placed in the record that is identified in the inputRecord property. The record must be a basic record, which can be structured or non-structured. The record is not a gateway record.
  • Can return data to the requester in one of the following ways:
    • By invoking a show statement. The I/O object in the show statement must be non-structured and can be a basic or SQL record. The statement can be in a library function.

      A show statement is valid in a library only when the library is invoked from a UI program.

    • By returning control directly; that is, by ending without running the show statement and without transferring control to another program.
    • By invoking a converse statement; but only if the UI gateway service is deployed as an EGL REST-RPC service. The I/O object in the converse statement must be non-structured and can be a basic or SQL record. The statement can be in a library function, but a converse statement is valid in a library only when the library is invoked from a UI program.

      The data sent by a particular converse statement must be structured like the data received by that statement.

    If the UI program returns control to the requester, the requester receives the UI gateway record, and the following statements apply:
    • After the UI program invokes a show or converse statement, the data field of the UI gateway record holds the JSON equivalent of the business data.
    • The programName field of the UI gateway record is set to an empty string in the following cases:
      • The UI program ended by returning control directly.
      • The UI program ended by a show statement that did not involve a deferred transfer.
    • The terminated field of the UI gateway record is set to true in the following cases:
      • The UI program ended by returning control directly.
      • The UI program ended by a show statement.

    The show and converse statements do not use a JSON conversion function. The required conversions are handled for you, including the conversion that occurs after the converse statement, when the requester re-invokes the program and causes the program to process the statement that follows the converse statement.

The UI program properties are as follows:
alias
An optional string that identifies the program. If this string is specified, the requester must use it in place of the program name.
inputRecord
A record that receives data from a transferring program, as noted earlier.
inputUIRecord
A record that receives data from the UI gateway service, as noted earlier.
segmented
A Boolean value that indicates whether the UI program runs in segmented mode:
true (the default)
The program exits after the converse statements and reloads at the appropriate point after the user responds.

The benefit of accepting the default value is that you free application-server resources during user think time. However, the effect of the program exit might require additional coding because the EGL runtime code closes files and database connections, releases libraries, and resets the value of those EGL system variables that are not saved across a converse statement.

false
The program remains in memory while waiting for the response from the requester.

For additional details, see Segmentation in Text UI programs and UI programs.

When you generate the UI program, ensure that the j2ee build descriptor option is set to yes.

When you want to debug the UI program, note the following details:
  • The source of the UI gateway service is not available to you, and the service cannot be debugged.
  • You can debug a UI program only if the program is already running on a server.

Exceptions

Any exception that causes the UI gateway service or UI program to terminate is returned to the Rich UI application as a ServiceInvocationException. You can re-throw the exception to update the related message, but the detail returned to the requester is only what is provided by ServiceInvocationException. For example, the only effect of the boldfaced entry in the following code is to change the message that is displayed by the UI program in the application server:
Record MyException type Exception end

Program MyUIProgram type UIProgram {}
   function main()
      try
         // get an array of data from a relational database
         get mySQLRecord; 
            onException(except AnyException)
               throw new MyException{message = 
                         "Error at get mySQLRecord:  " + except.message};               
      end
   end
end

If the UI program times out during an ongoing conversation with a requester, the exception is returned the next time that the requester invokes the program.