Integration Server Transaction Support

Overview

This section describes how Integration Server supports transactions. Integration Server considers a transaction to be one or more interactions with one or more resources that are treated as a single logical unit of work. The interactions within a transaction are either all committed or all rolled back. For example, if a transaction includes multiple database inserts, and one or more inserts fail, all inserts are rolled back.

Integration Server supports the following types of transactions:

  • Local Transaction. Transaction to a resource's local transaction mechanism.
  • XAResource Transaction. Transaction to a resource's XAResource transaction mechanism.
Integration Server can manage both types of transactions, without requiring the adapter users' input.
  • Integration Server uses a container-managed (implicit) transaction management approach based on the JCA standard.
  • Integration Server performs additional connection management. This is because the adapter services use connections to create transactions.

For more information about implicit transactions, see Implicit Transaction Usage Cases. However, there are cases where adapter users need to explicitly control the transactional units of work. For more information about explicit transactions, see Explicit Transaction Usage Cases.

Integration Server relies on a built-in transaction manager to support transactions. The transaction manager is responsible for the following:

  • Beginning and ending transactions.
  • Maintaining a transaction context.
  • Enlisting newly connected resources into existing transactions.
  • Ensuring that local and XAResource transactions are not combined in invalid ways.
  • Manages operations performed by a transacted JMS trigger, or a built-in JMS service that uses a transacted JMS connection alias.
Important: You cannot create steps and trace a flow that contains a transacted adapter service.
Note: If you interact with a resource that does not support transactions, Integration Server does not create a transaction for it.

For more information about specifying the type(s) of transactions to support in your adapter, see Specifying Transaction Support in Connections.

Simple Transactions

The simplest Integration Server transaction scenario is a Flow Service (or a Java Service) that invokes one adapter service that interacts with one resource. For example, the transaction might perform a database insert.

Integration Server executes the transaction without requiring adapter users to perform any transaction management, as follows:

  1. Integration Server invokes the request as follows:
    1. Adapter service obtains a connection from the connection pool.
    2. Adapter service creates a transaction.
    3. Adapter service enlists the connection in the current transaction.
    4. Adapter service performs the database insert. If the insert fails, a ServiceException is thrown.
  2. Integration Server informs the transaction manager that the service request is completed as follows:
    • If the service request succeeds, the transaction manager commits the current transaction. If the commit fails, the transaction manager throws an exception that results in the failure of the service request, and a ServiceException is returned to the adapter user.
    • If the service request fails, the transaction manager rolls back the current transaction.
Note: The commit or rollback occurs after the service is complete, but before any response is sent to the client that invoked the service. This is because if the transaction commit fails, the service itself must fail. So, the transaction notification essentially becomes the last step of the service as opposed to occurring after the service is already complete.

More Complex Transactions

Suppose that a Flow Service or a Java Service invokes multiple adapter services. These adapter services might interact with a single resource (such as two services that perform two inserts into a single database) or with multiple resources (such as services that synchronize a database and an ERP system).

You can have one or more connections to a single resource. If multiple connections are used, then Integration Server enlists each connection in the transaction.

When the service request is complete, Integration Server notifies the transaction manager, which closes all enlisted connections and transactions.

  • If the service request is successful, then Integration Server commits all transactions automatically using a two-phase commit if multiple resources are used.
  • If the service request returns an error, then Integration Server rolls back the transaction and returns an error; that causes the service to return an error.

As mentioned previously, there are cases where adapter users must explicitly control the transactional units of work. For more information, see Explicit Transaction Usage Cases.

Note: If a transaction accesses multiple resources, and more than one of the resources supports local transactions only, then the integrity of the transaction cannot be guaranteed. For example, if the first resource successfully commits, and the second resource fails to commit, the first resource interaction cannot be rolled back; it has already been committed. Integration Server detects this case when connecting to more than one resource that do not support two-phase commits and throws a runtime exception which results in the failure of the service execution.

Implicit Transaction Usage Cases

Integration Server handles implicit transactions. For a flow to be managed implicitly, it can contain one of the following:

  • One local transaction, interacting with one resource.
  • One or more XAResource transactions; each transaction can interact with one or more resources.
  • One or more XAResource transactions and one local transaction.

If a flow contains multiple local transactions, the adapter user must explicitly control the transactional units of work. For more information, see Explicit Transaction Usage Cases.

