Monday, March 22, 2010

Understanding Task Flow Transaction and Savepoint Support in Oracle ADF

This article is based on Steve Muench's "Not Yet Documented ADF Sample #140" and you can download his sample code here.

JDeveloper 11.1.1.2.0 is used in this demonstration. To get what is shown here, you need to modify code snippets in PageTemplate.jspx and create-department.xml on the ViewController project.

Change PageTemplate.jspx from :
<f:facet name="center">
<af:panelHeader text="#{attrs.PageTitle}"
inlineStyle="background-color:White;" id="pt_ph1">
<f:facet name="context"/>
<f:facet name="menuBar"/>
<f:facet name="toolbar"/>
<f:facet name="legend">
<af:facetRef facetName="ButtonArea"/>
</f:facet>
<f:facet name="info"/>
<af:facetRef facet/Name="MainArea"/>
</af:panelHeader>
</f:facet>

to:
<f:facet name="center">
<af:panelHeader text="#{attrs.PageTitle}"
inlineStyle="background-color:White;" id="pt_ph1">
<f:facet name="context"/>
<f:facet name="menuBar"/>
<f:facet name="toolbar"/>
<f:facet name="legend">
<af:facetRef facetName="MainArea"/>
</f:facet>
<f:facet name="info">
<af:facetRef facetName="ButtonArea"/>
</f:facet>
</af:panelHeader>
</f:facet>
Change create-department.xml from:
<task-flow-return id="Cancel">
  <outcome>
    <name>Cancel</name>
    <rollback/>
  </outcome>
</task-flow-return>

to:
<task-flow-return id="Cancel">
  <outcome>
    <name>Cancel</name>
    <rollback/>
    <restore-save-point/>
  </outcome>
</task-flow-return>


Before proceeding, adjust the properties of the scott connection in the Application Resources zone of the Application Navigator until you can successfully test a connection to a SCOTT schema. If you need to create the tables, use the provided CreateDeptEmpTables.sql.

Task Flow Transaction

Task flow transaction is different from database transaction (I mean the transaction returned by am.getDBTransaction()). Each task flow is associated with a data control frame. A data control frame is the container associated with a task flow that contains multiple data control instances. The ADF Model layer exposes the DataControlFrame interface to manage a transaction in which the data controls within the frame participate. DataControlFrame interface exposes methods such as:
  • beginTransaction()
  • commit()
  • rollback()
  • createSavepoint() -- Note that this is the savepoint maintained by the Oracle ADF Controller and is similar to database-level savepoint
  • isTransactionDirty()
To handle nested task flows, task flow transaction provides a high-level implementation using ADF Controller transaction across task flow boundaries. As a Fusion application developers, it is essential to understand what happens when commit or rollback in a nested task flow is issued.

Data changes can happen at different levels. Let's use Cancel as an example. With the cancel operation, data changes could be in four possible states:
  1. The user didn't change a value
  2. The user changed a value but this hasn't been submitted to the model
  3. The user has changed a value and the change has been submitted to the model but hasn't been persisted to the database.
  4. The user has changed a value; the change has been submitted to the model; and the change has been persisted to the database.
In this article, we will examine what happens when task flow returns with either commit or rollback property set. Specifically, we will discuss in which layer that data have been updated:
  • UI layer
  • Model layer
  • Database layer

Task Flow Transaction

