Transaction Management in MuleSoft/Anypoint Studio
Learn how MuleSoft and Anypoint Studio can handle transactions so that they will either successfully complete, or rollback and not commit.
Join the DZone community and get the full member experience.
Join For FreeTransaction Management is required everywhere, be it MuleSoft, Java, or any other language. When you buy a book from Amazon and you pay Amazon, transaction handling makes sure that you get your shipment, your credit company pays Amazon, and Amazon is able to receive the funds successfully.
If it fails at any point, your transaction should rollback and none of these events should happen.
Mule handles the concept of transactions in a similar way. A transaction will be either complete and succeed, or it will be incomplete and fail. If a transaction fails, Mule rolls back every single operation and there will be no commit.
How Mule Starts a New Transaction
The Mule flow starts a new transaction when a flow begins with a transactional resource (inbound connector).
The flow manages the outgoing operation as a transaction if the flow includes a transactional outbound connector.
In a flow with both an Inbound and Outbound connector, a transaction is initiated by an Inbound connector and the outgoing operation (Outbound) becomes a part of the same transaction.
Transaction Types
Mule supports three types of transactions:
1. Single resource
2. Multiple resource
3. XA transactions (extended architecture)
1. Single Resource Transactions
These are used to send or receive messages using only one single resource - JMS, VM, or JDBC.
The example below illustrates a flow which includes a single resource transaction applied to inbound and outbound JMS connectors.
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:jms="http://www.mulesoft.org/schema/mule/jms" 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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="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/jms http://www.mulesoft.org/schema/mule/jms/current/mule-jms.xsd">
<jms:connector name="JMS" validateConnections="true" doc:name="JMS"/>
<flow name="transactionmanagementFlow">
<jms:inbound-endpoint queue="test.input" connector-ref="JMS" doc:name="JMS">
<jms:transaction action="ALWAYS_BEGIN"/>
</jms:inbound-endpoint>
<logger level="INFO" doc:name="Logger"/>
<jms:outbound-endpoint doc:name="JMS" connector-ref="JMS" queue="test.output">
<jms:transaction action="ALWAYS_JOIN"/>
</jms:outbound-endpoint>
</flow>
</mule>
The above snippet has a JMS connector that receives messages on a test.input queue and another JMS connector that sends messages on a test.output queue. The action attribute tells how Mule initiates a transaction. In this snippet, a new transaction is initiated for every message received on the inbound connector and Mule will participate in a transaction in progress for every message it sends out on the outbound connector. A commit will happen only for those messages which pass successfully through the complete flow.
Performance
It performs better than multi-resource or XA transactions.
2. Multiple Resource Transactions
These are used to group together operations from multiple JMS or VM resources into a single transaction. If there is a need to group two different connectors to consolidate in a transaction, then we can use a multiple resource transaction.
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:wmq="http://www.mulesoft.org/schema/mule/ee/wmq" xmlns:jbossts="http://www.mulesoft.org/schema/mule/jbossts" xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core" xmlns:jms="http://www.mulesoft.org/schema/mule/jms" 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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="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/jms http://www.mulesoft.org/schema/mule/jms/current/mule-jms.xsd
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd
http://www.mulesoft.org/schema/mule/jbossts http://www.mulesoft.org/schema/mule/jbossts/current/mule-jbossts.xsd
http://www.mulesoft.org/schema/mule/ee/wmq http://www.mulesoft.org/schema/mule/ee/wmq/current/mule-wmq-ee.xsd">
<jms:connector name="JMS" validateConnections="true" doc:name="JMS"/>
<wmq:connector name="WMQ" hostName="localhost" port="1414" transportType="CLIENT_MQ_TCPIP" validateConnections="true" doc:name="WMQ"/>
<flow name="transactionmanagementFlow">
<jms:inbound-endpoint queue="test.input" connector-ref="JMS" doc:name="JMS">
<ee:multi-transaction action="ALWAYS_BEGIN"/>
</jms:inbound-endpoint>
<logger level="INFO" doc:name="Logger"/>
<wmq:outbound-endpoint queue="test.output" connector-ref="WMQ" doc:name="WMQ">
<ee:multi-transaction action="ALWAYS_JOIN"/>
</wmq:outbound-endpoint>
</flow>
</mule>
In the above example, a JMS transaction is initiated when Mule receives the message on the inbound JMS connector. Another WMQ transaction is initiated when it sends the message out on the outbound connector. As the connectors are configured as multiple resource transactions, WMQ transaction will be committed first and then it will commit the JMS transaction.
<ee:multi-transaction action="ALWAYS_BEGIN"/>
<ee:multi-transaction action="ALWAYS_JOIN"/>
Mule will either commit both transactions successfully or rolls back both of them as one unit.
If an inbound connector is configured as a multi-resource transaction, then other connectors should be configured as multi-resource transactions and the action set should be configured as "ALWAYS_JOIN" to make it part of the transactional unit.
Performance
It performs better than XA transactions but slower than Single Resource transactions.
It can handle partial commits and rollbacks.
It uses 1.5 phase commit protocol and is less reliable than XA.
3. XA Transactions
These can be used to group together a series of operations from multiple JDBC (deprecated now), JMS, or VM resources into a single, very reliable global transaction.
XA (eXtended Architecture) is an X/Open group standard which specifies the interface between a global transaction manager and local transactional resource managers. It defines a 2-phase commit protocol which can be used to more reliably coordinate and sequence a series of "all or no" operations across multiple servers, even servers of different types. Examples of transactional systems which often include local XA resource managers include databases, application servers, messaging queues, and transactional caches.
One global transaction manager communicates and works with multiple different transaction resources in a standard way. If any local resource manager reports an error in the global transaction, the global transaction manager coordinates the rollback of already prepared operations in each local resource manager.
This helps developers to keep their complex rollback or recovery logic outside of the application.
XA global transactions can add tremendous latency to your transactions and it can be difficult to recover if there are physical failures of systems in the middle of a global distributed transaction.
The following example illustrates a flow in which two connectors use an XA transaction to function as a single transactional unit.
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns:db="http://www.mulesoft.org/schema/mule/db" xmlns:wmq="http://www.mulesoft.org/schema/mule/ee/wmq" xmlns:jbossts="http://www.mulesoft.org/schema/mule/jbossts" xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core" xmlns:jms="http://www.mulesoft.org/schema/mule/jms" 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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="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/jms http://www.mulesoft.org/schema/mule/jms/current/mule-jms.xsd
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd
http://www.mulesoft.org/schema/mule/jbossts http://www.mulesoft.org/schema/mule/jbossts/current/mule-jbossts.xsd
http://www.mulesoft.org/schema/mule/ee/wmq http://www.mulesoft.org/schema/mule/ee/wmq/current/mule-wmq-ee.xsd
http://www.mulesoft.org/schema/mule/db http://www.mulesoft.org/schema/mule/db/current/mule-db.xsd
http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd">
<jms:connector name="JMS" validateConnections="true" doc:name="JMS"/>
<vm:connector name="VM" validateConnections="true" doc:name="VM"/>
<flow name="transactionmanagementFlow">
<jms:inbound-endpoint queue="test.input" connector-ref="JMS" doc:name="JMS">
<xa-transaction action="ALWAYS_BEGIN"/>
</jms:inbound-endpoint>
<logger level="INFO" doc:name="Logger"/>
<vm:outbound-endpoint exchange-pattern="one-way" path="test.output" connector-ref="VM" doc:name="VM">
<xa-transaction action="ALWAYS_JOIN"/>
</vm:outbound-endpoint>
</flow>
</mule>
Mule uses Bitronix to manage XA transactions.
Performance
XA is slower than the others but it is more reliable than the others.
It uses 2-phase commit protocol.
Transaction Configuration
How you want to configure the transactions depends on your requirement.
- Apply a transaction to an inbound connector if there is a need to handle the entire Mule flow as a transaction.
- Apply a transaction to an outbound connector if you want to make sure the outgoing operation should be a part of an existing transaction; then we can apply a transaction to an outbound connector.
- Apply a transactional scope if you want to put certain elements in a flow a part of the transaction; then we can use the transactional scope. This should be used when the flow does not begin with an Inbound connector.
Hope this article helps you in understanding transaction management in MuleSoft! Enjoy.
Opinions expressed by DZone contributors are their own.
Comments