始める前に
ロード可能インプリメンテーション・ライブラリー、または LIL、 は C ノード (またはパーサー) のインプリメンテーション・モジュールです。 LIL はダイナミック・リンク・ライブラリー (DLL) としてインプリメントされます。 これにはファイル拡張子 .dll は付けられず、.lil が付けられます。
開発者が作成する必要のあるインプリメンテーション関数は、C 言語ノード・インプリメンテーション関数でリストしています。このプロセスに役立てるために WebSphere Business Integration Message Broker によって提供されるユーティリティー関数は、C 言語ノード・ユーティリティー関数でリストしています。
WebSphere Business Integration Message Broker では、SwitchNode および TransformNode という名前の 2 つのサンプル・ユーザー定義ノードのソースが準備されています。 これらのノードは現行の状態で使用することもできますし、変更を加えてもかまいません。
概念上、メッセージ処理ノードは何らかの形でメッセージを処理するために使用され、 出力ノードはメッセージをビット・ストリームとして出力するために使用されます。 しかし、メッセージ処理ノードや出力ノードをコーディングするとき、 これらは基本的に同じものです。 出力ノードでメッセージ処理を実行することもできますし、 同様に、メッセージ処理ノードを使用してメッセージをビット・ストリームとして出力することもできます。 単純化するため、 このトピックではメッセージ処理ノードとしてノードを主に参照していますが、 どちらのタイプのノードの機能についても取り上げます。
多くの場合、ユーザー定義ノードは、 その入力ターミナルで受け取ったメッセージの内容にアクセスする必要があります。 メッセージは、構文エレメントのツリーとして表されます。 ユーティリティー関数のグループが、メッセージ管理、メッセージ・バッファー・アクセス、 構文エレメント・ナビゲーション、および構文エレメント・アクセス用に提供されます。 (ユーティリティー関数の詳細については、C 言語ノード・ユーティリティー関数を参照してください。)
たとえば、本体の最初の子の名前とタイプを照会するには、次のようにします。
void cniEvaluate( ... ){ ... /* Navigate to the target element */ rootElement = cniRootElement(&rc, message); bodyElement = cniLastChild(&rc, rootElement); bodyFirstChild = cniFirstChild(&rc, bodyElement); /* Query the name and value of the target element */ cniElementName(&rc, bodyFirstChild, (CciChar*)&elementname, sizeof(elementName)); bytes = cniElementCharacterValue( &rc, bodyfirstChild, (CciChar*)&eValue, sizeof(eValue)); ... }
受信した入力メッセージは読み取り専用です。 したがって、メッセージを変換するには、まず cniCreateMessage 関数を使用して、それを新しい出力メッセージに書き込む必要があります。 入力メッセージからエレメントをコピーするか、 あるいは、新しいエレメントを作成してそれらをメッセージに付加することができます。 新しいエレメントは通常はパーサーのドメインに入ります。
{ ... context = cniGetMessageContext(&rc, message)); outMsg = cniCreateMessage(&rc, context)); ... }
cniSetElementIntegerValue(&rc, targetElement, L"newValue", 8);
cniDeleteMessage(&rc, outMsg);
ノードは、Compute ノードの ESQL 構文を使用して ESQL 式を呼び出すことができます。 ユーザーは、ESQL 式を使用してメッセージのコンポーネントを作成および変更し、 cniSqlCreateStatement、 cniSqlSelect、 cniSqlDeleteStatement 、および cniSqlExecute 関数を使用して、 入力メッセージと外部データベースのデータの両方を参照できます。
たとえば、 データベース・テーブル内の列の内容から Result エレメントを取り込むには、 次のようにします。
{ ... sqlExpr = cniSqlCreateStatement(&rc, (NODE_CONTEXT_ST *)context->nodeObject, L"DB", CCI_SQL_TRANSACTION_AUTO, L"SET OutputRoot.XML.Result[] = (SELECT T.C1 AS Col1 FROM Database.TABLE AS T;"); ... cniSqlSelect(&rc, sqlExpr, destinationList, exceptionList, message, outMsg); cniSqlDeleteStatement(&rc, sqlExpr); ... }
ESQL の詳細については、ESQLを参照してください。
cniFinalize(&rc, outMsg, CCI_FINALIZE_NONE);
if (terminalObject) { if (cniIsTerminalAttached(&rc, terminalObject)) { if (rc == CCI_SUCCESS) { cniPropagate(&rc, terminalObject, destinationList, exceptionList, outMsg); } }
cniDeleteMessage(&rc, outMsg);
{ ... cniWriteBuffer(&rc, message); writeToDevice(cniBufferPointer(&rc, message), cniBufferSize(&rc, message)); ... }メッセージは一度だけ直列化できます。
以下の手順は、ノードをブローカーへ宣言する方法を表しています。
CciFactory LilFactoryExportPrefix * LilFactoryExportSuffix bipGetMessageflowNodeFactory()
{ CciFactory* factoryObject; int rc = 0; CciChar factoryName[] = L"SwitchNodeFactory"; CCI_EXCEPTION_ST exception_st; /* Create the Node Factory for this node */ factoryObject = cniCreateNodeFactory(0, factoryName); if (factoryObject == CCI_NULL_ADDR) { if (rc == CCI_EXCEPTION) { /* Get details of the exception */ cciGetLastExceptionData(&rc, &exception_st); /* Any local error handling can go here */ /* Rethrow the exception */ cciRethrowLastException(&rc); } /* Any further local error handling can go here */ } else { /* Define the nodes supported by this factory */ defineSwitchNode(factoryObject); } /* Return address of this factory object to the broker */ return(factoryObject); }
void defineSwitchNode(void* factoryObject){ static CNI_VFT vftable = {CNI_VFT_DEFAULT}; /* Setup function table with pointers to node implementation functions */ vftable.iFpCreateNodeContext = _createNodeContext; vftable.iFpDeleteNodeContext = _deleteNodeContext; vftable.iFpGetAttributeName = _getAttributeName; vftable.iFpSetAttribute = _setAttribute; vftable.iFpGetAttribute = _getAttribute; vftable.iFpEvaluate = _evaluate; cniDefineNodeClass(0, factoryObject, L"SwitchNode", &vftable); return; }これは構成スレッドから呼び出されます。
ユーザー定義ノードは、cniEvaluate 関数をインプリメントすることによって、 入力ノードの機能を提供するという役割を果たします。 ユーザー定義ノードは、 cniEvaluate インプリメンテーションか cniRun インプリメンテーションのいずれか、 または両方をインプリメントしていなければなりません。 そうでないと、ブローカーはそのユーザー定義ノードをロードせず、 cniDefineNodeClass ユーティリティー関数が失敗して、 CCI_MISSING_IMPL_FUNCTION が戻されます。
ユーザー定義メッセージ処理ノードが含まれたメッセージ・フローが正常にデプロイされていれば、 メッセージ・フローに渡される各メッセージごとに、 そのノードの cniEvaluate 関数が呼び出されます。
メッセージ・フロー・データがノードの入力ターミナルで受信されます。 メッセージ・フロー・データとは、メッセージ、グローバル環境、ローカル環境、および例外リストです。
void cniEvaluate( CciContext* context, CciMessage* destinationList, CciMessage* exceptionList, CciMessage* message ){ ... }
以下の手順は、ノードをインスタンス化する方法を表しています。
CciContext* _Switch_createNodeContext( CciFactory* factoryObject, CciChar* nodeName, CciNode* nodeObject ){ static char* functionName = (char *)"_Switch_createNodeContext()"; NODE_CONTEXT_ST* p; CciChar buffer[256];
p = (NODE_CONTEXT_ST *)malloc(sizeof(NODE_CONTEXT_ST)); if (p) { memset(p, 0, sizeof(NODE_CONTEXT_ST));
p->nodeObject = nodeObject;
CciCharNCpy((CciChar*)&p->nodeName, nodeName, MAX_NODE_NAME_LEN);
{ const CciChar* ucsIn = CciString("in", BIP_DEF_COMP_CCSID) ; insInputTerminalListEntry(p, (CciChar*)ucsIn); free((void *)ucsIn) ; } { 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* 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) ; }
ブローカーがキューからメッセージを取り出し、 そのメッセージがユーザー定義のメッセージ処理ノードまたは出力ノードの入力ターミナルに到着すると、 ブローカーはインプリメンテーション関数 cniEvaluate を呼び出します。 この関数はメッセージ処理スレッド上に呼び出され、メッセージを使用して何を行うかを決定します。 特に追加のインスタンスが使用される場合に、この関数はマルチスレッド上に呼び出される場合もあります。
ノードのインスタンスを削除するには、 cniDeleteNodeContext 関数を使用します。 たとえば、以下のようになります。
void _deleteNodeContext( CciContext* context ){ static char* functionName = (char *)"_deleteNodeContext()"; return; }
cniDeleteNodeContext 関数はユーザーによって 提供され、メッセージ・フローが削除されたときにブローカーによって呼び出されます。
注意 |
商標 |
ダウンロード |
ライブラリー |
技術サポート |
フィードバック
![]() ![]() |
as09980_ |