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!!!!