Wednesday, 15 November 2017

Demystifying getActiveUnitofWork property of DB Adpater

Here in this I am going to discuss one of the interaction options available in Database adapter configuration, getActiveUnitofWork
The property is defined in Oracle Adapter guide as below

GetActiveUnitOfWork is an advanced JCA 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. Similarly, the same underlying TopLink session is used for both invokes, meaning if you merge the same object twice, it is inserted/updated once. All merge invokes that set GetActiveUnitOfWork as true are cumulative.
Set GetActiveUnitOfWork to true when making multiple incremental changes to the same record across multiple invokes in the same SOA instance.GetActiveUnitOfWork ensures that all Database Adapter invokes which participate by setting the option to true, and which are within the same JTA transaction, and to the same eis/DB/ instance, use the same EclipseLink session for all operations. For EclipseLink-based operations (excluding stored procedures and pure SQL) all writes are deferred until JTA before Completion.
This means if you insert/merge the same object in two invokes, it is written once. Since EclipseLink-based writes are deferred, a select all may not conform to previous invokes which did writes. Selects by primary key conform, however. As writes happen inside the JTA callbacks, there is no way to handle exceptions which occur at that time and BPEL's global transaction will unexpectedly fail.GetActiveUnitOfWork is frequently used to guarantee that operations on two invokes used the same physical SQL connection.
I have performed some POCs to check the behaviour of this property and below are some scenarios
Case 1- Here in this scenario, two consecutive insert operations insert1, and insert2 are being performed to insert data in tables of a XA data source. Both operations are being performed in the same BPEL and hence the same transaction.

If getActiveUnitOfWork=false, insert1 will be committed even when insert2 fails
If getActiveUnitOfWork=true, insert1 will be rolled back when insert2 fails. As roll back fault can’t be handled using catch or catchall, instance audit trail will not be visible on em .

Note- Rollback fault in the callee BPEL can only be handled in caller BPEL if both exist in different transactions. In case of different transactions, this fault will be captured in the caller BPEL as a remote fault which can then be handled using catch block.

Case 2- In this scenario, BPEL1 has the logic of insert1, to insert data in table of a XA data source, followed by an invocation to BPEL2. BPEL2 has insert2 to insert data in table of a XA data source. Both operations are being performed in the different BPELs which can participate in both different/same transaction. Following are the possibilities explored by me-

      1)     When, bpel.config.transaction=RequiresNew
       bpel.config.oneWayDeliveryPolicy=sync
       getActiveUnitOfWork=true
       Faults are handled in both BPEL1 and BPEL2

As both BPEL 1 and BPEL2 execute in different transactions, when INSERT2 fails INSERT1 gets committed. Fault is not caught in BPPEL2. Remote fault is thrown to BPEL1 which is handled

     2)     When, bpel.config.transaction=Required
      bpel.config.oneWayDeliveryPolicy=sync
      getActiveUnitOfWork=true
      Faults are handled in both BPEL1 and BPEL2

When INSERT2 fails, INSERT1 is automatically rolled back. The rollback error can’t be handled in BPEL1 as both BPEL1 and BPEL2 are in same transaction.

     3)    When, bpel.config.transaction=Required
     bpel.config.oneWayDeliveryPolicy=sync
     getActiveUnitOfWork=false

When INSERT2 fails, INSERT1 gets committed.
If fault is not handled in BPEL2, fault of BPEL2 gets promoted to BPEL1 and can be handled in BPEL1.
I fault is caught in BPEL2, both BPEL1 and BPEL2 gets completed with only INSERT1 executed successfully.
   
   4)    When, bpel.config.transaction=RequiresNew
    bpel.config.oneWayDeliveryPolicy=sync
    getActiveUnitOfWork=false

When INSERT2 fails, INSERT1 gets committed.
If fault is not handled in BPEL2, fault of BPEL2 gets promoted to BPEL1 and can be handled in BPEL1.
If fault is caught in BPEL2, both BPEL1 and BPEL2 gets completed with only INSERT1 executed successfully.

 HAPPY LEARNING!!!!

Demystifying getActiveUnitofWork property of DB Adpater

Here in this I am going to discuss one of the interaction options available in Database adapter configuration, getActiveUnitofWork The p...