transactions - Mule ESB 3.3 异常策略和回滚莫名其妙的行为

标签 transactions esb mule rollback

设置:
Tabe: CREATE TABLE test (id int PRIMARY KEY NOT NULL, name varchar(25));

基本测试流程:

enter image description here

前提条件:数据库已有id=2的记录(强制SqlException)

案例 1:

当按原样调用基本流程时,第二个插入由于违反主键而失败,并且第一个插入被回滚。似乎是合理的默认行为。

案例 2:

通过添加一个回滚异常策略修改基本流程,并在异常策略中添加一个记录器,以便在它被调用时打印一些东西。
调用流时,第二个插入由于违反主键而失败,并且第一个插入被回滚 RollbackExceptionStrategy 永远不会被调用!
几乎没有人会期望。

所以这里的问题是:为什么回滚异常策略没有被调用,我需要做什么才能调用它?

案例三:

通过添加Catch Exception Strategy 修改基本流程,并在异常策略中添加一个记录器,以便在它被调用时打印一些东西。
调用流程时,第二次插入因违反主键而失败。这次调用了异常策略,但现在事务没有回滚。

这里的问题是:为什么事务没有被回滚,以及如何在不同于回滚策略的异常策略中强制回滚?

任何帮助将不胜感激


Edit1:这是流程的完整 xml(仅基本情况):

<mule>
    <spring:beans>
        <spring:bean id="dataSource" name="dataSource" class="org.enhydra.jdbc.standard.StandardDataSource" destroy-method="shutdown">
            <spring:property name="driverName" value="org.h2.Driver" />
            <spring:property name="url" value="jdbc:h2:tcp://localhost/~/mule" />
            <spring:property name="user" value="sa" />
            <spring:property name="password">
                <spring:value></spring:value>
            </spring:property>
        </spring:bean>

        <spring:bean id="transactionFactory" name="transactionFactory" class="org.mule.transport.jdbc.JdbcTransactionFactory" />

    </spring:beans>

    <jdbc:connector name="dbConnector" dataSource-ref="dataSource" validateConnections="true" queryTimeout="-1" pollingFrequency="0" doc:name="Database" />

    <flow name="TriggerFlow" doc:name="TriggerFlow">
        <http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" doc:name="HTTP" />
        <vm:outbound-endpoint exchange-pattern="request-response" path="txFlow" doc:name="VM" />
    </flow>

    <flow name="TxFlow" doc:name="case1Flow">
        <vm:inbound-endpoint exchange-pattern="request-response" path="txFlow" doc:name="case1">
            <custom-transaction factory-ref="transactionFactory" action="ALWAYS_BEGIN" timeout="10" />
        </vm:inbound-endpoint>
        <jdbc:outbound-endpoint exchange-pattern="request-response" queryKey="insert" queryTimeout="-1" connector-ref="dbConnector" doc:name="insert into test values (1, 'Test 1')">
            <jdbc:transaction action="ALWAYS_JOIN" />
            <jdbc:query key="insert" value="insert into test values (1, 'Test 1')" />
        </jdbc:outbound-endpoint>
        <jdbc:outbound-endpoint exchange-pattern="request-response" queryKey="insert2" queryTimeout="-1" connector-ref="dbConnector" doc:name="insert into test values (2, 'Test 2')">
            <jdbc:transaction action="ALWAYS_JOIN" />
            <jdbc:query key="insert2" value="insert into test values (2, 'Test 2')" />
        </jdbc:outbound-endpoint>
    </flow>

</mule>

Edit2:事实证明,情况 2 单独运行有效,但在更复杂的流程中不起作用,例如:

<mule>
    <spring:beans>
        <spring:bean id="dataSource" name="dataSource" class="org.enhydra.jdbc.standard.StandardDataSource" destroy-method="shutdown">
            <spring:property name="driverName" value="org.h2.Driver" />
            <spring:property name="url" value="jdbc:h2:tcp://localhost/~/mule" />
            <spring:property name="user" value="sa" />
            <spring:property name="password">
                <spring:value></spring:value>
            </spring:property>
        </spring:bean>

        <spring:bean id="transactionFactory" name="transactionFactory" class="org.mule.transport.jdbc.JdbcTransactionFactory" />

    </spring:beans>

    <jdbc:connector name="dbConnector" dataSource-ref="dataSource" validateConnections="true" queryTimeout="-1" pollingFrequency="0" doc:name="Database" />

    <flow name="TriggerTxFlow" doc:name="TriggerTxFlow">
        <http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" doc:name="HTTP" />
        <set-variable variableName="flow" value="#[message.inboundProperties['http.query.params']['flow']]" doc:name="Variable"/>
        <vm:outbound-endpoint exchange-pattern="request-response" path="#[flow]" doc:name="VM" />
    </flow>

    <flow name="case1Flow" doc:name="case1Flow">
        <vm:inbound-endpoint exchange-pattern="request-response" path="case1" doc:name="case1">
            <custom-transaction factory-ref="transactionFactory" action="ALWAYS_BEGIN" timeout="10" />
        </vm:inbound-endpoint>
        <jdbc:outbound-endpoint exchange-pattern="request-response" queryKey="insert" queryTimeout="-1" connector-ref="dbConnector" doc:name="insert into test values (1, 'Test 1')">
            <jdbc:transaction action="ALWAYS_JOIN" />
            <jdbc:query key="insert" value="insert into test values (1, 'Test 1')" />
        </jdbc:outbound-endpoint>
        <jdbc:outbound-endpoint exchange-pattern="request-response" queryKey="insert2" queryTimeout="-1" connector-ref="dbConnector" doc:name="insert into test values (2, 'Test 2')">
            <jdbc:transaction action="ALWAYS_JOIN" />
            <jdbc:query key="insert2" value="insert into test values (2, 'Test 2')" />
        </jdbc:outbound-endpoint>
    </flow>

    <flow name="case2Flow" doc:name="case2Flow">
        <vm:inbound-endpoint exchange-pattern="request-response" path="case2" doc:name="case2">
            <custom-transaction factory-ref="transactionFactory" action="ALWAYS_BEGIN" timeout="10" />
        </vm:inbound-endpoint>
        <jdbc:outbound-endpoint exchange-pattern="request-response" queryKey="insert" queryTimeout="-1" connector-ref="dbConnector" doc:name="Database">
            <jdbc:transaction action="ALWAYS_JOIN" />
            <jdbc:query key="insert" value="insert into test values (1, 'Test 1')" />
        </jdbc:outbound-endpoint>
        <jdbc:outbound-endpoint exchange-pattern="request-response" queryKey="insert2" queryTimeout="-1" connector-ref="dbConnector" doc:name="Database">
            <jdbc:transaction action="ALWAYS_JOIN" />
            <jdbc:query key="insert2" value="insert into test values (2, 'Test 2')" />
        </jdbc:outbound-endpoint>
        <rollback-exception-strategy doc:name="Rollback Exception Strategy" enableNotifications="false" maxRedeliveryAttempts="0">
            <on-redelivery-attempts-exceeded doc:name="Redelivery exhausted">
                <logger message="========= Inside Exception Strategy =========" level="INFO" doc:name="Logger"/>
            </on-redelivery-attempts-exceeded>
        </rollback-exception-strategy>
    </flow>

    <flow name="case3Flow" doc:name="case3Flow">
        <vm:inbound-endpoint exchange-pattern="request-response" path="case3" doc:name="VM">
            <custom-transaction factory-ref="transactionFactory" action="ALWAYS_BEGIN" timeout="10" />
        </vm:inbound-endpoint>
        <jdbc:outbound-endpoint exchange-pattern="request-response" queryKey="insert" queryTimeout="-1" connector-ref="dbConnector" doc:name="Database">
            <jdbc:transaction action="ALWAYS_JOIN" />
            <jdbc:query key="insert" value="insert into test values (1, 'Test 1')" />
        </jdbc:outbound-endpoint>
        <jdbc:outbound-endpoint exchange-pattern="request-response" queryKey="insert2" queryTimeout="-1" connector-ref="dbConnector" doc:name="Database">
            <jdbc:transaction action="ALWAYS_JOIN" />
            <jdbc:query key="insert2" value="insert into test values (2, 'Test 2')" />
        </jdbc:outbound-endpoint>
        <catch-exception-strategy doc:name="Catch Exception Strategy">
            <logger message="========= Inside Exception Strategy =========" level="INFO" doc:name="Logger"/>
        </catch-exception-strategy>
    </flow>

</mule>

最佳答案

案例 1:耶!

案例 2:

为什么回滚异常策略没有被调用,我需要做什么才能调用它?

根据doc应该调用该策略。这可能是您这边的配置问题,因为如果我添加:

<rollback-exception-strategy>
    <logger message="---> In Rollback exception strategy!!!" />
</rollback-exception-strategy>

到“TxFlow”,我可以看到控制台中记录的文本。

案例 3:

为什么事务没有被回滚?

这就是 Catch Exception Strategy 的主要目的,来自 doc :

ensure that a transaction processed by the flow will not be rolled back when an error occurs (i.e. The transaction is never “rolled back” to reattempt processing; Mule commits the transaction.)

如何在不同于回滚策略的异常策略中强制回滚

我认为你做不到。您可以尝试从策略中抛出异常,但恐怕此时事务已经提交。

关于transactions - Mule ESB 3.3 异常策略和回滚莫名其妙的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14264693/

相关文章:

ssl - Mule SOAP 调用 SSL 结果为 "unable to find valid certification path to requested target"

mysql - 超过等待超时后mysql事务会发生什么?

java - 声明式事务 vs 程序化事务

jakarta-ee - @Singleton bean 在标记为 TransactionAttribute=NOT_SUPPORTED 时无法初始化,因为不是预期的事务状态 4

java - 在 JBoss esb 服务器中找不到我的 bean

java - 尝试在 Mule 中进行 PGP 加密时,publicKey 不应为空

jaxb - 骡问题 : More than one JAXBContext

google-analytics - Google Analytics 电子商务中缺少数据

java - 从 Mule 中的虚拟机队列发布到 REST 端点

java - Apache Camel 合并来自不同路径的两个文件