Following are examples of implicit transactions.

One Local Transaction

In this example, a flow with two adapter services interacts with the same local transaction resource. The flow performs two inserts into two tables of a database:

BEGIN FLOW  
INVOKE insertDatabase1TableA // Local Transaction Resource1  
INVOKE insertDatabase1TableB // Local Transaction Resource1  
END FLOW
  • Integration Server starts the transaction when insertDatabase1TableA is invoked.
  • Integration Server opens a connection to the resource, enlists it in the transaction, and performs the insert into TableA.
  • When insertDatabase1TableB is invoked, Integration Server reuses the same connection to insert data into TableB.
  • When the request is complete, Integration Server closes the connection and commits the transaction.

Two Local Transactions

The following flow is invalid because it tries to interact with two local transaction resources as follows:

BEGIN FLOW  
INVOKE insertDatabase1TableA // Service for Resource1  
INVOKE insertDatabase2TableA // Service for Resource2  
END FLOW

Three XAResource Transactions

The following flow is valid because a flow can contain any number of XAResource transactions.

BEGIN FLOW  
INVOKE insertDatabase1TableA // XAResource Transaction Resource1  
INVOKE insertDatabase2TableA // XAResource Transaction Resource2  
INVOKE insertDatabase3TableA // XAResource Transaction Resource3  
END FLOW

One Local Transaction and One XAResource Transaction

Continuing with the previous case, this flow contains an additional insert to a different database that accepts XAResource transactions as follows:

BEGIN FLOW  
INVOKE insertDatabase1TableA // Local Transaction Resource1  
INVOKE insertDatabase1TableB // Local Transaction Resource1  
INVOKE insertDatabase2TableA // XAResource Transaction Resource1  
END FLOW
  • When Integration Server invokes insertDatabase2TableA, a transaction is already in progress with the first database enlisted. Integration Server performs the following:
    • Establishes a second connection to Database2.
    • Enlists the new connection in the XAResource transaction.
    • Performs the insert to tableA.
  • When the request is complete
    • Integration Server closes both connections.
    • Transaction Manager performs a local commit for the non-XAResource and then a two-phase commit for the XAResource enlisted in the transaction.

Explicit Transaction Usage Cases

Adapter users must explicitly start and end each transaction, except the first one to include multiple local transactions in a single flow.

Depending on what the flow needs to accomplish, adapter users may explicitly start and end XAResource transactions as well. This way, the adapter users can create a flow that includes multiple local transactions and multiple XAResource transactions.

Integration Server provides the following built-in services to support multiple local transactions and multiple XAResource transactions:

  • pub.art.transaction.startTransaction
  • pub.art.transaction.commitTransaction
  • pub.art.transaction.rollbackTransaction
  • pub.art.transaction.setTransactionTimeout

For more information, see Built-In Services For Explicit Transactions.

For example, the following flow includes a local transaction nested within another local transaction:

BEGIN FLOW                       // start transaction 1  
.  
.  
.  
    INVOKE startTransaction(2)      // start transaction 2  
    .  
    .  
    .  
    INVOKE commitTransaction(2)     // commit transaction 2  
END FLOW                         // commit transaction 1

A nested transaction must adhere to the same rules that apply to container-manager transactions. That is, a nested transaction can contain one of the following:

  • One local transaction, interacting with one resource.
  • One or more XAResource transactions; each transaction can interact with one or more resources.
  • One or more XAResource transactions and one local transaction.

Following are some examples of explicit transactions.

Two Local Transactions

To make this flow work properly, explicitly start and commit the nested local transaction, using the startTransaction and commitTransaction services as follows:

BEGIN FLOW                     // start transaction 1  
INVOKE interactWithResourceA   // service for transaction 1  
  
   INVOKE startTransaction(2)     // start transaction 2  
   INVOKE interactWithResourceB   // service for transaction 2  
   INVOKE commitTransaction(2)    // commit transaction 2  
  
END FLOW                       // commit transaction 1

