我有一个带有主线程和 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 的根本误解。
代理消息传递的基本原则之一是生产者和消费者在逻辑上彼此断开。换句话说...生产者向代理发送一条消息,它不一定关心该消息是否被成功消费,并且它当然不会知道谁消费它或有任何保证当它被消耗时。同样,消费者不一定知道消息何时或为何发送,或者是谁发送的。这为生产者和消费者之间提供了极大的灵 active 。 JMS 坚持生产者和消费者断开连接的这一原则。
消费者没有直接方式通知生产者其发送的消息的消费出现问题。也就是说,您可以采用所谓的“请求/响应模式”,以便消费者可以向生产者提供某种反馈。您可以找到此模式的解释以及示例代码 here .
此外,您使用的 AsyncCallback
类不是 JMS 的一部分。我相信是org.apache.activemq.AsyncCallback
由 ActiveMQ 本身独家提供,它仅提供实际发送操作成功或失败的回调(即不用于消息的消费)。
最后,您应该知道,从 javax.jms.MessageListener
的 onMessage
方法抛出 RuntimeException
被视为“编程错误” “符合 JMS 规范,应该避免。 JMS 2 规范第 8.7 节指出:
It is possible for a listener to throw a
RuntimeException
; however, this is considered a client programming error. Well behaved listeners should catch such exceptions and attempt to divert messages causing them to some form of application-specific 'unprocessable message' destination. The result of a listener throwing aRuntimeException
depends on the session's acknowledgment mode.
AUTO_ACKNOWLEDGE
orDUPS_OK_ACKNOWLEDGE
- the message will be immediately redelivered. The number of times a JMS provider will redeliver the same message before giving up is provider-dependent. The JMSRedelivered message header field will be set, and the JMSXDeliveryCount message property incremented, for a message redelivered under these circumstances.
CLIENT_ACKNOWLEDGE
- the next message for the listener is delivered. If a client wishes to have the previous unacknowledged message redelivered, it must manually recover the session.Transacted Session - the next message for the listener is delivered. The client can either commit or roll back the session (in other words, a
RuntimeException
does not automatically rollback the session).
关于Java JMS - 消息监听器和 onException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60348330/