2016-05-11 10 views
0

私は春AMQPのRabbitMQの実装を要求/応答パターンをテストしていると私はそれを動作させることができない...RabbitMQの要求/応答「RabbitTemplateがリスナーとして構成されていない」

私は次のように構成ガット成果物:

グリーティングキューでtest_exchangeルーティングキー=挨拶
reply_exchangeと返信キュー。ルーティングキーは=私はgithubのに次の例た

@Bean 
public ConnectionFactory connectionFactory() { 
    CachingConnectionFactory connectionFactory = 
      new CachingConnectionFactory("....IP of broker..."); 
    connectionFactory.setUsername("guest"); 
    connectionFactory.setPassword("guest"); 
    return connectionFactory; 
} 

@Bean 
public Queue greeting() { 
    return new Queue("greeting"); 
} 

@Bean 
public Queue replies() { 
    return new Queue("replies"); 
} 

MessageListener receiver() { 
    return new MessageListenerAdapter(new RabbitMqReceiver(), "onMessage"); 
} 

@Bean 
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, Queue replies) { 
    RabbitTemplate template = new RabbitTemplate(connectionFactory); 
    template.setExchange("test_exchange"); 
    template.setRoutingKey("greeting");  
    template.setReplyAddress("reply_exchange"+"/"+replies.getName()); 
    template.setReplyTimeout(60000); 
    return template; 
} 

@Bean 
public SimpleMessageListenerContainer replyContainer(ConnectionFactory connectionFactory, 
     RabbitTemplate rabbitTemplate, Queue replies) { 
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(); 
    container.setConnectionFactory(connectionFactory); 
    container.setMessageListener(rabbitTemplate); 
    container.setQueues(replies); 
    return container; 
} 

@Bean 
public SimpleMessageListenerContainer serviceListenerContainer(
     ConnectionFactory connectionFactory) { 
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(); 
    container.setConnectionFactory(connectionFactory); 
    container.setQueues(greeting()); 
    container.setMessageListener(receiver()); 
    return container; 
} 

を返信するが、それはでクラッシュ:java.lang.IllegalStateException:

によって引き起こさRabbitTemplateが MessageListenerのように構成されていません - 'を使用することはできませんreplyAddress':

:rep​​ly_exchangeは/

ドキュメントは言う返信

バージョン1.5以降、RabbitTemplateは応答を受信するMessageListenerとして構成されているかどうかを検出します。そうでない場合、返信アドレスでメッセージを送受信する試みは、(応答が受信されないため)IllegalStateExceptionで失敗します。

これは優れていますが、RabbitTemplateはそれをどのようにしていますか? MessageListenerとして設定されている場合、どのように検出されますか?事前に

おかげ

PS:コード送信:返信用コンテナが開始

public void send() { 
    Message message = MessageBuilder.withBody("Payload".getBytes()) 
      .setContentType("text/plain") 
      .build(); 
    Message reply = this.template.sendAndReceive(message); 
    System.out.println("Reply from server is: "+new String(reply.getBody())); 
} 

答えて

1

は、それはテンプレートがListenerContainerAwareであることを検出し、replyAddress場合、応答キュー(またはnullを取得するためにexpectedQueueNames()を呼び出します形式はexch/rkです)。 null以外の結果が返された場合、コンテナはキューが正しいことをチェックします。 EXCH/RKが返信アドレスである場合は、この方法は、無条件にそのexeptionを回避isListenerブール値を設定し、この

logger.debug("Cannot verify reply queue because it has the form 'exchange/routingKey'"); 

になるだろう。したがって、メッセージを送信する前にコンテナが開始されていないように見えます。コンテキストが完全に初期化される前に送信していますか?

RabbitMQは直接reply-toを実装しているため、通常は応答コンテナを使用する必要はありません(HA応答キューが必要な場合やその他の理由で明示的な応答キューが必要な場合を除く)。 Direct reply-toを使用すると、応答コンテナのメカニズムを実装するためのパフォーマンス上の問題がなくなりました。

0

ゲイリー、あなたの直感はいつものように完璧でした。

私はから私の送信コードを変更:すべてのBeanの準備ができて、要求されたときに送信されるように確保するために

@SpringBootApplication 
public class App 
{ 
public static void main(String[] args) throws Exception { 
    final ConfigurableApplicationContext configAppContext = SpringApplication.run(App.class, args); 
    final RabbitMqSender sender = configAppContext.getBean(RabbitMqSender.class); 
    sender.send(); 
} 

}

/:に

@SpringBootApplication 
public class App 
{ 
    @Bean(initMethod="send") 
    public RabbitMqSender sender() { 
     final RabbitMqSender sender = new RabbitMqSender(); 
     return sender; 
    } 

    public static void main(String[] args) throws Exception { 
     SpringApplication.run(App.class, args); 
    } 

}

レスポンスが優れています!

はい、私はdefinitelly Direct-TOパターンも試してみます。

ゲーリーにお手伝いしてください。

よろしく

トマス

関連する問題