2009-03-09 15 views
14

メッセージリスナーを一時的に無効にするにはどうすればいいですか?私が解決したい問題がある:一時的にメッセージリスナーを無効にする方法

  • A JMSメッセージは、メッセージを処理しようとしたとき、私はエラーを取得するメッセージリスナー
  • で受信されます。
  • システムがメッセージを処理できるようになるのを待っています。
  • 私のシステムが準備完了するまで、私はもうメッセージは必要ありません。
  • ...メッセージリスナーを無効にしたいと思います。
  • 私のシステムは、もう一度処理する準備ができています。
  • 失敗したメッセージが処理され、JMSメッセージが確認応答されます。
  • メッセージリスナーを再度有効にします。

現在、私はSun App Serverを使用しています。 MessageConsumerでnullに設定してメッセージリスナーを無効にし、setMessageListener(myOldMessageListener)を使用してメッセージリスナーを再度有効にしましたが、その後はメッセージが表示されません。

答えて

14

システムがメッセージを再度処理する準備ができるまで、onMessage()リスナーメソッドから戻らない場合はどうですか?これにより、JMSはそのコンシューマーで別のメッセージを配信できなくなります。

これは、同期の場合にreceive()を呼び出さないことと同じです。

特定のJMSセッションにマルチスレッドがないため、メッセージのパイプラインはonMessage()メソッドが戻るまで保持されます。

私はsetMessageListener()を動的に呼び出すことの意味に慣れていません。 javadocは、「メッセージが既存のリスナーまたはコンシューマコンシューマによって消費されている場合」と呼ばれる場合はthere's undefined behaviorと表示します。 onMessage()内から呼び出す場合は、その未定義のケースに当たるように聞こえます。

接続レベルでstart/stopのメソッドがありますが、これはそれほど粗雑ではありません。

+0

ああ、それは本当に簡単でした。私はもっ​​と多くのスレッドがonMessageメソッドを呼び出すことを期待していました。本当にありがとう! – davidi

+0

接続はスレッドセーフです。ダウンセッション(セッション、コンシューマ、プロデューサ)はスレッドセーフではありません。あなたのコードはマルチスレッドアクセスを避ける必要があります。これを強制するために、JMSは1つのコンシューマでリスナー呼び出しをマルチスレッドできませんでした。 –

+3

私は、JMS仕様がこのシリアル配信動作を明示的に指定していることに気付きました。 JMS 1.0.2仕様のセクション4.4.16です。過去に私はそれがスレッドのルールによって暗示されていると思っていました。 –

0

メッセージが配信されているように見えますが、リスナーが接続されていないため、何も起こっていません。私はJMSを使って何かをしてからしばらくしていますが、システムを修復している間にメッセージをデッドレターのキューなどに送りたい場合は、メッセージを元のキューに戻してくださいもう一度処理する準備ができましたか?

+0

これはどういうことでしょう。残念ながら、私はjmsサーバーの制御を持っていません。私ができるのは、メッセージを取得するキューを指定することです。デッド・レター・キューはありません。私はQueueConnectionを停止することができたと思うが、それはmessagelistenerスレッドからは行えない。 – davidi

+0

どうしてあなたはJMSサーバにアクセスできない。 duffymoが正しく指摘したように、あなたがアクセスしたいエラーキュー。それ以外の場合は、JMSサーバが提供するコードの動作を複製することになります – tddmonkey

+0

私の開発環境ではJMSサーバへのアクセス権がありますが、私はアプリケーションのユーザであるとは思いません(2つのメッセージングシステム間のブリッジ)は、JMSサーバと同じ権限を持ちます。そのデッドレターキューは、これらの問題に対処する通常の方法ですか? – davidi

0

WebLogicでは、max retries、max retry limitを超えるメッセージを処理するエラーキュー、およびその他のパラメータを設定できます。私は自分の頭の上からはっきりとしているわけではありませんが、待機期間を指定することもできます。これはすべて管理コンソールで利用できます。私はあなたが持っているJMSプロバイダの管理者に似たようなことができるかどうかを見ていきたいと思います。

2

問題は、メッセージリスナーをreceive()ループで置き換えることで回避できますが、メッセージリスナーを無効にしてもう一度有効にする方法はまだ興味があります。

0

JBossでは、次のコードは、トリックを行います:

MBeanServer mbeanServer = MBeanServerLocator.locateJBoss(); 
    ObjectName objName = new ObjectName("jboss.j2ee:ear=MessageGateway.ear,jar=MessageGateway-EJB.jar,name=MessageSenderMDB,service=EJB3"); 
    JMSContainerInvokerMBean invoker = (JMSContainerInvokerMBean) MBeanProxy.get(JMSContainerInvokerMBean.class, objName, mbeanServer); 

    invoker.stop(); //Stop MDB 
    invoker.start(); //Start MDB 
0

私はあなたのMessageListenerの実装内

messageConsumer.setMessageListener(null); 

を呼び出し、(ScheduledExecutorServiceで例えば)再構築タスクをスケジュールすることができると思います。このタスクは

connection.stop(); 
messageConsumer.setMessageListener(YOUR_NEW_LISTENER); 
connection.start(); 

となり、動作します。 start()メソッドとstop()メソッドは、TCP接続ではなく配送構造体の再起動に使用されます。

のJavadoc https://docs.oracle.com/javaee/7/api/javax/jms/Connection.html#stop--

を読む一時的に接続による着信メッセージの配信を停止します。接続のstartメソッドを使用して配信を再開できます。接続が停止すると、すべての接続のメッセージコンシューマへの配信が禁止されます。同期受信ブロックであり、メッセージはメッセージリスナに配信されません。 JMS仕様に従ったので、ちょうどMessageListenerからconnection.stop()を呼び出すことはありませんhttps://docs.oracle.com/javaee/7/api/javax/jms/Connection.html#stop--

:一時的にするために

0

あなたはConnectionインターフェイスからstop()メソッドを使用する必要がある接続による着信メッセージの配信を停止します。デッドロックまたは例外が発生します。代わりにconnection.stop()を別のスレッドから呼び出すことができます。MessageListenerと同期する必要があり、機能との接続を中断するスレッドconnection.stop()

関連する問題