【问题标题】:What happens on a JMS queue when onMessage() throws a JMSException?当 onMessage() 抛出 JMSException 时,JMS 队列会发生什么?
【发布时间】:2011-02-05 07:45:11
【问题描述】:

我将 Spring 2.5 与实现 MessageListener 的自定义类一起使用。如果在我的 onMessage() 方法中抛出 JmsException,队列的状态会发生什么变化?

在调用 onMessage 的那一刻,消息是否被队列视为“已传递”?或者 JmsException 是否触发某种回滚并且消息重新进入队列?

提前致谢!

【问题讨论】:

    标签: spring exception jms


    【解决方案1】:

    来自 JMS 1.1 规范...

    4.5.2 异步传递

    客户端可以使用 MessageConsumer 注册实现 JMS MessageListener 接口的对象。当消息到达消费者时,提供者通过调用侦听器的 onMessage 方法来传递它们。

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

    监听器抛出 RuntimeException 的结果取决于会话的确认模式。

    • AUTO_ACKNOWLEDGE 或 DUPS_OK_ACKNOWLEDGE - 消息 将立即重新交付。这 JMS 提供程序将执行的次数 之前重新发送相同的消息 放弃取决于提供者。这 JMSRedelivered 消息头字段 将为重新传递的消息设置 在这种情况下。
    • CLIENT_ACKNOWLEDGE - 下一条消息 为听众送达。如果一个 客户希望拥有以前的 重新发送未确认的消息, 它必须手动恢复会话。
    • 事务处理的会话 - 下一条消息 为听众送达。这 客户端可以提交或回滚 会话(换句话说,一个 RuntimeException 没有 自动回滚会话)。

    JMS 提供者应该使用正在抛出的消息侦听器来标记客户端 RuntimeExceptions 可能出现故障。

    【讨论】:

    • 如果 onMessage 内部发生未处理的异常并且方法永远不会返回,会发生什么?消息是否有可能没有从队列中删除?这是否意味着(对于同步客户端)onMessage 必须返回确认以便可以从队列中删除消息?
    • @bluelurker - 我对你的问题感到困惑。规范语言是关于允许 RuntimeException 从 onMessage() 方法传播出去的。如果您的方法通过抛出异常来完成,那么这是“正常”返回的替代方法。所以我不明白“永远不会回来”的部分。它没有返回,而是通过传播异常来完成。
    • @JohnM 来自 onMessage() 方法,如果我抛出 RunTimeException 则该消息将保留在队列中并再次传递。将再次抛出消息。它将再次交付。等等....我的理解正确吗?这就是我在测试中看到的情况。
    • @KaushikLele 关于无休止的重新交付......我认为这是一个非标准化的事情,一些供应商产品具有限制无休止重新交付的功能。有时称为“毒消息队列”,其中消息在 N 次失败的传递尝试后进入。检查供应商的文档。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-12
    • 1970-01-01
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多