2012年8月14日星期二

ADF_200:Task Flow使用指南之九:Remote TaskFlow

运行环境:JDeveloper 11.1.2.2.0 + Oracle Database 10g Express Edition 10.2.0.1。

试想一下这种情况:一个人部署了一个ADF应用,其中包括一个Bounded TaskFlow,另一个人想在自己的应用调用该TaskFlow。

重要步骤说明:

1. 创建Remote TaskFlow Producer
详细步骤请参考《Task Flow使用指南之四:获取Task Flow返回值(1)》。
这里为了保证Remote TaskFlow Producer应用是正确的,在该应用中增加了调用TaskFlow的页面和逻辑。
唯一要注意的地方是:设置URL Invoke=url-invoke-allowed


2. 创建Remote TaskFlow Consumer
详细步骤请参考《Task Flow使用指南之四:获取Task Flow返回值(1)》。
(1)由于无法Reference到Remote TaskFlow Producer定义,因此只能拖放一个TaskFlow Call Activity,忽略所有的警告信息。

(2)手工设置属性Document、ID、Remote Application URL,为保证设置正确,有必要查看Remote TaskFlow的XML文件。


(3)为了增加灵活性,把Remote Application URL值设置在web.xml中。

<context-param>
<param-name>adf.remote.taskflow.url</param-name>
<param-value>http://127.0.0.1:7101/ADF_TaskFlow_RemoteProducer-ViewController-context-root/faces/adf.task-flow</param-value>
</context-param>


3. 运行
(1)首先运行Remote TaskFlow Producer
(2)然后运行Remote TaskFlow Consumer
点击Select Department,传送输入参数departmentId。

点击Return Selected Employee,返回输出参数employeeId。

在Consumer的页面中接收到了Remote TaskFlow的返回值:employeeId。


Project 下载:ADF_RemoteTaskFlow.7z

参考文献:
1. http://andrejusb.blogspot.jp/2008/06/how-to-call-remote-task-flow-in.html
2. http://biemond.blogspot.jp/2008/12/reuse-remote-task-flows.html
3. http://www.oracle.com/technetwork/developer-tools/adf/learnmore/43-remote-task-flow-169185.pdf
4. http://www.oracle.com/technetwork/developer-tools/adf/learnmore/march2012-otn-harvest-1571998.pdf

ADF_199:Task Flow使用指南之八:Transaction(5)

运行环境:JDeveloper 11.1.2.2.0 + Oracle Database 10g Express Edition 10.2.0.1。

ADF TaskFlow的Transaction与数据库的Transaction的原理不同。
ADF TaskFlow的Transaction是在控制器层的,数据库的Transaction是在数据层的。
ADF TaskFlow的Transaction与Java EE的Transaction的原理也不同。
Java EE的Transaction是由Container管理事务,因此如果在TaskFlow中调用一个带事务批注的EJB方法,二者无法在同一个事务之中。
我们知道,ADF Model层可以生成Data Control,而每个ADF TaskFlow与一个Data Control Frame相关联。
一个Data Control Frame是一个容器,它负责管理与该TaskFlow相关联的多个Data Control实例。
同在一个Data Control Frame中的Data Control实例是在一个事务中的。
DataControlFrame Interface有如下方法:
(1)beginTransaction()
(2)commit()
(3)rollback()
(4)createSavepoint()
(5)isTransactionDirty()

在TaskFlow的Transaction的设置中,还有一个重要的属性:Share Data Control with Calling TaskFlow。
Transaction与Share Data Control之间的关系如下:
(1)Transaction=No Controller Transaction
选中Share Data Control,没有事务的父与子TaskFlow共享Data Control Frame中的Data Control实例;
未选中Share Data Control,没有事务的父与子TaskFlow各自创建和使用各自的Data Control Frame中的Data Control实例。
(2)Transaction=Always begin new transaction
选中Share Data Control,如果已经有了一个事务,抛出异常,否则,开始一个新事务;
未选中Share Data Control,开始一个新事务,无论是否已经有了一个事务。
(3)Transaction=Always Use Existing Transaction
选中Share Data Control,如果没有事务,抛出异常;
未选中Share Data Control,此时本选项无效。
(4)Transaction=Use Existing Transaction if Possible
选中Share Data Control,如果没有事务,开始一个新事务,否则使用已有的事务;
未选中Share Data Control,开始一个新事务,无论是否已经有了一个事务。

