Empfangsknoten in Java erstellen

Vorbereitungen

Stellen Sie sicher, dass Sie die folgenden Abschnitte gelesen und verstanden haben:

Neues Java-Projekt erstellen

Java-Knoten können Sie in der Workbench erstellen. Gehen Sie für die Erstellung des dazu erforderlichen neuen Java-Projekts folgendermaßen vor:
  1. Wechseln Sie zur Java-Perspektive.
  2. Klicken Sie Datei > Neu > Projekt. Wählen Sie im linken Menü Java aus, und wählen Sie anschließend aus dem rechten Menü Java Project (Java-Projekt) aus.
  3. Benennen Sie das Projekt.

    Die Anzeige 'Java Settings' (Java-Einstellungen) erscheint.

  4. Wählen Sie die Registerkarte 'Libraries' (Bibliotheken) aus, und klicken Sie auf Add External JARs (Externe JARs hinzufügen).
  5. Wählen Sie Installationsverzeichnis\classes\jplugin2.jar aus.
  6. Folgen Sie den Eingabeaufforderungen in den anderen Registerkarten, um weitere Build-Einstellungen zu definieren.
  7. Klicken Sie auf Fertig stellen.
Sie können anschließend die Quelle für Ihren Java-Knoten in diesem Projekt entwickeln.

Klasse des Empfangsknotens deklarieren

Jede Klasse, durch die MbInputNodeInterface implementiert wird und im LIL-Pfad des Brokers enthalten ist, wird mit dem Broker als Empfangsknoten registriert. Bei der Implementierung von MbInputNodeInterface muss auch eine run-Methode für diese Klasse implementiert werden. Die Methode run zeigt den Start des Nachrichtenflusses an, enthält die Daten, in der die Nachricht erfasst wird, und gibt die Daten an den Fluss weiter. Der Broker ruft die Methode run auf, wenn Threads gemäß dem angegebenen Threading-Modell verfügbar werden.

Wenn Sie beispielsweise die Klasse des Empfangsknotens deklarieren möchten, gehen Sie folgendermaßen vor:

package com.ibm.jplugins;

import com.ibm.broker.plugin.*;

public class BasicInputNode extends MbInputNode implements MbInputNodeInterface
{
...
In der Workbench können Sie dazu folgende Schritte ausführen:
  1. Klicken Sie auf Datei > Neu > Klasse.
  2. Legen Sie für die Namensfelder des Pakets und der Klasse die entsprechenden Werte fest.
  3. Löschen Sie den Text im Textfeld 'Superclass' (Superklasse), und klicken Sie auf die Schaltfläche Durchsuchen.
  4. Wählen Sie MbInputNode aus.
  5. Klicken Sie neben dem Textfeld 'Interface' (Schnittstelle) auf die Schaltfläche Hinzufügen, und wählen Sie MbInputNodeInterface aus.
  6. Klicken Sie auf Fertig stellen.

Knotenkonstruktor definieren

Wenn eine Instanz des Knotens erstellt wird, wird der Konstruktor der Knotenklasse des Benutzers aufgerufen. Dabei können Sie die Knotenterminals erstellen und Standardwerte für die Attribute initialisieren.

Einem Empfangsknoten sind eine Reihe von Ausgabeterminals zugeordnet, er verfügt jedoch normalerweise nicht über Eingabeterminals. Verwenden Sie die Methode createOutputTerminal, um einem Knoten Ausgabeterminals hinzuzufügen, wenn eine Instanz des Knotens erstellt wird. Im Folgenden finden Sie ein Beispiel für die Erstellung eines Knotens mit drei Ausgabeterminals:

public BasicInputNode() throws MbException
{
	createOutputTerminal ("out");
	createOutputTerminal ("failure");
	createOutputTerminal ("catch");
setAttribute ("firstParserClassName","myParser");
attributeVariable = "none";
}

Externe Daten in einem Puffer empfangen

Ein Empfangsknoten kann wie jedes andere Java-Programm Daten aus allen Arten von externen Quellen, z. B. einem Dateisystem, einer Warteschlange oder einer Datenbank, empfangen, solange die Ausgabe des Knotens im richtigen Format vorliegt.

Sie müssen einen Eingabepuffer (oder einen Bitstrom) bereithalten, in dem Eingabedaten enthalten sind, und ihn einem Nachrichtenobjekt zuordnen. Dann erstellen Sie mit der Methode createMessage der Klasse MbInputNode eine Nachricht aus einer Bytefeldgruppe, und anschließend generieren Sie aus dieser Nachricht ein gültiges Nachrichten-Assembly. Weitere Informationen zu diesen Methoden finden Sie im Abschnitt Java-API. Wenn Sie beispielsweise die Eingabe aus einer Datei lesen möchten, gehen Sie wie folgt vor:

