Die Anweisungen CREATE FUNCTION und CREATE PROCEDURE definieren eine aufrufbare Funktion oder Prozedur, die in der Regel als "Routine" bezeichnet wird.
Die Anweisungen CREATE FUNCTION und CREATE PROCEDURE definieren eine aufrufbare Funktion oder Prozedur, die in der Regel als "Routine" bezeichnet wird.
Routinen sind bei der Erstellung wiederverwendbarer Codeblöcke hilfreich, die unabhängig mehrere Male ausgeführt werden können. Sie lassen sich als Reihe von ESQL-Anweisungen, als Java-Methode oder als in einer Datenbank gespeicherte Prozedur implementieren. Diese Vielfalt der Implementierungsmöglichkeiten bedeutet, dass einige der Klauseln im Syntaxdiagramm nicht für alle Routinetypen zutreffen (oder nicht zulässig sind).
Jede Routine hat einen Namen, der innerhalb des Schemas, der die Routine angehört, eindeutig sein muss. Routinenamen können daher nicht überladen werden: wenn der Broker eine überladene Routine feststellt, gibt er eine Ausnahmebedingung aus.
Geben Sie den Namen der Routine mit der Klausel Routinename und die Parameter der Routine mit der Klausel Parameterliste an. Wenn die LANGUAGE-Klausel ESQL angibt, muss die Routine unter Verwendung einer einzelnen ESQL-Anweisung implementiert werden. Diese Anweisung ist sehr nützlich, wenn es sich um eine Verbindungsanweisung handelt (BEGIN ... END), da sie dann so viele ESQL-Anweisungen enthalten kann, wie zur Ausübung ihrer Funktionen erforderlich sind.
Alternativ können Sie in der LANGUAGE-Klausel eine andere Sprache als ESQL angeben, anstatt einen ESQL-Hauptteil für die Routine bereitzustellen. Auf diese Weise sind Sie in der Lage, mit der EXTERNAL NAME-Klausel auf den tatsächlichen Hauptteil der Routine zu verweisen, wenn er extern zum Broker lokalisiert ist. Weitere Informationen zur Verwendung der EXTERNAL NAME-Klausel finden Sie unter Gespeicherte Prozeduren aufrufen und Eine Java-Routine aufrufen.
Routinen mit beliebigem LANGUAGE-Typ können die Parameter IN, OUT und INOUT haben. Auf diese Weise kann der Aufrufende mehrere Werte in die Routine einstellen sowie mehrere aktualisierte Werte zurückempfangen. Dies ist ergänzend zu möglichen RETURNS-Klauseln, die die Routine haben kann. Die RETURNS-Klausel ermöglicht der Routine, einen Wert an den Aufrufenden zurückzuleiten.
Routinen, die in verschiedenen Sprachen implementiert sind, haben ihre eigenen Einschränkungen dahingehend, welche Datentypen eingestellt oder zurückgegeben werden können. Sie sind nachfolgend dokumentiert. Der Datentyp des zurückgegebenen Wertes muss dem Datentyp des Wertes entsprechen, der laut Definition von der Routine zurückgegeben werden soll. Wenn eine Routine laut Definition einen Rückgabewert haben soll, kann ihn der Aufrufende der Routine nicht ignorieren. Ausführliche Informationen finden Sie in der CALL-Anweisung.
Bezüglich der Sprache oder des Routinetyps muss die Methode des Aufrufens der Routine der Methode ihrer Deklaration entsprechen. Wenn die Routine eine RETURNS-Klausel besitzt, verwenden Sie entweder die Aufrufsyntax FUNCTION oder eine CALL-Anweisung mit einer INTO-Klausel. Umgekehrt gilt: Hat eine Routine keine RETURNS-Klausel, müssen Sie eine CALL-Anweisung ohne INTO-Klausel verwenden.
Hat die Routine den Typ FUNCTION (Funktion), ist der Richtungsanzeiger (IN, OUT, INOUT) für jeden Parameter optional. Wir empfehlen jedoch dringend, aus Dokumentationsgründen einen Richtungsanzeiger für alle neuen Routinen mit beliebigem Typ festzulegen.
ESQL-Variablen, die als CONSTANT deklariert sind (oder Verweise auf als CONSTANT deklarierte Variablen) dürfen nicht die Richtung OUT oder INOUT haben.
ESQL-Routinen sind in ESQL geschrieben, und ihre LANGUAGE-Klausel gibt die Sprache ESQL an. Als Hauptteil einer ESQL-Routine wird für gewöhnlich eine Verbindungsanweisung in der Form von BEGIN … END verwendet, die mehrere Anweisungen zur Verarbeitung der Parameter enthält, die an die Routine übermittelt wurden.
CREATE PROCEDURE swapParms ( IN parm1 CHARACTER, OUT parm2 CHARACTER, INOUT parm3 CHARACTER ) BEGIN SET parm2 = parm3; SET parm3 = parm1; END;
Diese Beispielprozedur zeigt die rekursive Verwendung einer ESQL-Routine. Sie analysiert die Syntax einer Baumstruktur an sämtlichen Stellen am und unterhalb des angegebenen Ausgangspunkts und dokumentiert anschließend das Ergebnis:
SET OutputRoot.MQMD = InputRoot.MQMD; DECLARE answer CHARACTER; SET answer = ''; CALL navigate(InputRoot.XML, answer); SET OutputRoot.XML.Data.FieldNames = answer; CREATE PROCEDURE navigate (IN root REFERENCE, INOUT answer CHARACTER) BEGIN SET answer = answer || 'Reached Field... Type:' || CAST(FIELDTYPE(root) AS CHAR)|| ': Name:' || FIELDNAME(root) || ': Value :' || root || ': '; DECLARE cursor REFERENCE TO root; MOVE cursor FIRSTCHILD; IF LASTMOVE(cursor) THEN SET answer = answer || 'Field has children... drilling down '; ELSE SET answer = answer || 'Listing siblings... '; END IF; WHILE LASTMOVE(cursor) DO CALL navigate(cursor, answer); MOVE cursor NEXTSIBLING; END WHILE; SET answer = answer || 'Finished siblings... Popping up '; END;
Lautet die Eingabenachricht wie folgt:
<Person> <Name>John Smith</Name> <Salary period='monthly' taxable='yes'>-1200</Salary> </Person>
dann erstellt die Prozedur die folgende Ausgabe, die manuell formatiert wurde:
Reached Field... Type:16777232: Name:XML: Value :: Field has children... drilling down Reached Field... Type:16777216: Name:Person: Value :: Field has children... drilling down Reached Field... Type:16777216: Name:Name: Value :John Smith: Field has children... drilling down Reached Field... Type:33554432: Name:: Value :John Smith: Listing siblings... Finished siblings... Popping up Finished siblings... Popping up Reached Field... Type:16777216: Name:Salary: Value :-1200: Field has children... drilling down Reached Field... Type:50331648: Name:period: Value :monthly: Listing siblings... Finished siblings... Popping up Reached Field... Type:50331648: Name:taxable: Value :yes: Listing siblings... Finished siblings... Popping up Reached Field... Type:33554432: Name:: Value :-1200: Listing siblings... Finished siblings... Popping up Finished siblings... Popping up Finished siblings... Popping up Finished siblings... Popping up
>>--"-- Klassenname---.---Methodenname--"--------------><Dabei steht Klassenname für die Klasse, die die Methode enthält, und Methodenname gibt die Methode an, die aufgerufen werden soll. Wenn die Klasse Teil eines Pakets ist, muss der Teil mit der Klassen-ID das komplette Paketpräfix einschließen, z. B. "com.ibm.broker.test.MyClass.myMethod".
Um nach der Java-Klasse zu suchen, geht der Broker wie im Abschnitt Implementierung von Java-Klassen beschrieben vor.
public static <Rückgabetyp> <Methodenname> (< 0 - N Parameter>)
Dabei muss der <Rückgabetyp> in der Liste der Java-Datentypen IN aus der Tabelle in der Zuordnung von ESQL zum Java-Datentyp stammen (ausgenommen REFERENCE, da dieser Typ als Rückgabewert unzulässig ist) oder dem Java-Datentyp 'void' entsprechen. Die Parameterdatentypen müssen ebenfalls aus der Tabelle der Zuordnung von ESQL zum Java-Datentyp stammen. Zudem darf die Java-Methode keine exception throws-Klausel (Ausnahmeauslöser) in ihrer Signatur haben.
Sie können in Ihrer Java-Methode die API des benutzerdefinierten Java-Knotens verwenden, wenn Sie die in Einschränkungen bei Java-Routinen aufgeführten Einschränkungen beachten. Weitere Informationen zur Verwendung der API des benutzerdefinierten Knotens finden Sie unter Benutzerdefinierten Java-Knoten kompilieren.
Diese Routine enthält drei Parameter unterschiedlicher Richtungen und gibt eine Ganzzahl zurück, die dem Java-Rückgabetyp java.lang.Long entspricht.
CREATE FUNCTION myProc1( IN P1 INTEGER, OUT P2 INTEGER, INOUT P3 INTEGER ) RETURNS INTEGER LANGUAGE JAVA EXTERNAL NAME "com.ibm.broker.test.MyClass.myMethod1";
Sie können für den Aufruf von myProc1 folgenden ESQL-Ausdruck verwenden:
CALL myProc1( intVar1, intVar2, intVar3) INTO intReturnVar3; -- oder SET intReturnVar3 = myProc1( intVar1, intVar2, intVar3);
Diese Routine enthält drei Parameter unterschiedlicher Richtungen und hat den Java-Rückgabetyp void (typenlos).
CREATE PROCEDURE myProc2( IN P1 INTEGER, OUT P2 INTEGER, INOUT P3 INTEGER ) LANGUAGE JAVA nEXTERNAL NAME "com.ibm.broker.test.MyClass.myMethod2";
Sie müssen für den Aufruf von myProc2 folgenden ESQL-Ausdruck verwenden:
CALL myProc2(intVar1, intVar2, intVar3);
Die folgende Java-Klasse bietet eine Methode für jedes der Java-Beispiele:
package com.ibm.broker.test; class MyClass { public static Long myMethod1( Long P1, Long[] P2 Long[] P3) { ... } public static void myMethod2( Long P2, Long[] P2 Long[] P3) { ... } /* Wenn eine dieser Methoden aufgerufen wird: P1 kann den Wert NULL haben oder nicht (abhängig vom Wert von intVar1). P2[0] hat stets den Wert NULL (unabhängig vom Wert von intVar2). P3[0] kann den Wert NULL haben oder nicht (abhängig vom Wert von intVar3). Alles entspricht der Verwendung von LANGUAGE ESQL-Routinen. Wenn diese Methoden Werte zurückgeben: intVar1 ist unverändert intVar2 kann immer noch den Wert NULL oder einen anderen Wert haben intVar3 kann denselben Wert oder einen anderen Wert haben Alles entspricht der Verwendung von LANGUAGE ESQL-Routinen. Wenn myMethod1 Folgendes zurückgibt: intReturnVar3 ist entweder NULL (wenn die Methode NULL zurückgibt) oder enthält den Wert, den die Methode zurückgegeben hat. */ }
ESQL-Datentypen 1 | Java IN-Datentypen | Java INOUT- und OUT-Datentypen |
INTEGER, INT | java.lang.Long | java.lang.Long [] |
FLOAT | java.lang.Double | java.lang.Double[] |
DECIMAL | java.math.BigDecimal | java.math.BigDecimal[] |
CHARACTER, CHAR | java.lang.String | java.lang.String[] |
BLOB | byte[] | byte[][] |
BIT | java.util.BitSet | java.util.BitSet[] |
DATE | com.ibm.broker.plugin.MbDate | com.ibm.broker.plugin.MbDate[] |
TIME 2 | com.ibm.broker.plugin.MbTime | com.ibm.broker.plugin.MbTime[] |
GMTTIME 2 | com.ibm.broker.plugin.MbTime | com.ibm.broker.plugin.MbTime[] |
TIMESTAMP 2 | com.ibm.broker.plugin.MbTimestamp | com.ibm.broker.plugin.MbTimestamp[] |
GMTTIMESTAMP 2 | com.ibm.broker.plugin.MbTimestamp | com.ibm.broker.plugin.MbTimestamp[] |
INTERVAL | Wird nicht unterstützt | Wird nicht unterstützt |
BOOLEAN | java.lang.Boolean | java.lang.Boolean[] |
REFERENCE (auf eine Nachrichtenbaumstruktur) 3 4 5 6 | com.ibm.broker.plugin.MbElement | com.ibm.broker.plugin.MbElement[] (Wird für INOUT unterstützt, nicht für OUT) |
ROW | Wird nicht unterstützt | Wird nicht unterstützt |
LIST | Wird nicht unterstützt | Wird nicht unterstützt |
Wenn beispielsweise ein ESQL-Verweis auf OutputRoot.XML.Test als INOUT-MbElement an eine Java-Methode übergeben wird, bei Rückkehr des Aufrufs aber ein anderes MbElement an ESQL zurückgegeben wird, muss dieses andere Element ebenfalls auf eine Position innerhalb der OutputRoot-Baumstruktur verweisen.
Ein Verweis auf eine Skalarvariable kann im Aufruf einer Java-Methode verwendet wurde, vorausgesetzt, der Datentyp der Variablen, auf die verwiesen wird, entspricht dem entsprechenden Datentyp in der Java-Programmsignatur.
Es ist zulässig, Threads innerhalb Ihrer Methode zu starten. Einmal gestartete Threads dürfen jedoch keine Java-Plug-in-APIs verwenden und müssen die Steuerung wieder an den Broker zurückgeben.
Beachten Sie, dass alle Einschränkungen hinsichtlich der Verwendung der API des benutzerdefinierten Knotens auch für Java-Methoden gelten, die aus ESQL aufgerufen werden.
Die JAR-Datei wird am effizientesten und flexibelsten im Broker implementiert, wenn Sie sie der BAR-Datei hinzufügen.
Sie können die JAR-Datei manuell oder automatisch unter Verwendung der Tools zur BAR-Datei hinzufügen. Mit Hilfe der Tools lässt sich die JAR-Datei der BAR-Datei am einfachsten hinzufügen.
Wenn die Tools die korrekte Java-Klasse in einem geöffneten Java-Projekt im Arbeitsbereich finden, wird die Java-Klasse automatisch in eine JAR-Datei kompiliert und zur BAR-Datei hinzugefügt. Diese Prozedur ist mit der Prozedur für die Implementierung eines Java-Rechenknotens in einer JAR-Datei identisch (siehe Klassenladen für benutzerdefinierte Knoten.
Wenn Sie eine JAR-Datei unter Verwendung der Tools implementieren, werden bei der erneuten Implementierung der BAR-Datei, die die JAR-Datei enthält, die Java-Klassen, auf die verwiesen wird, vom neu implementierten Fluss erneut geladen; dasselbe passiert, wenn ein Nachrichtenfluss, der auf eine Java-Klasse verweist, gestoppt und neu gestartet wird. Stellen Sie sicher, dass Sie alle Flüsse, die auf die zu aktualisierende JAR-Datei verweisen, stoppen und neu starten (bzw. erneut implementieren). Damit verhindern Sie, dass einige Flüsse mit der alten Version der JAR-Datei und andere Flüsse mit der neuen Version ausgeführt werden.
Hinweis: Von den Tools werden nur JAR-Dateien und keine eigenständigen Java-Klassendateien implementiert.
Diese Prozedur muss manuell ausgeführt werden. Die Tools können für diesen Vorgang nicht verwendet werden.
Bei diesem Verfahren werden bei einer erneuten Implementierung des Nachrichtenflusses die Java-Klassen, auf die verwiesen wird, nicht erneut geladen, und der Nachrichtenfluss wird nicht gestoppt und neu gestartet. In diesem Fall können die Klassen nur neu geladen werden, indem Sie den Broker stoppen und neu starten.
Damit der Broker eine Java-Klasse finden kann, müssen Sie sicherstellen, da sie sich in einem der oben genannten Verzeichnisse befindet. Wenn der Broker die angegebene Klasse nicht finden kann, löst er eine Ausnahme aus.
Obwohl Ihnen die oben genannten Auswählmöglichkeiten für die Implementierung der JAR-Datei zur Verfügung stehen, bietet die Implementierung der BAR-Datei durch die Tools die größte Flexibilität für die erneute Implementierung der JAR-Datei.