web-dev-qa-db-ja.com

パブリッシュ/サブスクライブトピックの@JmsListenerの使用法

@JmsListenerアノテーションに基づいてパブリッシュ/サブスクライブの例を作成しようとしています: https://github.com/lkrnac/book-eiws-code-samples/tree/master/05-jms/0515-publish-サブスクライブ

関連するコードスニペット:

@Slf4j
@SpringBootApplication
@EnableScheduling
public class JmsPublishSubscribeApplication {

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

    @Bean
    public ActiveMQTopic simpleTopic() {
        return new ActiveMQTopic("simpleTopic");
    }

}

@Component
public class SimpleMessageListener1 {

    @JmsListener(destination = "simpleTopic")
    public void readMessage(String message) {
      //....
    }

}

@Component
public class SimpleMessageListener2 {

    @JmsListener(destination = "simpleTopic")
    public void readMessage(String message) {
      //....
    }

}

問題は、この動作を取得することです。

2015-05-17 20:07:04.985  INFO 22983 --- [pool-1-thread-1] n.l.b.e.chapter05.SimpleMessageSender    : Sending message: simple message
2015-05-17 20:07:05.070  INFO 22983 --- [enerContainer-1] n.l.b.e.c.JmsPublishSubscribeApplication : Message Received: simple message via listener 2
2015-05-17 20:07:05.975  INFO 22983 --- [pool-1-thread-1] n.l.b.e.chapter05.SimpleMessageSender    : Sending message: simple message
2015-05-17 20:07:05.986  INFO 22983 --- [enerContainer-1] n.l.b.e.c.JmsPublishSubscribeApplication : Message Received: simple message via listener 1
2015-05-17 20:07:06.975  INFO 22983 --- [pool-1-thread-1] n.l.b.e.chapter05.SimpleMessageSender    : Sending message: simple message
2015-05-17 20:07:06.987  INFO 22983 --- [enerContainer-1] n.l.b.e.c.JmsPublishSubscribeApplication : Message Received: simple message via listener 2
2015-05-17 20:07:07.975  INFO 22983 --- [pool-1-thread-1] n.l.b.e.chapter05.SimpleMessageSender    : Sending message: simple message
2015-05-17 20:07:07.994  INFO 22983 --- [enerContainer-1] n.l.b.e.c.JmsPublishSubscribeApplication : Message Received: simple message via listener 1

ただし、トピックの定義により、各メッセージは両方のリスナーによって消費される必要があります。何が足りないのですか?

13
luboskrnac

@JmsListenerを使用する場合は、拡張するDefaultMessageListenerContainerを使用します JmsDestinationAccessor デフォルトではpubSubDomainfalseに設定されています。このプロパティがfalseの場合、キューで動作しています。トピックを使用する場合は、このプロパティ値をtrueに設定する必要があります。

Spring Boot を使用しているので、spring.jms.pub-sub-domainプロパティをapplication.propertiesに追加し、それをtrueに設定することで、このプロパティをtrueに簡単に設定できます。

spring.jms.pub-sub-domain=true

@JmsListener を使用する場合、jmsListenerContainerFactoryという名前のBeanを探します。それが利用できない場合は、デフォルトのBeanが必要です。独自のBeanを含めて、このプロパティをtrueにプログラムで設定することもできます。

@Bean
public DefaultMessageListenerContainer jmsListenerContainerFactory() {
    DefaultMessageListenerContainer dmlc = new DefaultMessageListenerContainer();
    dmlc.setPubSubDomain(true);
    // Other configuration here
    return dmlc;
}

これはもちろん機能しますが、より多くの作業が必要になります。これに関する詳細は、 @EnableJmsアノテーション のドキュメントに記載されています。

30
M. Deinum

@JmsListenerのデフォルトの宛先タイプをQueueからTopicに切り替えることは、プロパティを変更したりXMLを使用したりすることなく、Javaで完全に実行できます。

スプリングガイド には、DefaultMessageListenerContainerによって提供されるデフォルト設定をカスタマイズするための例が含まれています。

次のようにカスタムBeanを定義する必要があります。

@Bean
public JmsListenerContainerFactory<?> myFactory(ConnectionFactory connectionFactory,
                                                DefaultJmsListenerContainerFactoryConfigurer configurer) {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    // This provides all boot's default to this factory, including the message converter
    configurer.configure(factory, connectionFactory);
    // You could still override some of Boot's default if necessary.
    factory.setPubSubDomain(true);
    return factory;
}

これは、@JmsListenerアノテーション付きメソッドで使用できます。

@JmsListener(destination = "mailbox", containerFactory = "myFactory")
public void receiveMessage(Email email) {
    // implementation
}
7
ldz