  1. Erstellen Sie einen Eingabedatenstrom, um die Daten aus der Datei zu lesen:
    FileInputStream inputStream = new FileInputStream("myfile.msg");
  2. Erstellen Sie eine Bytefeldgruppe, die dieselbe Größe wie die Eingabedatei hat:
    byte[] buffer = new byte[inputStream.available()];
  3. Lesen Sie die Daten aus der Datei in die Bytefeldgruppe ein:
    inputStream.read(buffer);
  4. Schließen Sie den Eingabedatenstrom:
    inputStream.close();
  5. Erstellen Sie eine Nachricht, die in die Warteschlange eingereiht werden soll:
    MbMessage msg = createMessage(buffer);
  6. Erstellen Sie ein neues Nachrichten-Assembly, das diese Nachricht enthalten soll:
    msg.finalizeMessage(MbMessage.FINALIZE_VALIDATE);
    MbMessageAssembly newAssembly =
         new MbMessageAssembly( assembly, msg );

Nachricht weitergeben

Wenn Sie ein Nachrichten-Assembly erstellt haben, können Sie dies an einen der Terminals des Knotens weitergeben.

Geben Sie beispielsweise Folgendes ein, um das Nachrichten-Assembly an das Ausgangsterminal weiterzugeben:
MbOutputTerminal out = getOutputTerminal("out");
out.propagate(newAssembly);
Gehen Sie zum Löschen der Nachricht folgendermaßen vor:
msg.clearMessage();

Rufen Sie zum Löschen des Speichers, der der Nachrichtenbaumstruktur zugeordnet ist, die clearMessage()-Funktion innerhalb des letzten Try-/Catch-Blocks auf.

Threading und Transaktionalität steuern

Die Broker-Infrastruktur verarbeitet Transaktionen wie das Festschreiben einer WebSphere MQ- oder Datenbank-Arbeitseinheit, wenn die Nachrichtenverarbeitung abgeschlossen ist. Allerdings befinden sich Ressourcen, die in einem benutzerdefinierten Knoten geändert wurden, nicht zwangsläufig unter transaktionsorientierter Steuerung des Brokers.

Jeder Thread eines Nachrichtenflusses wird aus einem Thread-Pool zugewiesen, der für jeden Nachrichtenfluss verwaltet wird, und beginnt die Ausführung in der Methode run.

Der benutzerdefinierte Knoten verwendet Rückgabewerte, um anzugeben, ob eine Transaktion erfolgreich war, um zu steuern, ob Transaktionen festgeschrieben oder zurückgesetzt werden, und um zu steuern, wann der Thread an den Pool zurückgegeben wird. Alle nicht verarbeiteten Ausnahmebedingungen werden von der Broker-Infrastruktur abgefangen, und die Transaktion wird zurückgesetzt.

Sie bestimmen das Verhalten von Transaktionen und Threads, indem Sie den entsprechenden Rückgabewert verwenden:

MbInputNode.SUCCESS_CONTINUE
Die Transaktion wird festgeschrieben, und der Broker ruft die Methode run erneut mit demselben Thread auf.
MbInputNode.SUCCESS_RETURN
Die Transaktion wird festgeschrieben, und der Thread wird an den Thread-Pool zurückgegeben, wobei vorausgesetzt wird, dass dies nicht der einzige Thread für diesen Nachrichtenfluss ist.
MbInputNode.FAILURE_CONTINUE
Die Transaktion wird zurückgesetzt, und der Broker ruft die Methode run erneut mit demselben Thread auf.
MbInputNode.FAILURE_RETURN
Die Transaktion wird zurückgesetzt, und der Thread wird in den Thread-Pool zurückgegeben. Dabei wird vorausgesetzt, dass es sich nicht um den einzigen Thread für diesen Nachrichtenfluss handelt.
MbInputNode.TIMEOUT
Die Methode run darf nicht unbegrenzt blockieren, während sie auf Eingabedaten wartet. Während der Nachrichtenfluss durch Benutzercode blockiert wird, können Sie den Broker nicht beenden oder neu konfigurieren. Die Methode run muss die Steuerung regelmäßig durch Rückgabe an den Broker abgeben. Wenn nach einer bestimmten Zeit (z. B. 5 Sekunden) keine Eingabedaten empfangen wurden, sollte die Rückgabe der Methode mit dem Rückkehrcode TIMEOUT erfolgen. Die Methode run des Empfangsknotens wird dann gleich wieder aufgerufen, vorausgesetzt, der Broker muss nicht neu konfiguriert oder beendet werden.
Um Multithread--Nachrichtenflüsse zu erstellen, rufen Sie die Methode dispatchThread auf, nachdem eine Nachricht erstellt wurde, aber bevor die Nachricht an ein Ausgabeterminal weitergegeben wird. Dadurch wird gewährleistet, dass nur ein Thread auf Daten wartet, während andere Threads die Nachricht verarbeiten. Neue Threads werden bis zu dem Maximalwert, der durch das Attribut 'additionalInstances' des Nachrichtenflusses angegeben wird, aus dem Thread-Pool abgerufen. Beispiel:
public int run( MbMessageAssembly assembly ) throws MbException
{
  byte[] data = getDataWithTimeout();  // user supplied method
                                       // returns null if timeout
  if( data == null )
    return TIMEOUT;

  MbMessage msg = createMessage( data );
  msg.finalizeMessage( MbMessage.FINALIZE_VALIDATE );
  MbMessageAssembly newAssembly =
       new MbMessageAssembly( assembly, msg );

  dispatchThread();

  getOutputTerminal( "out" ).propagate( newAssembly );

  return SUCCESS_RETURN;
}

Knotennamen deklarieren

Der Knotennamen muss so deklariert werden, wie er von der Workbench gekennzeichnet wird. Alle Knotennamen müssen die Endung "Node" haben. Deklarieren Sie die Namen mit der folgenden Methode:

public static String getNodeName()
{
   return "BasicInputNode";
}
Wenn diese Methode nicht deklariert ist, erstellt das Framework der Java-API einen standardmäßigen Knotennamen nach folgenden Regeln:
  • Der Klassenname wird an den Paketnamen angehängt.
  • Die Punkte werden entfernt, und der erste Buchstabe von jedem Teil des Paket- und Klassenamens wird in Großbuchstaben gesetzt.
Beispiel: Standardmäßig wird folgender Klasse der Knotenname "ComIbmPluginsamplesBasicInputNode" zugewiesen:
package com.ibm.pluginsamples;
public class BasicInputNode extends MbInputNode implements MbInputNodeInterface
{
   ...

Attribute deklarieren

Knotenattribute werden auf die gleiche Weise deklariert wie Eigenschaften von JavaBeans. Die Methoden GET und SET müssen für die Attribute geschrieben werden, und das API-Framework schließt aus den Regeln für die JavaBean-Introspektion auf die Attributnamen. Sie können beispielsweise die folgenden zwei Methoden deklarieren:

private String attributeVariable;

public String getFirstAttribute()
{
  return attributeVariable;
}

publc void setFirstAttribute(String value)
{
  attributeVariable = value;
}

Der Broker schließt daraus, dass in diesem Knoten ein Attribut mit der Bezeichnung 'firstAttribute' enthalten ist. Dieser Name wird von den Namen der Methoden zum Abrufen und Festlegen abgeleitet, und nicht von den Variablennamen von Mitgliedern interner Klassen. Attribute können nur als Zeichenfolgen festgelegt werden. Deshalb müssen numerische Werte in den Methoden zum Abrufen und Festlegen in Zeichenfolgen umgewandelt werden. In der folgenden Methode wird beispielsweise ein Attribut mit der Bezeichnung 'timeInSeconds' definiert:

int seconds;

public String getTimeInSeconds()
{
  return Integer.toString(seconds);
}

public void setTimeInSeconds(String value)
{
  seconds = Integer.parseInt(value);
}

Knotenfunktion implementieren

Wie bereits beschrieben, wird die Methode run vom Broker zur Erstellung der Eingabenachricht aufgerufen. Durch diese Methode wird die erforderliche Verarbeitungsfunktion für den Empfangsknoten bereitgestellt.

Standardmäßige Attribute des Nachrichtenparsers überschreiben (optional)

Die Implementierung eines Empfangsknotens bestimmt normalerweise, durch welchen Nachrichtenparser eine Eingabenachricht anfangs syntaktisch analysiert wird. Beispiel: Der Primitive-Knoten MQInput gibt an, dass ein MQMD-Parser für die Syntaxanalyse des MQMD-Headers erforderlich ist. Durch einen benutzerdefinierten Empfangsknoten können ein entsprechender Header oder Nachrichtenparser sowie der Modus ausgewählt werden, durch den die Syntaxanalyse gesteuert wird, indem die folgenden, standardmäßig enthaltenen Attribute verwendet werden, die überschrieben werden können:

rootParserClassName
Definiert den Namen des Root-Parsers, durch den die vom benutzerdefinierten Empfangsknoten unterstützten Nachrichtenformate syntaktisch analysiert werden. Die Standardeinstellung ist der bereitgestellte Root-Parser GenericRoot, durch den der Broker die verschiedenen Parser zuordnet und verkettet. Dieser Attributwert wird von einem Knoten normalerweise nicht geändert.
firstParserClassName
Definiert den Namen des ersten Parsers in einer Parser-Kette, durch die die Syntaxanalyse des Bitstroms durchgeführt wird. Die Standardeinstellung ist XML.
messageDomainProperty
Optionales Attribut, durch das der Name des Nachrichtenparsers definiert wird, der für die Syntaxanalyse der Eingabenachricht erforderlich ist. Die unterstützten Werte entsprechen den Werten, die vom MQInput-Knoten unterstützt werden. (Weitere Informationen zum MQEmpfangsknoten finden Sie unter MQEmpfangsknoten.)
messageSetProperty
Optionales Attribut, das die Nachrichtengruppen-ID oder den Nachrichtengruppennamen im Feld Nachrichtengruppe definiert, falls der MRM-Parser durch das Attribut messageDomainProperty angegeben wurde.
messageTypeProperty
Optionales Attribut, das die Nachrichten-ID im Feld Nachrichtentyp definiert, falls der MRM-Parser durch das Attribut messageDomainProperty angegeben wurde.
messageFormatProperty
Optionales Attribut, das das Nachrichtenformat im Feld Nachrichtenformat definiert, falls der MRM-Parser durch das Attribut messageDomainProperty angegeben wurde.

Knoteninstanz löschen

Eine Knoteninstanz wird durch folgende Aktionen gelöscht:
  • Beenden des Brokers.
  • Entfernen des Knotens oder den Nachrichtenflusses, in dem der Knoten enthalten ist, und erneutes Einsetzen der Konfiguration.
Beim Löschen muss der Knoten möglicherweise unterrichtet werden, damit Vorgänge zur Bereinigung, wie beispielsweise das Schließen von Sockets, ausgeführt werden können. Wenn durch den Knoten die optionale Methode onDelete implementiert wird, wird diese Aktion durch den Broker direkt vor dem Löschen des Knotens aufgerufen.

Implementieren Sie die Methode onDelete folgendermaßen:

public void onDelete()
{
  // perform node cleanup if necessary
}
Zugehörige Informationen
Java-API
Bemerkungen | Marken | Downloads | Bibliothek | Unterstützung | Rückmeldung
Copyright IBM Corporation 1999, 2006 Letzte Aktualisierung: 23. Aug. 2006
as09950_