2016-05-06 11 views
3

私はBeanアノテーションで厳密に設定され、WebshpereMQからメッセージを読み込んでいるSpringブートJMSアプリケーションで作業しています。私はこのアプリケーションを安全にシャットダウンする方法を理解することができない限り、すべて動作します。 JMSListenerメソッドがすべてのメッセージを読み込むと、それは単にアイドル状態のままです。私はキューへの初期接続を行い、キューの深さにアクセスします。キューの深さがゼロのときは、それをまとめてシャットダウンするのが理想的です。安全にSpring JMSアプリケーションを終了する

public void shutDownApplication() { 
     logger.info("Initiating shutdown of application..."); 
     System.out.println("Terminating application..."); 
     Thread.currentThread().interrupt(); 
     System.exit(0); 
    } 

私は、このソリューションが好きではない:私の現在の回避策は(と私は全くそれを好きではない)の深さがゼロのときに私は(む〜、リスナーの内側から)を呼び出し、この小さな方法です。また、Springはエラー処理の中断として明らかに中断され、アプリケーションが終了する前にJMSListenerがロールバックを開始し、残りの単一の最後のメッセージをキューに戻すためです。

私は、次のソースを見た後、他のいくつかの解決策を試してみました:

How can I Stop/start/Pause a @JmsListener (the clean way)

How to gracefully shut down a Spring JMS MessageListenerAdapter

http://forum.spring.io/forum/spring-projects/integration/jms/124980-graceful-shutdown-of-jms-message-listener

をこれは私の最も最近の解決策だった:

public class JMSShutdownService { 

    public void initiateShutdown() { 
     JmsListenerEndpointRegistry jmsListenerEndpointRegistry = new JmsListenerEndpointRegistry(); 
     Collection<MessageListenerContainer> col = jmsListenerEndpointRegistry 
       .getListenerContainers(); 
     for (MessageListenerContainer cont : col) { 
      cont.stop(Thread.currentThread()); 
     } 
     System.exit(0); 
    } 

} 

これはアプリケーションを終了させますが、最後のメッセージをキューに戻します。私はまだ理解しようとしている春の複雑さがたくさんあるので、すべてそれは本当に下に来る。主な問題は、シャットダウンのために私が聴取した信号の中にあるということです。私が集めたものから、リスナーはその責任を負いません。しかし、リスナーが起動する前にアプリケーションをシャットダウンする方法を定義する方法や、キューの深さがゼロのときにリスナーからポップする方法がわかりません。

アイデア?

答えて

2
JmsListenerEndpointRegistry jmsListenerEndpointRegistry = new JmsListenerEndpointRegistry(); 

これは役に立たない。 @JmsListenerを使用している場合は、新しいレジストリにはコンテナがありません。アプリケーションコンテキストからレジストリを取得する必要があります。

System.exit(0); 

これはJVMを強制終了します。

最後の行は、別のスレッドでコンテナを停止することです。タスク実行プログラムを使用して新しいスレッドを開始してコンテナを停止します。コンテナは、スレッドが停止する前にリスナーを終了するのを待ちます。

コンテナを停止した後、JVMを強制終了するまで猶予期間を待つ必要があります。

あなたは本当にあなたが完了したことをどのように知っていますか?コンテナを停止すると、別のメッセージが表示されることがあります。その場合、コンテナが停止しているために拒否されたメッセージに関するログにノイズが発生する可能性があります。私のリスナーで

EDIT

...

... 
if (timeToShutDown()) { 
    Executors.newSingleThreadExecutor.execute(new Runnable() { 

     public void run() { 
      stopTheContainer(); 
     } 
    } 
} 
// exit the listener so the container can actually stop. 
+0

'container'を停止するために、新しいスレッドを開始するタスク実行を使用します。場合は、まさにこの新しいスレッドの作成が起こるのでしょうか?リスナーが立ち​​去る前、または実際にリスナーに来る前に?そして、このスレッドは、コンテナに「私が完了した信号を得て、シャットダウンしました」と伝えるものです。 –

+0

右 - リスナーは、 'Executors.newSingleThreadExecutor.execute(...)'を停止して呼び出すときに、リスナースレッドを解放するコンテナを 'Runnable'で停止させ、コンテナがそれを待つ実際に停止する前に。 –

+0

最後の質問ですが、私は答えを知っていると思うので謝罪しますが、私は確認したいと思います。あなたが「そしてRunnableで」と言うとき、Runnableは新しく作成されたスレッドを参照していますか? –

関連する問題