Skip to main content

Using shared transaction options for nested taskflows even when they use different data sources

Sharing a tip that I learned a couple of days back. Thanks to John Smiljanic for detailing the secret of the magical property that I'm going to talk in this post, also thanks to  Ricky Frost who mentioned about this property in one of the discussion.

Use cases here is not something new, rather an age old requirement only: There are two task flows, both use ADF BC,  one talks to database-1 and this calls another task flow that talks to database-2. Now the developer wants to leverage the declarative transaction mechanism offered by task flow, that is, a commit call on the task flow return should commit changes in both the flows. Wondering what is big the deal here? Well, here is the short answer. The default task flow implementation assumes that when one a task flow shares transaction with another, both uses same data source. In other words, if the AM used in second task flow(callee) uses  different data source, framework will not bother to look up this data source , rather it will ask the AM used in second to reuse the data source looked for the first task flow(calling). At run-time, you may see some object not found error at while executing SQL in second task flow.

There exists a work around solution for the above case. Open the DataBindings.cpx used in the second task flow(callee), scroll down and locate the BC4JDataControl entry for the AM uses in second task flow. In the property inspector, enter some unique literal(logically meaningful) as value for TransactionName. Please see the following xml snippet from DataBindings.cpx.

<BC4JDataControl id="EmpAppModuleDataControl" Package="model.emp"
  SupportsFindMode="true" SupportsRangesize="true" 
  SupportsSortCollection="true" Configuration="EmpAppModuleLocal" 

When this attribute is not defined and a taskflow transaction is started, all BC4J Data Controls in the taskflow share the same transaction/connection if the callee task flow is configured to use existing transaction.  When this attribute(TransactionName) is defined and a taskflow transaction is started, the data control will use a different transaction than the taskflow's default  transaction mechanism.  The named transaction still participates in the taskflow transaction lifecycle, in the same way a Bean Data Control and a BC4J Data Control  both participate in a taskflow transaction. that is the data control will still receive commit or rollback messages on task flow return call.


You can download the sample work-space from here.
[ Runs with Oracle JDeveloper or higher + HR Schema ].

This has two task flows, each use different AMs connecting two different instance of HR data base. To check the above discussed TransactionName property offerings, do the following:

1. Change the connections to point to two different HR schema. 
2. Run the main.jsf. It displays two task flows(dept and employee), each talking to different DB, still sharing same transaction. This implementation works because of  the TransactionName setting in DataBindings.cpx used in the second task flow
3. In the UI Make changes in both department and employees details(they are coming from different task flows, pointing to different DB)
4. On commit, framework commits both task flows


Priyank Khare said…
What if task flows are called dynamically.

Popular posts from this blog

How to set Bind Variable Values at runtime ?

In this post I'm sharing a couple of approaches for programmatically setting bind variables values at run time. This post is an attempt to explain 'When to use what ?'[ In case if you are familiar with 'Bind Variables' in ADF BC, please refer Section 5.10, Working with Bind Variables in Fusion Developer's Guide ]

1. Set the Bind Variable value using RowSet::setNamedWhereClauseParam(...)

You can use use the setNamedWhereClauseParam(...) method on the ViewObject interface (which extends oracle.jbo.RowSet) to set the value for bind variables. Please note this sets the value on default RowSet. In other words, this doesn't have any effect on the secondary RowSets that you/system generates.
ViewObject vo = am.findViewObject("EmployeesView1"); vo.setNamedWhereClauseParam("bindVarDeptId", new Number(10)); vo.executeQuery();
2. Set the Bind Variable value using ViewObject's VariableValueManager::setVariableValue(...)

VariableValueManager Ma…