There are three possible discrete transaction boundaries within BizTalk Server.
The first boundary surrounds the BizTalk adapter, receive pipeline, and BizTalk MessageBox. The adapter can (transport permitting) enlist in a transaction with the source system, effectively creating a transaction spanning the source system and the in-bound BizTalk architecture. This way, the message will not be removed from the source system until the message is committed into the BizTalk MessageBox and is therefore safe in a durable store.
The second transaction boundary is between the BizTalk MessageBox and orchestrations. This ensures that any messages being processed by an orchestration are handled within the scope of a transaction. If an orchestration fails for whatever reason, the message will be returned to the MessageBox ready for reprocessing or the orchestration itself will resume from a previous checkpoint.
The third transaction boundary is between the BizTalk MessageBox and Send adapter. The adapter can, transport permitting, flow the transaction to a destination system, thus creating a transaction spanning from the BizTalk MessageBox to the destination system. This way, the message is not removed from the BizTalk MessageBox until the message has been successfully committed into the destination system.
These transaction boundaries are critical to ensuring that messages are not lost either by BizTalk or by remote systems, and these boundaries provide a high level of transactional integrity for your messages.
Below figure depicts the boundaries.
The figure depicts the transaction flowing between BizTalk and an MSMQ queue, as both MSMQ and the MSMQ adapter support transactions. However, this is optional depending on your solution. The figure also depicts a custom Receive pipeline component enlisting on the transaction (which is, again, optional).
BizTalk support Atomic and Long Running transactions.
Atomic: short execution time (typically seconds)
- Fulfill all ACID attributes
- Acquires data locks on Resource Managers (ex: SQL Server)
- Operations succeed (commit) or fail (rollback) as a unit via Transaction Manager (ex: DTC)
Long-Running: might span hours or days
- Must not acquire data locks for such long time
- Commit and rollback are done explicitly by code. No Transaction Manager to aid in this
- Rollback more commonly knows as Compensation. Compensate an action rather than undo it. Ex: You cannot undo sending a payment message, but you can compensate by sending a cancellation message
An Orchestration Scope shape can be configured with a transaction type
- None (Default)
- Long Running
Transaction Type can be set at Orchestration Level (default None):
- Cannot contain other transactional scopes
- Entire Orchestration will be Atomic; therefore will persist once at the end
- Can contain both Atomic and Long Running scopes
Transaction Type at Scope Shape level:
- Atomic scope cannot contain other transactional scopes (nesting not allowed)
- Long Running scopes can contain both Long Running and Atomic scopes.
Compensation, as the name implies, is the process by which you can provide a compensating action for an operation that has previously occurred, unlike a transactional rollback, which occurs before the operation has been committed.
Compensation is supported for both Long Running and Atomic Transactions.
Compensation is often used for long-running transactions, as there is no other way to roll back things that have happened within the transaction. With atomic scopes, you ensure that everything is happy before committing. Compensation also can be used for atomic scopes where you need to reverse the results of a previously committed transaction.
Compensation is a multistep process; you must provide the code to undo the action previously performed. Again, this is different from atomic transactions, as any operations are done within the scope of a transaction and none are committed persistently until the overall transaction has completed.
Compensation blocks are called using the Compensate Shape inside Exception Handler blocks.
Compensation blocks will be executed in reverse order, following an exception being thrown within the orchestration. Compensation blocks can contain any combinations of orchestration shapes.
Compensation occurs only for committed Transactions.
So here in this case will transaction will be called?
The answer is NO because the compensation is only valid for committed transaction.
Here the transaction has failed.So it’s a case of exception handling.
In reality, however, compensation should be used with care. It is important that you fully understand the consequences of using it for your scenario.
The reason for this is that there are side effects from transactions that are committed. For example, suppose that a business transaction is constructed from two transactions: #1 – credit payee’s account, followed by #2 – debit payer’s account.
Let’s assume that transaction #2 fails. Therefore, you need to execute the compensating transaction for transaction #1. All’s well and good. You simply debit the account the amount that you credited it, and you are back where you started, right?
Well, actually no, because for this scenario when the payee’s account exceeds 100,000, he becomes classed as a premier customer. As such, the interest rate applied to his account is automatically adjusted upward. This now means that to correctly compensate you need to execute the business rules to determine whether he is still a premier customer.
This example is relatively trivial, but the point is that many business transactions have side effects. For compensation to work correctly, these side effects need to be accounted for. This usually adds a great deal of complexity, and for many integration scenarios that level of complexity can be overwhelming.
An Orchestration Scope shape can be configured with a transaction type of atomic. This signifies that anything executed within the scope will take part in an atomic transaction that conforms to the four usual ACID attributes: atomicity, consistency, isolation, and durability.
- Atomicity – All changes effected within the scope of an atomic transaction must complete successfully or all changes must be rolled back.
- Consistency – Once an atomic transaction is committed, it must ensure that any data modified remains consistent; it is not acceptable for an atomic transaction to leave a database in a inconsistent state by invalidating rules or constraints.
- Isolation – Any changes made during an atomic transaction must be kept isolated from other read operations until the transaction is completed.
- Durability – Once an atomic transaction has successfully committed, the changes must be durable and therefore not held in memory but instead in a durable store such as a SQL Server database. Such changes must be committed to a physical medium, such as a hard drive, to ensure that the changes survive a machine failure. It’s not acceptable for data to be subsequently rolled back following a committed atomic transaction.
To provide atomic transaction support, an atomic scope incurs a persistence point at the end of an atomic scope. This is done to ensure that, following the completion of an atomic scope, it cannot be executed again — for example, if the orchestration rolls back following a later failure in the orchestration.
Due to the nature of an atomic transaction, the orchestration cannot be dehydrated while within an atomic scope. Therefore, it’s wise to ensure that you keep the size of the atomic scope down and, as required consider splitting a large atomic scope into separate discrete atomic scopes and providing compensation handlers.
When would you want to use an atomic scope? There are three main reasons
- To use a .NET class that is not marked as serializable
- Serialization is critical to orchestration execution, however, an atomic scope prevents serialization during execution of an atomic scope, enabling you to use non-serializable components.
- It’s worth emphasizing that the use of an atomic scope will produce an extra persistence point in your orchestration, which will introduce performance overhead to your solution.
- To minimize the number of persistence points
- An atomic scope itself causes a persistence point, although this can be mitigated if, for example, you wrap two or more Send shapes, each of which incurs a persistence point.
- In this scenario, you can turn two persistence points into one because the atomic scope optimizes the persistence points down to one by committing both send operations at the same time.
- To call a COM+ component
- You might need to call a COM+ component (ServicedComponent) that you want to participate in the scope of the orchestration transaction.
- Atomic Transactions are not propagated to and from BizTalk:
- Orchestration cannot participate in other component transaction
- Other components cannot participate in Orchestration transaction
- Ex: calling a .NET component which uses TransactionScope from an Expression Shape, will not roll back the DB operations, if the Atomic scope fails in the Orchestration. Atomic scope is scoped only over MessageBox variables and messages.
- If Transaction propagation is needed, external assemblies must use COM+ objects derived from System.EnterpriseServices.ServicedComponents
Atomic Transactions and Messaging
Send shape inside an Atomic scope will not actually send the message out, until scope is committed. Message will be sent to MessageBox, but will not be available to subscribers until scope commits.
Request/Response pattern is not allowed inside Atomic scope. If Request is not sent, then Response won’t come.
Similarly, Initialize/Follow correlation sets are not allowed inside Atomic scope
Atomic transactions are perfectly suited to short-term operations that require the full ACID behavior and are using technologies that explicitly support transactions. But they may not be the most appropriate solution to your problem due to the isolation part of ACID.
Isolation effectively means that you have to place locks on any data involved in the ACID transaction to prevent modification by other people and, in the strictest sense, even reading of the data (although this can be controlled by lowering the isolation level).
Taking into account a typical BizTalk scenario involving a third party, you would not want a third party to lock any of transactional resources over the Internet or for a long period of time. This is where long running transactions come into play. They enable you to implement long-running business processes that do not require or cannot support atomicity or isolation.
Compensation is instead used to provide a manual form of rollback for your business process — a manual version of atomic transactions’ rollback features.
Atomic transactions aren’t always suitable, especially when you want to understand if a transaction rolled back for auditing purposes. An atomic transaction effectively erases all the history of a transaction.
To this end, you should consider full auditing of such operations and ensure that the auditing operation is not transactional itself. This will ensure that the audit trail is preserved even if the transaction has been rolled back.