The flow executes as follows:

  1. When interactWithResourceA is invoked, Integration Server starts transaction 1 and enlists ResourceA.
  2. Transaction 2 executes as follows:
    1. When startTransaction(2) is invoked, Integration Server starts a new, nested transaction.
    2. When interactWithResourceB is invoked, ResourceB is enlisted in transaction 2.
    3. When commitTransaction(2) is invoked, the connection to ResourceB is closed, and transaction 2 is committed. At this point, only the work done on ResourceB is committed; transaction 1 is still open, and the work done with ResourceA is not yet committed.
  3. When the flow ends, Integration Server closes the connection for transaction 1 and commits its work to ResourceA.
Note: Each transaction is a separate unit of work. Transaction 1 could be rolled back (or the commit could fail), while transaction 2 remains committed (or vice versa).

Alternatively, to achieve the same result, you can explicitly start transaction 1 before the adapter service is invoked, and explicitly commit it as follows:

BEGIN FLOW  
INVOKE startTransaction(1)     // start transaction 1  
INVOKE interactWithResourceA   // service for transaction 1  
INVOKE startTransaction(2)     // start transaction 2  
INVOKE interactWithResourceB   // service for transaction 2  
INVOKE commitTransaction(2)    // commit transaction 2  
INVOKE commitTransaction(1)    // commit transaction 1  
END FLOW

Two XAResource Transactions

The following flow includes two XAResource transactions: one that interacts with ResourceA, and a nested transaction that interacts with ResourceB and ResourceC.

BEGIN FLOW                      // start transaction 1  
INVOKE interactWithResourceA    // service for transaction 1  
  
   INVOKE startTransaction(2)      // start transaction 2  
   INVOKE interactWithResourceB    // service for transaction 2  
   INVOKE interactWithResourceC    // service for transaction 2  
   INVOKE commitTransaction(2)     // commit transaction 2  
  
END FLOW                        // commit transaction 1

The flow executes as follows:

  1. When interactWithResourceA is invoked, Integration Server starts transaction 1 and enlists ResourceA.
  2. Transaction 2 executes as follows:
    1. When startTransaction(2) is invoked, Integration Server starts a new, nested transaction.
    2. When interactWithResourceB and interactWithResourceC are invoked, both resources are enlisted in transaction 2.
    3. When commitTransaction(2) is invoked, the connections to ResourceB and ResourceC are closed, and transaction 2 is committed. At this point, only the work done on ResourceB and ResourceC is committed; transaction 1 is still open, and the work done with resourceA is not yet committed.
  3. When the flow ends, Integration Server closes the connection for transaction 1 and commits its work to ResourceA.

One XAResource Transaction and Two Nested Local Transactions

The following flow includes three transactions: one XAResource transaction that interacts with two resources, and two nested local transactions that interact with one resource each.

BEGIN FLOW                        // start XAResource transaction 1  
INVOKE interactWithXAResourceA    // service for XAResource transaction 1  
INVOKE interactWithXAResourceB    // service for XAResource transaction 2  
   INVOKE startTransaction(2)         // start local transaction 1  
   INVOKE interactWithLocalResourceA  // service for local transaction 1  
   INVOKE commitTransaction(2)        // commit local transaction 1  
   INVOKE startTransaction(3)         // start local transaction 2  
   INVOKE interactWithLocalResourceB  // service for local transaction 2  
   INVOKE commitTransaction(3)        // commit local transaction 2  
END FLOW                          // commit XAResource transaction 1

The flow executes as follows:

  1. When interactWithXAResourceA is invoked, Integration Server starts transaction 1 and enlists XAResourceA.
  2. When interactWithXAResourceB is invoked, Integration Server enlists XAResourceB in transaction 1.
  3. Transaction 2 is executed as follows:
    1. When startTransaction(2) is invoked, Integration Server starts a new, nested transaction.
    2. When interactWithLocalResourceA is invoked, LocalResourceA is enlisted in transaction 2.
    3. When commitTransaction(2) is invoked, the connection to LocalResourceA is closed, and transaction 2 is committed. At this point, only the work done on LocalResourceA is committed; transaction 1 is still open, and the work done with XAResourceA and XAResourceB is not yet committed.
  4. Transaction 3 is executed as follows:
    1. When startTransaction(3) is invoked, Integration Server starts a new, nested transaction.
    2. When interactWithLocalResourceB is invoked, LocalResourceB is enlisted in transaction 3.
    3. When commitTransaction(3) is invoked, the connection to LocalResourceB is closed, and transaction 3 is committed. At this point, only the work done on LocalResourceA and LocalResourceB is committed; transaction 1 is still open, and the work done with XAResourceA and XAResourceB is not yet committed.
  5. When the flow ends, Integration Server closes the connection for transaction 1 and commits its work to XAResourceA and XAResourceB.

