WebSphere Message Broker Version 8.0.0.5 Betriebssysteme: AIX, HP-Itanium, Linux, Solaris, Windows, z/OS

Sehen Sie sich die Informationen zur aktuellen Produktversion im IBM Integration Bus Version 9.0 an.

Empfangsknoten in C erstellen

Sie können einen benutzerdefinierten Empfangsknoten in C für den Empfang von Nachrichten in einem Nachrichtenfluss erstellen.

Vor dem Start

Eine ladbare Implementierungsbibliothek (Loadable Implementation Library, LIL) ist das Implementierungsmodul für einen C-Knoten. Eine LIL wird als gemeinsam genutzte Bibliothek oder als Dynamic Link Library (DLL) implementiert, hat jedoch die Dateierweiterung .lil, nicht .dll.

Die Implementierungsfunktionen, die Sie für den Knoten schreiben, werden unter Implementierungsfunktionen für C-Knoten aufgeführt. Sie können Dienstprogrammfunktionen aufrufen, die im Laufzeitbroker implementiert werden, um die Knotenoperation zu unterstützen; diese Funktionen werden unter Dienstprogrammfunktionen für C-Knoten aufgeführt.

WebSphere Message Broker stellt die Quelle für die zwei benutzerdefinierten Musterknoten 'SwitchNode' und 'TransformNode' bereit. Sie können diese Knoten in ihrem aktuellen Zustand verwenden oder sie ändern.

Knoten deklarieren und definieren

Sie müssen zum Deklarieren und Definieren eines benutzerdefinierten Knotens für den Broker eine Initialisierungsfunktion, bipGetMessageflowNodeFactory, in Ihrer LIL einfügen. Im Folgenden wird erläutert, wie die Initialisierungsfunktion vom Broker aufgerufen wird und wie durch diese Funktion der benutzerdefinierte Knoten deklariert und definiert wird:

  1. Die Funktion bipGetMessageflowNodeFactory zur Initialisierung wird vom Broker aufgerufen, nachdem die LIL-Datei vom Betriebssystem geladen und initialisiert wurde. Der Broker ruft diese Funktion auf, um die Möglichkeiten der LIL-Datei zu überprüfen und um herauszufinden, wie die LIL-Datei vom Broker aufgerufen werden kann. Beispiel:
    CciFactory LilFactoryExportPrefix * LilFactoryExportSuffix
    bipGetMessageflowNodeFactory()
  2. Durch die Funktion bipGetMessageflowNodeFactory wird die Dienstprogrammfunktion cniCreateNodeFactory aufgerufen. Diese Funktion gibt für alle Knoten, die von der LIL-Datei unterstützt werden, einen eindeutigen Factory-Namen (oder Gruppennamen) zurück. Jeder zurückgegebene Factory-Name (oder Gruppenname) muss für alle LIL-Dateien in einem einzelnen Laufzeit-Broker eindeutig sein.
  3. Durch die LIL-Datei muss die Dienstprogrammfunktion cniDefineNodeClass für die Übergabe der eindeutigen Namen der einzelnen Knoten und eine virtuelle Funktionstabelle mit den Adressen der Implementierungsfunktionen aufgerufen werden.
    Der folgende Code deklariert und definiert beispielsweise einen einzelnen Knoten namens 'InputxNode':
    {
    	CciFactory*      factoryObject;
    	int                rc = 0;
    		CciChar factoryName[] = L"MyNodeFactory";
    		CCI_EXCEPTION_ST exception_st;
    
    		/* Create the Node Factory for this node */
    		factoryObject = cniCreateNodeFactory(0, factoryName);
    	if (factoryObject == CCI_NULL_ADDR) {
    		
    		/* Any local error handling can go here */
    	}
    	else {
    				/* Define the nodes supported by this factory */
    		static CNI_VFT vftable = {CNI_VFT_DEFAULT};
    
    	/* Definition der Funktionstabelle mit Zeigern zu Funktionen für Knotenimplementierung */
    	vftable.iFpCreateNodeContext = _createNodeContext;
    	vftable.iFpDeleteNodeContext = _deleteNodeContext;
    	vftable.iFpGetAttributeName2 = _getAttributeName2;
    	vftable.iFpSetAttribute      = _setAttribute;
    	vftable.iFpGetAttribute2     = _getAttribute2;
    		vftable.iFpRun = _run;
    
    		cniDefineNodeClass(0, factoryObject, L"InputxNode", &vftable);
    	}
    
    	/* Rückkehradresse dieses Factory-Objekts zum Broker */
    	return(factoryObject);
    }

    Ein benutzerdefinierter Knoten stellt die Funktion eines Empfangsknotens bereit, indem er die Implementierungsfunktion cniRun implementiert.

    Benutzerdefinierte Knoten müssen entweder eine cniRun- oder cniEvaluate-Implementierungsfunktion implementieren. Ist dies nicht der Fall, lädt der Broker den benutzerdefinierten Knoten nicht und die Dienstprogrammfunktion cniDefineNodeClass schlägt mit dem Rückkehrcode CCI_MISSING_IMPL_FUNCTION fehl.

    Beispiel:
    int cniRun(                       
      CciContext* context,                
      CciMessage*      localEnvironment,        
      CciMessage* exceptionList,          
      CciMessage* message
    ){          
      ...
      /* Get data from external source */
      return CCI_SUCCESS_CONTINUE;                                    
    }
    Verwenden Sie den Rückgabewert in regelmäßigen Abständen, um die Steuerung an den Broker zurückzugeben.

    Nach dem erfolgreichen Einsetzen eines Nachrichtenflusses mit benutzerdefiniertem Empfangsknoten wird die Funktion cniRun des Knotens wiederholt aufgerufen, damit der Knoten Nachrichten abrufen und an den übrigen Nachrichtenfluss weitergeben kann.

    Informationen zum Code, der mindestens erforderlich ist, um einen benutzerdefinierten Knoten in C zu kompilieren, finden Sie unter Basiscode für C-Knoten.

