2009年1月29日星期四

理解ADF ManagedBean Scope

概述

本文主要说明ADFManagedBean中的不同Scope

由于ADF Controller是在JSF的基础上扩展而来的,因此,在ADF中,在包含了JSF的三种Scope的基础上,又扩展出了另外三种Scope,使ADF Controller在实际应用中更为灵活和方便。

JSF标准Scope

Applicati onScope

sessionScope

requestScope

ADF Controller扩展Scope

pageFlowScope

backingBeanScope

viewScope

下面将针对每种Scope进行详细说明,以作用域由大到小排列。


详细说明

1、applicationScope

就从字面意思就可以看出,applicationScope是作用范围最广的,在作用于整个应用的运行周期内。通常情况下,applicationScope中的参数等都是在应用启动(web server启动)时即被初始化,因此,一般对于独立于特定的职责和角色的,且需要在整个应用的周期内都需要的资源会定义在applicationScopeManagedBean中。

2、sessionScope

仅次于applicationScope的是sessionScopesessionScope作用于从用户登录开始到用户主动结束该session,一般来说,都会为session设置超时时间,若超过服务器设置的超时时间的话,则该session被自动释放。在实际的应用中,经常会将类似于用户信息,预置文件信息或授权信息等设置到session中。

3、requestScope

requestScope的作用周期是在一次request之内,只要是在同一个request内,即使是在不同的页面也可以访问到作用在requestScope的内容。

4、pageFlowScope

ADF中引入了Task-Flow的概念, pageFlowScope作用于同一个Task Flow中,例:分别有A,B,C三个页面,同属于一个Task FlowD页面不属于该Task Flow,且A,B,C三个页面可以通过定义的action相互进行导航,同时也可以从这三个页面导航到D页面,建立pageFlowScopeManaged Bean此时,A,B,C三个页面可以同时访问到该Managed Bean中的属性。

5、viewScope

viewScope是指view id发生更改之前都可用,即作用于同一页面内,例如,在不同页面之间跳转时,viewScopeManaged Bean中的数据都会丢失。

6、backingBeanScope

backingBeanScope多用于page fragmentsdeclarative components,由于同一个页面中可能会拥有多个page fragmentsdeclarative components,因此,为了避免相互之间数据冲突,可以考虑使用backingBeanScopeManaged Bean

7、none

none的意思是说,即使在同一个页面,也不能访问到彼此none scopeManaged Bean中的属性。

下面是上述六种Scope的生命周期示意图:


2009年1月26日星期一

应用ADF Logger

本文主要描述在ADF开发中如何应用ADF Logger帮助开发人员调试和诊断错误。

场景:

ADF开发过程中,经常会遇到各种各样的错误,其中有些错误比较容易排查,但是有一些则相对比较难以发现错误根源,此时,经常会使用到日志来显示诊断信息以帮助发现错误。在Java应用中,可以通过创建Java Logger显示Java的诊断信息,在ADF中,即应用ADF Logger进行显示。

Java.util.logging JDK的说明文档中,描述了关于使用日志的四个目标:

1、由最终用户和系统管理员进行问题诊断,这由简单的常见问题日志组成,可在本地解决或跟踪这些问题,如资源不足、安全失败和简单的配置错误。

2、 由现场服务工程师进行问题诊断,现场服务工程师使用的日志信息可以相当复杂和冗长,远超过系统管理员的要求。通常,这样的信息需要特定子系统中的额外日志记录。

3、由开发组织进行问题诊断,在现场出现问题时,必须将捕获的日志信息返回到原开发团队以供诊断。此日志信息可能非常详细,并且相当费解。这样的信息可能包括对特定子系统进行内部执行的详细跟踪。

4、由开发人员进行问题诊断,Logging API 还可以用来帮助调试正在开发的应用程序。这可能包括由目标应用程序产生的日志信息,以及由低级别的库产生的日志信息。但是要注意,虽然这样使用非常合理,但是 Logging API 并不用于代替开发环境中已经存在的调试和解析工具

java.util.logging.level类中定义了一组可以用来控制日志输出的标准日志级别,按照严重程度由高到低依次为:

1SERVER

2WARNING

3INFO

4CONFIG

5FINE

6FINER

7FINEST

