【问题标题】:Create durable topic and subscriber spring boot jms with ActiveMQ使用 ActiveMQ 创建持久主题和订阅者 spring boot jms
【发布时间】:2018-01-15 08:59:25
【问题描述】:

我需要为 ActiveMQ 创建一个主题和一个持久订阅者,我的问题是我不知道在哪里指定。我可以创建主题并使用消息,但是当我关闭订阅者然后继续发送消息并再次打开订阅者时,它不会读取它们。

这是我目前所拥有的:

发送消息:

    JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
    jmsTemplate.setPubSubDomain(true);
    jmsTemplate.setDeliveryMode(DeliveryMode.PERSISTENT);
    jmsTemplate.setDeliveryPersistent(true);
    jmsTemplate.convertAndSend("venta.topic",venta);

收到消息:

@JmsListener(destination = "venta.topic",id = "comercial",subscription = "venta.topic")
public void receiveMessage(Venta venta) {
    logger.log(Level.INFO, "RECEIVED : {0}",venta);      
    repository.save(venta);
}

我已阅读 this article 并了解我需要创建持久订阅者。

我也看过spring docs

我认为这与DefaultJmsListenerContainerFactory(我没有实现,我使用的是默认配置)有关,文档显示:

@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
    DefaultJmsListenerContainerFactory factory =
            new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory());
    factory.setDestinationResolver(destinationResolver());
    factory.setConcurrency("3-10");
    return factory;
}

但我似乎无法找到创建持久会话的位置。我的生产者和订阅者都连接到一个独立的 activemq 二进制文件。

希望你能帮助我,在此先感谢。

【问题讨论】:

    标签: java spring spring-boot jms activemq


    【解决方案1】:

    很难确定,但这个问题的一个常见原因是忘记在 connectionFactory bean 上配置唯一的 clientId。它必须是独一无二的,并且是经纪人可以区分每个客户的方式。

    【讨论】:

      【解决方案2】:

      DefaultJmsListenerContainerFactory 应该有唯一的 clientId 和持久的 sub。真正的设置如下代码:

      @Bean
      public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
          DefaultJmsListenerContainerFactory factory =
                  new DefaultJmsListenerContainerFactory();
          factory.setConnectionFactory(connectionFactory());
          factory.setDestinationResolver(destinationResolver());
          factory.setConcurrency("3-10");
          factory.setClientID("brokerClientId");
          factory.setSubscriptionDurable(true);
          return factory;
      }
      

      【讨论】:

      • 感谢您为我指明了正确的方向,但我仍然遇到问题,看来我需要在 JMSListener 上注册工厂
      • 正确,你需要在你的JmsListener中注册自定义的containerFactory。
      • 可以通过修改yaml配置文件来实现吗?
      【解决方案3】:

      正如前面的答案所指出的,有必要在工厂上设置客户端ID和持久订阅:

      @Bean
      public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
          DefaultJmsListenerContainerFactory factory =
                  new DefaultJmsListenerContainerFactory();
          factory.setConnectionFactory(connectionFactory());
          factory.setDestinationResolver(destinationResolver());
          factory.setConcurrency("3-10");
          factory.setClientID("brokerClientId");
          factory.setSubscriptionDurable(true);
          return factory;
      }
      

      但仅此一项并没有将客户端注册为持久订阅者,这是因为JMSListener 需要指定containerFactory,否则它只会采用默认值:

      @JmsListener(
      destination = "venta.topic",
      id = "comercial",
      subscription = "venta.topic",
      //this was also needed with the same name as the bean above
      containerFactory = "jmsListenerContainerFactory" 
      )
      public void receiveMessage(Venta venta) {
                  logger.log(Level.INFO, "RECEIVED : {0}",venta);      
                  repository.save(venta);
      }
      

      值得一提的是,this post 让我意识到自己的错误。

      我希望这对其他人有帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-30
        • 2017-01-24
        • 2013-11-10
        • 2012-05-30
        • 2018-08-14
        • 2014-10-12
        • 1970-01-01
        • 2018-03-27
        相关资源
        最近更新 更多