Ошибка фиксации JMS

У нас есть приложение, которое использует 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().

  • Если мы используем JMS-реализации Spring Boot по умолчанию, то есть 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

person blueSky    schedule 16.07.2018    source источник


Ответы (1)


Это исключение EMS происходит, когда срок действия некоторых ваших сообщений в этой транзакции истек. Только что попробовал это сам.

Когда вы работаете вне режима отладки, все кажется достаточно быстрым. Но когда вы находитесь в режиме отладки, ваше время до фиксации() намного больше. Поэтому, если время жизни вашего производителя тем временем истекает, коммит предполагает, что что-то не так (EMS знает, что в этой транзакции должно быть, например, 5 сообщений, но одно из них уже истекло) и выдает это исключение.

Чтобы проверить время жизни вашего производителя, посмотрите последнюю опцию вашего вызова MessageProducer.send() или msgProducer.setTimeToLive() и обратите внимание, что это время в миллисекундах, а не в секундах. Другой способ проверить, не в этом ли проблема, — запустить в режиме отладки и «действительно быстро» продолжить работу с потоком. Это может изменить ваше поведение.

person Axel Podehl    schedule 18.07.2018
comment
Как упоминалось выше: мы установили это свойство: spring.jms.template.time-to-live=36000 Это сообщит серверу JMS о том, что срок действия сообщения истекает через 36 миллисекунд, поэтому, как только сообщение будет получено из очереди, сервер JMS не смог найти сообщения для подтверждения и, следовательно, ошибки. Как только мы избавились от этого свойства времени жизни, мы смогли отправлять/получать сообщения, и фиксация JMS также прошла успешно. - person blueSky; 18.07.2018