如何正确关闭JMS连接

如何正确关闭JMS连接,jms,activemq,dead-letter,Jms,Activemq,Dead Letter,我有下面一段代码来轮询JMS中的死信队列 Message m = mconsumer.receive(3000L); while (m != null) { try { sendMessageToDB(m); } catch (DBException ex) { writeToDeadLetterQueueBack(m); } m = messageConsumer.rec

我有下面一段代码来轮询JMS中的死信队列

Message  m = mconsumer.receive(3000L);
      while (m != null) {
        try {
          sendMessageToDB(m);   
        } catch (DBException ex) {
          writeToDeadLetterQueueBack(m);
        } 
       m = messageConsumer.receive(3000L);
      }
现在,在这个while循环中,如果发生
DBException
,我的连接不会关闭,如果我关闭catch块中的连接,下面的一行将在会话现在关闭时失败

m=messageConsumer.receive(3000L)


如何处理此问题。

通常公认的最佳做法是不将消息“写回”到死信队列,而是使用事务会话“回滚”

在您的设计中,在数据库中断的情况下,您将有一个无限循环,不断地消耗消息并将消息预发布回死信队列。你最好在计时器上启动这件事(每小时运行一次,等等)。。或者让它有某种退避逻辑,在错误场景中停止不断轮询DLQ

基于常规会话的一次一条消息提交和回滚处理,在finally块中使用适当的对象关闭例程

Session session = connection.createSession(true, Session.TRANSACTED);
MessageConsumer consumer = session.createConsumer(session.createQueue('MY.QUEUE.DLQ');

Message  m = mconsumer.receive(3000L);
  while (m != null) {
    try {
      sendMessageToDB(m);
      session.commit();
      m = messageConsumer.receive(3000L);
    } catch (DBException ex) {
      session.rollback();
      logger.error("Rolling back messageId {} due to database error {}", m.getJMSMessageId(), ex);
    } finally {
      if(consumer != null) {
          try { consumer.close(); } catch (JMSException e) { logger.error("Error closing consumer.."); } 
      }
      if(session != null) {
          try { session.close(); } catch (JMSException e) { logger.error("Error closing session.."); } 
      }
      if(connection != null) {
          try { connection.close(); } catch (JMSException e) { logger.error("Error closing connection.."); } 
      }
    }
  }

如果catch块中的连接会中断应用程序,为什么要关闭该连接?如果从DLQ回滚,会发生什么情况。消息是否将回滚到主队列。执行回滚()时,代理将被告知消费者不接受消息。然后,代理将其保留在队列中。通常(取决于ActiveMQ中的目标策略),在尝试向使用者传递一定数量的消息后,代理会将消息移动到死信队列中,或将其丢弃。在上面的例子中,我向您展示了如何关闭连接,这样您就不会重复进行重新交付。上述方法可以很好地用作触发的定时作业,以清除死信队列中的消息,但不能用作“始终在线服务”。