如何正确关闭 JMS 连接

How to close JMS Connection properly

我有以下代码来轮询 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);

如何处理。

普遍接受的最佳做法是不 'write-back' 将消息发送到死信队列,而是 'roll it back' 使用事务处理会话。

在您的设计中,如果发生数据库中断,您将有一个不断消费和预发布消息返回死信队列的无限循环。你最好在计时器上启动这个东西(运行 每小时等).. 或者让它有某种退避逻辑来停止在错误情况下不断轮询 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.."); } 
      }
    }
  }