ユーザー定義メッセージ処理またはユーザー定義出力ノードを C で作成してから、その機能を拡張することができます。
トピックC でのメッセージ処理ノードまたは出力ノードの作成に目を通しておきます。
多くの場合、ユーザー定義ノードは、入力ターミナルで受け取ったメッセージの内容にアクセスする必要があります。 メッセージは、構文エレメントのツリーとして表されます。 ユーティリティー関数のグループが、メッセージ管理、メッセージ・バッファー・アクセス、 構文エレメント・ナビゲーション、および構文エレメント・アクセス用に提供されます。 (ユーティリティー関数の詳細については、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));
...
}
エレメント・ツリーのビット・ストリーム表現にアクセスするには、cniElementAsBitstream 関数を使用することができます。 この関数を使用すると、メッセージ内の任意のエレメントのビット・ストリーム表現を取得できます。 この関数およびサンプル・コードの使用方法の詳細については、cniElementAsBitstreamを参照してください。
受信した入力メッセージは読み取り専用です。したがって、メッセージを変換するには、まず cniCreateMessage 関数を使用して、それを新しい出力メッセージに書き込む必要があります。 入力メッセージからエレメントをコピーするか、 あるいは、新しいエレメントを作成してそれらをメッセージに付加することができます。 新しいエレメントは通常はパーサーのドメインに入ります。
{
...
context = cniGetMessageContext(&rc, message));
outMsg = cniCreateMessage(&rc, context));
...
}
cniCopyElementTree(&rc, sourceElement, targetElement);
cniSetElementIntegerValue(&rc, targetElement, L"newValue", 8);
cniDeleteMessage(&rc, outMsg);
cniCreateElementAsFirstChildUsingParser
cniCreateElementAsLastChildUsingParser
cniCreateElementAfterUsingParser
cniCreateElementBeforeUsingParser
cniCreateElementAsFirstChild
cniCreateElementAsLastChild
cniCreateElementAfter
cniCreateElementBefore
ノードは、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.XMLNS.Result[] = (SELECT T.C1 AS Col1 FROM Database.TABLE AS T;");
...
cniSqlSelect(&rc, sqlExpr, localEnvironment, exceptionList, message, outMsg);
cniSqlDeleteStatement(&rc, sqlExpr);
...
}
ESQL の詳細については、ESQL の概要を参照してください。
ユーザー定義ノードが主として ESQL を使用する場合は、Compute ノードの使用を検討してください。
cniFinalize(&rc, outMsg, CCI_FINALIZE_NONE);
if (terminalObject) {
if (cniIsTerminalAttached(&rc, terminalObject)) {
if (rc == CCI_SUCCESS) {
cniPropagate(&rc, terminalObject, localEnvironment, exceptionList, outMsg);
}
}
上記の例で、 cniIsTerminalAttached 関数は、 メッセージを指定されたターミナルに伝搬できるか検査するために使用されています。 cniIsTerminalAttached 関数が使用されず、 ターミナルがコネクターによって他のノードに付加されていない場合、 メッセージは伝搬されず、警告メッセージは戻されません。 cniIsTerminalAttached 関数を使用して、このエラーが起こらないようにしてください。
cniDeleteMessage(&rc, outMsg);
変換されたメッセージはビット・ストリームにシリアライズされる必要があります。メッセージは、一度のみシリアライズできます。
{
...
cniWriteBuffer(&rc, message);
writeToDevice(cniBufferPointer(&rc, message), cniBufferSize(&rc, message));
...
}
この例では、メソッド writeToDevice は、
出力装置にビット・ストリームを書き込むユーザー作成メソッドです。WebSphere MQ キューにメッセージを書き込むときは、ユーザー定義出力ノードを作成しないでください。この場合には、提供されている MQOutput ノードを使用します。 これは、ブローカーが、スレッド単位で、内部的に WebSphere MQ 接続およびオープン・キュー・ハンドルを保守し、 それらはパフォーマンスを最適化するためにキャッシュに入れられるからです。 さらに、ブローカーは特定の WebSphere MQ イベントの発生時に リカバリー・シナリオを処理しますが、 WebSphere MQ MQI 呼び出しが ユーザー定義出力ノードで使用された場合、このリカバリーは不利な影響を受けます。