我有一个带有主线程和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的基本误解。
代理消息传递的基本原则之一是,生产者和消费者在逻辑上是彼此断开的。换句话说...生产者向代理发送消息,它不一定在乎消息是否被成功使用,并且肯定不知道 直接AsyncCallback
类也不属于JMS。我相信它是org.apache.activemq.AsyncCallback
由ActiveMQ本身专门提供,并且它仅为实际send操作的成功或失败提供回调(即,不用于消息的消耗)。
最后,您应该知道,从 听众有可能抛出org.apache.activemq.AsyncCallback
的RuntimeException
方法中抛出onMessage
被JMS规范视为“编程错误”,应避免。 JMS 2规范的8.7节规定:javax.jms.MessageListener
;但是,这被认为是客户端编程错误。行为良好的侦听器应捕获此类异常,并尝试将导致它们定向到某种形式的特定于应用程序的“不可处理的消息”目的地的消息转移。侦听器抛出RuntimeException
的结果取决于会话的确认模式。RuntimeException
或AUTO_ACKNOWLEDGE
-消息将立即重新发送。 JMS提供者在放弃之前重新传递相同消息的次数取决于提供者。对于在这种情况下重新传递的消息,将设置JMSRedelivered消息头字段,并增加JMSXDeliveryCount消息属性。
DUPS_OK_ACKNOWLEDGE
-传递给侦听器的下一条消息。如果客户端希望重新传递之前的未确认消息,则必须手动恢复会话。
Transacted Session-传递给侦听器的下一条消息。客户端可以提交或回滚会话(换句话说,CLIENT_ACKNOWLEDGE
不会自动回滚会话)。