下面举一例说明:
3个BTFs,A调用B,B调用C。A和B使用同一个Data Control Frame(即同一个AM),而C使用不同的Data Control Frame(即另一个AM)。
如果选中Share Data Control(默认情况下是选中的),当进入BTF A时,首先创建A的Data Control实例;A调用B,进入BTF B时,不会再创建新的Data Control实例,而是使用A的Data Control实例。
当B调用C,进入BTF C时,因为与A和B的Data Control Frame不同,所以会创建C的Data Control实例;虽然使用的是不同的Data Control实例,但ADF会把C的Data Control实例交由A的Data Control实例管理,类似于嵌套的AM。
选中Share Data Control的好处是多个BTFs可以使用同一个数据库连接。

最后用一个Project来说明选中和未选中Share Data Control的区别。
1. 设计说明
(1)main.jsf页面中有一个Region,一个InputText,用于输入,一个按钮,调用方法hello(),另一个InputText,显示输出。

(2)jobs.jsff页面中有一个Table,一个按钮,也调用方法hello(),一个InputText,显示输出。

(3)hello()方法是定义在AM中的,暴露给Client Interface。

(4)TaskFlow的定义中,Share Data Control默认是选中的(蓝色的小方块)。


2. 运行
(1)点击Call hello inside BTF,jobs.jsff页面中的InputText显示了新的值。

(2)为Greeting InputText输入一个值,然后点击Call hello outside BTF,发现jobs.jsff页面中的InputText和main.jsf页面中InputText的都显示了同样的新的值。


3. 修改TaskFlow的定义中,设置Share Data Control=false


4. 再次运行
为Greeting InputText输入一个值,然后点击Call hello outside BTF,这次发现只有main.jsf页面中InputText的显示了新的值,而jobs.jsff页面中的InputText没有改变。


实验小结:当设置设置Share Data Control=false后,子TaskFlow不再使用父TaskFlow的Data Control实例,而是创建自己的实例。因此,虽然绑定的依然是hello()方法的返回值,但是不是同一个实例。

Project 下载:ADF_TaskFlow_ShareDataControl.7z


参考文献:
1. http://jjzheng.blogspot.com/2011/03/does-your-task-flow-need-transaction.html
2. http://xmlandmore.blogspot.com/2010/03/understanding-task-flow-transaction-and.html
3. http://tompeez.wordpress.com/2012/07/27/jdeveloper-adf-carefully-select-the-data-control-scope-of-bounded-task-flows/
4. http://andrejusb.blogspot.com/2011/08/adf-dialog-framework-and-adf-task-flow.html

2012年8月13日星期一

ADF_198:Task Flow使用指南之八:Transaction(4)

运行环境:JDeveloper 11.1.2.2.0 + Oracle Database 10g Express Edition 10.2.0.1。

在Bounded TaskFlow的Return Activity上有一个Restore Save Point属性,该属性与Transaction的关系如下:
(1)Transaction=Always Use Existing Transaction或UseExisting Transaction if Possible
当进入该TaskFlow时,会自动创建隐含的Save Point。
此时,如果Return Activity上的Restore Save Point=true,表明回退到刚进入TaskFlow时创建的Save Point。也就是说,放弃在TaskFlow中做的所有修改。
(2)Transaction=Always Begin New Transaction
Restore Save Point选项此时不起作用,因为永远开始一个新Transaction的TaskFlow与父TaskFlow的Transaction没有任何关系。
(3)Transaction=No Controller Transaction
Restore Save Point选项此时不起作用,因为TaskFlow没有关联Transaction。

1. 回顾上一个实验的重要设置:
(1)Update Location TaskFlow是第1层TaskFlow,其Transaction分别设置为Always Begin New Transaction。
(2)Update Department TaskFlow是第1层TaskFlow,其Transaction分别设置为Always Use Existing Transaction。
(3)Update Employee TaskFlow是第1层TaskFlow,其Transaction分别设置为Use Existing Transaction if Possible。
(4)Transaction只在Update Location TaskFlow中完成,Update Department TaskFlow和Update Employee TaskFlow只是加入Update Location TaskFlow的Transaction,不做完成Transaction的操作。

