복붙노트

[SPRING] 게시 구독 주제에 대한 @JmsListener 사용

SPRING

게시 구독 주제에 대한 @JmsListener 사용

@JmsListener 주석을 기반으로 publish-subscribe에 대한 예제를 만들려고합니다. 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

그러나 각 메시지는 주제의 정의에 의해 두 청취자 모두에 의해 소비되어야합니다. 내가 뭘 놓치고 있니?

해결법

  1. ==============================

    1.@JmsListener를 사용하는 경우, JmsDestinationAccessor를 확장하는 DefaultMessageListenerContainer를 사용합니다. 디폴트에서는, pubSubDomain가 false로 설정됩니다. 이 속성이 false이면 대기열에서 작동합니다. 주제를 사용하려면이 특성 값을 true로 설정해야합니다.

    @JmsListener를 사용하는 경우, JmsDestinationAccessor를 확장하는 DefaultMessageListenerContainer를 사용합니다. 디폴트에서는, pubSubDomain가 false로 설정됩니다. 이 속성이 false이면 대기열에서 작동합니다. 주제를 사용하려면이 특성 값을 true로 설정해야합니다.

    Spring Boot를 사용할 때 spring.jms.pub-sub-domain 속성을 application.properties에 추가하고 true로 설정하여이 속성을 true로 설정할 수 있습니다.

    spring.jms.pub-sub-domain=true
    

    @JmsListener를 사용할 때 jmsListenerContainerFactory라는 이름의 bean을 찾고, 사용할 수 없다면 기본 bean이 필요합니다. 당신은 또한 자신의 bean을 포함하고이 속성을 프로그래밍 방식으로 설정할 수있다.

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

    이것은 물론 작동하지만 더 많은 작업이 필요합니다. 자세한 내용은 @EnableJms 주석의 설명서를 참조하십시오.

  2. ==============================

    2.@JmsListener의 기본 대상 유형을 Queue에서 Topic으로 전환하는 것은 속성을 수정하거나 XML을 사용하지 않고 Java로 완전히 수행 할 수 있습니다.

    @JmsListener의 기본 대상 유형을 Queue에서 Topic으로 전환하는 것은 속성을 수정하거나 XML을 사용하지 않고 Java로 완전히 수행 할 수 있습니다.

    Spring 가이드에는 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
    }
    
  3. from https://stackoverflow.com/questions/30291067/jmslistener-usage-for-publish-subscribe-topic by cc-by-sa and MIT license