Spring JMS - 通过将消息发送回同一队列而不是回滚事务来重新传递

时间:2013-12-04 10:42:43

标签: spring transactions queue rollback spring-jms

这是我在这里发表的第一篇文章,所以如果我不尊重格式规则,我会事先道歉 其他一般规则。

我有一个基于Spring JMS的客户端应用程序,它使用多个使用者从队列中读取。 我的约束是:在发生故障和消息重复检测的情况下保证重新发送。

Spring配置

<bean id="jndiDestinationResolver" class="org.springframework.jms.support.destination.DynamicDestinationResolver" />


    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <constructor-arg ref="MyConnectionFactory" />
        <property name="destinationResolver" ref="jndiDestinationResolver" />
        <property name="receiveTimeout" value="100" />
    </bean>


    <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
            <property name="destinationResolver" ref="jndiDestinationResolver" />
            <property name="connectionFactory" ref="MyConnectionFactory" />
            <property name="destinationName" value="my_Queue" />
            <property name="messageListener" ref="MyListener" />
            <property name="maxConcurrentConsumers" value="10"/>
            <property name="sessionTransacted" value="true"/>
    </bean>

我的监听器代码类似于:


    protected void processTextMessage(TextMessage textMessage) {
        try {
            // process message
        } catch(Exception e) {
            try {
                sendTextMessage("my_Queue",correlationID, textMessage.getText());
            } catch (JMSException e1) {
                log.error("Error writing message back to the queue!");
                throw JmsUtils.convertJmsAccessException(e1);

            }
        }
    }


    protected void sendTextMessage(String queueName, final byte[] correlationID, String message) {
        jmsTemplate.convertAndSend(queueName, message, new MessagePostProcessor() {
            public Message postProcessMessage(Message message) throws JMSException {
                message.setJMSCorrelationIDAsBytes(correlationID);
                return message;
            }
        });
    }

我使用ActiveMQ进行了一些本地故障测试,并且重新发送正常(我注意到redelivered标志为false)。 我还试图在处理期间残酷地停止应用程序服务器,并且能够检查当前队列包含1个带有redelivered = true的消息。

这是实现目标的正确方法吗?

我希望这对于我将使用的JMS提供程序是透明的(在生产环境中使用Websphere MQ)。 目前我想避免通过抛出异常来回滚事务:我希望重新安排我失败的消息,就像队列中的新消息一样。 对于重复检测,我认为插入业务存在检查就足够了。

提前致谢并提出最好的问候

2 个答案:

答案 0 :(得分:1)

是的,这是正确的方法。

答案 1 :(得分:0)

除当前( SUBMIT )队列外,拥有 ERROR 队列可能是更好的方法。

有几个原因:

  1. 如果来自源的信息无效,则可以更好地分析错误消息。 您可以在邮件头上具有MSG_PROCESSED_CNT属性,并根据需要使用它来重新处理邮件。当您在业务逻辑中进行外部集成时,它非常有用。

  2. 如果您的代码[try-block]因错误或集成问题而反复抛出异常会怎样?使用ERROR队列,您会看到深度上升,并可通过设置阈值监视器来通知问题。

  3. 将重新处理工作(非业务相关)委派给第三方应用程序。您的代码只包含您的业务逻辑。