Bounded Task flow ‘Transaction’ & ‘Share DC’ properties

-> Data Control scope [Shared/Isolated] & Transaction Options:
If bounded taskflow Overview -> behavior -> check box ‘shared data controls with calling Tf’ is Not checked means that this taskflow get its own data control frame. means having Isolated data controls.
If the property is checked means BTF uses the parent page(calling page) datacontrol frame instead creatig a new one.

Refer- Share data controls behavior [same data to be displayed on base page and region present it]:
https://tompeez.wordpress.com/2012/07/27/jdeveloper-adf-carefully-select-the-data-control-scope-of-bounded-task-flows/

Refer- (Transaction optios& datacontrol scope options): http://www.oracle.com/technetwork/developer-tools/adf/learnmore/adf-task-flow-trans-fund-v1-0-1723395.pdf?bcsi_scan_510c2960d4f4e50e=5IfxgIvC5gAAdZN467HNcuezvLAFAAAA7KQgLA==&bcsi_scan_filename=adf-task-flow-trans-fund-v1-0-1723395.pdf

Eg: Let’s take a basepage and display departments as readonly table. Keep two buttons to call two different bounded taskflows. for BTF1 keep the datacontrols scope proeprty to ‘shared’. So when you navigatte from basepage to BTF1 on click of button1 then the row selection in basePage will be maintained here also. Now chagne row and navigate back to basePage, again the row selection is mainainted. This is because by keeping the option to ‘shared’ will use the same datacontrol instance/frame.
Now for BTF2 keep the datacontrol proeprty to ‘isolated’ and call this BTF2 on click on button2 from base page. when you naviagate from basePage to BTF2 row selection is not maintained. Now chagne row and naviagate back to the basePagea again you can see row selection in basePage is different from selected row in BTF2. Beacause we set the datacontrol option to Isolated, it creaetd two different datacontrol instances for basepage and BTF2. [BTF2 is not using the basepage instance]
Note: 1)In above example the transaction property is left default which is “<No Controller Transaction>”
2) You can have N number BTF calling chain having datacontrol option as isolated/shared for each.
eg: UnboundedTF -> BTF1(shared) -> BTF2(isolated) -> BTF3(isolated) -> BTF4(shared)
In the above flow BTF1 uses the UTF’s datacontrol instacne (for matching datacontrols metadata)
BTF2 creates its new datacontrol instacne.
BTF3 creates its new datacontrol instacne.
BTF4 uses the BTF3’s datacontrol instacne (for matching datacontrols metadata)
3) if base page has Employee table and it is calling a BTF whose data control property is ‘shared’ and which has a page showing Departments table. Here though you set datacontrol property to ‘shared’ for BTF, as there are no datacontrol in BTF which present in basePage, a new datacontrol instance/frame will be created for the BTF.
We need to undertand from here is that datacontrol can be shared only if the metadata of datacontrol is same in current page and calling BTF. datacontrols meta data is present in page definition files.
4) (Not sure, mostly correct) Now let’s take another example, base page showing employees table and it is calling a BTF whose datacontrols property is set to ‘shared’ and which is having a page showing ‘Employees table’ and ‘departments’ table and ‘Jobs’ table. Now in this case only employees datacontrols are sahred and when you navigate from base page to BTF you can see the row selection will be maintained. but for deaprtments, jobs datacontrols it creates a new datacontrolFrame/ datacontrol instance as the department datacontrol, jobs datacontrol metadata is not present in parent page. the created dataControlFrame has datacontrols of departments, jobs only. Employees datacontrol will be taken from the existing dataControlFrame

5) So far we discussed about this property (Share data control with calling TF) behavior when navigating from one UBT/BTF to other BTF.
But this can also be used when you have differnt BTFs and they are present in a page as regions. If you set ‘shared data control with calling TF’ property to both the TFs present in the page then, selecting in one TFs table/row will be also change the current row in otehr TF if both have common data controls.

->
Transaction Options:
bounded taskflow Overview -> behavior -> Transaction drop down
‘No Controller Transaction’
‘Always Begin New Transaction’
‘Always Use the Existing Transaction’
‘Use the Existing Transaction If Possible’

Note: 1) Is transaction is open/Not for a datacontrol frame will be known to the framework by using method ‘ DataControlFrame.getOpenTransactionName()’
2) DataControlFrame also contains commit(), rollback() methods. Note that these are not the data control’s associated commit and rollback operations. DataControlFrame contains many datacontrols and the commit/rollbak methods in it applies to all the datacontrols in it.


Always Begin New Transaction:
Transaction (Always Begin New Transaction) + Datacontrol Scope (Isolated) => Valid
Transaction (Always Begin New Transaction) + Datacontrol Scope (Shared ) => throw error “ADFC-00020 + Task flow ‘<name>’ requires a new transaction, but a transaction is already open on the frame” at runtime.

If this option is set then, TF must call a Taskflow Return activity with ‘End Transaction’ property to ‘Commit/Rollback’ options.

