2

MQ メッセージ用のメッセージ フォワーダー/ルーターのようなものがあります。いくつかのルールに基づいてメッセージを転送しようとしています。この転送は、1 つのキューからメッセージを受信し、(同じ内容または変更された内容の) 新しいメッセージを作成し、それを別のキューに入れることによって簡単に実行されます。フォワーダーの存在は、可能な限り透過的である必要があります。

現時点で私の問題はPutApplicationTypeメッセージ プロパティです。このプロパティを変更できないようです。私は.NETとJavaの両方のサンプル実装を持っており、単純に使用しようとしています:

MQMessage forwardedMessage = new MQMessage();
forwardedMessage.putApplicationType = CMQC.MQAT_UNIX;

どのような値を使用しようとしても問題ありません。.NET バージョンは常にMQAT_DEFAULT/MQAT_WINDOWS_NTでメッセージを送信し、Java バージョンは常に でメッセージを送信しますMQAT_JAVA

このヘッダーを変更することは可能ですか? そうでない場合、値を変更しないとレガシーシステムに問題が発生する可能性がありますか? 値を変更できないのはなぜですか?

ところで。元のメッセージの転送も機能しません - 私のアプリケーションはPutApplicationTypeプロパティも変更します。

編集: ネイティブ C API を使用すると、このプロパティの内容を制御できますか?

4

4 に答える 4

3

T.Rob として、manaul を読む必要があると述べました (Java を使用した WMQ または .Net を使用した WMQ)。上記のように、メッセージの転送は簡単な作業ではありません。正しく設定する必要があるいくつかのオプション/パラメーターがあります。

すべての例外処理を削除した Java コード スニペットを次に示します。

int openInputOptions  = MQC.MQOO_INQUIRE + MQC.MQOO_FAIL_IF_QUIESCING + MQC.MQOO_INPUT_SHARED + MQC.MQOO_SAVE_ALL_CONTEXT;
int openOutputOptions = MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING + MQC.MQOO_PASS_ALL_CONTEXT;

MQQueue _inQ = _qMgr.accessQueue( inQueueName, openInputOptions, null, null, null );

MQQueue _outQ = _qMgr.accessQueue( outputQueueName, openOutputOptions, null, null, null );

MQGetMessageOptions getOptions = new MQGetMessageOptions();
getOptions.options = MQC.MQGMO_NO_WAIT + MQC.MQGMO_FAIL_IF_QUIESCING;

MQMessage mqMsg = new MQMessage();

mqMsg.correlationId = MQC.MQCI_NONE;
mqMsg.messageId = MQC.MQMI_NONE;

_inQ.get(mqMsg, getOptions);

MQPutMessageOptions pmo = new MQPutMessageOptions();
pmo.options =  MQC.MQPMO_FAIL_IF_QUIESCING + MQC.MQPMO_PASS_ALL_CONTEXT;
pmo.contextReference = _inQ;

_outQ.put(mqMsg, pmo);
于 2012-07-09T18:38:00.730 に答える
1

これは転送には機能しますが、並列処理に関連する多くの新しい質問が発生します。同じMQQueueインスタンスから複数のメッセージを並列処理することはできますか?

確かに、私はスレッドが常に並行して実行されているアプリケーションを作成しています。各スレッドがキュー・マネージャーへの独自の接続を持っていることを確認してください。

最後に受信したメッセージのコンテキストのみを保持できると思います。

本当です。(その特定のスレッドの場合)

また、PutApplicationTypeフィールドを設定するだけでは、私の主な質問には答えられません。おそらく、@T.Robが述べたように新しいコンテキストの作成に関連しています。

T.Robから提供されたマニュアルページを読んでいないので、おそらくMQコースを受講する必要があります。これらのページ(およびサブセクション)を読むと、MQMDには7つのフィールドがあり、単純に設定することはできず、キュー・マネージャーによって制御されることがわかります。

キューマネージャーのコントロール:

  1. アイデンティティコンテキスト:

    • ユーザーID
    • AccountingToken
    • アプリケーションID
  2. オリジンコンテキスト:

    • PutApplType
    • PutApplName
    • PutDate
    • PutTime