There are four transaction options that a bounded task flow can use (note that unbounded task flow doesn't support transaction):
  1. No Controller Transaction: The called bounded task flow does not participate in any ADF Controller transaction management.
  2. 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.
  3. Always Use Existing Transaction: When called, the bounded task flow participates in an existing transaction already in progress.
  4. 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.
There are three task flows in the sample implementation:
  1. manage-employees task flow: it has its transaction property set to Always Begin New Transaction to indicate that it should only be used as a top-level task when no other current transaction is in effect.
  2. modify-employee task flow: it has its transaction property set to Always Use Existing Transaction to indicate that it only makes sense to be called as part of an existing transaction (but cannot be called on its own), since it requires parameters to work correctly.
  3. create-department task flow: it has its transaction property set to Use Existing Transaction if Possible which allows it to be used either as a top-level transactional flow, or else as a part of another task flow with a transaction already in effect.

Data Control Scope

For each task flow that has data to be committed, you need to set data-control-scope property in the task flow in addition to the transaction property.

data-control-scope property is used to specify whether data control instances are shared between the calling and called task flows. You must set a data-control-scope value of either shared or isolated on the called bounded task flow. shared is the default value.

Based on the settings of data-control-scope and transaction properties, the following table summarizes the runtime behaviors of created task flow:






























Transaction
Setting
Share
Data Control Scope

Isolate
Data Control Scope
No Controller TransactionThe DataControlFrame is shared without an open controller transactionA new DataControlFrame is created without an open controller transaction
Always begin new transactionIf a transaction is already open, throws an exception; otherwise, begins a new transaction.Always begins a new transaction.
Always
Use Existing Transaction
Throws an exception if the
transaction is not already open.
Invalid.
Use
Existing Transaction if Possible

Begins a new transaction if one
is not already open.
Always begins a new transaction.
The most important rule to remember is:
  • Data control instances cannot be shared across more than one Controller transaction at the same time.

Examining the Runtime Behavior of Task Flows

In this article, we'll examine an application flow that consists of all three task flows in the sample code:
  1. manage-employees task flow
  2. modify-employee task flow
  3. create-department task flow
From the home page, select Manage Employees:

This will launch manage-employees task flow which has the following setting:
  • transaction option = "Always Begin New Transaction"
  • data-control-scope = "shared task flow with calling task flow" (This is the default value)
A new data control frame was created for the ADF unbounded task flow. manage-employees task flow will begin a new transaction and share the data control frame with calling task flow (i.e., unbounded task flow).

On Manage Employees page, specify Smith in the search field and click the arrow button. This brings up Smith's record in the table:


Let's click Edit button and this will launch modify-employee task flow which has the following settings:
  • transaction option = "Always Use Existing Transaction"
  • data-control-scope = "shared task flow with calling task flow"
Before we modify any value on Smith's record. Let's click Add New Department button. This will launch create-department task flow which has the following setting:
  • transaction option = "Use Existing Transaction if Possible"
  • data-control-scope = "shared task flow with calling task flow"
Up to now, all three task flows share the same data control frame and transaction. On Create Department page, let's create a new department named Finance:

Notice that there are two buttons (i.e., OK and Cancel) which can trigger two different Task Flow Return Activities, which are set up this way:
  • OK button
    • End Transaction = "commit"
    • Restore save point = "false"
  • Cancel button
    • End Transaction = "rollback"
    • Restore save point = "true"
Because create-department task flow participates in an existing transaction, an implicit savepoint will be created when the task flow is entered. So, what Cancel needs to do is just restore to the previous save point and what OK needs to do is nothing because we don't want to commit the whole transaction yet.

So, the new Finance record will be seen in:
  • UI layer and model layer, but not database layer if OK button is pressed
  • None of the layers if Cancel button is pressed
Let's click OK button and return to the Edit Employee page. Notice that the new department Finance is shown on the dropdown list:
On Edit Employee page, let's enter "10" in Comm field. After doing that, we can click on either OK or Cancel button. For OK button, it will trigger a Task Flow Return Activity with the following settings:
  • End Transaction = "none"
  • Restore save point = "false"
while Cancel button will trigger a Task Flow Return Activity with the following settings:
  • End Transaction = "none"
  • Restore save point = "true"
Because modify-employee task flow is set up with a transaction option: Always Use Existing Transaction, an implicit save point will be saved when the task flow is entered. So, what Cancel needs to do is just restore to the previous save point and what OK needs to do is nothing because we don't want to commit the whole transaction yet.

If you click on Cancel button at this point, it will restore to a previous save point when modify-employee task flow is entered. That means our new Comm field and new Department record will all be canceled.

If you click on OK button at this point, on the Manage Employees page, you will find the new Comm value (i.e., 10) for Smith.


Notice that new changes have not been persisted to database layer yet. The new Comm value and new Department record have only been saved in model layer.

On Manage Employees page, there are also two buttons: OK and Cancel. For OK button, it will trigger a Task Flow Return Activity with the following settings:
  • End Transaction = "commit"
  • Restore save point = "false" (default)
So, if you click on OK now, all changes will be persisted to the database layer.

For Cancel button, it will trigger a Task Flow Return Activity with the following settings:
  • End Transaction = "rollback"
  • Restore save point = "false" (default)
So, if you click on Cancel now, all changes will be rolled back.

Page Refresh

In this article, we saw changes on one page was reflected on another page (i.e., referred to as UI layer update). Sometimes this happens automatically and sometimes you need to set it up appropriately. The issue of how to refresh a page or region to reflect changes in model layer or database layer is another interesting topic.

Read More...

  1. A Ride at the OK (or Cancel) Corral by Steve Muench
  2. Oracle Fusion Middleware Fusion Developer’s Guide for Oracle Application Development Framework 11g Release (11.1.1)
  3. Book Review: Developing Web Applications with Oracle ADF Essentials (Xml and More)

5 comments:

sai_explorer said...

Your blog was very helpful .It has cleared most of my doubts on transaction management with Task flow

Jobinesh Purushothaman said...

Nice One!Please keep blogging

Anonymous said...

Your blog very helpful and clear, but I tried to refer to sample code but Unfortunately its not existed, please can provide us correct link for sample.

Thanks too much

Travel for Life said...

A Ride at the OK (or Cancel) Corral http://www.oracle.com/us/technologies/virtualization/oraclevm/o29frame-088050.html

Unknown said...

Your blog is very useful and understandable by even the beginners.The way of presentation is very good and elaborate.Looking forward for your work on fusion web applications.
sap upgrade tool