Always Use the Existing Transaction:
Transaction (Always Use Existing Transaction) + Datacontrol Scope (Shared) => Valid
Transaction (Always Use Existing Transaction) + Datacontrol Scope (Isolated) => throw error “ADFC-00006: Existing
transaction is required when calling task flow <task flow name>” at runtime.

If this option is set then, TF SHOULD NOT call a Taskflow Return activity with End Transaction property to ‘Commit/Rollback’ options. If you do so, at design time only the return activity will be flagged as error and agt run time they’ll be ignored. You can set the return activity ‘End Transaction’ property to ‘None’.

Use the Existing Transaction If Possible: [If you are not sure about parent transaction, choose this option]
Transaction (Use Existing Transaction if Possible) + Datacontrol Scope (Isolated) == Transaction (Always Begin New Transaction) + Datacontrol Scope (Isolated)
Transaction (Use Existing Transaction if Possible) + Datacontrol Scope (Shared) (If datacontrol frame of parent has Open the transaction) then == Always Use Existing Transaction + Shared
Transaction (Use Existing Transaction if Possible) + Datacontrol Scope (Shared) (If datacontrol frame of parent has not Not Open the transaction) then == Always Begin New Transaction + Shared

Let’s see an example (here arrow (->) means navigaiton (calling))
UTF -> BTF1 (TXN-exisitng) -> BTF2 (TXN-New) -> BTF3 (TXN-New) -> BTF4 (TXN-exisitng)

BTF1: it uses exisitng transaction. uses same AM instance of UTF. [I assume dataControl proeprty is shared]
BTF2: it begins new transaction. new AM isntance created. so it must call taskflow return with End transaction prperty as Commit/Rollback [I assume dataControl proeprty is Isolated]
BTF3: it begins new transaction. new AM isntance created. so it must call taskflow return with End transaction prperty as Commit/Rollback [I assume dataControl proeprty is Isolated]
BTF4: it uses exisitng transaction of UTF. Here you can not set ‘End Transaction’ property of taskflow return activity to commit/rollback. it should be default (none). Once control is returned to UTF then from there you can commit/rollback.
When you commit int UTF now, then data changed in UTF& BTF4 will get committed. (BTF2, BTF3 data has to be committed there itself).
If you do not set the Transaction property to the BTF then Transaction will not be started. And if perform any transaction events, then you get run time exception.
————————————–
-> <No Controller Transaction>: The called bounded task flow does not participate in any transaction management.
-> Always Use Existing Transaction: When called, the bounded task flow participates in an existing transaction already in progress.
-> Use Existing Transaction If Possible: When called, the bounded task flow either participates in an existing transaction if one exists, or starts a new transaction upon entry of the bounded task flow if one doesn’t exist.
-> Always Begin New Transaction: A new transaction starts when the bounded task flow is entered, regardless of whether or not a transaction is in progress. The new transaction completes when the bounded task flow exits.
————————————–
Programatically call a DataControl frame and commit one datacontrol in it.

BindingContext bc = BindingContext.getCurrent();
String dcfName = bindingContext.getCurrentDataControlFrame();
DataControlFrame dcf = bc.findDataControlFrame(dfcName);
dcf.commit(); // or dcf.rollback();
——————————————–

References:

http://www.oracle.com/technetwork/developer-tools/adf/learnmore/adf-task-flow-trans-fund-v1-0-1723395.pdf?bcsi_scan_510c2960d4f4e50e=MK7LAETxsnA5rjnzFCVS1zXfnVgHAAAA/0s/QA==&bcsi_scan_filename=adf-task-flow-trans-fund-v1-0-1723395.pdf

 

Advertisements

Task Flow Refresh property

Let us discuss about this property with real time examples:

Example 1:

-> Let’s take a requirement, there is a base page and it has two regions(BTFs). If you update data in one region, it should update the data in other region. [be clear that there is no navigation from one one region (BTF1) to other region (BTF2), so DC scope could be anything isolated or shared, that doesn’t matter as BTF2 will creates new datacontrol frame and won’t use BTF1s datacontrol frame as there is no navigation from BTF1 to BTF2. so setting DCScope for BTF2 to shared really doesn’t matter. You also note that BTF1, BTF2 are present inside base page(UTF) so if you set DCScope to shared for them, then they may use the exisitng datacontrol frame created by UTF for the common datacontrols present in BTFs and UTF. In this example assume data in base page and BTFs is different. But BTF1 and BTF2 displaying same data from DB]

-> On updating data and save it commits data to DB in BTF1, and then as BTF2 also displaying same data, it should be refreshed and show updated data. [if BTF1 is displayed first and then if it is calling BTF2 then by using DC Scope to ‘Shared’ you can get latest data from BTF1. but here requirement is to display BTF1 and BTF2 both in same page and there is no navigation from BTF1 to BTF2]

-> To do this, we have to use the ‘Refresh’ property available for the BTF bindings in the base page. Set the Refresh property for BTF2 binding to ‘If Needed’ in base page bindings.  So what it will do is, if there is any change in the input parameters value of BTF2, then it refreshes the entire BTF2 taskflow.

