3

セットアップ:
テーブル:CREATE TABLE test (id int PRIMARY KEY NOT NULL, name varchar(25));

基本的なテスト フロー:

ここに画像の説明を入力

前提条件: データベースには既に id=2 のレコードがあります (SqlException を強制するため)。

ケース 1:

基本フローをそのまま呼び出すと、2 回目の挿入が主キー違反で失敗し、最初の挿入がロールバックされます。合理的なデフォルトの動作のようです。

ケース 2:

ロールバック例外戦略を追加して基本フローを変更し、例外戦略内にロガーを追加して、呼び出されたときに何かを出力します。
フローが呼び出されると、主キー違反が原因で 2 番目の挿入が失敗し、最初の挿入はロールバックされます、RollbackExceptionStrategy は呼び出されません!
誰もが期待することはほとんどありません。

ここでの質問は、ロールバック例外戦略が呼び出されないのはなぜですか、それを呼び出すために何をする必要があるのですか?

ケース 3:

Catch Exception ストラテジーを追加して基本フローを変更し、例外ストラテジー内にロガーを追加して、呼び出されたときに何かを出力します。
フローが呼び出されると、主キー違反が原因で 2 番目の挿入が失敗します。今回は、例外戦略が呼び出されましたが、トランザクションはロールバックされませんでした。

ここでの問題は、トランザクションがロールバックされない理由と、ロールバック戦略とは異なる例外戦略内でロールバックを強制する方法です。

どんな助けでも大歓迎です


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>
4

2 に答える 2

3

ケース 1 : わーい!

ケース 2 :

ロールバック例外戦略が呼び出されないのはなぜですか? また、それを呼び出すために何をする必要がありますか?

ドキュメントによると、戦略を呼び出す必要があります。私が追加した場合、それはおそらくあなたの側の設定の問題です:

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

「TxFlow」に、テキストがコンソールに記録されているのを確認できます。

ケース 3 :

トランザクションがロールバックされないのはなぜですか?

これが、ドキュメントからのCatch Exception Strategyの主な目的です。

エラーが発生したときに、フローによって処理されたトランザクションがロールバックされないようにします (つまり、処理を再試行するためにトランザクションが「ロールバック」されることはありません。Mule はトランザクションをコミットします)。

ロールバック戦略とは異なる例外戦略内でロールバックを強制する方法

私はあなたができるとは思わない。ストラテジー内から例外をスローしてみることができますが、その時点でトランザクションは既にコミットされていると思います。

于 2013-01-10T18:45:27.033 に答える