Mule’s transaction framework is agnostic to the underlying transaction manager. The transaction could be a JDBC transaction, XA transaction, or a JMS transaction or message acknowledgment.All transaction types can be handled the same way. Mule transactions are configured on synchronous endpoints, where an endpoint can be configured to start a new transaction or join an existing one. Transactions are configured on an endpoint using
<transaction>, which maps to the
class. This element defines what action an endpoint should take when it receives an event and the transaction factory to use to create transactions.
|If you have multiple transactional inbound or outbound endpoints in a flow and you specify a transaction for one of them, you must specify transactions for all of them. For example, if you have two outbound endpoints and you specify a transaction for the first one, you must also specify a transaction for the second one.|
For an excellent article on distributed transactions using both XA and non-XA approaches, see http://www.javaworld.com/javaworld/jw-01-2009/jw-01-spring-transactions.html. The multi-resource transaction support described below maps to the Best Efforts 1PC pattern described in the article.
For more details on the elements you configure for transactions, see Transactions Configuration Reference.
For information on using exception strategies to determine whether a transaction gets committed or rolled back in case of an error, see Error Handling with Transactions.
Single-resource transactions (also called "local transactions") are transactions that are provided by the underlying resource, such as JDBC transactions and JMS transactions. These kind of transactions can be used to receive and/or send messages using a single resource only.
An example configuration for a single-resource transaction might look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <jms:endpoint name="In" queue="test.In" connector-ref="jmsConnector1" /> <jms:endpoint name="Out" queue="test.Out" connector-ref="jmsConnector1" /> <flow> ... <inbound-endpoint ref="In"> <jms:transaction action="ALWAYS_BEGIN" /> </inbound-endpoint> ... <outbound-endpoint ref="Out"> <jms:transaction action="ALWAYS_JOIN" /> </outbound-endpoint> ... </flow>
This configuration defines a global JMS endpoint that receives on a "test.In" queue and another global JMS endpoint that sends on a "test.Out" queue. The action attribute tells Mule what to do for each message. In this case, create a new transaction for every message received. The outbound endpoint uses the resource enlisted in the current transaction, if one is running. In this case, it uses the same JMS session that has been used to receive the event. When the message routes from the inbound endpoint to the outbound endpoint, the transaction commits or rolls back.
You can set action values on the
<transaction> element as follows:
NONE - Never participate in a transaction.
ALWAYS_BEGIN - Always start a new transaction when receiving a message. If a previous transaction exists, it commits that transaction.
BEGIN_OR_JOIN - If a transaction is already in progress when an event is received, join the transaction, otherwise start a new transaction.
ALWAYS_JOIN - Always expect a transaction to be in progress when an event is received. If there is no transaction, an exception is thrown.
JOIN_IF_POSSIBLE - Join the current transaction if one is available. Otherwise, don’t create a transaction.
If you are using Mule Enterprise Edition, you can use the
<multi-transaction> element to enable a series of operations from multiple JMS resources to be grouped into a single virtual transaction. Multi-resource transactions work without the overhead of XA. The trade-off is that XA reliability guarantees aren’t provided, and your flows must be ready to handle duplicates. This is very similar to a 1.5 phase commit concept (for a discussion of different approaches, see the JavaWorld article on distributed transactions).
Multi-resource transactions are useful for creating transactional non-XA bridges. For example, if you want to bridge two different JMS connectors, each of which is running local transactions instead of XA transactions, you could configure the multi-resource transaction as follows:
|The Multi-Resource Transactions feature works only with JMS.|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <?xml version="1.0" encoding="UTF-8"?> <mule xmlns="http://www.mulesource.org/schema/mule/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jms="http://www.mulesource.org/schema/mule/jms" xmlns:wmq="http://www.mulesource.org/schema/mule/ee/wmq" xmlns:ee="http://www.mulesource.org/schema/mule/ee/core" xmlns:test="http://www.mulesource.org/schema/mule/test" xsi:schemaLocation=" http://www.mulesource.org/schema/mule/test http://www.mulesource.org/schema/mule/test/3.2/mule-test.xsd http://www.mulesource.org/schema/mule/core http://www.mulesource.org/schema/mule/core/3.2/mule.xsd http://www.mulesource.org/schema/mule/ee/core http://www.mulesource.org/schema/mule/ee/core/3.2/mule-ee.xsd http://www.mulesource.org/schema/mule/jms http://www.mulesource.org/schema/mule/jms/3.2/mule-jms.xsd http://www.mulesource.org/schema/mule/ee/wmq http://www.mulesource.org/schema/mule/ee/wmq/3.2/mule-wmq-ee.xsd> <jms:activemq-connector name="jmsConnector" maxRedelivery="3" disableTemporaryReplyToDestinations="true"/> <wmq:connector name="wmqConnector" hostName="winter" port="1414" disableReplyToHandler="true" disableTemporaryReplyToDestinations="true" queueManager="MY_QUEUE_MANAGER" targetClient="NONJMS_MQ" transportType="CLIENT_MQ_TCPIP" specification="1.1" numberOfConsumers="16" username="" password=""/> <flow name="MultiTxFlow"> <jms:inbound-endpoint queue="in"> <ee:multi-transaction action="ALWAYS_BEGIN"/> </jms:inbound-endpoint> <test:component/> <wmq:outbound-endpoint queue="out"> <ee:multi-transaction action="ALWAYS_JOIN"/> </wmq:outbound-endpoint> </flow> </mule>
In this example, the local JMS transaction is started when the message is received on the "in" endpoint, and the local WMQ transaction is started when the message is sent out on the "out" endpoint. The last transaction (WMQ) is committed first, and then the previous transaction (JMS) is committed.
Note that when the inbound endpoint has a multi-resource transaction configured on it, any outbound endpoints must also be configured with multi-resource transaction support and the action set to "ALWAYS_JOIN" to become part of the virtual transaction.
You can use XA transactions if you want to enlist multiple managed resources within the same transaction and require 100% reliability. The inbound endpoints are configured in the same manner as for single-resource transactions, but the connectors need to be configured to use XA-enabled resources.
If you run Mule outside an application server, you can use JBoss Transaction Manager to configure an embedded transaction manager.
Currently, only the following transports support XA transactions:
The following example of an XA transaction configuration uses a single transaction to read from a JMS queue and write to a database.
1 2 3 4 5 6 7 8 <flow name="JmsToJdbc"> <jms:inbound-endpoint queue="my.queue" reuseSession="false"/> <xa-transaction action="ALWAYS_BEGIN" timeout="60000"/> </jms:inbound-endpoint> <jdbc:outbound-endpoint address="writeTest" type="2"> <xa-transaction action="ALWAYS_JOIN"/> </jdbc:outbound-endpoint> </flow>
Because the inbound JMS endpoint has an XA transaction configured on it, any outbound endpoints must also be configured with XA transaction support to become part of the XA transaction. This requires that the transport type supports XA transactions. For this configuration to work, you will need to configure a JMS connector that uses a JMS XA Connection Factory and a JDBC connector that is configured to use an XA data source.
Note that although Java EE does not support nested transactions, XA transactions have a suspend/resume concept. Therefore, if a flow is configured with an XA transaction set to ALWAYS_BEGIN, and the message is forwarded to another flow with an XA transaction set to ALWAYS_BEGIN, the first transaction is suspended until the second transaction completes.
xa-transaction element is a child element of the
abstract-transaction element. It inherits the
action attribute from
abstract-transaction and the
action settings have the same meaning for
xa-transaction as they do for
xa-transaction does not inherit the
timeout attribute, except as noted in the section below on setting polling frequency.
xa-transaction element includes another attribute,
interactWithExternal, which is a boolean type. When set to true,
interactWithExternal causes Mule ESB to interact with transactions begun outside of Mule ESB. For instance, if an external transaction is active and
interactWithExternal is set to true, then the BEGIN_OR_JOIN setting for
action results in Mule ESB joining the existing transaction while the ALWAYS_BEGIN
action attribute setting causes an exception to be thrown. Note that the default value for the
interactWithExternal attribute is false.
When you configure an inbound JMS endpoint with XA transactions, the receiver polls every 100 ms. You can change the polling frequency by setting the
pollingFrequency property as follows:
1 2 3 4 5 6 <jms:inbound-endpoint queue="my.queue" reuseSession="false"> <xa-transaction action="ALWAYS_BEGIN" timeout="60000"/> <properties> <spring:entry key="pollingFrequency" value="5000"/> </properties> </jms:inbound-endpoint>
This property is only applicable if you are using the
, which is the default receiver on inbound JMS endpoints that use XA transactions. If you are using JBoss transactions, please read here for information on how to configure the
javax.transaction.TransactionManager for managing transaction spanning multiple resources (XA). If you need the SUSPEND semantics for your transactions (which is what EJB’s
RequiresNew transaction attribute value does), you must use the transaction manager. Conversely, the more typical
javax.transaction.UserTransaction is just a thin handle to a transaction manager with limited (though in most cases sufficient) functionality that does not let you suspend the current transaction.
Note: Depending on your application server vendor, the transaction manager might be available via JNDI or only through proprietary APIs.
The following table summarizes some common Java EE servers:
|Application Server||Remote||Embedded||Common Location||Lookup class|
Proprietary API call
Specified via a jndiName property
For example, to use Weblogic’s transaction manager, you would configure Mule as follows:
1 <transaction-manager factory="org.mule.transaction.lookup.WeblogicTransactionManagerLookupFactory" />
Transaction demarcation is set on endpoints. The actual management of transactions is handled by the
Note that any transacted event flows will be synchronous. The Transaction Coordinator is a singleton manager that looks after all the transactions for a Mule instance and provides methods for binding and unbinding transaction and retrieving the current transaction state.
For example, to determine whether a transaction is an XA transaction, you could use
By default, an outbound endpoint from a non-transactional transport will now ignore an active transaction rather than rejecting it. (That is, the default transactional action for such endpoints is no longer
NONE). This allows flows such as the following:
1 2 3 4 5 6 <flow name="transactionalVM"> <vm:inbound-endpoint path="orders" exchange-pattern="one-way"> <vm:transaction action="ALWAYS_BEGIN"/> </vm:inbound-endpoint> <file:outbound-endpoint ref="receivedOrders"/> </flow>
As described in Transactional Inbound VM Queues, messages read from the VM queue are processed synchronously and transactionally. The File transport in the code example above is not transactional. So strictly speaking, writing to the file is not part of the transaction. However, any exception thrown while creating the file will roll back the transaction, causing the message to be reprocessed. This gives the effect of a multi-resource transaction.