我正在尝试在处理邮件时处理两种不同类型的问题。
第一个问题是远程数据库是否已关闭。在这种情况下,邮件应该停止处理,稍后再试。此消息永远不应该转到DLQ,并应继续尝试,直到远程数据库启动。
第二个问题是邮件出现问题。在这种情况下,它应该转到DLQ。
我应该如何构建以下代码?
@Override
public void onMessage(Message message) {
try {
// Do some processing
messageProcessing(message); // Should DLQ if message is bad
// Save to the database
putNamedLocation(message); // <<--- Exception when external DB is down
} catch (Exception e) {
logger.error(e.getMessage());
mdc.setRollbackOnly();
}
}
答案 0 :(得分:0)
假设您可以在MDB的代码主体中明确地检测到错误消息,我会直接将错误消息写入DLQ。这使您可以更自由地对错误进行分类,并可选择将不同类型的错误消息发送到不同的“DLQ-Like”队列,和/或将生存时间应用于DLQ消息,以便不希望 - 正在处理的类型消息永远不会堆积在队列中。您可以将@Resource带注释的实例变量添加到引用ConnectionFactory和Queue引用的MDB类,以支持将消息发送到目标DLQ。最重要的是,确保您自己检测到错误和DLQ消息。
对于数据库关闭,您可以通过在获取连接或编写更新时捕获异常来检测此问题。在这种情况下,清理资源并抛出RuntimeException。这将导致重新传递消息,但您需要检查JMS配置以获取两件事:
为了避免#2(如果您的JMS实现不支持redilvery延迟,如WebSphereMQ,这很棘手),您可以使用JBoss JMX管理接口让MDB在MDB上停止(以及稍后重新启动)传递。但是,您不能在处理消息的同一个线程中的MDB内部执行此操作,因为MDB将等待消息完成处理,而它不能因为它正在等待MDB停止,它可以因为... [等等]所以...你最好的选择是启动某种轮询DB的哨兵,当它找到它时,停止MDB,当它再次找到它时,重新启动它。有关如何执行该操作的摘要,请参阅此question。
最后一部分应该有助于处理消息验证导致的任何意外异常。 (即数据库很好,但由于某种原因,该消息完全是fubar导致未捕获的异常导致重新传递消息)。由于down-DB消息不应该被重新传递超过几次(由于你的哨兵),你可以检查消息的重新传递计数,如果它是非常高的那么你知道你有毒药消息,你可以抛弃它,或DLQ它。
希望这有帮助。