EGL bietet eine Technologie, die einem Service mit Zustandsüberwachung
(STATEFUL) entspricht und eine Logik darstellt, die Werte von einem Aufruf zum nächsten
beibehält.
Die Technologie besteht aus zwei Hauptkomponenten, die auf einem mit
Java™ EE kompatiblen Anwendungsserver ausgeführt
werden. In der Regel werden beide Komponenten im selben Webprojekt implementiert.
Die beiden Komponenten sind ein UI-Programm und ein UI-Gateway-Service.
- Das UI-Programm ist ein EGL-Hauptprogramm, das die Geschäftslogik
enthält. Die Logik kann vom Anforderer präzise gesteuert werden, und das Programm stellt als Antwort auf jede
Anforderung bestimmte Datensätze bereit. Ferner kann die Logik den Datenaustausch in einem größeren Ausmaß
steuern, wobei der Anforderer eine Folge von Ereignissen auslöst.
Das Programm könnte beispielsweise Daten
zur Darstellung in einem Bildschirmformat übergeben, auf die Formateingabe warten und anhand der Eingabe bestimmen,
welche Formatdaten als nächstes gesendet werden.
Das Programm ist als
UIProgram
stereotypisiert, wie im folgenden Entwurf einer vom Anforderer gesteuerten Logik
dargestellt:
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 diesem Fall endet die while-Schleife, wenn das Programm
die Endbedingung als Antwort auf einen bestimmten Wert des Anforderers definiert. In einem anderen Fall
kann die while-Schleife enden, wenn der Anforderer
ServiceLib.endStatefulServiceSession aufruft.
Diese zweite Option wird vor allem dann nicht empfohlen, wenn der Anforderer des Gateway-Service eine
Rich-UI-Anwendung ist und der EGL-Rich-UI-Proxy sich in derselben Sitzung wie das UI-Programm befindet.
In diesem Fall wird bei Beendigung des UI-Programms durch Aufruf der Funktion
ServiceLib.endStatefulServiceSession auch die Zugriffsmöglichkeit der
Rich-UI-Anwendung auf Services beendet.
Im Folgenden ist der Entwurf eines zweiten
UI-Programms aufgeführt, das den Datenaustausch mit dem Anforderer
steuert:
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
- Der UI-Gateway-Service ist ein Service, der das UI-Programm
aufruft und für den Datenaustausch zwischen einem Anforderer und diesem Programm zuständig
ist. Für diesen Service muss keine Logik geschrieben werden. Der Service ist vordefiniert und verfügt über
einen einzelnen Eingangspunkt namens invokeProgram.
Der UI-Gateway-Service
kann als EGL-REST-RPC-Service und/oder SOAP-Service ohne Zustandsüberwachung implementiert werden:
- Ein EGL-REST-RPC-Service kann in der Sitzung des Anwendungsservers verbleiben, um den Datenaustausch zwischen
dem Anforderer und dem UI-Programm zu überwachen.
Diese Funktion ist erforderlich, wenn die
EGL-Anweisung converse im UI-Programm codiert werden soll.
- Ein SOAP-Service passt möglicherweise besser zu den Geschäftsprozessen.
Die Weitergabe der Details zu einem Servicezugriff erfolgt durch die Bereitstellung einer EGL-generierten
WSDL-Datei.
Wenn Sie zur Implementierung des UI-Gateway-Service als Web-Service den
Editor für den EGL-Implementierungsdeskriptor verwenden, wird ein Implementierungsdeskriptoreintrag
zur Verfügung gestellt, so als ob Sie den Service codiert hätten. Wenn ein EGL-REST-RPC-Service mit
Zustandsüberwachung (STATEFUL) implementiert werden soll, können Sie dies auf der Registerkarte
Serviceimplementierung des Editors angeben.
Der Anforderer startet das UI-Programm und empfängt Daten, wenn das UI-Programm
eine der beiden folgenden Anweisungen aufruft:
- Die Anweisung converse, die das Programm zum Warten auf nachfolgende Eingaben
desselben Anforderers veranlasst.
- Die Anweisung show, die das Programm beendet.
Die Anweisung show kann eine verzögerte Übertragung veranlassen.
In diesem Fall wird bei einer nachfolgenden Anforderung des Anforderers an den UI-Gateway-Service ein zweites
UI-Programm gestartet.
Ferner kann das UI-Programm die Steuerung durch Aufruf der folgenden Anweisungen übertragen:
- Die Anweisung call, mit deren Hilfe die Steuerung synchron an ein aufgerufenes
Programm übertragen wird.
- Die Anweisung transfer, die ein weiteres Hauptprogramm startet und die
Verarbeitung des übertragenden Programms beendet.
Ein vollständiges Beispiel für ein UI-Programm finden Sie in 'End-to-end-Verarbeitung mit UI-Programm und Datengrid'.
Gateway-Datensatz
Wie im nächsten Abschnitt beschrieben übergibt und empfängt
der Anforderer Geschäftsdaten im JSON-Format. Die JSON-Zeichenfolge wird in ein Feld eines Datensatzes vom Typ
'UIGatewayRecord' eingebettet. Im Allgemeinen werden Datensätze dieses Typs beim Codieren eines Anforderers und
nicht beim Codieren eines UI-Programms verarbeitet.
Der
Typ 'UIGateRecord' ist ein Datensatzabschnitt des Systems, der wie folgt strukturiert ist:
Record UIGatewayRecord
uiProgramName STRING;
data STRING;
dataEncoding EncodingKind;
terminated Boolean;
end
Bedeutung der einzelnen Felder:
- uiProgramName
- Eine Zeichenfolge, die den vollständig qualifizierten Namen des UI-Programms
angibt, das aufgerufen werden soll. Wenn der Name eines im Paket myPkg enthaltenen
UI-Programms beispielsweise Translate und der Gateway-Datensatz gateRec lautet,
gilt die folgende Zuordnung:
gateRec.uiProgramName = "myPkg.Translate";
Bei der Antwort des Service auf
den Anforderer wird sichergestellt, dass der Feldwert den nächsten aufzurufenden EGL-Abschnitt darstellt
(sofern vorhanden). Auch hier wird der Gateway-Datensatz normalerweise nicht explizit im UI-Programm aktualisiert.
- data
- Eine Zeichenfolge mit den Geschäftsdaten im JSON-Format. Mithilfe der
ServiceLib-Konvertierungsfunktionen kann der Anforderer die JSON-Zeichenfolge
nach Bedarf speichern oder abrufen.
Die in oder aus JSON konvertierten Geschäftsdaten bestehen in der Regel
aus einem Container, der die relevanten Inhalte enthält. Der folgende Datensatzabschnitt enthält beispielsweise
eine ganze Zahl:
Record InitialContainer
initialValue INT;
end
Der folgende Datensatzabschnitt enthält zwei Integer und eine Feldgruppe mit
SQL-Datensätzen:
Record RepeatedContainer
numberOfRecords INT;
pageNumber INT = 1;
sendList theSQLRecord[]{};
end
- dataEncoding
- Ein Wert, der das Format der Geschäftsdaten angibt, die zwischen dem Anforderer und dem UI-Programm
ausgetauscht werden. Dieser Wert veranlasst automatische Datenkonvertierungen. Daten werden in das JSON-Format
übertragen und für das Feld dataEncoding ist 'EncodingKind.JSON' der einzig gültige Wert.
- terminated
- Ein boolescher Wert, der angibt, ob das Programm beendet wird. Für das Feld
terminated darf kein Wert zugeordnet werden.
Das Feld wird vom UI-Programm automatisch eingestellt. Der Anforderer kann das Feld lesen, um nachfolgende
Verarbeitungsaktivitäten zu steuern.
Verhalten des Anforderers
Der Anforderer funktioniert wie folgt:
- Deklaration einer Servicezugriffsvariablen des Typs 'UIGatewayService':
gatewayServiceVar UIGatewayService{@BindService{bindingKey="UIGatewayService"}};
Das
UIGatewayService-Binding
im EGL-Implementierungsdeskriptor verfügt über einen Basis-URL-Eintrag wie diesem:
http://localhost:8080/MyWebProject/restservices/uiGatewayService
- Deklaration eines UI-Gateway-Datensatzes vom Typ 'UIGatewayRecord':
gateRec UIGatewayRecord;
- Verwendung der Funktion ServiceLib.convertToJSON zum Konvertieren von Geschäftsdaten
in eine JSON-Zeichenfolge, die in das Feld data des UI-Gateway-Datensatzes eingefügt
wird. Wenn beispielsweise sendToProgram ein EGL-Datensatz ist, der an das UI-Programm gesendet
wird, muss die folgende Anweisung codiert werden:
gatewayRec.data = ServiceLib.convertToJSON( sendToProgram );
Die Zeichenfolge gibt den Inhalt wieder, der für das UI-Programm gedacht ist.
- Einschluss einer Servicezugriffsanweisung, die den UI-Gateway-Datensatz
übergibt. Der Aufruf ist asynchron, wenn er innerhalb von Rich UI erfolgt, und
synchron, wenn der außerhalb von Rich UI erfolgt. Beispiel für eine Servicezugriffsanweisung für
Rich UI:
call gatewayServiceVar.invokeProgram(gateRec)
returning to callbackFunc onException handleException;
Die Signatur
der Funktion
invokeProgram des UI-Gateway-Service lautet wie
folgt:
function invokeProgram(gatewayRecord UIGatewayRecord INOUT);
- Verwendung eines Datensatzes vom Typ 'UIGatewayRecord' für den Empfang der vom UI-Gateway-Service
zurückgegebenen Daten. Im Folgenden ist die Signatur einer Callback-Funktion im
Rich-UI-Handler aufgeführt:
function callbackFunc(gatewayRecord UIGatewayRecord in)
Für
den Anforderer, der auf eine Anweisung converse des UI-Programms antwortet,
muss die Struktur des data-Feldinhalts im empfangenen Gateway-Datensatz
der Struktur des data-Feldinhalts entsprechen, der an das UI-Programm
zurückgesendet wird. Nur der Inhalt der Daten kann variieren.
Die an das UI-Programm gesendeten Daten
enthalten den vollständig qualifizierten Namen des aufzurufenden EGL-Abschnitts, also den Paket- und den
Abschnittsnamen. Wenn der Abschnitt über einen Aliasnamen verfügt, wird der Aliasname anstelle des Abschnittsnamens
verwendet. Der Abschnitt kann ein anderes UI-Programm oder eine EGL-Bibliothek sein.
- Verwendung der Funktion ServiceLib.convertFromJSON zum Konvertieren der vom
UI-Programm empfangenen Daten und Einfügen der konvertierten Daten in eine EGL-Variable. Beispiel: Wenn
dataRecord ein EGL-Datensatz ist, dessen Struktur mit der Struktur der
erwarteten Daten des UI-Programms übereinstimmt, könnte die Callback-Funktion von RICH UI die folgende
Anweisung enthalten:
ServiceLib.convertFromJSON( gatewayRecord.data, dataRecord);
- Wenn der UI-Gateway-Service ein EGL-REST-RPC-Service mit Zustandsüberwachung (STATEFUL)
ist, kann der Anforderer ServiceLib.endStatefulServiceSession zum Beenden des Programms
aufrufen. Wenn der Anforderer eine Rich-UI-Anwendung ist, muss der Benutzer in diesem Fall die Anwendung im
Browser erneut herunterladen, bevor die Anwendung das UI-Programm neu starten kann.
Beachten Sie,
dass die Beendigung der Sitzung zu einer Fehlernachricht führen kann, die auf dem Anwendungsserver mit dem UI-Programm
angezeigt wird: Beispiel:
EGL2156E Die Sitzung, die dem Programm 'MyUIProgram' zugeordnet ist, wurde inaktiviert.
Der Anforderer verwendet JSON-Konvertierungsfunktionen, das UI-Programm üblicherweise aber nicht.
Verhalten des UI-Programms
Das UI-Programm funktioniert wie folgt:
- Daten können auf zweierlei Weise empfangen werden:
- Daten können wie folgt an den Anforderer zurückgegeben werden:
- Durch Aufruf einer Anweisung show. Es ist erforderlich, dass das E/A-Objekt in der
Anweisung show nicht strukturiert ist. Ferner kann es sich um einen Basis- oder
SQL-Datensatz handeln. Die Anweisung kann in einer Bibliotheksfunktion enthalten
sein.
Die Anweisung show ist in einer Bibliothek nur dann gültig, wenn die
Bibliothek über ein UI-Programm aufgerufen wird.
- Durch direkte Rückgabe der Steuerung. Das heißt, die Beendigung erfolgt ohne Ausführung der
Anweisung show und die Steuerung wird nicht an ein anderes Programm übertragen.
- Durch Aufruf einer Anweisung converse. Dies gilt allerdings
nur dann, wenn der UI-Gateway-Service als EGL-REST-RPC-Service implementiert wird.
Es ist erforderlich, dass das E/A-Objekt in der Anweisung converse nicht strukturiert
ist. Ferner kann es sich um einen Basis- oder
SQL-Datensatz handeln. Die Anweisung kann in einer Bibliotheksfunktion enthalten sein.
Die Anweisung converse ist in einer Bibliothek jedoch nur dann gültig, wenn die
Bibliothek über ein UI-Programm aufgerufen wird.
Die von einer bestimmten Anweisung converse
gesendeten Daten müssen wie die von dieser Anweisung empfangenen Daten strukturiert sein.
Wenn das
UI-Programm die Steuerung an den Anforderer zurückgibt, empfängt der Anforderer den UI-Gateway-Datensatz. Dabei
gelten die folgenden Aussagen:
- Nach dem Aufruf einer Anweisung show oder converse durch
das UI-Programm enthält das Feld data des UI-Gateway-Datensatzes die JSON-Entsprechung
der Geschäftsdaten.
- Das Feld programName des UI-Gateway-Datensatzes wird in den folgenden Fällen auf eine
leere Zeichenfolge gesetzt:
- Das UI-Programm wurde durch direkte Rückgabe der Steuerung beendet.
- Das UI-Programm wurde durch eine Anweisung show ohne verzögerte Übertragung beendet.
- Das Feld terminated des UI-Gateway-Datensatzes wird in den folgenden Fällen auf
den Wert 'true' gesetzt:
- Das UI-Programm wurde durch direkte Rückgabe der Steuerung beendet.
- Das UI-Programm wurde von einer Anweisung show
beendet.
Die Anweisungen show und converse
verwenden keine JSON-Konvertierungsfunktion. Die erforderlichen Konvertierungen werden für Sie ausgeführt.
Dazu gehört auch die Konvertierung, die nach der Anweisung converse erfolgt,
wenn der Anforderer das Programm erneut aufruft und es zur Verarbeitung der Anweisung veranlasst, die auf die
Anweisung converse folgt.
Die Eigenschaften des UI-Programms lauten wie folgt:
- alias
- Eine optionale Zeichenfolge, die das Programm angibt. Bei Angabe dieser Zeichenfolge muss der Anforderer diesen
Wert anstelle des Programmnamens verwenden.
- inputRecord
- Ein Datensatz, der Daten von einem übertragenden Programm empfängt (siehe oben).
- inputUIRecord
- Ein Datensatz, der Daten vom UI-Gateway-Service empfängt (siehe oben).
- segmented
- Ein boolescher Wert, der angibt, ob das UI-Programm im Segmentmodus ausgeführt wird:
- true (Standardwert)
- Das Programm wird nach den converse-Anweisungen beendet und nach
der Benutzerantwort an der entsprechenden Stelle neu geladen.
Die Übernahme des Standardwerts hat den
Vorteil, dass während der Bedenkzeit des Benutzers Anwendungsserverressourcen freigegeben
werden. Der Effekt der Programmbeendigung erfordert jedoch möglicherweise eine zusätzliche Codierung,
da der EGL-Laufzeitcode Dateien und Datenbankverbindungen schließt, Bibliotheken freigibt und die
Werte der EGL-Systemvariablen zurücksetzt, die nicht innerhalb einer converse-Anweisung
gespeichert werden.
- false
- Das Programm verbleibt im Speicher, während auf eine Antwort vom Anforderer gewartet
wird.
Weitere Informationen finden Sie in 'Segmentierung in
Text-UI-Programmen und UI-Programmen'.
Stellen Sie bei der Generierung
des UI-Programms sicher, dass die Builddeskriptoroption j2ee auf 'yes'
gesetzt ist.
Beachten Sie beim Debug des UI-Programms die folgenden Hinweise:
- Die Quelle des UI-Gateway-Service ist nicht verfügbar und das Debug für den Service ist nicht möglich.
- Das Debug für ein UI-Programm ist nur dann möglich, wenn das Programm bereits auf einem
Server ausgeführt wird.
Ausnahmebedingungen
Ausnahmebedingungen, die eine Beendigung des
UI-Gateway-Service oder UI-Programms zur Folge haben, werden als 'ServiceInvocationException' an die Rich-UI-Anwendung
zurückgegeben. Die Ausnahmebedingung kann zur Aktualisierung der zugehörigen Nachricht erneut ausgelöst
werden, aber an den Anforderer werden nur die von 'ServiceInvocationException' bereitgestellten Details zurückgegeben.
Der in Fettdruck dargestellte Eintrag im folgenden Code hat beispielsweise nur zur Folge, dass die
Nachricht geändert wird, die vom UI-Programm auf dem Anwendungsserver angezeigt wird:
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
Kommt es während eines laufenden Datenaustauschs mit einem Anforderer zu einer Überschreitung des
Zeitlimits für das UI-Programm, wird die Ausnahmebedingung beim nächsten Aufruf des Programms durch den
Anforderer zurückgegeben.