Spring DefaultMessageListenerContainer, ActiveMQ и повторная доставка сообщений

если я использую DefaultMessageListenerContainer< /a> из Spring для получения сообщений JMS, сообщения JMS не доставляются повторно, даже если я установил sessionAcknowledgeMode до 2.

В случае RuntimeException в onMessage() моего JavaBean сообщение не подтверждается поставщиком JMS (ActiveMQ ), он остается ожидающим в очереди. Но он никогда не доставляется повторно, что, я думаю, вызвано тем фактом, что Spring никогда не вызывает session.recover(), что согласно документация ActiveMQ.

Может ли кто-нибудь дать мне подсказку, как я могу настроить DefaultMessageListenerContainer для вызова session.recover() в случае RuntimeExceptions?

С уважением,
Мартин


person Martin C.    schedule 02.02.2010    source источник
comment
У меня была аналогичная проблема. SessionAwareListener выдаст неожиданное исключение среды выполнения, но DMLC повторит сообщение примерно 32 раза, прежде чем остановиться. Не знаете, как установить этот номер повторной попытки...?   -  person Jose    schedule 11.05.2012


Ответы (1)


Вы указываете, что используете sessionAcknowledgeMode 2, то есть Session.CLIENT_ACKNOWLEDGE. Следующий оператор взят непосредственно из JavadocsAbstractMessageListenerContainer:

  • CLIENT_ACKNOWLEDGE: автоматическое подтверждение сообщения после успешного выполнения слушателя; нет повторной доставки в случае возникновения исключения.

Таким образом, проблема не в Spring DMLC, а в его способности вызывать Session.recover() при возникновении исключения во время выполнения. Возможно ли, чтобы вы использовали try/catch в методе вашего слушателя onMessage() для обработки исключений во время выполнения, вызывая Session.recover() самостоятельно?

Обновлять:

Вы делаете хорошее замечание о шаблонном коде. Он разбрызгивается во многих местах и ​​требует рефакторинга. Разве вы не можете абстрагироваться от такого кода? Это распространенное решение. Создание абстрактного родительского класса с методом, содержащим try/catch с соответствующей обработкой, должно помочь. Затем просто расширьте родительский класс, чтобы реализовать столько пользовательских процессоров, сколько необходимо. Вы даже можете соответствующим образом связать процессоры вместе, используя контекст вашего приложения Spring.

У меня никогда не было проблем с добавлением в приложение специфичного для Spring кода, потому что он работает где угодно. Это было важно для меня еще тогда, когда я начал использовать Spring. Это не относится к какому-либо отдельному серверу приложений или контейнеру сервлетов, поэтому я не загоняю себя в угол с помощью Spring, как если бы я импортировал com.ibm или com.oracle в свой исходный код. Фактически, я использовал API-интерфейсы Spring JMS с одним MOM и переключился на другой MOM, не меняя ничего, кроме определения фабрики соединений JMS.

person bsnyder    schedule 03.02.2010
comment
Спасибо, я знаю об этом возможном решении (извините, не написал об этом), но оно добавляет шаблонный код к каждому используемому мной bean-компоненту и заставляет меня использовать SessionAwareMessageListener (который является зависимостью Spring) вместо javax.jms.MessageListener. И, честно говоря, я бы предпочел не вводить напрямую зависимость Spring в свои процессоры сообщений. - person Martin C.; 06.02.2010