Java での入力ノードの作成

始める前に

以下のトピックを読み、理解していることを確認してください。
Java ユーザー定義ノードは、.jar ファイルとして配布されます。 このトピックでは、 Java を使用して入力ノードを作成するために実行する必要のあるステップについて説明します。 以下のステップについて要約しています。
  1. 新規 Java プロジェクトの作成
  2. 入力ノード・クラスの宣言
  3. ノードのコンストラクターの定義
  4. 外部データのバッファーへの受信
  5. メッセージの伝搬
  6. スレッド化とトランザクション性の制御
  7. ノード名の宣言
  8. 属性の宣言
  9. ノード機能のインプリメント
  10. デフォルトのメッセージ・パーサー属性のオーバーライド (オプション)
  11. ノードのインスタンスの削除

新規 Java プロジェクトの作成

ワークベンチ内から Java ノードを作成できます。 このためには、次のようにして新規 Java プロジェクトを作成する必要があります。
  1. Java パースペクティブに切り替えます。
  2. 「ファイル」>「新規」>「プロジェクト」をクリックします。 左方のメニューから「Java」を選択して、 右方のメニューから「Java プロジェクト」を選択します。
  3. プロジェクトに名前を付けます。

    「Java 設定」パネルが表示されます。

  4. 「ライブラリー」タブを選択して、「外部 JAR の追加」をクリックします。
  5. install_dir¥classes¥jplugin2.jar を選択します。
  6. 「その他」タブのプロンプトに従って、他のビルド設定を定義します。
  7. 「完了」をクリックします。
このようにしたら、次はこのプロジェクトの中で Java ノードのソースを開発することができます。

入力ノード・クラスの宣言

MbInputNodeInterface をインプリメントし、ブローカーの LIL パスに含められるクラスは、 入力ノードとしてブローカーに登録されます。 MbInputNodeInterface をインプリメントする場合は、このクラスの run メソッドもインプリメントしなければなりません。run メソッドは、 メッセージ・フローの開始を表し、 メッセージを公式化するデータを含んでいて、これをフローに伝搬します。 ブローカーは、スレッドが使用可能になると、 指定されたスレッド化モデルに従って run メソッドを呼び出します。

入力ノード・クラスを宣言するには、例えば次のようにします。

package com.ibm.jplugins;

import com.ibm.broker.plugin.*;

public class BasicInputNode extends MbInputNode implements MbInputNodeInterface
{
...
次のようにして、ワークベンチで実行できます。
  1. 「ファイル」>「新規」>「クラス」をクリックします。
  2. パッケージおよびクラス名フィールドに適切な値を設定します。
  3. 「スーパークラス」テキスト・フィールドのテキストを削除し、「ブラウズ」をクリックします。
  4. MbInputNode を選択します。
  5. 「インターフェース」テキスト・フィールドの横にある「追加」ボタンをクリックして、 MbInputNodeInterface を選択します。
  6. 「完了」をクリックします。

ノードのコンストラクターの定義

ノードがインスタンス化されるときは、 ユーザーのノード・クラスのコンストラクターが呼び出されます。 これは、ノードのターミナルを作成し、属性のデフォルト値を初期設定する場所です。

入力ノードには、いくつかの出力ターミナルが関連付けられますが、 通常は入力ターミナルはありません。 ノードに出力ターミナルを追加するには、 ノードをインスタンス化するときに createOutputTerminal メソッドを使用します。 例えば、3 つの出力ターミナルを持つノードを作成するには、 次のようにします。

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

外部データのバッファーへの受信

入力ノードは、ノードからの出力が正しい形式になっている限り、 どんなタイプの外部ソース (ファイル・システム、キュー、またはデータベースなど) からでも、 他の Java プログラムと同じようにデータを受信することができます。

ユーザーは入力データを格納する入力バッファー (またはビット・ストリーム) を準備し、これをメッセージ・オブジェクトと関連付けます。 MbInputNode クラスの createMessage メソッドを使用してバイト・アレイからメッセージを作成し、 このメッセージから有効なメッセージ・アセンブリーを生成します。 これらのメソッドについての詳細は、Java API を参照してください。例えば、ファイルから入力データを読み取るには、次のようにします。

