java - Java JMS - 消息侦听器和 onException
问题描述
我有一个带有主线程和 JMS 线程的应用程序,它们通过 ActiveMQ 5.15.11 相互通信。我可以很好地发送消息,但是我想要一种发回状态或错误的方法。我注意到MessageListener
允许onSuccess()
和onException(ex)
作为两个事件来监听,但是我发现只有onSuccess()
被调用。
这是我的代码片段。
JMS 线程:
ConnectionFactory factory = super.getConnectionFactory();
Connection connection = factory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(super.getQueue());
MessageConsumer consumer = session.createConsumer(queue);
consumer.setMessageListener(m -> {
try {
super.processRmbnConfigMsg(m);
} catch (JMSException | IOException e) {
LOG.error(e.getMessage(), e);
// I can only use RuntimeException.
// Also this exception is what I am expecting to get passed to the onException(..)
// call in the main thread.
throw new RuntimeException(e);
}
});
connection.start();
主线程(向 JMS 发送消息):
sendMessage(xml, new AsyncCallback() {
@Override
public void onException(JMSException e) {
// I am expecting this to be that RuntimeException from the JMS thread.
LOG.error("Error", e);
doSomethingWithException(e);
}
@Override
public void onSuccess() {
LOG.info("Success");
}
});
我所期望的是,即使被包装new RuntimeException(e)
了,事件侦听器也会以某种方式接收到抛出的异常。onException(JMSException e)
RuntimeException
相反,我总是收到onSuccess()
事件。我想该onException(..)
事件是在通信问题期间发生的,但我想要一种将异常发送回给调用者的方法。
如何实现在 JMS 线程中收集错误并将其发送回调用线程的目标?
解决方案
您的期望是基于对 JMS 的根本误解。
代理消息传递的基本原则之一是生产者和消费者在逻辑上彼此断开连接。换句话说……生产者向代理发送消息,它不一定关心它是否消费成功,它当然不会知道是谁消费它,也不知道什么时候会被消费。同样,消费者不一定知道消息何时发送、为何发送或是谁发送的。这在生产者和消费者之间提供了极大的灵活性。JMS 遵循断开生产者和消费者的这一原则。
消费者没有直接的方法来通知生产者关于它发送的消息的消费问题。也就是说,您可以使用所谓的“请求/响应模式”,以便消费者可以向生产者提供某种反馈。您可以在此处找到此模式的说明以及示例代码。
此外,AsyncCallback
您使用的类不是 JMS 的一部分。我相信它是org.apache.activemq.AsyncCallback
由 ActiveMQ 本身专门提供的,它只为实际发送操作的成功或失败提供回调(即不用于消息的消费)。
最后,您应该知道,RuntimeException
从 a 的onMessage
方法中抛出 ajavax.jms.MessageListener
被 JMS 规范视为“编程错误”,应该避免。JMS 2 规范的第 8.7 节规定:
侦听器可以抛出
RuntimeException
; 但是,这被认为是客户端编程错误。表现良好的侦听器应捕获此类异常并尝试将导致它们的消息转移到某种形式的特定于应用程序的“无法处理的消息”目的地。监听器抛出 a 的结果RuntimeException
取决于会话的确认模式。
AUTO_ACKNOWLEDGE
或DUPS_OK_ACKNOWLEDGE
- 消息将立即重新传递。JMS 提供者在放弃之前重新传递相同消息的次数取决于提供者。对于在这些情况下重新传递的消息,将设置 JMSRedelivered 消息头字段,并增加 JMSXDeliveryCount 消息属性。
CLIENT_ACKNOWLEDGE
- 为侦听器传递下一条消息。如果客户端希望重新传递先前未确认的消息,它必须手动恢复会话。Transacted Session - 传递给监听器的下一条消息。客户端可以提交或回滚会话(换句话说,a
RuntimeException
不会自动回滚会话)。
推荐阅读
- excel - 如果函数在 Excel 中返回文本而不是数字?
- android - 如何在 Android/kotlin 中使用 CLIPS 规则引擎获取输出
- excel - 增强宏
- java - 基于自定义 Nifi 处理器的 Maven 构建在测试中失败,java.lang.UnsupportedOperationException
- r - 当子集的长度变为零时,如何简洁地处理子集?
- javascript - 为什么我会收到作为 React Child 功能的警告
- elasticsearch - ElasticSearch 中的映射和模板是什么?
- javascript - 在 AWS CDK 中使用 AWS 开发工具包的正确方法
- python - Pandas:如何在具有多个非重叠时间序列的长数据框中填充缺失的日期?
- javascript - 在设置器中设置新值时获取旧值(javascript)