Java メッセージ処理または出力ノードの機能の拡張

始める前に

以下のトピックを読み、理解していることを確認してください。

メッセージ・データへのアクセス

多くの場合、ユーザー定義ノードは、 その入力ターミナルで受け取ったメッセージの内容にアクセスする必要があります。 メッセージは、構文エレメントのツリーとして表されます。 ユーティリティー関数のグループが、メッセージ管理、メッセージ・バッファー・アクセス、 構文エレメント・ナビゲーション、および構文エレメント・アクセス用に提供されます。

MbElement クラスには、構文エレメントへのインターフェースがあります。 Java API の詳細については、Javadoc を参照してください。

例を以下に示します。

  1. XML メッセージの中の関係のある構文エレメントにナビゲートするには、次のようにします。
        MbElement rootElement = assembly.getMessage().getRootElement();
        MbElement switchElement =
    			rootElement.getLastChild().getFirstChild().getFirstChild();
  2. このエレメントの値で示されたターミナルを選択するには、次のようにします。
        String terminalName;
        String elementValue = (String)switchElement.getValue();
        if(elementValue.equals("add"))
          terminalName = "add";
        else if(elementValue.equals("change"))
          terminalName = "change";
        else if(elementValue.equals("delete"))
          terminalName = "delete";
        else if(elementValue.equals("hold"))
          terminalName = "hold";
        else
          terminalName = "failure";
        
        MbOutputTerminal out = getOutputTerminal(terminalName);

メッセージ・オブジェクトの変換

受信した入力メッセージは読み取り専用です。 したがって、メッセージを変換するには、まずそれを新しい出力メッセージに書き込む必要があります。 入力メッセージからエレメントをコピーするか、 あるいは、新しいエレメントを作成してそれらをメッセージに付加することができます。 新しいエレメントは通常はパーサーのドメインに入ります。

MbMessage クラスには、コピー・コンストラクターと、 メッセージのルート・エレメントを取得するメソッドがあります。 MbElement クラスには、構文エレメントへのインターフェースがあります。

たとえば、組み込みメッセージを含む着信メッセージ・アセンブリーがある場合は、次のようにします。
  1. メッセージ・アセンブリーとその組み込みメッセージの新しいコピーを作成します。
            MbMessage newMsg = new MbMessage(assembly.getMessage());
            MbMessageAssembly newAssembly = new MbMessageAssembly(assembly, newMsg);
  2. XML メッセージの中の関係のある構文エレメントにナビゲートします。
        MbElement rootElement = newAssembly.getMessage().getRootElement();
            MbElement switchElement =
    			rootElement.getFirstElementByPath("/XML/data/action");
  3. 既存のエレメントの値を変更します。
      String elementValue = (String)switchElement.getValue();
            if(elementValue.equals("add"))
                switchElement.setValue("change");
            else if(elementValue.equals("change"))
                switchElement.setValue("delete");
            else if(elementValue.equals("delete"))
                switchElement.setValue("hold");
            else
                switchElement.setValue("failure");
  4. 切り替えタグの子として新しいタグを追加します。
        MbElement tag = switchElement.createElementAsLastChild(MbElement.TYPE_NAME,
                                                                                                                          "PreviousValue",
                                                                                                                          elementValue);
  5. この新しいタグに属性を追加します。
        tag.createElementAsFirstChild(MbElement.TYPE_NAME_VALUE,
                                                                        "NewValue",
                                                                        switchElement.getValue());
    
        MbOutputTerminal out = getOutputTerminal("out");
変換の一部として、新規メッセージ本体を作成する必要があるかもしれません。 新規メッセージ本体を作成するために、以下のメソッドが使用可能です。
createElementAfter
createElementAsFirstChild
createElementAsLastChild
createElementBefore
createElementAsLastChildFromBitstream
これらのメソッドは、パーサーをメッセージ・ツリー・フォルダーに割り当てるための固有のものであるため、使用する必要があります。
以下のメソッドは、所有パーサーをフォルダーに関連付けないため、メッセージ本体を作成する時、これらを使用しないでください。
createElementAfter
createElementAfter
createElementAsFirstChild
createElementAsFirstChild
createElementAsLastChild
createElementAsLastChild
createElementBefore
createElementBefore

ESQL へのアクセス

ノードは、Compute ノードの ESQL 構文を使用して ESQL 式を呼び出すことができます。 ユーザーは、ESQL 式を使用してメッセージのコンポーネントを作成および変更し、 入力メッセージと外部データベースのデータの両方を参照できます。

以下の手順は、 ESQL を使用してユーザー定義ノードのトランザクションを制御する方法を表しています。
  1. 使用する ODBC データ・ソースの名前を設定します。 例を以下に示します。
    String dataSourceName = "myDataSource";
  2. 実行する ESQL ステートメントを設定します。
    String statement =
       "SET OutputRoot.XML.data =
              (SELECT Field2 FROM Database.Table1 WHERE Field1 = 1);";
    あるいは、結果を戻さないステートメントを実行する場合は、次のようにします。
    String statement = "PASSTHRU(
                            'INSERT INTO Database.Table1 VALUES(
                                 InputRoot.XML.DataField1,
                                 InputRoot.XML.DataField2)');";
  3. 以下の中から、トランザクションのタイプを選択します。
    MbSQLStatement.SQL_TRANSACTION_COMMIT
    ESQL ステートメントの実行の直後にトランザクションをコミットします。
    MbSQLStatement.SQL_TRANSACTION_AUTO
    メッセージ・フローの完了時にトランザクションをコミットします。 (必要に応じてロールバックが実行されます。)
    例を以下に示します。
    int transactionType = MbSQLStatement.SQL_TRANSACTION_AUTO;
  4. ESQL ステートメントを取得します。 例を以下に示します。
    MbSQLStatement sql =
           createSQLStatement(dataSourceName, statement, transactionType);
    トランザクション・タイプをデフォルトの MbSQLStatement.SQL_TRANSACTION_AUTO) にする場合は、 メソッド createSQLStatement(dataSource, statement) を使用することができます。
  5. 伝搬する新しいメッセージ・アセンブリーを作成します。
    MbMessageAssembly newAssembly =
           new MbMessageAssembly(assembly, assembly.getMessage());
  6. ESQL ステートメントを実行します。
    sql.select(assembly, newAssembly);
    あるいは、結果を戻さない ESQL ステートメントを実行する場合は、次のようにします。
    sql.execute(assembly);