  1. ファイルから読み取る入力ストリームを作成します。
    FileInputStream inputStream = new FileInputStream("myfile.msg");
  2. 入力ファイルのサイズのバイト・アレイを作成します。
    byte[] buffer = new byte[inputStream.available()];
  3. ファイルからバイト・アレイに読み取ります。
    inputStream.read(buffer);
  4. 入力ストリームを閉じます。
    inputStream.close();
  5. キューに書き込むメッセージを作成します。
    MbMessage msg = createMessage(buffer);
  6. このメッセージを保管するための新しいメッセージ・アセンブリーを作成します。
    msg.finalizeMessage(MbMessage.FINALIZE_VALIDATE);
    MbMessageAssembly newAssembly =
         new MbMessageAssembly(assembly, msg);

メッセージの伝搬

メッセージ・アセンブリーを作成したら、それをノードのターミナルの 1 つに伝搬することができます。

例えば、メッセージ・アセンブリーを "out" ターミナルに伝搬するには、次のようにします。
MbOutputTerminal out = getOutputTerminal("out");
out.propagate(newAssembly);
メッセージを削除するには、次のようにします。
msg.clearMessage();

メッセージ・ツリー用に割り振られているメモリーをクリアするには、最後の try/catch ブロック内で clearMessage() 関数を呼び出します。

スレッド化とトランザクション性の制御

ブローカー・インフラストラクチャーは、 メッセージ処理の完了時の WebSphere MQ やデータベースの作業単位のコミットの制御などのトランザクション問題を処理します。 ただし、ユーザー定義ノード内から変更されたリソースは、ブローカーのトランザクション制御に置かれるとは限りません。

各メッセージ・フロー・スレッドは、 各メッセージ・フローごとに維持されているスレッドのプールから割り振られ、 run メソッドで実行を開始します。

ユーザー定義ノードが戻り値を使用して、トランザクションが正常かどうかを示し、 トランザクションをコミットするかロールバックするか、 また、いつスレッドをプールに戻すかを制御します。 ブローカーのインフラストラクチャーが処理されない例外を検出した場合、 トランザクションはロールバックされます。

トランザクションとスレッド化の動作は、以下の適切な戻り値を使用して判断します。

MbInputNode.SUCCESS_CONTINUE
トランザクションはコミットされ、 ブローカーが同じスレッドを使用して再び run メソッドを呼び出します。
MbInputNode.SUCCESS_RETURN
トランザクションがコミットされ、 このメッセージ・フローに対する唯一のスレッドでなければ、スレッドがスレッド・プールに戻されます。
MbInputNode.FAILURE_CONTINUE
トランザクションはロールバックされ、 ブローカーが同じスレッドを使用して再び run メソッドを呼び出します。
MbInputNode.FAILURE_RETURN
トランザクションがロールバックされ、 このメッセージ・フローに対する唯一のスレッドでなければ、スレッドがスレッド・プールに戻されます。
MbInputNode.TIMEOUT
run メソッドが、 入力データの到着を待ちながらいつまでもフローを阻止することがあってはなりません。 フローがユーザー・コードによってブロックされている間は、 そのブローカーをシャットダウンしたり再構成したりすることができません。 run メソッドは、 定期的に run メソッドから制御を戻してブローカーに譲る必要があります。 特定の期間 (例えば、5 秒間) が過ぎても入力データが受信されない場合、 メソッドは TIMEOUT 戻りコードと共に制御を戻さなければなりません。 ブローカーをシャットダウンしたり再構成したりする必要がなければ、 入力ノードの run メソッドがすぐにまた呼び出されます。
マルチスレッド・メッセージ・フローを作成する場合は、 メッセージの作成後、そのメッセージを出力ターミナルに伝搬する前に、 dispatchThread メソッドを呼び出します。 こうすると、他のスレッドがメッセージを処理している間に、 1 つのスレッドだけがデータを待つようになります。 スレッド・プールからは、 メッセージ・フローの additionalInstances 属性で指定された最大限度までの新規スレッドが取得されます。 例えば、次のようにします。
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;
}

ノード名の宣言

ノードの名前を宣言して、ノードがワークベンチに識別されるようにする必要があります。 すべてのノード名は末尾が "Node" でなければなりません。 名前は以下のメソッドを使用して宣言します。

