SOA Suite 11g - Transaction(s) & boundaries; Part One

As we added new/updated components I figured it'd be wise to post a little bit about transaction semantics in 11g - and how they can be used to leverage the underlying JTA infrastructure that is backing the execution of components.

a) Mediator:
On the inbound side, when mediator is invoked via binding.ws it will create an manage a new transaction, otherwise (e.g. if invoked through an adapter it will inherit the existing transaction)

In more generic terms:
If a transaction is present, Mediator participates in that existing transaction. If transaction is not present, Mediator starts the transaction

In case of sync (aka sequential) routing rules, they will be all executed in the same transaction, and if an error occurs, a rollback will be issued.
Note: in this case even a fault policy that is configured against a mediator fault will NOT trigger.

In case of async routing rules, each rule will be executed in a new transaction, and if errors occur, a rollback will happen, and a fault policy can be configured to react to it.

b) BPEL:
By default (as in previous releases) BPEL will create a new transaction on request basis - that is if one already exists, it will be suspended, and a new one created. Upon completion of the child, the master one resumes.
However, if the request is async (that is one-way) we either inherit the transaction for the insert into the dehydration store (that is dlv_message in this case) or if one exists enlist transparently into it. So we guarantee you zero message loss. Either the invocation message is in the dehydration store, to be processed, or otherwise the consumer is notified via a fault.

In 10.1.3 we had a couple of flags that one could set on the consuming process (that is the partnerlink) as well as on the providing one, to chain an execution into a single global transaction. Namely, on the consumer side, one had to set transaction=participate on the partnerlink binding in bpel.xml, and on the providing side transaction=participate in the <configurations> section of bpel.xml.
In 11g BPEL - we adopted a more j(2)ee alike concept - and one only needs to set the (new) transaction flag on the calee bpel component. This can be done in the composite editor's source by adding bpel.config.transaction into a bpel component - as shown below


<component name="InternalWarehouseService">
<implementation.bpel src="InternalWarehouseService.bpel"/>
<property name="bpel.config.transaction"
many="false" type="xs:string">required | requiresNew</property>
</component>

The two possible values are required, which makes BPEL inherit the tx that is already there, or if not creating a new one (required), or suspending one if exists, and ALWAYS create a new one (requiresNew).

What are the implications of setting the above (the default is requiresNew)?

Case one - BPELCaller calls BPELCallee (the latter has requiresNew set)
a) BPELCallee replies (that is uses <reply>) with a fault: BPELCallee transaction is saved, BPELCaller get's the fault and can catch it
b) BPELCallee throws (that is uses <throw>) a fault, that is NOT handled: BPELCallee tx get's rolled back, BPELCaller get's the fault and can catch it
c) BPELCallee replies back with a fault (FaultOne), and then throws a fault (FaultTwo): BPELCallee tx get's rolled back, and BPELCaller get's FaultOne
d) BPELCallee throws (that is uses <throw>) a bpelx:rollback fault: BPELCallee tx get's rolled back, BPELCaller get's a remote fault

Case two - BPELCaller calls BPELCallee (the latter has required set)
a) BPELCallee replies (that is uses <reply>) with a fault: BPELCaller get's the fault and can catch it, BPELCaller owns the transaction - hence if he catches it - tx is committed, if BPELCaller does not handle it - global rollback.
b) BPELCallee throws (that is uses <throw>) a fault BPELCaller get's the fault and can catch it
c) BPELCallee replies back with a fault (FaultOne), and then throws a fault (FaultTwo): BPELCaller get's FaultOne
d) BPELCallee throws (that is uses <throw>) a bpelx:rollback fault: BPELCaller tx get's rolled back, no way to catch it.

So with the above in place - one thing that I usually have people try when they are in my 11g courses is to create two processes (BPELMaster and BPELChild), both sync, each using the same db adapter reference that inserts the same record (and hence causes a PK violation). (And of course has set xADatasourceName)

So what happens in the default (that is without bpel.config.transaction property set). Once the fault occurs, and is not handled - the BPELChild will rollback. If the BPELMaster has a catch block his transaction will commit, so you end up with the record from the Master in the db.

If you don't catch the fault in the master as well - you get a second rollback - two different transactions though :-)

The second exercise is to set the bpel.config.transaction to required, and run the testcase again. If no fault handlers are in place - the whole tx will rollback, based on the BPELMaster's unhandled fault.

Now add a fault handler in the BPELMaster to catch the Fault from the BPELClient - and throw up a rollback fault. Globally the tx will rollback as well.

With this in place - you can really control transaction boundaries and model end2end transactional flows (if your source / targets are transactional as well of course)

Comments:

Dear Clemens, Thank you for the post, brings wonderful clarity. Is there a way I can force rollback upto a certain point in the called process? I have tested a scenario having the bpel component two disparate target - one jms queue post followed by a database insert. It works fine. However, in case of a rollback, say I want to post another (error) message in the same queue. But it seems everything from called process would be rolled back. I tried different things, posting the error message from a catch-all block, attempting a checkPoint() call first). Seems the only way would be handling the error from callee, whereas ideally it would be more meaningful to have the logic inside the called component. Regards, sibendu

Posted by Sibendu on March 04, 2010 at 03:38 PM PST #

Dear Clemens, Thank you for the post, brings wonderful clarity. Is there a way I can force rollback upto a certain point in the called process? I have tested a scenario having the bpel component two disparate target - one jms queue post followed by a database insert. It works fine. However, in case of a rollback, say I want to post another (error) message in the same queue. But it seems everything from called process would be rolled back. I tried different things, posting the error message from a catch-all block, attempting a checkPoint() call first). Seems the only way would be handling the error from callee, whereas ideally it would be more meaningful to have the logic inside the called component. Regards, sibendu

Posted by Sibendu on March 04, 2010 at 04:38 PM PST #

Hey Sibendu. If you want to use a global transaction, and rollback - you can do so by using the above means. Error handling has to be in the caller then, because we will NOT allow you to do anything else in the process instance. So one way to do this is to encapsulate the transaction into a sub process - bubble the fault up into the master (which has its own tx) and handle it there.

Posted by Clemens on March 04, 2010 at 04:48 PM PST #

Thank you very much once more for quick clarification, Clemens; saves my further effort to explore if I was missing some controls knobs. regards.

Posted by sibendu on March 04, 2010 at 06:53 PM PST #

Hi Clemens, This worked fine in 11.1.1.1.0. But not working in 11.1.1.1.3. Do we need to do any extra configuartion for 11.1.1.1.3? Regards Pavankumar.M

Posted by PavanKumar on July 02, 2010 at 05:47 PM PDT #

can you qualify what does NOT work? what are you seeing?

Posted by clemens.utschig on July 03, 2010 at 04:06 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Tips and tricks straight from the SOA / BPM development team at Oracle HQ

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today