2. 设置Cancel Return Activity的Restore Save Point=true
(1)修改Update Department TaskFlow的Cancel Return Activity

(2)修改Update Employee TaskFlow中的Cancel Return Activity


3. 运行
(1)导航到Update Location TaskFlow,修改Location数据

(2)接着导航到Update Department TaskFlow,导航到修改Department数据

(3)接着导航到Update Employee TaskFlow,修改Employee数据

(4)在Update Employee页面中,点击Cancel,放弃修改的Employee数据,并返回Update Department TaskFlow。
(5)在Update Department页面中,点击OK,并返回Update Location TaskFlow。
(6)在Update Location页面中,点击OK,Commit事务。
(7)检查数据库表,发现Location和Department数据都成功修改了,而Employee数据没有变。

Project 下载:ADF_TaskFlow_MultiTransactions(2).7z

参考文献:
1. http://jjzheng.blogspot.jp/2011/03/does-your-task-flow-need-transaction.html
2. http://www.oracle.com/us/technologies/virtualization/oraclevm/o29frame-088050.html

ADF_197:Task Flow使用指南之八:Transaction(3)

运行环境:JDeveloper 11.1.2.2.0 + Oracle Database 10g Express Edition 10.2.0.1。

本实验场景:3层嵌套的TaskFlow,Transaction分别设置为Always Begin New Transaction、Always Use Existing Transaction、Use Existing Transaction if Possible,测试三个TaskFlow中的修改操作是否在同一个事务之中。

实验设计说明:

1. adfc-config.xml


2. 第1层TaskFlow:update-location-btf.xml
(1)

(2)Transaction设置为Always Begin New Transaction

(3)点击OK按钮,Commit事务

(4)点击Cancel按钮,Rollback事务


3. 第2层TaskFlow:update-department-btf.xml
(1)Transaction设置为Always Begin New Transaction

(2)Transaction设置为Always Use Existing Transaction

(3)点击OK按钮,不Commit事务,只是返回到上一层TaskFlow

(4)点击Cancel按钮,不Rollback事务,只是返回到上一层TaskFlow


4. 第3层TaskFlow:update-employee-btf.xml
(1)Return Activity上的红色叉子警告可以忽略,因为我没有在Return Activity上Commit或Rollback事务

(2)Transaction设置为Use Existing Transaction if Possible

(3)点击OK按钮,不Commit事务,只是返回到上一层TaskFlow
(4)点击Cancel按钮,不Rollback事务,只是返回到上一层TaskFlow

5. 运行
(1)导航到Update Location TaskFlow,修改Location数据

(2)接着导航到Update Department TaskFlow,导航到修改Department数据

(3)接着导航到Update Employee TaskFlow,修改Employee数据

(4)然后点击OK按钮从Update Employee TaskFlow返回到Update Department TaskFlow
(5)然后再点击OK按钮从Update Department TaskFlow返回到Update Location TaskFlow。
(6)最后点击OK按钮,Commit事务。
(7)检查数据库表,发现Location、Department、Employee的数据都修改成功了。

说明:事务由第1层TaskFlow发起,因此也应该在第1层结束,在其它层Commit或Rollback事务是不行的。
我曾试验在Update Employee TaskFlow中Commit,发现数据并未提交。

Project 下载:ADF_TaskFlow_MultiTransactions.7z

参考文献:
1. https://blogs.oracle.com/raghuyadav/entry/adf_taskflow_transaction_manag
2. http://xmlandmore.blogspot.jp/2010/03/understanding-task-flow-transaction-and.html

ADF_196:Task Flow使用指南之八:Transaction(2)

运行环境:JDeveloper 11.1.2.2.0 + Oracle Database 10g Express Edition 10.2.0.1。

本实验场景:一个TaskFlow中有多个修改页面,测试修改操作是否在同一个事务之中。