具体说明参见文档(P892 b31973.pdf

下面我们将为应用howtoapplyadflogger应用Adflogger,该应用完成了简单的浏览公司职位信息(Jobs)功能。

实现:

1、开启诊断日志,需要设置Java系统参数jbo.debugoutput值为console,在Jdeveloper中可以进行设置:双击打开Model项目,选择“Run/Debug/Profile”项,在“Run Configurations”中选中Default,点击“Edit”按钮,在Java Options中填入-Djbo.debugoutput=console,用于开启诊断日志,这个也是最简单的开启诊断日志的方法。


2、此时运行AppModuleAM),可以看到诊断日志已经在Jdeveloper中打印出来。

[322] *** Using bean introspection to lookup value :clientProxyInterfaceName

[323] Replacing: null with: AppModule_JobsVO1PageDef

[324] Resolving VO:AppModule.JobsVO1 for iterator binding:oracle_jbo_uicli_binding_JUIteratorBinding_0

[325] UIMessageBundle (language base) being initialized

[326] DCUtil, RETURNING: for AppModule.JobsVO1

[327] Tester startup time: 6 s.

[328] INFO: No app _def_ in BindingContext for: AppModule

[329] DCUtil, returning:oracle.jbo.uicli.binding.JUApplication, for AppModule

[330] Replacing: null with: AppModule_JobsVO1_0PageDef

[331] INFO: No app _def_ in BindingContext for: AppModule

[332] DCUtil, returning:oracle.jbo.uicli.binding.JUApplication, for AppModule

[333] INFO: No app _def_ in BindingContext for: PROJECT_GLOBAL_VARIABLES

[334] INFO: mDCRefMap lookup failed. Does the cpx have a dataControlUsages 'dc' entry? PROJECT_GLOBAL_VARIABLES

[335] Resolving VO:AppModule.JobsVO1 for iterator binding:oracle_jbo_uicli_binding_JUIteratorBinding_1

[336] DCUtil, RETURNING: for AppModule.JobsVO1

[337] JobsVO1 ViewRowSetImpl.execute caused params to be "un"changed

[338] Column count: 4

[339] ViewObject: JobsVO1 Created new QUERY statement

[340] JobsVO1>#q computed SQLStmtBufLen: 144, actual=117, storing=147

[341] SELECT JobsEO.JOB_ID, JobsEO.JOB_TITLE, JobsEO.MIN_SALARY, JobsEO.MAX_SALARY FROM JOBS JobsEO

[342] Bind params for ViewObject: JobsVO1

[343] **** refreshControl() for BindingContainer :AppModule_JobsVO1_0PageDef

[344] *** DCDataControl.sync() called from :DCBindingContainer.refresh

3、在完成了前面的设置以后,就 可以使用业务组件浏览器来进行诊断和调试了,例如,我们为JobsEO生成对应的实现类JobsEOImpl.java,在其中添加如下代码:

private static ADFLogger logger =

ADFLogger.createADFLogger(JobsEOImpl.class);

/**

* This is the default constructor (do not remove).

*/

public JobsEOImpl() {

//Modified by Eleven.Xu, 2008.1.8

logger.info("JobsEOImpl AdfLogger Test!");

}

4、此时再次运行业务组件浏览器,发现刚才修改的代码中添加的日志已经被打印出来。

[335] Resolving VO:AppModule.JobsVO1 for iterator binding:oracle_jbo_uicli_binding_JUIteratorBinding_1

[336] DCUtil, RETURNING: for AppModule.JobsVO1

[337] JobsVO1 ViewRowSetImpl.execute caused params to be "un"changed

[338] Column count: 4

[339] ViewObject: JobsVO1 Created new QUERY statement

[340] JobsVO1>#q computed SQLStmtBufLen: 144, actual=117, storing=147

[341] SELECT JobsEO.JOB_ID, JobsEO.JOB_TITLE, JobsEO.MIN_SALARY, JobsEO.MAX_SALARY FROM JOBS JobsEO

[342] Bind params for ViewObject: JobsVO1

2009-1-8 14:13:21 howto.adflogger.model.entities.JobsEOImpl

信息: JobsEOImpl AdfLogger Test!

5、完成了对于Model项目的设置,为在应用运行时打印出必要的诊断日志,接下来将继续对配置文件和ViewController项目进行一些必要的设置,在设置前重新启动服务器并运行Main.jspx页面,没有诊断日志被打印。

2009-1-8 9:28:38 com.sun.faces.spi.InjectionProviderFactory getProviderInstance