「Set」または「Pass」IDコンテキスト、または「SetAll」または「PassAll」オリジンコンテキストを使用できます。MQMDのPutApplTypeフィールド(Originコンテキストの一部)を変更する場合は、「Set All」コンテキストを使用する必要があり、キューマネージャーは設定しないため、MQMDの7つのコンテキストフィールドすべてを設定する必要があります。

したがって、「すべて設定」オプションを使用すると、アプリケーションが明示的に設定しない上記の7つのフィールドのいずれかがnullになります(PutDate / PutTimeを含む)。

于 2012-07-10T15:21:22.653 に答える
1

はい、MQ .NET はこれらすべてのコンテキスト関連のプロパティもサポートしています。

元の送信アプリケーションによって設定されたのと同じアプリケーション タイプでメッセージを転送する、私のバージョンの .NET アプリケーションを次に示します。

メッセージを同じアプリケーションに入れているため、MQOO_SET_ALL_CONTEXT を使用する

            MQQueue recvQ = qm.AccessQueue("Q1", MQC.MQOO_INPUT_SHARED | MQC.MQOO_OUTPUT | MQC.MQOO_SET_ALL_CONTEXT | MQC.MQOO_SAVE_ALL_CONTEXT | MQC.MQOO_FAIL_IF_QUIESCING);
            MQQueue fwdQ = qm.AccessQueue("Q2", MQC.MQOO_OUTPUT | MQC.MQOO_PASS_ALL_CONTEXT | MQC.MQOO_FAIL_IF_QUIESCING);

            MQMessage putMsg = new MQMessage();
            putMsg.WriteString("Verify PutApplicationType");
            putMsg.Persistence = MQC.MQPER_NOT_PERSISTENT;

            putMsg.PutApplicationType = MQC.MQAT_UNIX;
            putMsg.PutApplicationName = "UnixApplication";
            putMsg.Format = MQC.MQFMT_STRING;

            MQPutMessageOptions pmo = new MQPutMessageOptions();
            pmo.Options = MQC.MQPMO_SET_ALL_CONTEXT;
            recvQ.Put(putMsg,pmo);

            MQGetMessageOptions gmo = new MQGetMessageOptions();
            gmo.WaitInterval = MQC.MQWI_UNLIMITED;
            gmo.Options = MQC.MQGMO_WAIT;
            MQMessage fwdMsg = new MQMessage();
            recvQ.Get(fwdMsg, gmo);

            MQPutMessageOptions pmoF = new MQPutMessageOptions();
            pmoF.Options = MQC.MQPMO_FAIL_IF_QUIESCING + MQC.MQPMO_PASS_ALL_CONTEXT;
            pmoF.ContextReference = recvQ;
            fwdQ.Put(fwdMsg, pmoF);

            recvQ.Close();
            fwdQ.Close();
于 2012-07-10T10:04:33.887 に答える
1

これを行う方法は 2 つあります。必要なセキュリティの程度によって異なります。最初のより安全な方法は、元のメッセージからコンテキストを渡すことです。このメソッドは、プログラムが何も変更することを許可せずにコンテキストを保持します。これはMQOO_SAVE_ALL_CONTEXT、メッセージを取得するためのキューのオープンと、メッセージを書き込むためのキューを使用して実現さMQOO_PASS_ALL_CONTEXTれます。

もう 1 つのオプションは、コンテキストを直接設定することです。アプリケーションはフィールドに任意の値を設定できるため、これは安全性が低くなります。メッセージを消費するアプリケーションが承認のコンテキストに依存している場合、これにより、上流のアプリケーションはその承認をバイパスできます。アプリがアクセスする必要がある一連のコンテキスト情報に応じて、いくつかのオプションがあります。

ナレッジ センターのメッセージ コンテキスト情報の制御を参照してください。

これはすべて、C 実装に確実に当てはまります。.Net 実装でどの程度公開されているかはわかりません。おそらく、シャシは別の回答でその詳細を記入します.

于 2012-07-09T14:48:18.647 に答える