如何正确关闭JMS连接

时间:2018-06-24 07:37:17

标签: jms activemq dead-letter

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

如何处理。

1 个答案:

答案 0 :(得分:0)

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

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