严重: JSF1030: The specified InjectionProvider implementation 'com.bea.faces.WeblogicInjectionProvider' cannot be loaded.

Application Deployed Successfully.

Elapsed time for deployment: 30 seconds

---- Deployment finished. ---- Jan 8, 2009 9:28:40 AM

Run startup time: 32125 ms.

[Application howtoapplyadflogger deployed to Server Instance DefaultServer]

Target URL -- http://127.0.0.1:7101/howtoapplyadflogger-ViewController-context-root/faces/Main.jspx

2009-1-8 9:28:56 oracle.adfinternal.controller.faces.lifecycle.JSFLifecycleImpl setLifecycleContextBuilder

警告: ADFc: 'oracle.adfinternal.controller.application.model.JSFDataBindingLifecycleContextBuilder' 替换 ADF 页生命周期实施。

2009-1-8 9:28:56 oracle.adfinternal.controller.util.model.AdfmInterface initialize

信息: ADFc: BindingContext 存在, 并且将 ADFm API 用于 DataControlFrames

2009-1-8 9:28:56 oracle.adfinternal.controller.metadata.provider.MdsMetadataResourceProvider

信息: ADFc: 启用了对 MDS 元数据资源的控制器高速缓存。

2009-1-8 9:28:56 oracle.adf.controller.internal.metadata.MetadataService$Bootstrap add

信息: ADFc: '/WEB-INF/adfc-config.xml' 加载引导元数据。

6、修改logging.xml文件,该文件的位置位于:

1)如果设置了JDEV_HOME,则在该环境变量对应路径下的system/DefaultDomain/config文件夹中。

2)如果没有设施JDEV_HOME,则在Jdeveloper安装目录下的system/system/DefaultDomain/config文件夹中。

查看该文件

红色部分name为空,表示应用于所有package,其日志显示级别为WARNING,则可以显示WARNING或比WARNING更高级的日志信息,这里是Oracle的建议方式,通过这种方式过滤一些低级别的日志信息,保留该默认设置,如果需要对某些package进行更低级别的日志打印,则需要在蓝色部分添加对应信息,例:我们添加打印了oraclehowto两个package的日志信息,级别都为INFO

7、重新启动服务器并运行页面,发现还是不能打印出诊断信息,还需要对于ViewController项目进行简单的设置:双击打开ViewController项目,选择“Run/Debug/Profile”项,在“Run Configurations”中选中Default,点击“Edit”按钮,在Java Options中填入-Djbo.debugoutput=console

8、为查看View层中的日志,在Main.jspx页面添加新按钮,并在对应的Backing ScopeManaged Bean中该Button的事件方法中打印出了日志信息,代码如下:

public String loggerTest() {

logger.info("Managed Bean(Button) Logger Test!");

logger.fine("Fine Level Managed Bean(Button) Logger Test!");

return null;

}

9、重新启动服务器并运行Main.jspx页面,查看日志显示情况。

补充:Jdeveloper中有可能设置了日志显示级别为FINE或者FINEST后,却仍然不能显示出对应级别的日志信息, 是由于在Jdeveloper使用的JRElib中的logging.property文件中规定了默认日志显示的级别为INFO.level= INFO),可以根据情况进行调整,以显示对应级别的日志信息,必须注意的是,伴随日志显示级别的降低,日志打印内容越来越多,由于Java需要大量操作IO,必然导致运行速度变慢,因此,一般情况下,只需将其中的级别设置为INFO

[366] **** refreshControl() for BindingContainer :howto_adflogger_view_MainPageDef

[367] valiateToken:Decompressed BC state:BCST:=0%V%=NJobsVO1Iterator=-D-,

[368] DCUtil, returning:oracle.adf.model.binding.DCParameter, for AppModuleDataControl

[369] (oracle.adf.model.bc4j.DataControlFactoryImpl.SyncMode = Immediate

[370] Reusing a cached session application module instance

[371] **** PoolMessage REQ ATTACH LWS

[372] Invoke refresh for :JobsVO1Iterator

[373] Executing and syncing on IteratorBinding.refresh from :JobsVO1Iterator

[374] Resolving VO:JobsVO1 for iterator binding:JobsVO1Iterator

2009-1-8 14:10:55 howto.adflogger.view.backing.Main loggerTest

信息: Managed Bean(Button) Logger Test!

相关代码请查看:

applyadflogger.rar