ESQL の詳細については、ESQL の概要を参照してください。

例外の処理

mbException クラスを使用して、 例外をキャッチして例外に接続します。 mbException クラスは、 ブローカー例外リスト内の例外の子を表す例外オブジェクトの配列を戻します。 戻される各エレメントは、その例外タイプを指定します。 例外に子が存在しない場合には、空の配列が戻されます。 次のコード・サンプルは、MbException クラスの使用法の例を示しています。

public void evaluate(MbMessageAssembly assembly, MbInputTerminal inTerm) throws MbException
  {
    try
      {

        // plug-in functionality

      }
    catch(MbException ex)
      {
        traverse(ex, 0);

        throw ex; // if re-throwing, it must be the original exception that was caught
      }
  }

  void traverse(MbException ex, int level)
  {
    if(ex != null)
      {
        // Do whatever action here
        System.out.println("Level: " + level);
        System.out.println(ex.toString());
        System.out.println("traceText:  " + ex.getTraceText());

        // traverse the hierarchy
        MbException e[] = ex.getNestedExceptions();
        int size = e.length;
        for(int i = 0; i < size; i++)
          {
            traverse(e[i], level + 1);
          }
      }
  }

mbException クラスの使用法の詳細については、javadoc を参照してください。

すべての現行の例外にアクセスできるような仕方で、ユーザー定義メッセージ処理ノードまたは出力ノードを開発できます。 たとえば、 データベース例外をキャッチするには MbSQLStatement クラスを使用できます。 このクラスは「throwExceptionOnDatabaseError」属性の値を設定します。 この属性はデータベース・エラーの発生時のブローカー動作を決定します。 true に設定すると、例外がスローされる場合、ユーザー定義拡張機能がキャッチして処理できます。

次のコード・サンプルは、 MbSQLStatement クラスの使用法の例を示しています。

public void evaluate(MbMessageAssembly assembly, MbInputTerminal inTerm) throws MbException
  {
    MbMessage newMsg = new MbMessage(assembly.getMessage());
    MbMessageAssembly newAssembly = new MbMessageAssembly(assembly, newMsg);

    String table =
       assembly.getMessage().getRootElement().getLastChild().getFirstChild().getName();

    MbSQLStatement state = createSQLStatement( "dbName",
       "SET OutputRoot.XML.integer[] = PASSTHRU('SELECT * FROM " + table + "');" );

    state.setThrowExceptionOnDatabaseError(false);
    state.setTreatWarningsAsErrors(true);

    state.select( assembly, newAssembly );

    int sqlCode = state.getSQLCode();
    if(sqlCode != 0)
      {
        // Do error handling here

        System.out.println("sqlCode = " + sqlCode);
        System.out.println("sqlNativeError = " + state.getSQLNativeError());
        System.out.println("sqlState = " + state.getSQLState());
        System.out.println("sqlErrorText = " + state.getSQLErrorText());
      }

    getOutputTerminal("out").propagate(assembly);
  }

メッセージの伝搬

メッセージを伝搬する前に、何のメッセージ・フロー・データを伝搬するか、 また、どのノードのターミナルでデータを受信するかを決定する必要があります。 メッセージは伝搬する前にファイナライズする必要があります。 メッセージを伝搬したら、 出力メッセージを削除しなければなりません。

例を以下に示します。
  1. 出力ターミナル "out" にメッセージを伝搬するには、次のようにします。
    MbOutputTerminal out = getOutputTerminal("out");
            out.propagate(newAssembly);
  2. 出力メッセージを削除するには、次のようにします。
      newMsg.clearMessage();	

出力装置への書き込み

出力装置に書き込みをするには、 論理 (階層) メッセージをビット・ストリームに変換し直す必要があります。 これは、以下のように、MbMessagegetBuffer メソッドを使用して実行します。

public void evaluate( MbMessageAssembly assembly, MbInputTerminal in)
                                                     throws MbException
{
  MbMessage msg = assembly.getMessage();
  byte[] bitstream = msg.getBuffer();

  // write the bitstream out somewhere
  writeBitstream( bitstream );   // user method

 }

通常、出力ノードの場合はメッセージは出力ターミナルに伝搬されないので、 ここで戻すことができます。

注: WebSphere MQ キューに書き込むときは、提供されている MQOutput ノードを使用しなければなりません。 これは、ブローカーが、スレッド単位で、内部的に WebSphere MQ 接続およびオープン・キュー・ハンドルを保守し、 それらはパフォーマンスを最適化するためにキャッシュに入れられるからです。 さらに、ブローカーは特定の WebSphere MQ イベントの発生時に リカバリー・シナリオを処理しますが、 WebSphere MQ MQI 呼び出しが ユーザー定義出力ノードで使用された場合、これは不利な影響を受けます。
関連資料
例外リスト構造
特記事項 | 商標 | ダウンロード | ライブラリー | サポート | フィードバック
Copyright IBM Corporation 1999, 2005 Last updated: 11/07/2005
as24990_