EBS 11.5.10.2
需求
下图是Oracle标准页面,有一个简单的开发需求,当Expense Template等于“管理费用”时,Approver的LOV输入框默认为“XXX”,并且LOV
只读,不能进行选择。
分析
这个看似极其简单的开发,其背后所隐藏的技术知识却是不那么简单的。
当Expense Template选择为“管理费用”时,Approver
LOV
输入框只读,这里牵涉到的开发基本为给Expense Template加上FireAction
的功能,
然后在Expense Template的Value Change事件
中去修改Approver
LOV
的只读属性。
因为开发规范是不允许直接修改Oracle的代码,所以此开发将通过集成标准的控制器类,在客户化的控制器类中实现添加Expense Template的FireAction功能,和修改Approver
LOV
只读属性,
然后通过个性化,将控制器类替换成客户化的控制器类。
技术要点
1,修改Approver
LOV
的只读属性
刚刚进行OAF
开发的开发人员可能觉得这是很简单的事,只要在客户化的控制器类的processFormRequest
()方法中调用以下代码:
1
2
|
OAMessageLovInputBean lovBean =
(
OAMessageLovInputBean)
webBean.findChildRecursive
(
"Approver"
)
;
lovBean.setReadOnly
(
true
)
;
|
就可以实现了,如果这样做开发,那么就错了,在运行时会抛出异常:
1
2
3
|
The OA passivation framework coding standard has been violated.
Web bean properties cannot be modified in the controller processFormData or processFormRequest method.
Web bean properties should be modified in the processRequest method only.
|
(这里有两个方法是例外,setValue()和setText(),因为Value并不影响控件树)为什么把LOV
设为只读会出错呢?这是因为OAF
在运行时,表现为一棵控件树。
当进入页面时,控件树被初始化创建,而当用户事件触发POST请求时,控件树并不会被重新生成(提高性能),要改变控件的属性只有两个办法,一个是重新生成控件树,二是使用PPR。
方法一:重构控件树
重构控件树就意味着在processFormRequest()方法处理事件时,需要Forward
到本页,并通过参数控制来设置Approver
LOV
只读,这样会刷新整个页面,而且对编码也带来困难。
方法二:使用PPR
实现方法是利用OAF
数据绑定机制
,将Approver LOV的ReadOnly属性绑定到视图对象的属性,通过改变视图对象属性的值来控制Approver
LOV
的只读。
这里又引出第2个技术要点:
2,动态创建视图对象
创建视图对象需要首先创建OAViewDef
对象,然后利用OAViewDef对象来创建视图对象。
这里谈一下Oracle的一个开发规范,OAViewDef接口在oracle.apps.fnd.framework.server
包下,按照Oracle的规范,任何webui下的类不允许import任何server下的类。我是一个规范的严格遵守者,这样就会使开发变得更复杂。
要在server包下引用OAViewDef接口,就必须创建应用程序模块,将动态创建视图对象的代码移到应用程序模块中实现。在客户化控制器类中,动态创建应用程序模块,然后调用应用程序模块的方法。
实现步骤
假设开发人员对Oracle标准的页面结构都已经非常了解了,包括需要集成哪个标准的控制器,页面上所使用的视图对象。
1、创建客户化应用程序模块cux.oracle.apps.ap.oie.entry.server.CuxPVOAM
2、创建视图对象cux.oracle.apps.ap.oie.entry.server.CuxPVO,视图对象中只有一个临时属性ReadOnlyFlag,类型为Boolean(此步可选)
3、创建客户化控制器类,继承标准的控制器类
4、在CuxPVOAMImpl.java中创建两个方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
import
oracle.apps.fnd.framework.OAViewObject
;
import
oracle.apps.fnd.framework.server.OAViewDefImpl
;
import
oracle.jbo.AttributeDef
;
import
oracle.jbo.Row
;
……
public
void
initPVO(
)
{
OAApplicationModuleImpl rootAM =
(
OAApplicationModuleImpl)
getRootApplicationModule(
)
;
// 创建视图对象
OAViewDefImpl viewDef =
(
OAViewDefImpl viewDef)
getOADBTransaction(
)
.createViewDef
(
)
;
viewDef.setFullName
(
"CuxPVODef"
)
;
viewDef.setViewObjectClass
(
"oracle.apps.fnd.framework.server.OAViewObjectImpl "
)
;
viewDef.addTransientAttrDef
(
"ReadOnlyFlag"
,
"java.lang.Boolean"
,
null
,
false
,
AttributeDef.UPDATEABLE
)
;
OAViewObject pvo =
(
OAViewObject)
rootAM.createViewObject
(
"CuxViewPVO"
, viewDef)
;
// 初始化PVO
if
(
!
pvo.isPreparedForExecution
(
)
)
{
pvo.executeQuery
(
)
;
}
pvo.setMaxFetchSize
(
1
)
;
Row row =
pvo.createRow
(
)
;
pvo.insertRow
(
row)
;
row.setAttribute
(
"ReadOnlyFlag"
, Boolean
.FALSE
)
;
}
public
void
handleTemplateChange(
)
{
OAApplicationModuleImpl rootAM =
(
OAApplicationModuleImpl)
getRootApplicationModule(
)
;
OAViewObject vo =
(
OAViewObject)
rootAM.findViewObject
(
"XxxVO1"
)
;
//标准的VO
OAViewObject pvo =
(
OAViewObject)
rootAM.findViewObject
(
"CuxViewPVO"
)
;
if
(
<
expense template的值等于X>
)
{
pvo.first
(
)
.setAttribute
(
"ReadOnlyFlag"
, Boolean
.TRUE
)
;
vo.first
(
)
.setAttribute
(
"Xxx"
, <
value>
)
;
// 设置Approver LOV绑定的视图对象属性值
}
else
{
pvo.first
(
)
.setAttribute
(
"ReadOnlyFlag"
, Boolean
.FALSE
)
;
}
}
}
|
5、在客户化控制器中添加相应代码
processRequest代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public
void
processRequest(
OAPageContext pageContext, OAWebBean webBean)
{
super
.processRequest
(
pageContext, webBean)
;
// 启用Expense Template的FireAction功能
OAMessageChoiceBean choiceBean =
(
OAMessageChoiceBean)
webBean.findChildRecursive
(
"ExpenseTemplate"
)
;
choiceBean.setFireActionForSubmit
(
"change"
,
null
,
null
,
true
)
;
// 创建客户化应用程序模块
OAApplicationModule rootAM =
pageContext.getRootApplicationModule
(
)
;
OAApplicationModule pvoAM =
(
OAApplicationModule)
rootAM.findApplicationModule
(
"CuxPVOAM"
)
;
if
(
pvoAM ==
null
)
{
rootAM.createApplicationModule
(
"CuxPVOAM"
,"cux.oracle.apps.ap.oie.entry.server.CuxPVOAM"
)
;
pvoAM =
HssCustomizeHelper.getNestedAMInstance
(
rootAM, "CuxPVOAM"
)
;
}
pvoAM.invokeMethod
(
"initPVO"
)
;
// 将ReadOnly属性绑定到视图对象属性
OAMessageLovBean approverLov =
(
OAMessageChoiceBean)
webBean.findChildRecursive
(
"Approver"
)
;
approverLov.setAttributeValue
(
READ_ONLY_ATTR, new
OADataBoundValueViewObject(
approverLov,"ReadOnlyFlag"
,"CuxPVO"
)
)
;
}
|
将开发测试后的代码发布到服务器。(测试可以在本地,将页面上的控制器类替换成客户化的控制器来进行)
processFormRequest代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public
void
processFormRequest(
OAPageContext pageContext, OAWebBean webBean)
{
super
.processFormRequest
(
pageContext, webBean)
;
OAApplicationModule rootAM =
pageContext.getRootApplicationModule
(
)
;
OAApplicationModule pvoAM =
(
OAApplicationModule)
rootAM.findApplicationModule
(
"CuxPVOAM"
)
;
if
(
pvoAM ==
null
)
{
rootAM.createApplicationModule
(
"CuxPVOAM"
,"cux.oracle.apps.ap.oie.entry.server.CuxPVOAM"
)
;
pvoAM =
HssCustomizeHelper.getNestedAMInstance
(
rootAM, "CuxPVOAM"
)
;
}
if
(
"change"
.equals
(
pageContext.getParameter
(
EVENT_PARAM)
)
)
{
pvoAM.invokeMethod
(
"handleTemplateChange"
)
;
}
}
|
HssCustomizeHelper.getNestedAMInstance()的代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public
static
OAApplicationModule getNestedAMInstance(
OAApplicationModule parentAM, String
nestedAMName)
{
OAApplicationModule am =
null
;
String
[
]
amNames =
parentAM.getApplicationModuleNames
(
)
;
for
(
int
i=
0
;
i&
lt;
amNames.length
;
i++
)
{
if
(
amNames[
i]
.endsWith
(
nestedAMName)
)
{
return
(
OAApplicationModule)
parentAM.findApplicationModule
(
amNames[
i]
)
;
}
else
{
am =
getNestedAMInstance(
(
OAApplicationModule)
parentAM.findApplicationModule
(
amNames[
i]
)
,nestedAMName)
;
if
(
am !=
null
)
{
return
am;
}
}
}
return
am;
}
|
7、重启Apache
8、进入页面,设置个性化,替换标准的控制器类为客户化控制器类。
分享到:
相关推荐
根据提供的文档信息,我们可以深入探讨“06 OAF客户化开发实例之Helpdesk”这一主题。这份文档主要涉及Oracle Application Framework (OAF) 的客户化开发实例,具体来说是关于帮助台(Helpdesk)文档管理的功能开发...
在Oracle E-Business Suite(EBS)中,个性化标准OAF页面是指基于Enterprise Object(EO)或SQL的版本,通过替换Value Object(VO)添加客户化属性来实现个性化的页面开发。下面是相关的知识点: 个性化EBS标准OAF...
根据提供的文档信息,本文将详细解析“07 OAF客户化开发实例之Helpdesk文档下载”这一主题,重点介绍OAF环境下实现文档下载功能的具体步骤和技术要点。 ### 一、OAF开发环境搭建 #### 1.1 XP操作系统JDEV环境配置 ...
Oracle_OAF个性化,通过学习该文档能初步掌握OAF个性化。
OAF客户化开发实例之FTP项目成果展示开发实例,对于初学者可以看看
文档"03OAF客户化开发实例之Helpdesk问题处理者管理员开发实例v1.0.pdf"主要介绍了如何进行Oracle Application Framework (OAF)的客户化开发,特别是针对Helpdesk问题处理者的管理功能。OAF是Oracle E-Business ...
### OAF 客户化开发实例之FTP服务器文件下载开发实例 #### 一、OAF开发环境搭建与理解 - **环境配置**:文档提到在XP操作系统下的JDeveloper环境中进行开发。首先需要在`<jdev_install_dir>\jdev`目录下创建`my...
根据提供的文档信息,本文将详细解析“02 OAF客户化开发实例之Helpdesk公告用户显示开发实例v1.0.pdf”中所涉及的关键知识点,包括OAF开发环境的搭建、OAF框架的理解与运用、OAF开发规范的遵循、OAF页面的基本布局...
### 一、OAF开发环境搭建与理解 #### 1.1 概述 OAF(Oracle Application Framework)是Oracle提供的一种基于Java的技术框架,用于构建企业级应用程序。本篇文档主要介绍了如何在XP操作系统环境下配置JDeveloper环境...
### OAF个性化设计详解 #### 一、个性化系统概述 OAF(Oracle Applications Framework)个性化设计是Oracle E-Business Suite (EBS)中一个重要的功能模块,它允许用户根据自身需求定制应用程序界面,从而提高用户...
本实例包含了OAF的基本开发实例,包括helloword程序,查询功能模块,新增功能模块,删除功能模块,更新功能模块;采用的Oracle JDeveloper 10g作为开发工具,本实例是中文文档,对于初学者有很好的指导作用。
OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程OAF教程
Oracle Application Framework (OAF) 是Oracle公司提供的一种企业级应用开发框架,主要用于构建基于Web的用户界面,尤其在Oracle E-Business Suite (EBS) 中广泛使用。本教程旨在帮助初学者逐步掌握OAF开发的核心...
在Oracle Application Framework (OAF) 开发中,CO、VO、AM 和 EO 是四个关键的组件,它们构成了这个企业级应用框架的核心。以下是对这些概念的详细解释以及它们在实际开发中的常见用法: 1. **CO(Controller)**...
这个文档将指导你配置开发环境,包括安装必要的软件,设置EBS系统权限,以及初始化开发工具。只有正确设置了环境,你才能顺利进行后续的开发工作。 总的来说,这个初步文档系列旨在让你掌握Oracle EBS中的OAF开发...