2016-05-17 11 views
2

私はamqpを春にして新しく、異なる動作をする2つの異なるリスナーを作成したいと思います。問題は、コンパイル時にキュー名がわからないため、thisソリューションを使用できないことです。java spring boot amqp異なる動作をする2つのリスナー

私がしたいことは、「サイドチャネル」キューから最初のメッセージを読み込んだり(削除して)、これは{"queues":["queue1","queue2"]}のようになります。

ここで、最初のメッセージをqueue1とqueue2から読み取ってから削除します。その後、手順1に進み、サイドチャネルの最初のメッセージを読む

以下のコードで見られるように、2つのSimpleMessageListenerContainersを別のリスナーで作成しようとしましたが、思った通りに動作しません。

マイコード:

@SpringBootApplication 
public class Main implements CommandLineRunner { 

final static String queueName = "sidechannel"; 

@Autowired 
AnnotationConfigApplicationContext context; 

@Autowired 
RabbitTemplate rabbitTemplate; 

@Bean 
Queue queue() { 
    return new Queue(queueName, false); 
} 

@Bean 
TopicExchange exchange() { 
    return new TopicExchange("spring-boot-exchange"); 
} 

@Bean 
Binding binding(Queue queue, TopicExchange exchange) { 
    return BindingBuilder.bind(queue).to(exchange).with(queueName); 
} 

@Bean 
public ConnectionFactory rabbitConnectionFactory() { 
    CachingConnectionFactory connectionFactory = 
      new CachingConnectionFactory("localhost"); 
    connectionFactory.setUsername("guest"); 
    connectionFactory.setPassword("guest"); 
    return connectionFactory; 
} 

@Bean 
public SimpleMessageListenerContainer messageListenerContainer() { 
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(); 
    container.setConnectionFactory(rabbitConnectionFactory()); 
    container.setQueueNames(queueName); 
    container.setMessageListener(sidechannelListener()); 
    return container; 
} 

@Bean 
public SimpleMessageListenerContainer messageListenerContainer2() { 
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(); 
    container.setConnectionFactory(rabbitConnectionFactory()); 
    container.setQueueNames("queue1","queue2"); 
    container.setMessageListener(queueListener()); 
    return container; 
} 



@Bean 
public MessageListener sidechannelListener() { 
    return message -> { 
     String msg = new String(message.getBody()); 
     System.out.println(msg); 
     try { 
      Map<String, Object> map = jsonToMap(msg); 
      for (String name : (ArrayList<String>) map.get("queues")) { 
       System.out.println("Waiting for " + name + " message"); 
       rabbitTemplate.receive(name); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

    }; 
} 

@Bean 
public MessageListener queueListener() { 
    return message -> { 
     String msg = new String(message.getBody()); 
     System.out.println("Received message: "); 
     System.out.println(msg); 
    }; 
} 


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

@Override 
public void run(String... args) throws Exception { 
    rabbitTemplate.setReceiveTimeout(-1); 

    while(true) { 
     System.out.println("Waiting for side channel message"); 
     rabbitTemplate.receive(queueName); 
    } 
//  context.close(); 
} 
} 

まず、何らかの理由で、sidechannelキュー内のメッセージは処理された後に削除されません。 第二に、私はこのような出力を期待していたとき:

Waiting for side channel message 
{"queues":["queue1","queue2"]} 
Waiting for queue1 message 
Received message: 
"message from queue1" 
Waiting for queue2 message 
"message from queue2" 
Waiting for side channel message 

と私はそれらの異なるキュー上のメッセージを受信して​​も、何も(理由rabbitTemplate.setReceiveTimeout(-1);の)起こらないだろうが、どういうわけか、それは私が受け取るすべてのメッセージに反応することを

...

また

、私は理解していないが、私は最初、sidechannelするメッセージを送信する場合、それはのように行くQUEUE1すること、である:

Waiting for side channel message 
{"queues":["queue1","queue2"]} 
Waiting for queue1 message 
Received message: 
"message from queue1" 

とし、今、私は別のものを送信する場合(A秒)メッセージをqueue1に送信すると、th eメッセージに続いてWaiting for queue2 messageと入力します。

サイクルを続けるには2つのメッセージが必要です...私は何が間違っているのか分かりません。

+0

私はあまりにも複雑に見えますが、なぜあなたは構成を使っていませんか?起動時にキュー名を指定します(Exchangeに配置できる場合は、プロパティファイルに配置することもできます)。 –

+0

私は言ったように、私はamqpを芽生えるのが初めてで、それを理解するのがまだ難しいので、非常に複雑かもしれません。しかし、私はコンパイル時にキュー名を知らないので、それらをプロパティファイルに追加することはできませんか、間違っていますか?とにかくゲイリーの答えは、私が問題を解決するのに役立ちました、あなたの返信に感謝:) –

+0

あなたはコンパイル時にそれらを知る必要はありません。私はリファレンスガイドを読むことをお勧めします。あなたは起動時にプロパティを提供することができ、プロパティは後で定義することができ、固定プロパティ名のみが必要です。 –

答えて

0

あなたはパラダイムを混在させるようです。メッセージ駆動型のリスナーコンテナがあり、ポーリング(template.receive())も使用しています。一般的には、QUEUE1のコンテナは、キュー2は既にこれらのキューからのメッセージを処理していますし、タイムアウトが< 0であれば、この

  System.out.println("Waiting for " + name + " message"); 
      rabbitTemplate.receive(name); 

は永遠にブロックします。したがって元のメッセージは決してackされません。

+0

あなたが正しいです、リスナーコンテナがメッセージ駆動型であることはわかりませんでした。何とかそれを全体的に説明し、解決することができます。ありがとうございます! –

関連する問題