2016-08-19 11 views
1

Spring Rabbitを使用して、RabbitTemplate.convertAndSendを使用して複数のメッセージをRabbitキューに配置して終了するスクリプトを作成しました。しかし、ウサギの接続は、メッセージがエンキューされた後でもアプリを生かし続けるように見えます。メッセージがエンキューされた後、Rabbitサーバーに停止するように通知する方法はありませんでした。Spring RabbitのRabbitTemplateをきれいにシャットダウンできますか?

最高の解決策は、convertAndSend呼び出しをconvertSendAndReceiveに変更して、メッセージが正常にエンキューされたことを確認してから、System.exit(0)を使用して終了することです。私はconvertAndSendAndSendがバックグラウンドスレッドやsomesuchで起こっているように見えるのでconvertSendAndReceiveに切り替えました。これらの呼び出しをいくつか行った後にSystem.exit(0)を実行すると、最初のものだけが成功するためです。

RabbitTemplateを作成してもこの動作は発生しません。 "send"メソッドの1つを使ってそれを使用します。

次のコードは、この問題を示しています。

import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; 
import org.springframework.amqp.rabbit.connection.ConnectionFactory; 
import org.springframework.amqp.rabbit.core.RabbitTemplate; 

import static issues.RabbitSettings.*; //Static fields containing my test Rabbit connection info 

public class RabbitTemplateShutdownIssue { 
    public static void main(String[] args) { 
     RabbitTemplate rabbitTemplate = createRabbitTemplate(); 
     rabbitTemplate.convertAndSend(ROUTING_KEY, "Test"); // Or convertSendAndReceive 
     // The app never exits 
    } 

    private static RabbitTemplate createRabbitTemplate() { 
     RabbitTemplate rabbitTemplate = new RabbitTemplate(getConnectionFactory()); 
     rabbitTemplate.setExchange(EXCHANGE); 
     rabbitTemplate.setMandatory(true); 
     return rabbitTemplate; 
    } 

    private static ConnectionFactory getConnectionFactory() { 
     CachingConnectionFactory connectionFactory = new CachingConnectionFactory(HOSTNAME); 
     connectionFactory.setPublisherConfirms(true); 
     connectionFactory.setVirtualHost(VIRTUAL_HOST); 
     connectionFactory.setUsername(USERNAME); 
     connectionFactory.setPassword(PASSWORD); 
     return connectionFactory; 
    } 
} 

シャットダウンするようにウサギのクライアントを伝える方法があり、理想的に後のすべてのメッセージがエンキューされていますか?

+0

** **を停止します。 Spring Beansを 'ApplicationContext'で使用しています - これは対処するPITAです。あなたが例外を出さないように物事をシャットダウンする必要があるからです。シンプルなソリューションですか?それを正しくしてください! –

+0

@BoristheSpider私の例ではSpringコンテナは実行されていないので、シャットダウンするSpringはありません。 –

+0

それは**正確に**私のポイントです。 –

答えて

3

SpringがBeanを管理するようにすれば、終了時にアプリケーションのコンテキストをclose()にすることができます。

接続のファクトリでdestroy()と呼ぶことができます。

このようなものに静的メソッドを使用することは、アンチパターンです。静的フィールドにファクトリを格納して、テンプレートが使用しているファクトリを破棄する必要があります。

ウサギがセンドを受け取ったという確認を得るには、確認コールバックが必要です。

+0

公平なところでは、実際のスクリプトは、基本的なメッセージのエンキューを行い、その後終了するGroovyスクリプトであり、本格的な制作アプリではありません。私はちょうど静的メソッドを使って私の例を書いています。なぜなら、Javaを使うことはGroovyよりもSpringの聴衆に理解されているように思われるからです。 –

+0

十分に良い。ウサギがセンドを受け取ったことを確認するには、テンプレートで確認コールバックが必要です。 –

+0

接続ファクトリのdestroy()は、まさに私が探していたものでした。 –

関連する問題