Custom Search SOABYTE here

Monday, November 8, 2010

XA Configuration - 2 DBAdapter invokes committing/rolling back as a unit

To make 2 invokes commit or rollback as a unit requires the following: both DBAdapter invokes must be configured to participate in global transactions, both invokes must participate in the same global transaction, and the failure of either invoke must cause the global transaction to rollback.

1 Configuring DBAdapter for Global Transaction participation

In the deployment descriptor (oc4j-ra.xml), you must set xADataSourceName.  The matching data-source entry (in data-sources.xml) must be configured for transaction participation, i.e.
<managed-data-source name="BPELSamplesDataSource" connection-pool-name="BPEL_POOL" jndi-name="jdbc/BPELSamplesDataSource" tx-level="global" />
Notice the tx-level="global" property.  It can be omitted as "global" is the default value, but if the value is "local" then it is not configured correctly.

True XA: Two-Phase (XA) vs One-Phase (Emulated) Commit

XA is a two-phase commit protocol, which is more robust than a 1 phase commit or emulated protocol.  The difference is that with a one-phase protocol you may very rarely still see message loss or other rollback/commit inconsistency, on the order of one per one thousand generally.
A true XA config in data-sources.xml is shown below:
<connection-pool name='dbSample_CONNECTION_POOL'
    <connection-factory factory-class='oracle.jdbc.xa.client.OracleXADataSource'
<managed-data-source name='DBSampleNonEmulatedDS'
    jndi-name='jdbc/dbSample' tx-level="global" />
Notice the setting of connection-factory-class to an OracleXADataSource.

RAC Configuration

When running in a RAC setup you should also set the fast connection failover property, so the connection-factory element should look something like:
    <connection-factory factory-class='oracle.jdbc.xa.client.OracleXADataSource'
          <property name="loginTimeout" value="30"/>
          <property name="connectionCachingEnabled" value="true"/>
          <property name="fastConnectionFailoverEnabled" value="true"/>
Also if you have multiple components using the same RAC database, make sure that they share the same managed datasource definition, not just the same connection pool definition.

True XA Configuration with 3rd Party Drivers

When configuring true XA for 3rd party drivers (i.e. SQLServer, DB2), see if the driver jars contain a class that implements javax.sql.XADataSource.
For data direct drivers the naming happens to be, or

Both Invokes in Same Global Transaction 

Once the invokes participate in global transactions, to commit/rollback as a unit they must be participating in the same global transaction.  In BPEL this requires understanding where are the transaction boundaries, at what points a checkpoint to write to the dehydration store commits the current global transaction and starts a new one.
 The 'transaction boundaries' in a BPEL process are:
-before a receive activity (but not the initial one!)
-before a wait activity (otherwise the engine could run into a tx timeout)
-before an onMessage, or pick(extended onMessage) activity
-when invoking a synchronous child BPEL process, unless the transaction participate property is set on the partnerlink.  Otherwise the parent process is broken into two transactions and the child process executes in its own transaction.

3 Failure Must Cause Rollback

Finally, even if both invokes participate in the same global transaction, the failure of either invoke may not cause the global transaction to rollback.
The only cases where a failure can actually cause a global rollback are:
-A DBAdapter operation that inserts/updates multiple tables as part of one invoke fails after having succeeded in some writes but not others.  In this case the adapter will mark the global transaction 'rollback only', as the invoke operation was not atomic and a commit could cause data corruption.
-The global transaction participate property is set in bpel.xml, so that when BPEL catches a fault from the DBAdapter invoke it will allow the fault to propogate up and cause a global rollback.
-The invoke retries multiple times in a database down scenario, until the global transaction times out and is rolled back.
-An explicit bpelx:rollback fault is thrown from within the BPEL process.
GetActiveUnitOfWork="true" in WSDL
GetActiveUnitOfWork is an advanced WSDL property you can set on any DBInteractionSpec.  It causes the invoke to register itself with the two-phase commit callbacks, and all writes to the database are performed as part of the two-phase commit.  By setting this property on any failure the transaction is automatically rolled back, as there is no way to 'handle' a fault at this late stage.  The global transaction participate property is not required to be set.  Likewise the same underlying TopLink session is used for both invokes, meaning if you merge the same object twice, it will only be inserted/updated once.  All merge invokes which set GetActiveUnitOfWork="true" are cumulative.

Related Questions

Can I guarantee that both invokes use the same sql connection?

You cannot guarantee this but you can normally expect it.  If you notice it is not the case, and you are using an XADataSource, you can set the property GetActiveUnitOfWork="true" on all participating invokes.

Does a scope form a transaction boundary?

 No, a scope does not form a transaction boundary.  XA commit/rollback and compensation are really orthogonal to each other.  They ae also a little mutually exclusive.  You should decide on one or the other.
I configured the process for XA but on failure no instance appears in the BPELConsole?
This is actually expected.  The easiest test of whether the global transaction actually rolled back or not is to see if the instance appears in the BPELConsole.  If it appears as faulted that means the transaction was committed anyway, so the auditing to the dehydration store could proceed.

How do you configure transaction participate?

On a child process invoke, set transaction participate on the partnerlink:
         <partnerLinkBinding name="...">
            <property name="transaction">participate</property>
To set the global property, so that a failed invoke will cause the entire transaction to rollback:
        <property name="transaction">participate</property>

How do you throw a rollback fault in bpel?

<throw name="Throw" faultName="bpelx:rollback"/>

How do I find out more about XA?

Please look at the DBAdapter samples 122.DBAdapter/advanced/dmlInvoke/XAInsert, and 122.DBAdapter/InsertWithCatch.

How to make a DBAdapter receive (polling) and invoke part of the same XA transaction?

You must configure the polling DBAdapter to synchronously initiate the BPEL process.  Please see the README for 122.DBAdapter/advanced/endToEnd/DirectSqlPerformance/README.txt for step-by-step instructions.


Post a Comment

Blogger Profile