One XAResource Transaction and One Nested Local and XAResource Transaction

The following flow includes two transactions: one XAResource transaction that interacts with two resources, and one nested transaction that interacts with one local resource and one XAResource.

BEGIN FLOW                        // start XAResource transaction 1  
INVOKE interactWithXAResourceA    // service for XAResource transaction 1  
INVOKE interactWithXAResourceB    // service for XAResource transaction 2  
  
   INVOKE startTransaction(2)           // start transaction 2  
   INVOKE interactWithLocalResourceA    // service for transaction 2  
   INVOKE interactWithXAResourceC       // service for transaction 2  
   INVOKE interactWithLocalResourceA    // service for transaction 2  
   INVOKE commitTransaction(2)          // commit transaction 2  
  
END FLOW                          // commit XAResource transaction 1

The flow executes as follows:

  1. When interactWithResourceA is invoked, Integration Server starts an XAResource transaction 1 and enlists ResourceA.
  2. When interactWithXAResourceB is invoked, Integration Server enlists XAResourceB in transaction 1.
  3. Transaction 2 is executed as follows:
    1. When startTransaction(2) is invoked, Integration Server starts a new, nested transaction.
    2. When interactWithLocalResourceA is invoked, LocalResourceA is enlisted in transaction 2.
    3. When interactWithXAResourceC is invoked, XAResourceC is enlisted in transaction 2.
    4. When interactWithLocalResourceA is invoked, LocalResourceA is enlisted in transaction 2.
    5. When commitTransaction(2) is invoked, the connection to both resources of transaction 2 is closed, and transaction 2 is committed. At this point, only the work done on LocalResourceA and XAResourceC is committed; transaction 1 is still open, and the work done with XAResourceA and XAResourceB is not yet committed.
  4. When the flow ends, Integration Server closes the connection for transaction 1 and commits its work to XAResourceA and XAResourceB.

Built-In Services For Explicit Transactions

Use the built-in services described in this section to manage explicit transactions for your webMethods Adapter Development Kit services.

Explicit transactions are transactions that is manually controlled within flow services using built-in services. Implicit transactions are automatically handled by the Integration Server's transaction manager. When you define an explicit transaction, it is nested within the implicit transactions that are controlled by the transaction manager. You can have more than one explicit transaction defined within an implicit transaction. You can also nest explicit transactions within each other.

Any flow service steps found between a pub.art.transaction:startTransaction service and either a pub.art.transaction:commitTransaction service or a pub.art.transaction:rollbackTransaction service are part of an explicit transaction rather than the implicit transaction.

Within both implicit and explicit transactions, you cannot have multiple connections with a transaction type of LOCAL_TRANSACTION because you will not be able to rollback the first LOCAL_TRANSACTION after it is committed. Use the built-in services to define explicit transactions to prevent from inadvertently committing transactions if you need to rollback the transaction.

The table below briefly describes the public services in Integration Servers' WmART package. The sections that follow describe each service in detail.

Service Function
pub.art.transaction:startTransaction Starts an explicit transaction.
pub.art.transaction:commitTransaction Commits an explicit transaction.
pub.art.transaction:rollbackTransaction Rolls back an explicit transaction.
pub.art.transaction:setTransactionTimeout Enables you to manually set a transaction timeout interval for implicit and explicit transactions.

pub.art.transaction:startTransaction

Starts an explicit transaction. The service must be used in conjunction with either a pub.art.transaction:commitTransaction service or pub.art.transaction:rollbackTransaction service. If a corresponding pub.art.transaction:commitTransaction service or pub.art.transaction:rollbackTransaction service is not provided, then the flow service receives a runtime error.

Input Parameters

startTransactionInput Document. Document that contains the variable transactionName.
transactionName String. Used to associate a name with an explicit transaction. The transactionName must correspond to the transactionName in any pub.art.transaction:rollbackTransaction or pub.art.transaction:commitTransaction services associated with the explicit transaction.

Output Parameters