本实验的设计与上一个实验完全一样:



不同的地方是:Location VO、Department VO、Employee VO分别来自三个不同的AM。


测试结果和上一个实验完全一样,说明ADF TaskFlow的事务特性是跨AM的。

Project 下载: ADF_TaskFlow_Transaction_MulitiAM.7z

参考文献:
1. http://andrejusb.blogspot.com/2008/05/adf-task-flows-managing-transactions.html

ADF_195:Task Flow使用指南之八:Transaction(1)

运行环境:JDeveloper 11.1.2.2.0 + Oracle Database 10g Express Edition 10.2.0.1。

ADF Bounded TaskFlow有一个很重要的特性:Transaction。
这个Transaction的概念与Java EE中的Transaction是同一概念,只不过两者的配置方式不同。
在Java EE中的事务是直接使用批注配置在EJB的方法上或者配置在ejb.xml中,运行时由Container解析。
而TaskFlow中的事务是配置在控制器层的,其中的所有的Activity(View和其它非可视化的)都将属于一个事务。

打开一个Bounded Task Flow,在Property中找到Behavior,其中Transaction属性:

(1)No Controller Transaction:不加入任何事务。
(2)Always Begin New Transaction:开始一个新的事务,无论是否已经在一个事务之中。
(3)Always Use Existing Transaction:加入已有的事务,如果没有事务可加入,抛异常:ADFC-00006: Existing transaction is required when calling task flow。
(4)Use Existing Transaction If Possible:加入已有的事务,如果没有事务可加入,开始一个新的事务。
事务的提交是在Task Flow Return Activity上完成的,在Property中找到Behavior,其中End Transaction属性,我们可以设置如何提交事务(commit or rollback)。

本实验场景:一个TaskFlow中有多个修改页面,测试修改操作是否在同一个事务之中。

重点步骤说明:
1. 1个AM,1个DB Connection,1个Bounded TaskFlow


2. 其中的TaskFlow包括两个修改页面



3. 设置Transaction=Always Begin New Transaction


4. 每个修改页面都没有事务提交功能,而是交给Task Flow Return Activity负责


5. 运行
先后修改Department和Employee数据,发现改动后的数据均成功入库,说明修改操作是在一个事务之中。

Project 下载:ADF_TaskFlow_Transaction.7z

参考文献:
1. http://andrejusb.blogspot.com/2008/03/adf-task-flows-managing-transactions.html

ADF_194:Task Flow使用指南之七:SavePoints(3)

运行环境:JDeveloper 11.1.1.1.6 + Oracle Database 10g Express Edition 10.2.0.1。

前两个实验使用的都是Explicit SavePoints,本实验介绍如何使用Implicit SavePoints,即隐式SavePoints。

重点步骤说明:

1. 修改adf-config.xml,设置enable-implicit-savepoint=true

<adf-controller-config xmlns="http://xmlns.oracle.com/adf/controller/config">
<savepoint-datasource>
java:comp/env/jdbc/HRConnDS
</savepoint-datasource>
<enable-implicit-savepoints>true</enable-implicit-savepoints>
</adf-controller-config>


2. 设置Bounded TaskFlow的Critical=true
这里只设置Department TaskFlow的Critical=true,Location TaskFlow和Employee TaskFlow的Critical=false。


3. 运行
(1)main.jspx页面

(2)Location TaskFlow
修改一些信息,并点击Submit,然后点击To Department TaskFlow。

(3)Deparment TaskFlow
修改一些信息,并点击Submit,然后点击To Employee TaskFlow。

这时会弹出一个确认窗口,这是因为Department TaskFlow的Critical=true。

(4)点击确定后,数据库表ORADFCSAVPT中会增加一条记录

(5)关闭浏览器,模拟用户做了一般的工作,然后关闭浏览器。
(6)重新访问应用,选择Save Point ID,然后点击Restore。

(7)发现页面直接导航到了Employee TaskFlow

(8)点击Back按钮,发现Department页面的数据依然保留着最后的修改

(9)点击Back按钮,发现Location页面的数据依然保留着最后的修改


Project 下载:ADF_TaskFlow_SavePoints_Implicit.7z