public static String getNodeName()
{
   return "BasicInputNode";
}
このメソッドが宣言されていない場合は、 Java API フレームワークが以下の規則に従ってデフォルトのノード名を作成します。
  • パッケージ名にはクラス名が付加されます。
  • ドットは除去され、 パッケージ名とクラス名の各部の最初の文字が大文字になります。
例えば、 デフォルトでは以下のクラスにノード名 "ComIbmPluginsamplesBasicInputNode" が割り当てられます。
package com.ibm.pluginsamples;
public class BasicInputNode extends MbInputNode implements MbInputNodeInterface
{
   ...

属性の宣言

ノード属性は、Java Bean プロパティーと同じ方法で宣言します。 属性の getter メソッドおよび setter メソッドはユーザーが作成しなければなりません。 API フレームワークは、Java Bean イントロスペクションを使用して属性名を推測します。 例えば、以下の 2 つのメソッドを宣言するには、次のようにします。

private String attributeVariable;

public String getFirstAttribute()
{
  return attributeVariable;
}

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

ブローカーは、このノードが firstAttribute という属性を持つことを推測します。 この名前は、内部クラス・メンバー変数名ではなく、get または set メソッドの名前に由来します。 属性はストリングとしてしか公開できないので、 get または set メソッドで、数値タイプとストリングの変換を行う必要があります。 例えば、次のメソッドは timeInSeconds という属性を定義します。

int seconds;

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

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

ノード機能のインプリメント

先に述べたとおり、ブローカーは run メソッドを呼び出して入力メッセージを作成します。 このメソッドは、入力ノードのためのすべてのアプリケーション処理機能を備えている必要があります。

デフォルトのメッセージ・パーサー属性のオーバーライド (オプション)

入力ノードは通常、 最初に入力メッセージを構文解析するメッセージ・パーサーを判別します。 例えば、プリミティブ MQInput ノードは、 MQMD ヘッダーを構文解析するために MQMD パーサーが必要であることを指示します。 ユーザー定義入力ノードは、 デフォルトとして組み込まれる、オーバーライドも可能な以下の属性を使用することによって、 適切なヘッダーかメッセージ・パーサー、および構文解析の制御のモードを選択することができます。

rootParserClassName
ユーザー定義入力ノードによってサポートされているメッセージ形式を構文解析するルート・パーサーの名前を定義します。 デフォルトでは GenericRoot に設定されます。 これは、ブローカーにパーサーを割り振らせたりチェーニングするために提供されているルート・パーサーです。 おそらく、ノードでこの属性値を変更する必要はありません。
firstParserClassName
ビット・ストリームを構文解析する役割を持つパーサーのチェーンの中で、 最初のパーサーの名前を定義します。 デフォルトでは XML に設定されます。
messageDomainProperty
入力メッセージを構文解析するのに必要なメッセージ・パーサーの名前を定義するオプションの属性。サポートされる値は、MQInput ノードによってサポートされるものと同じです。 (MQInput ノードの詳細については、MQInput ノードを参照してください。)
messageSetProperty
MRM パーサーが messageDomainProperty 属性によって指定された場合にのみ、 Message Set フィールドのメッセージ・セットの ID (またはメッセージ・セット名) を定義するオプションの属性。
messageTypeProperty
MRM パーサーが messageDomainProperty 属性によって指定された場合にのみ、 MessageType フィールドのメッセージの ID を定義するオプションの属性。
messageFormatProperty
MRM パーサーが messageDomainProperty 属性によって指定された場合にのみ、 Message Format フィールドのメッセージの形式を定義するオプションの属性。

ノードのインスタンスの削除

ノードのインスタンスは、次のいずれかの場合に削除します。
  • ブローカーがシャットダウンされた。
  • ノードまたはノードを含むメッセージ・フローを除去し、 構成を再デプロイした。
ノードの削除中は、 ノードがソケットの終了などの終結処理操作を実行できるよう、 ノードに情報が通知されるようにする必要がある場合があります。 ノードがオプションの onDelete メソッドをインプリメントしていれば、 ノードが削除される前にこれがブローカーによって呼び出されます。

onDelete メソッドは次のようにしてインプリメントします。

public void onDelete()
{
    // perform node cleanup if necessary
}
関連情報
Java API
特記事項 | 商標 | ダウンロード | ライブラリー | サポート | フィードバック
Copyright IBM Corporation 1999, 2006 最終更新: 08/21/2006
as09950_