【问题标题】:Spring integration message-store rolled back before error handlerSpring 集成消息存储在错误处理程序之前回滚
【发布时间】:2015-04-21 23:21:52
【问题描述】:

我需要在我的 Spring 集成流程中处理某些错误情况。我的流程是使用消息存储并在轮询器上设置错误通道。我曾想过,如果我在错误处理程序中处理消息,则不会发生回滚,但在执行错误流程之前,messageStore remove (delete) 正在回滚。

这是一个重复我的问题的伪流程。

<int:channel id="rollbackTestInput" >
    <int:queue message-store="messageStore"/>
</int:channel>

<int:bridge input-channel="rollbackTestInput" output-channel="createException" >
    <int:poller fixed-rate="50" 
        error-channel="myErrorChannel">
        <int:transactional />
    </int:poller>
</int:bridge>

<int:transformer input-channel="createException" output-channel="infoLogger"
    expression="T(GarbageToForceException).doesNotExist()" />

<int:channel id="myErrorChannel">
    <int:queue/> 
</int:channel>

<!-- JDBC Message Store -->
<bean id="messageStore" class="org.springframework.integration.jdbc.JdbcMessageStore">
    <property name="dataSource">
        <ref bean="dataSource" />
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
<property name="dataSource" ref="dataSource"/>

此流程将导致无限回滚/轮询循环。如何处理错误而不回滚?

【问题讨论】:

    标签: spring-integration


    【解决方案1】:

    这是正确的行为。轮询任务的 TX 建议周围接受 error-channel 逻辑。

    代码如下:

    @Override
    public void run() {
        taskExecutor.execute(new Runnable() {
            @Override
            public void run() {
                int count = 0;
                while (initialized && (maxMessagesPerPoll <= 0 || count < maxMessagesPerPoll)) {
                    try {
                        if (!pollingTask.call()) {
                            break;
                        }
                        count++;
                    }
                    catch (Exception e) {
                        if (e instanceof RuntimeException) {
                            throw (RuntimeException) e;
                        }
                        else {
                            throw new MessageHandlingException(new ErrorMessage(e), e);
                        }
                    }
                }
            }
        });
    }
    

    TX Advice 在pollingTask.call() 上,但错误处理是从taskExecutor 完成的:

    this.taskExecutor = new ErrorHandlingTaskExecutor(this.taskExecutor, this.errorHandler);
    

    您的error-channelerrorHandler 上配置为MessagePublishingErrorHandler

    要达到您的要求,您可以尝试在&lt;poller&gt; 上关注synchronization-factory

    <int:transaction-synchronization-factory id="txSyncFactory">
        <int:after-rollback channel="myErrorChannel" />
    </int:transaction-synchronization-factory>
    

    或者为您的&lt;int:transformer&gt; 提供&lt;request-handler-advice-chain&gt;

    <int:request-handler-advice-chain>
        <bean class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice">
            <property name="onFailureExpression" value="#exception" />
            <property name="failureChannel" value="myErrorChannel" />
            <property name="trapException" value="true" />
        </bean>
    </int:request-handler-advice-chain>
    

    【讨论】:

    • 我都试过了。所有 3 个选项(包括我的原始选项)都进入错误通道。但是没有一个选项可以阻止回滚。我错过了什么?
    • 哦!抱歉,我错过了 ExpressionEvaluatingRequestHandlerAdvicetrapException=true 选项。看看我对答案的编辑
    • 现在我得到一个异常,需要对变压器做出响应...我想存储错误并完成。不幸的是,transformer 命名空间中的 requiresReply 参数不可用,我担心设置此参数会对正常流程产生任何影响。
    • 另外...为什么轮询器被配置为处理事务流之外的错误?这不是入站通道适配器的工作方式。使用入站通道适配器,如果我处理错误,则事务不会回滚。
    • 您可以将错误流中的一些“假”消息返回给转换器,并将&lt;filter&gt; 放在infoLogger 上以丢弃它们。你“不回滚”的情况很具体,所以真的没有直接给你的解决方案。
    【解决方案2】:

    我找到了一种不同的解决方案,可以满足我的要求并且侵入性较小。

    我可以使用通知链来指定我应该回滚和不应该回滚哪些异常,而不是在轮询器上使用事务性。就我而言,我不想回滚大多数异常。所以我回滚 Throwable 并列出我想要回滚的任何特定异常。

    <int:bridge input-channel="rollbackTestInput"
        output-channel="createException">
        <int:poller fixed-rate="50"
            error-channel="myErrorChannel">
            <int:advice-chain>
                <int:ref bean="txAdvice"/>
            </int:advice-chain>
        </int:poller>
    </int:bridge>
    
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" rollback-for="javax.jms.JMSException"
                no-rollback-for="java.lang.Throwable" />
        </tx:attributes>
    </tx:advice>
    

    【讨论】:

    • @Artem 对这种方法有任何顾虑吗?
    • 是的,这是另一种进行条件回滚的声明方式。注意:&lt;transactional&gt; 只是&lt;tx:advice&gt; 的一个特例。
    猜你喜欢
    • 1970-01-01
    • 2013-03-30
    • 2020-04-05
    • 1970-01-01
    • 1970-01-01
    • 2017-12-26
    • 1970-01-01
    • 2018-08-25
    • 1970-01-01
    相关资源
    最近更新 更多