startTransactionOutput Document. Document that contains the variable transactionName.
transactionName String. Used to associate a name with an explicit transaction. The transactionName must correspond to the transactionName in any pub.art.transaction:rollbackTransaction or pub.art.transaction:commitTransaction services associated with the explicit transaction.

pub.art.transaction:commitTransaction

Commits an explicit transaction. The service must be used in conjunction with the pub.art.transaction:startTransaction service. If a corresponding pub.art.transaction:startTransaction service is not provided, then the flow service receives a runtime error.

Input Parameters

commitTransactionInput Document. Document that contains the variable transactionName.
transactionName String. Used to associate a name with an explicit transaction. The transactionName must correspond to the transactionName in any pub.art.transaction:startTransaction or pub.art.transaction:rollbackTransaction services associated with the explicit transaction.

pub.art.transaction:rollbackTransaction

Rolls back an explicit transaction. The service must be used in conjunction with a pub.art.transaction:startTransaction service. If a corresponding pub.art.transaction:startTransaction service is not provided, then the flow service receives a runtime error.

Input Parameters

rollbackTransactionInput Document. Document that contains the variable transactionName.
transactionName String. Used to associate a name with an explicit transaction. The transactionName must correspond to the transactionName in any WmART.pub.art.transaction:startTransaction or WmART.pub.art.transaction:commitTransaction services associated with the explicit transaction.

pub.art.transaction:setTransactionTimeout

Enables you to manually set a transaction timeout interval for implicit and explicit transactions. The service overrides the Integration Server's transaction timeout interval. For more information about changing the Integration Server default transaction timeout, see Changing the Integration Servers' Transaction Timeout Interval.

  • You must call this service within a flow before the start of any implicit or explicit transactions. Implicit transactions start when you call an adapter service in a flow. Explicit transactions start when you call the pub.art.transaction:startTransaction service.
  • If the execution of a transaction takes longer than the transaction timeout interval, all current executions associated with the flow are cancelled and rolled back if necessary.
  • The service only overrides the transaction timeout interval for the flow service in which you call it.

Input Parameters

timeoutSeconds Integer. Number of seconds that the implicit or explicit transaction stays open before the transaction manager aborts it.

Changing the Integration Servers' Transaction Timeout Interval

Configures the maximum number of seconds that a transaction can remain open and still be considered valid. This transaction timeout parameter does not halt the execution of a flow. Default value is NO_TIMEOUT.

For example, if a current transaction has a timeout value of 60 seconds and a flow takes 120 seconds to complete, the transaction manager rolls back all registered operations regardless of the execution status.

You can configure the following property on the Extended Settings screen (Settings > Extended) in Integration Server Administrator:
watt.art.tmgr.timeout=TransactionTimeout
where TransactionTimeout is the number of seconds before transaction timeout.

Restart Integration Server after configuring the property.

Transaction Error Situations

When Integration Server encounters a situation that compromises the transactional integrity, it throws an error. Such situations include the following:

  • A transaction includes a resource that only supports local transactions.

    If a transaction accesses multiple resources, and more than one of the resources support local transactions only, then the integrity of the transaction cannot be guaranteed. For example, if the first resource successfully commits, and the second resource fails to commit, the first resource interaction cannot be rolled back; it has already been committed. To prevent this, Integration Server detects this case when connecting to more than one resource that does not support two-phase commits, and throws a runtime exception resulting in the failure of the service execution.

  • A transactional or non-transactional resource is used in both a parent transaction and a nested transaction.

    This situation is ambiguous, and most likely means that a nested transaction was not properly closed.

  • A parent transaction is closed before its nested transaction.
  • After a service request has invoked all its services, but before returning results to the caller, the service may commit its work. This commit could fail if the resource is unavailable or rejects the commit and causes the entire request to fail, and the transaction is rolled back.

Specifying Transaction Support in Connections

Return the appropriate transaction support level in your WmManagedConnectionFactory.queryTransactionSupportLevel implementation to support transactions in your adapter.

  • For local transaction support, override the WmManagedConnection.getLocalTransaction method to return a javax.resource.spi.LocalTransaction object that is capable of interfacing with the transactional capabilities of your resource.
  • For XA transaction support, override the WmManagedConnection.getXAResource method to return a javax.transaction.xa.XAResource object that is capable of interfacing with the XA transactional capabilities of your resource.
Important: Do not call the super method when you override getLocalTransaction or getXAResource methods.