【问题标题】:Java JMS - Message Listener and onExceptionJava JMS - 消息侦听器和 onException
【发布时间】:2020-02-22 01:54:25
【问题描述】:

我有一个应用程序,它有一个主线程和一个 JMS 线程,它们通过 ActiveMQ 5.15.11 相互通信。我可以很好地发送消息,但是我想要一种发回状态或错误的方法。我注意到MessageListener 允许onSuccess() 和onException(ex) 作为两个要监听的事件,但是我发现只有onSuccess() 被调用。

这是我的代码的 sn-ps。

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 线程中收集错误并将其发送回调用线程的目标?

【问题讨论】:

    标签: java jms activemq


    【解决方案1】:

    您的期望是基于对 JMS 的根本误解。

    代理消息传递的基本原则之一是生产者和消费者在逻辑上彼此断开连接。换句话说......生产者向代理发送消息,它不一定关心它是否成功消费,它当然不会知道谁消费它或有任何保证什么时候消耗。同样,消费者不一定知道消息何时发送、为何发送或是谁发送的。这在生产者和消费者之间提供了极大的灵活性。 JMS 遵循断开生产者和消费者的这一原则。

    消费者没有直接的方式来通知生产者关于它发送的消息的消费问题。也就是说,您可以采用所谓的“请求/响应模式”,以便消费者可以向生产者提供某种反馈。您可以在示例代码here 中找到对此模式的解释。

    另外,您使用的AsyncCallback 类不是JMS 的一部分。我相信它是由 ActiveMQ 本身专门提供的org.apache.activemq.AsyncCallback,它只为实际的 send 操作(即不用于消息的消费)提供成功或失败的回调。

    最后,您应该知道,从 javax.jms.MessageListener 的 onMessage 方法中抛出 RuntimeException 被 JMS 规范视为“编程错误”,应该避免。 JMS 2 规范的第 8.7 节规定:

    监听器可以抛出RuntimeException;但是,这被认为是客户端编程错误。表现良好的侦听器应捕获此类异常并尝试将导致它们的消息转移到某种形式的特定于应用程序的“无法处理的消息”目的地。 监听器抛出 RuntimeException 的结果取决于会话的确认模式。

    • AUTO_ACKNOWLEDGE 或 DUPS_OK_ACKNOWLEDGE - 消息将立即重新传递。 JMS 提供者在放弃之前重新传递相同消息的次数取决于提供者。对于在这些情况下重新传递的消息,将设置 JMSRedelivered 消息头字段,并增加 JMSXDeliveryCount 消息属性。

    • CLIENT_ACKNOWLEDGE - 传递给侦听器的下一条消息。如果客户端希望重新传递之前未确认的消息,则必须手动恢复会话。

    • Transacted Session - 传递给侦听器的下一条消息。客户端可以提交或回滚会话(换句话说,RuntimeException 不会自动回滚会话)。

    【讨论】:

    • 感谢您的提示 - 我通过 activemq.apache.org/… 找到了答案,但它确认我使用 AsyncCallback 错误
    猜你喜欢
    • 1970-01-01
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    • 2011-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-07
    相关资源
    最近更新 更多