Instanz des Knotens erstellen

So instanziieren Sie Ihren Knoten:

  1. Wenn der Broker die Zeiger der Funktionstabelle erhalten hat, ruft er für jede Erstellung einer Instanz des benutzerdefinierten Knotens die Funktion cniCreateNodeContext auf. Wenn beispielsweise drei Nachrichtenflüsse vorhanden sind, die Ihren benutzerdefinierten Knoten verwenden, wird die Funktion cniCreateNodeContext für jeden dieser Knoten aufgerufen. Durch diese Funktion soll Speicher für die Instanzerstellung der benutzerdefinierten Knoten reserviert werden, damit dort die Werte der konfigurierten Attribute gespeichert werden können. Beispiel:
    1. Rufen Sie die Funktion cniCreateNodeContext auf:
      CciContext* _createNodeContext(
        CciFactory* factoryObject,
        CciChar* nodeName,
        CciNode* nodeObject
      ){
        static char* functionName = (char *)"_createNodeContext()";
        NODE_CONTEXT_ST* p;
        CciChar          buffer[256];
    2. Ordnen Sie dem lokalen Kontext einen Zeiger zu und löschen Sie den Kontextbereich:
        p = (NODE_CONTEXT_ST *)malloc(sizeof(NODE_CONTEXT_ST));
      
        if (p) {
           memset(p, 0, sizeof(NODE_CONTEXT_ST));
    3. Speichern Sie den Knotenobjektzeiger im Kontext:
         p->nodeObject = nodeObject;
    4. Speichern Sie den Knotennamen:
       CciCharNCpy((CciChar*) &p->nodeName, nodeName, MAX_NODE_NAME_LEN);
    5. Geben Sie den Knotenkontext zurück:
      return (CciContext*) p;
  2. Ein Empfangsknoten enthält eine Reihe von zugeordneten Ausgabeterminals, normalerweise aber keine Eingabeterminals. Verwenden Sie die Dienstprogrammfunktion cniCreateOutputTerminal, um einem Empfangsknoten Ausgabeterminals hinzuzufügen, wenn eine Instanz des Knotens erstellt wird. Diese Funktionen müssen innerhalb der Implementierungsfunktion cniCreateNodeContext aufgerufen werden. Gehen Sie beispielweise bei der Definition eines Knotens mit drei Ausgabeterminals folgendermaßen vor:
       {
          const CciChar* ucsOut = CciString("out", BIP_DEF_COMP_CCSID) ;
          insOutputTerminalListEntry(p, (CciChar*)ucsOut);
          free((void *)ucsOut) ;
        }
        {
          const CciChar* ucsFailure = CciString("failure", BIP_DEF_COMP_CCSID) ;
          insOutputTerminalListEntry(p, (CciChar*)ucsFailure);
          free((void *)ucsFailure) ;
        }    
        {
          const CciChar* ucsCatch = CciString("catch", BIP_DEF_COMP_CCSID) ;
          insOutputTerminalListEntry(p, (CciChar*)ucsCatch);
          free((void *)ucsCatch) ;    }
    Informationen zum Code, der mindestens erforderlich ist, um einen benutzerdefinierten Knoten in C zu kompilieren, finden Sie unter Basiscode für C-Knoten.

Attribute festlegen

Attribute werden festgelegt, wenn Sie den Broker starten oder den Nachrichtenfluss mit neuen Werten erneut einsetzen.

Nach der Erstellung von Ausgabeterminals wird vom Broker die Funktion cniSetAttribute aufgerufen, um die Werte der konfigurierten Attribute des benutzerdefinierten Knotens zu übergeben. Beispiel:
    {
      const CciChar* ucsAttr = CciString("nodeTraceSetting", BIP_DEF_COMP_CCSID) ;
      insAttrTblEntry(p, (CciChar*)ucsAttr, CNI_TYPE_INTEGER);
      _setAttribute(p, (CciChar*)ucsAttr, (CciChar*)constZero);
      free((void *)ucsAttr) ;
    }
    {
      const CciChar* ucsAttr = CciString("nodeTraceOutfile", BIP_DEF_COMP_CCSID) ;
      insAttrTblEntry(p, (CciChar*)ucsAttr, CNI_TYPE_STRING);
      _setAttribute(p, (CciChar*)ucsAttr, (CciChar*)constSwitchTraceLocation);
      free((void *)ucsAttr) ;
    }
Die Anzahl der Konfigurationsattribute in einem Knoten ist nicht begrenzt. Ein benutzerdefinierter Knoten darf jedoch kein Attribut implementieren, das bereits als Basiskonfigurationsattribut implementiert ist. Die Basisattribute lauten wie folgt:
  • label
  • userTraceLevel
  • traceLevel
  • userTraceFilter
  • traceFilter

Knotenfunktionen implementieren

Wenn der Broker einen Empfangsknoten entdeckt, ruft er in regelmäßigen Intervallen die Funktion cniRun dieses Knotens auf. Durch die Funktion cniRun wird die weitere Vorgehensweise entschieden. Wenn Daten zur Verarbeitung vorhanden sind, kann die cniRun-Funktion die Nachricht weitergeben. Wenn keine Daten zur Verarbeitung vorhanden sind, sollte von der cniRun-Funktion CCI_TIMEOUT zurückgegeben werden, damit der Broker mit den Konfigurationsänderungen fortfahren kann.

Gehen Sie beispielsweise folgendermaßen vor, um den Knoten für den Aufruf von cniDispatchThread und die Verarbeitung der Nachricht oder für die Rückgabe mit CCI_TIMEOUT zu konfigurieren:
If ( anything to do )
	CniDispatchThread;

   /* do the work */

		If ( work done O.K.)
				Return CCI_SUCCESS_CONTINUE;
	Else
				Return CCI_FAILURE_CONTINUE;
Else
  Return CCI_TIMEOUT;

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

Die Implementierung eines Empfangsknotens bestimmt normalerweise, durch welchen Nachrichtenparser eine Eingabenachricht anfangs syntaktisch analysiert wird. Beispiel: Der MQInput-Knoten 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 oder überschrieben werden:

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 sind mit den Werten identisch, die vom MQInput-Knoten unterstützt werden. (Weitere Informationen hierzu finden Sie unter MQInput-Knoten.)
messageSetProperty
Optionales Attribut, das die Nachrichtensatz-ID oder den Nachrichtensatznamen im Feld Nachrichtensatz 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.
Durch das Schreiben eines benutzerdefinierten Empfangsknotens, der immer mit den Daten einer bekannten Struktur beginnt, können Sie sicherstellen, dass ein bestimmter Parser die Ausführung am Beginn der Daten startet. Der MQInput-Knoten liest beispielsweise nur Daten aus den WebSphere MQ-Warteschlangen, somit beginnen diese Daten immer mit 'MQMD', und für 'firstParserClassName' wird vom MQInput der Wert 'MQHMD' festgelegt. Wenn Ihr benutzerdefinierter Knoten immer Daten bearbeitet, die mit einer Struktur beginnen, für die von einem bestimmten Parser (z. B. "MYPARSER") eine Syntaxanalyse durchgeführt werden kann, wird 'firstParserClassName' folgendermaßen auf 'MYPARSER' festgelegt:
  1. Deklarieren Sie die folgenden Implementierungsfunktionen:
    CciFactory LilFactoryExportPrefix * LilFactoryExportSuffix bipGetMessageflowNodeFactory()
    {
      ....
      CciFactory*      factoryObject;
      ....
      factoryObject = cniCreateNodeFactory(0, (unsigned short *)constPluginNodeFactory);
      ...
      vftable.iFpCreateNodeContext = _createNodeContext;
      vftable.iFpSetAttribute      = _setAttribute;
      vftable.iFpGetAttribute      = _getAttribute;
      ...  
      cniDefineNodeClass(&rc, factoryObject, (CciChar*)constSwitchNode, &vftable);
      ...
      return(factoryObject);
    }
  2. Legen Sie das Attribut in der cniCreateNodeContext-Implementierungsfunktion fest:
    CciContext* _createNodeContext(
      CciFactory* factoryObject,
      CciChar* nodeName,
      CciNode* nodeObject
    ){
      NODE_CONTEXT_ST* p;
      ...
    
        /* Allocate a pointer to the local context */
        p = (NODE_CONTEXT_ST *)malloc(sizeof(NODE_CONTEXT_ST));
        /* Create attributes and set default values */
        {
          const CciChar* ucsAttrName  = CciString("firstParserClassName", BIP_DEF_COMP_CCSID) ;
          const CciChar* ucsAttrValue = CciString("MYPARSER", BIP_DEF_COMP_CCSID) ;
          insAttrTblEntry(p, (CciChar*)ucsAttrName, CNI_TYPE_INTEGER);
          /*see sample BipSampPluginNode.c for implementation of insAttrTblEntry*/
    
          _setAttribute(p, (CciChar*)ucsAttrName, (CciChar*)ucsAttrValue);
          free((void *)ucsAttrName) ;
          free((void *)ucsAttrValue) ;
        }
    Im Codebeispiel oben wird die Methode insAttrTblEntry aufgerufen. Sie ist in den benutzerdefinierten Musterknoten 'Umschaltungsknoten' und 'Umsetzungsknoten' deklariert.

Knoteninstanz löschen

Knoten werden beim erneuten Einsetzen eines Nachrichtenflusses oder beim Stoppen des Prozesses der Ausführungsgruppe mithilfe des Befehls mqsistop gelöscht). Wenn ein Knoten gelöscht wird, sollten der gesamte verwendete Speicher und die verwendeten Ressourcen durch Aufruf der Funktion cniDeleteNodeContext freigegeben werden. Beispiel:

void _deleteNodeContext(
  CciContext* context
){
  static char* functionName = (char *)"_deleteNodeContext()";

  return;
}
Bemerkungen | Marken | Downloads | Bibliothek | Support | Feedback

Copyright IBM Corporation 1999, 2014Copyright IBM Corporation 1999, 2014.

        
        Letzte Aktualisierung:
        
        Letzte Aktualisierung: 2015-02-28 16:22:05


TaskthemaTaskthema | Version 8.0.0.5 | as09960_