JMS提交失败

时间:2018-07-16 22:57:45

标签: spring-boot jms spring-jms tibco tibco-ems

我们有一个将JMS与Tibco消息传递服务器一起使用的应用程序。它是通过Spring Boot实施的。 我们的会话是事务处理会话,并且确认模式设置为自动。 我们可以接收发送到队列的消息,但是由于某些原因commit()方法失败。

这是错误:

2018-07-13 15:50:35.858  WARN 2576 --- [enerContainer-8] o.s.j.l.DefaultMessageListenerContainer  : Execution of JMS message listener failed, and no ErrorHandler has been set.

javax.jms.TransactionRolledBackException: Commit failed

2018-07-13 15:50:35.914  WARN 2576 --- [enerContainer-8] o.s.j.l.DefaultMessageListenerContainer  : Setup of JMS message listener invoker failed for destination 'queue' - trying to recover. Cause: Commit failed; nested exception is javax.jms.JMSException: operation='ack' cause='Illegal state' queue='queue'

我应该提到两件事:

  • 仅在调试模式下运行时,我才看到commit()故障和堆栈跟踪。如果我只是打仗,我在日志中看不到任何提交失败的痕迹。我可以说我们已经收到了消息,但是不能说commit()是否失败。

  • 如果我们使用Spring Boot的默认JMS实现ActiveMQ,则commit()不管是否处于调试模式都不会失败,它只会在Tibco中发生。

有人知道为什么commit()失败吗?如果提交失败,事务将回滚,并且不会从队列中清除消息。

为什么我只能在调试模式下看到此错误?或者:的确,当我参战但未登录时会发生吗?

请在下面找到完整的堆栈跟踪:

15:50:35.858 [DefaultMessageListenerContainer-8] WARN  o.s.j.l.DefaultMessageListenerContainer - Execution of JMS message listener failed, and no ErrorHandler has been set.
javax.jms.TransactionRolledBackException: Commit failed
    at com.tibco.tibjms.Tibjmsx.buildException(Tibjmsx.java:596)
    at com.tibco.tibjms.TibjmsxSessionImp._confirmTransacted(TibjmsxSessionImp.java:3251)
    at com.tibco.tibjms.TibjmsxSessionImp._confirm(TibjmsxSessionImp.java:3643)
    at com.tibco.tibjms.TibjmsxSessionImp._commit(TibjmsxSessionImp.java:2898)
    at com.tibco.tibjms.TibjmsxSessionImp.commit(TibjmsxSessionImp.java:4860)
    at org.springframework.jms.support.JmsUtils.commitIfNecessary(JmsUtils.java:218)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.commitIfNecessary(AbstractMessageListenerContainer.java:776)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:680)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:318)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:257)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1189)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1179)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1076)
    at java.lang.Thread.run(Unknown Source)
2018-07-13 15:50:35.914  WARN 2576 --- [enerContainer-8] o.s.j.l.DefaultMessageListenerContainer  : Setup of JMS message listener invoker failed for destination 'queue' - trying to recover. Cause: Commit failed; nested exception is javax.jms.JMSException: operation='ack' cause='Illegal state' queue='queue'
2018-07-13 15:50:36.543  INFO 2576 --- [enerContainer-8] o.s.j.l.DefaultMessageListenerContainer  : Successfully refreshed JMS Connection
15:50:36.543 [DefaultMessageListenerContainer-8] INFO  o.s.j.l.DefaultMessageListenerContainer - Successfully refreshed JMS Connection

1 个答案:

答案 0 :(得分:1)

此交易中的某些消息同时过期时,将发生此EMS异常。我自己尝试过这个。

当您在调试模式之外运行时,事情似乎很快。但是,当您处于调试模式时,您在commit()之前的时间会更长。因此,如果您的生产者的生存时间在此期间到期,则提交将假定有问题(EMS知道此事务中应该有5条消息,但其中一条已经到期)并引发此异常。

要验证生产者的生存时间,请参阅MessageProducer.send()调用的最后一个选项或msgProducer.setTimeToLive()并注意,这是一个时间,以秒为单位,毫秒,而不是秒。检查这是否是问题的另一种方法是在调试模式下运行,并且“真正快速”地继续线程。那可能会改变您的行为。