MDP JMS-транзакция откатывается, а затем повторно обрабатывает сообщение в бесконечном цикле - PullRequest
0 голосов
/ 30 июня 2011

Если я включаю управление транзакциями в моем DefaultMessageListenerContainer, указав sessionTransacted=true или transactionManager=jmsTransactionManager, то при возникновении исключения в MDP транзакция откатывается и сообщение помещается обратно в очередь. Это приводит к тому, что сообщение обрабатывается снова, транзакция откатывается снова и снова, так что создается бесконечный цикл.

Полагаю, мой вопрос ... что мне здесь не хватает? Зачем вам возвращать сообщение в очередь, если оно просто означает, что оно будет обрабатываться снова и снова?

<!-- jms connection factory -->
<bean name="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:ConnectionFactory" />
</bean>

<!-- jms transaction manager -->
<bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
    <property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>

<!-- Destination for Inbound_Email_Q -->
<bean name="inboundEmailDestination" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="queue/inbound_Email_Queue" />
</bean>

<!-- JmsTemplate for Inbound_Email_Q -->
<bean name="jmsInboundEmailTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="jmsConnectionFactory" />
    <property name="defaultDestination" ref="inboundEmailDestination" />
    <property name="messageConverter" ref="xmlMessageConverter" />
</bean>

<!-- jms asynchronous listener -->
<bean id="emailMessageServiceMdp" class="org.site.wso.core.jms.EmailMessageServiceMdp" />
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="jmsConnectionFactory"/>
    <!-- <property name="transactionManager" ref="jmsTransactionManager" />  -->
    <!-- <property name="sessionTransacted" value="true"/>  -->
    <property name="destination" ref="inboundEmailDestination"/>
    <property name="messageListener" ref="messageListener"/>
</bean>

<!-- jms message listener adapter -->
<bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
    <constructor-arg>
        <bean class="org.site.wso.core.jms.EmailMessageServiceMdp"/>
    </constructor-arg>
    <property name="messageConverter" ref="xmlMessageConverter"/>
</bean>

А вот и мой MDP:

public class EmailMessageServiceMdp implements MessageDelegate {

    public void handleMessage(Object object) {

        EmailMessageRequestVO requestVO = (EmailMessageRequestVO) object;   

        try {
            //Service call that throw exception
        } catch (Exception e) {
            throw new ApplicationException(e);
        }

    }
}

1 Ответ

3 голосов
/ 03 июля 2011

Повторная доставка сообщений - это просто поведение по умолчанию для вашей [сконфигурированной] реализации JMS. Это бесконечная дискуссия о том, какова относительная полезность этого, но может показаться, что вместо отбрасывания сообщения с некоторыми потенциально невосстановимыми данными, некоторая повторная попытка является разумным и консервативным подходом. Например, в вашем случае вы, кажется, конвертируете сообщение JMS в сообщение электронной почты и отправляете его на SMTP-сервер. Если шлюз SMTP не работает, вы можете удерживать сообщения JMS и повторно обрабатывать их, когда шлюз возвращается.

В целом, я бы сказал, что ваши варианты обработки сообщения, которое не удалось обработать (в зависимости от реализации JMS):

  1. Откажитесь от сообщения.
  2. Написать сообщение в очередь ошибок.
  3. Повторное получение сообщения после задержки n секунд.
  4. Повторно доставить сообщение n раз, а затем записать сообщение в очередь ошибок.
  5. Повторно доставить сообщение после задержки n секунд x раз, а затем записать сообщение в очередь ошибок.

Если вы предпочитаете # 1, просто отмените исключение, подтвердите транзакцию и прощайте сообщение. В остальном конфигурация JMS (или конкретная конфигурация назначения) должна обрабатывать их.

Кроме того, если вы хотите что-то более конкретное, вы можете запросить getJMSRedelivered () сообщения и / или свойство заголовка сообщения для конкретной реализации, которое указывает, сколько раз сообщение было доставлено (поддерживается большинством JMS реализации, но не стандартные) и соответственно распоряжаться сообщением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...