Skip to main content

Forcing Task Flow instances with Shared Data Control to use different view object instances

If you have have a task flow designed to use shared data control, and still don't want different instances of task flows to use same view object instances, then this post is for you.

Use case: Multiple instances of task flow should share same transaction context, however each UI should work independently when they are embedded in a parent page. As of now, there is no direct support for this. In this post I'm sharing a work around solution for this kind of scenario.

Solution: As I said earlier, this is just a work around solution, and intended to give you some idea on the implementation. Feel free to modify the code in the attached sample to meet your use cases.

Step 1. Edit the iterator used for for those pages fragments which needs to work independently, and alter binding for the view object instance used for this iterator to use an EL. EL takes the view object instance name from a PageFlow scoped variable.

 <iterator Binds="#{pageFlowScope.VOInstName}" RangeSize="25" DataControl="AppModuleDataControl" id="DepartmentsView1Iterator"/>  

Step 2. The PageFlow scoped variable that stores view object instance name used in the EL(step1 ) is populated from task flow initializer with some unique names. Task flow has a default method activity defined which will create corresponding view object instance in the Application Module before showing the page.

Download

You can download the sample workspace from here.
[Runs with Oracle JDeveloper 11.1.2.0.0 (11g R2) + HR Schema]

A glance at the implementation

Run main.jsf.
This page contains multiple instances of dept-task-flow-definition. However the page fragment used in each instances of task flow works independently using different view object instances eve though the dept-task-flow-definition has shared Data Control scope. This is done using the above idea. Take a look at TaskFlowDCHelper class to learn more about the implementation. Method TaskFlowDCHelper::initDataSource() generates the view object instance name for each instance and the same is set as initializer for dept-task-flow-definition. Method TaskFlowDCHelper::cleanupDataSource() is set as finalizer for task flow.

Comments

Anonymous said…
Where do removeVO method execute?
or ... How can i implemnent it? (when taskflow change i.e.)
Jobinesh said…
One possible place could be taskflow finalizer
Anonymous said…
certainly, a very good post
Thanks
AM said…
I tried on 12c and got the following error: <ADF: Adding the following JSF error message: Object #{pageFlowScope.voInstName} of type View Object is not found.
oracle.jbo.NoObjException: JBO-25003: Object #{pageFlowScope.voInstName} of type View Object is not found.

I have double-checked that the pageFlowScope variable names that the bean puts the vo_name and vo_def_name are the same as the ones being passed to the am method binding.
AM,
I could see the sample attached in the post working on 12.1.3.0.0. May be you can try the sample attached in the post and compare that with yours
AM said…
Just downloaded and tried the sample. Weirdly for me on JDEVADF_12.1.2.0.0_GENERIC_130608.2330.6668 it seems the task flow instances don't seem to have their separate view object instances. When I change the department name from Shipping to Ship in one table and select another record, the new change reflects in all tables.
Oh OK. That behavior is expected because all the instances of the view objects in this example are based on same Entity Objects. so the changes would be reflected across all VO instances. This post discusses a use case where one may need to have different representation of same collection(based on different filtering logic), Not separating out the changes to individual VOs. In such case, you may really want to have isolated data control
AM said…
Hello Jobinesh, thanks for the clarification. So, the query collection and row set remain the same for all vo instances, only that each tf has its own independent rowset iterator?
Yes, you are right !
The blog post provides a work around solution for use cases where customer wanted to share same DC, but when used theses task flows in the UI multiple times, each one needs to work with its own collection instance.

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…