问题
EDIT: This only happens with MSSQL & jtds 1.2.6 Still investigating...
**Duplicate of : Mule 3.3.0 Jdbc Transaction Undesired Commit
**Mule Documentation sucks.
I want to rollback everything inside a flow that has several database endpoints.
I have a single JDBC datasource resource (i.e. no need for fancy XA, 2PC, etc).
I have managed to configure Mule to, at least, not complain that no Transaction Manager is configured, etc.... but: It doesn't work; i.e it does not rollback the transaction when an exception occurs.
Since I'm running Mule standalone, I don't have fancy weblogic, jboss, etc transactionmanagers so I thought I could use Spring's DataSourceTransactionManager. What other choice I have for this?
Here is my flow (flow1 is just for triggering flow2, wich is the one I want to be transactional):

And the XML:
<?xml version="1.0" encoding="UTF-8"?>
<mule version="CE-3.3.0">
<spring:beans>
<spring:bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<spring:property name="dataSource" ref="dataSource" />
</spring:bean>
<spring:bean id="transactionFactory"
class="org.mule.module.spring.transaction.SpringTransactionFactory">
<spring:property name="manager" ref="transactionManager" />
</spring:bean>
<spring:bean id="dataSource" name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<spring:property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<spring:property name="url" value="jdbc:mysql://localhost/mydb"/>
<spring:property name="username" value="sa"/>
<spring:property name="password" value=""/>
</spring:bean>
</spring:beans>
<jdbc:connector name="jdbcConnector" dataSource-ref="dataSource"
transactionPerMessage="true" queryTimeout="20000" pollingFrequency="10000"
doc:name="Database" validateConnections="false"></jdbc:connector>
<flow name="flow1" doc:name="flow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" doc:name="HTTP"/>
<vm:outbound-endpoint exchange-pattern="request-response" path="toFlow2" doc:name="VM"/>
</flow>
<flow name="flow2" doc:name="flow2">
<vm:inbound-endpoint exchange-pattern="request-response" path="toFlow2" doc:name="VM">
<custom-transaction factory-ref="transactionFactory" action="ALWAYS_BEGIN" timeout="10"/>
</vm:inbound-endpoint>
<jdbc:outbound-endpoint exchange-pattern="request-response" queryKey="query1" queryTimeout="-1" connector-ref="jdbcConnector" doc:name="Database">
<jdbc:query key="query1" value="insert into Foo (field1) values ('bar')"/>
<jdbc:transaction action="ALWAYS_JOIN"/>
</jdbc:outbound-endpoint>
<jdbc:outbound-endpoint exchange-pattern="request-response" queryKey="query2" queryTimeout="-1" connector-ref="jdbcConnector" doc:name="Database">
<jdbc:query key="query2" value="insert into Bar (field1) values ('foo')"/>
<jdbc:transaction action="ALWAYS_JOIN"/>
</jdbc:outbound-endpoint>
</flow>
</mule>
Not shown here, I also have a default exception catch strategy, that simply writes the faulty payload to a file. I don't know if I need to do a rollback explicitly, but I didn't find how.
Any help would be much appreciated.
回答1:
After two days of banging my head against Mule I finally managed to make this work.
Conclusions:
- You need to use jTDS's own DataSource (net.sourceforge.jtds.jdbcx.JtdsDataSource)
- You need to use mule's TransactionFactory (org.mule.transport.jdbc.JdbcTransactionFactory)
- You need to use the undocumented (or at least, under-documented) tag to start transaction
- jTDS ando/or Mule sucks (I don't know who is responsible for this particular issue).
- Mule Documentation sucks big time: this and this
- MuleStudio sucks big time (Sloooow, buggy, no way to wire transactions via the GUI, assertexceptions, flows gets messed up if you drag and drop scripts, etc, etc).
The final working flow:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting" xmlns:jdbc="http://www.mulesoft.org/schema/mule/jdbc" xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:spring="http://www.springframework.org/schema/beans"
version="CE-3.3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/jdbc http://www.mulesoft.org/schema/mule/jdbc/current/mule-jdbc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd ">
<spring:beans>
<spring:bean id="jtdsDataSource" name="jtdsDataSource" class="net.sourceforge.jtds.jdbcx.JtdsDataSource">
<spring:property name="user" value="your_user" />
<spring:property name="password" value="your_password" />
<spring:property name="databaseName" value="your_database" />
<spring:property name="serverName" value="your_host" />
</spring:bean>
<spring:bean id="transactionFactory" name="transactionFactory" class="org.mule.transport.jdbc.JdbcTransactionFactory" />
</spring:beans>
<jdbc:connector name="dbConnector" dataSource-ref="jtdsDataSource" 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" />
<vm:outbound-endpoint exchange-pattern="request-response" path="toTxFlow" doc:name="VM" />
</flow>
<flow name="TxFlow" doc:name="TxFlow">
<vm:inbound-endpoint exchange-pattern="request-response" path="toTxFlow" 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>
</flow>
</mule>
回答2:
In Mule you HAVE access to transaction managers. For instance you can configure a jboss transaction manager by adding this to your configuration:
<jbossts:transaction-manager/>
A custom transaction is not required to work with XA. You just have to use the xa-transaction element inside each endpoint instead.
Here you have your configuration updated to work with xa transactions in Mule.
<?xml version="1.0" encoding="UTF-8"?>
<mule version="CE-3.3.0">
<jdbc:connector name="jdbcConnector" dataSource-ref="dataSource"
transactionPerMessage="true" queryTimeout="20000" pollingFrequency="10000"
doc:name="Database" validateConnections="false">
</jdbc:connector>
<flow name="flow1" doc:name="flow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" doc:name="HTTP"/>
<vm:outbound-endpoint exchange-pattern="request-response" path="toFlow2" doc:name="VM"/>
</flow>
<flow name="flow2" doc:name="flow2">
<vm:inbound-endpoint exchange-pattern="request-response" path="toFlow2" doc:name="VM">
<xa-transaction action="ALWAYS_BEGIN" timeout="10"/>
</vm:inbound-endpoint>
<jdbc:outbound-endpoint exchange-pattern="request-response" queryKey="query1" queryTimeout="-1" connector-ref="jdbcConnector" doc:name="Database">
<jdbc:query key="query1" value="insert into Foo (field1) values ('bar')"/>
<xa-transaction action="ALWAYS_JOIN"/>
</jdbc:outbound-endpoint>
<jdbc:outbound-endpoint exchange-pattern="request-response" queryKey="query2" queryTimeout="-1" connector-ref="jdbcConnector" doc:name="Database">
<jdbc:query key="query2" value="insert into Bar (field1) values ('foo')"/>
<xa-transaction action="ALWAYS_JOIN"/>
</jdbc:outbound-endpoint>
</flow>
I agree that the documentation it's not as good as it should be but it's getting much better. In fact the first page you mention has been rewriting from scratch.
HTH, Pablo.
来源:https://stackoverflow.com/questions/13650959/mule-esb-3-transactional-flow-single-jdbc-resource-not-rolling-back-mssql-jtd