Java JMS - 消息监听器和 onException

标签 java jms activemq

我有一个带有主线程和 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.MessageListeneronMessage 方法抛出 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 a RuntimeException depends on the session's acknowledgment mode.

  • AUTO_ACKNOWLEDGE or DUPS_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/

相关文章:

java - Http 基本身份验证不适用于 Spring WS 和 WebServiceTemplate 凭据

java - JNI & C - 指向指针的指针

java - 使用java实现一个非常大的队列

java - 如果未完成客户确认会怎样?

java - 迭代、递归和乘法

JMeter:我可以使用任何 JMeter 采样器连接消息并将消息发送到 azurecloude 中的队列 - azure service bus

parallel-processing - Camel JMS 组件和并行处理

java - 多个持久的听众。他们同时工作吗?

java - ActiveMQ:没有合适的日志构造函数

java - 从 Camel 路由在 ActiveMQ 上强制套接字超时?