JMS 提交失败
JMS commit fails
我们有一个使用 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() 失败和堆栈跟踪,仅当我 运行 处于调试模式时。如果我将 war 设置为 运行,我在日志中看不到任何提交失败的痕迹。我可以说我们收到了消息,但不能说 commit() 是否失败。
如果我们使用 Spring Boot 的默认 JMS 实现,即 ActiveMQ,那么无论是否处于调试模式,commit() 都不会失败,它只发生在 Tibco 中。
有人知道 commit() 失败的原因吗?当提交失败时,事务回滚,消息不会从队列中清除。
为什么我只在调试模式下看到这个错误?或者:确实,当我 运行 war 但只是没有记录时确实发生了?
请在下面找到完整的堆栈跟踪:
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
当您在该交易中的某些消息同时过期时,会发生此 EMS 异常。我自己试过这个。
当您 运行 在调试模式之外时,事情似乎足够快。但是当你处于调试模式时,你在 commit() 之前的时间要长得多。因此,如果您的生产者的生存时间同时到期,则提交会假定出现问题(EMS 知道该事务中应该有例如 5 条消息,但其中一条已经过期)并抛出此异常。
要验证生产者的生存时间,请查看 MessageProducer.send() 调用或 msgProducer.setTimeToLive() 的最后一个选项并注意,这是 中的时间毫秒 ,而不是秒。另一种检查这是否是问题的方法是在调试模式下 运行 并继续您的线程 'really quick'。这可能会改变你的行为。
我们有一个使用 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() 失败和堆栈跟踪,仅当我 运行 处于调试模式时。如果我将 war 设置为 运行,我在日志中看不到任何提交失败的痕迹。我可以说我们收到了消息,但不能说 commit() 是否失败。
如果我们使用 Spring Boot 的默认 JMS 实现,即 ActiveMQ,那么无论是否处于调试模式,commit() 都不会失败,它只发生在 Tibco 中。
有人知道 commit() 失败的原因吗?当提交失败时,事务回滚,消息不会从队列中清除。
为什么我只在调试模式下看到这个错误?或者:确实,当我 运行 war 但只是没有记录时确实发生了?
请在下面找到完整的堆栈跟踪:
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
当您在该交易中的某些消息同时过期时,会发生此 EMS 异常。我自己试过这个。
当您 运行 在调试模式之外时,事情似乎足够快。但是当你处于调试模式时,你在 commit() 之前的时间要长得多。因此,如果您的生产者的生存时间同时到期,则提交会假定出现问题(EMS 知道该事务中应该有例如 5 条消息,但其中一条已经过期)并抛出此异常。
要验证生产者的生存时间,请查看 MessageProducer.send() 调用或 msgProducer.setTimeToLive() 的最后一个选项并注意,这是 中的时间毫秒 ,而不是秒。另一种检查这是否是问题的方法是在调试模式下 运行 并继续您的线程 'really quick'。这可能会改变你的行为。