-> So lets create a dummy input parameter to BTF2 and let’s change its value every time we click on ‘save’ button in BTF1.  [TF parameters -> Name: refeshFlag, class: java.lang.String, Value: #{pageFlowScope.refreshFlag}] so what ever value we assign to parameter ‘refeshFlag’ it stores into the page flow scope and makes it available through out the taskflow.

-> So on click of ‘save’ button using property listener, store some unique value (current time) to a scope variable #{sessionScope.refreshFlag}. Now we need to assign this value to the TF input parameter ‘refeshFlag’ in the base page bindings. Which then internally stores into #{pageFlowScope.refreshFlag} and makes it available through out TF. Of course we do not want that value, we just created input parameter only because if we change the input parameter value along with refresh condition to ‘ifNeeded’, it’ll refreshes the taskflow.

-> Use sample code below to generate unique value (current time) on click on save button in BTF1 and assign to a scope variable #{sessionScope.refreshFlag}.

<af:button text=”save” actionListener=”#{bindings.Commit.execute}”><af:setPropertyListener type=”action” from=”#{backingBeanScope.RefreshHelperBean.refreshToken}”  to=”#{sessionScope.refreshFlag}” /></af:button>

Bean code:  

public class RefreshHelper{

public RefreshHelper(){

super();

}

public String getRefreshToken(){

return String.valueOf(System.currentTimeMillis())

}

}
-> Now so far with our code what will happen is on click on ‘save’ button in BTF1, the current time will be fetched from system (which will be alway unique) and wil be assigned to #{sessionScope.refreshFlag}. As this value ‘#{sessionScope.refreshFlag}’ is given as value for the input paramter ‘refeshFlag’ of BTF2, it will be assigned to the refreshFlag parameter which stores into #{pageFlowScope.refreshFlag} which we defined in BTF2. As the value is changed for the input paramter of BTF2, the BTF2 refreshes.

-> We achieved our requirement right? Not completely, our requirement is not only to refresh the region but along with that we want to fetch latest data from DB again. [note: just refresh will not fetch latest data from DB]. so fetch latest data from DB, we need put execute action method before the jsff fragment in BTF2 and make it as default activity.  So whenever the input parameter value for BTF2 changes, it refreshes the BTF2. so it executes the ‘execute’ method action every time it refreshes.   So we get the latest data from DB which will appear in the page.

5.png
Note: If you set refresh=”ifNeeded” for BTF2 and not set any input paramers, is same as refresh=”default”, means it doesn’t refresh BTF2 [The BTF2 will be refreshed only once when the base page is loaded.]
—————

Example 2:

-> Now take another simple example so that you get more clear about this.There is a base page and it has a region (BTF). Base page displays departments table. On selecting a row in departments table should display the department name in the (BTF).
-> To implement above requirement first base page should contain the departments table ‘tree binginds’ along with ‘department id’ attribute binding [#{bindings.DepartmentId.inputValue}]. the BTF region should contain attr binding #{bindings.DepartmentName.inputValue}.
-> Now create an input parameter for BTF [TF parameters -> Name: deptFlag, class: java.lang.String, Value: #{pageFlowScope.deptFlag}]-> in the base page for BTF bindings set the Refresh proepty value to ‘ifNeeded’ and also set the input parameter  ‘deptFlag’ value to  #{bindings.DepartmentId.inputValue}.-> DCscope for BTF will be by default ‘shared’, so keep to shared/ default (do not set to isolated -means unchecking shared).

-> So when you click a row in the table, current for the table will be the selected row. As we have attr bindigns #{bindings.DepartmentId.inputValue} in the page, the value for that will be changed according to the current row. The same value we have assigned to the BTF input parameter ‘deptFlag’. So the input paramter deptFlag’s value will be updated. As we have refresh condition also set to ‘ifNeeded’ and input paramete value changed, the BTF will be refreshed.

-> BTF contains #{bindings.DepartmentName.inputValue} binding, which it tries to get it from the base page as the BTF DCScope is ‘shared’. As the currnet row changed in base page the value for #{bindings.DepartmentName.inputValue} will also be acoording to the current row, so the selcted row’s department name will be displayed in the BTF region.

-> the BTF input paramter value will be stored to #{pageFlowScope.deptFlag}, which we have not used to display anywhere in BTF. The input parameter here is only used for the purpose of BTF refresh. we are not dealing with its value anywhere.

-> If there are no rows in the table, then no value will be assigned to BTF input param, so it displyas value as null for #{bindings.DepartmentName.inputValue}.

Note: In the example we have added bindigns ‘#{bindings.DepartmentId.inputValue}’ to the base page. you can add any att binding of the table and assign to the input parameter of BTF, that doesn’t make any difference.
—————

References:

http://andrejusb.blogspot.in/2015/04/simple-effective-refresh-approach-for.html

http://www.oracle.com/technetwork/developer-tools/adf/learnmore/53-taskflow-in-popup-169196.pdf