我有以下代码来轮询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);
如何处理。
答案 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.."); }
}
}
}