Использование @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
}