Использование @JmsListener для публикации-тема подписки

Я пытаюсь создать пример для публикации-подписки на основе аннотации @JmsListener: https://github.com/lkrnac/book-eiws-code-samples/tree/master/05-jms/0515-publish-subscribe

соответствующие фрагменты кода:

@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

но каждое сообщение должно использоваться обоими слушателями по определению тем. Что я упускаю?

2 ответов


при использовании @JmsListener использует DefaultMessageListenerContainer которая расширяет JmsDestinationAccessor который по умолчанию имеет pubSubDomain значение false. Если это свойство имеет значение false, оно работает в очереди. Если вы хотите использовать темы, вы должны установить значение свойства true.

как вы используете Весна Загрузки вы можете легко установить это свойство в true, добавив spring.jms.pub-sub-domain свойства application.properties и установить его в true.

spring.jms.pub-sub-domain=true

когда с помощью @JmsListener ищет jmsListenerContainerFactory С именем bean, если это недоступно, ожидается значение по умолчанию. Вы также можете включить свой собственный компонент и программно установить это свойство yo true.

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

это, конечно, также будет работать, но будет больше работы, более подробную информацию об этом можно найти в документации @EnableJms аннотации.


переключение типа назначения по умолчанию @JmsListener С Queue to Topic можно сделать полностью на Java без изменения свойств или использования XML.

на направляющий выступ весны содержит пример настройки параметров по умолчанию, предоставляемых DefaultMessageListenerContainer.

это требует определения пользовательского компонента следующим образом:

@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
}