| |||
|
作者:Nitin Patel
就如何在 Oracle Identity Manager 中实现 Additional Request Information 特性提供了详细的分步技术指导
2013 年 4 月
下载
OracleIdentityManager
SampleAdditionalReqInfoApp
sandbox-AdditionalRequestInformat
Oracle Identity Manager (OIM) 11.1.2.2.0 版(R2PS2 版)引入了 Additional Request Information 特性。与此特性有关的文档可从这里获取。默认(现成)情况下,该特性在 OIM UI 中并不可用,必须由客户实现。实现涉及一些 UI 自定义,包括(但不限于)为 UI 自定义创建沙箱、开发自定义应用开发框架 (ADF) 任务流,以及在二者之间建立链接。
本文旨在帮助 OIM 客户、顾问和任何想要实现此特性的其他人,重点关注整体实现方法,以及为此特性开发一个分步示例实现。本文所提供示例包括示例沙箱 zip、Jdeveloper ADF 应用(含源码)以及 ADF 库 jar(含自定义任务流和托管 bean (mBean))。
注:本文假定读者熟悉 OIM 和 ADF 开发,了解这里所载 OIM UI 自定义的方方面面。
站在一定的高度看,此特性能够通过 UI 自定义指定与请求(用户操作)相关的其他信息。其他信息有助于请求审批决策或合规性。请参见本文末尾“用例”一节中所记载的示例用例。
要实现此特性,必须执行以下操作:
该特性一旦实现,请求者就会看到步骤 A 中在购物车提交页面中添加的自定义 UI 组件(命令链接/按钮)。单击该链接/按钮,即会启动步骤 B 中部署的自定义 ADF 有界任务流。请求者可在任务流中指定以 UI 输入组件形式显示的其他信息,也可以保存信息。该信息作为请求的一部分保存,可供跟踪请求的请求者(或其他可以查看请求的用户)查看。审批者可以查看和编辑请求者输入的信息,对分配给他们的相应审批任务采取适当的操作。
使用 Oracle Web Composer 创建沙箱(如文档中所述),执行 UI 自定义,在购物车提交页面中添加自定义组件(命令链接或按钮)。具体步骤如下:
xelsysadm
用户身份登录 OIM 自助控制台。role1
),默认情况下,该角色将发布到顶层组织。AdditionalRequestInformation
)。role1
,将其添加到购物车,并单击 Checkout 进入购物车提交页面。panelHeader
,添加 commandLink
组件(用于 Additional Cart Information),如图 1 和图 2 所示。 commandLink
(用于 Additional Cart Item Information),如图 3 所示。 #{backingBeanScope.cartReqBean.updateEnbled}
(参见图 6)。 开发一个自定义的 ADF 有界任务流,将其随 oracle.iam.ui.custom-dev-starter-pack.war
一起部署。该任务流应包含提交购物车时要收集的所有其他信息。此外,还可以开发和部署任何自定义的托管 bean(参见开发托管 Bean 和任务流),在其中包含自定义逻辑来实现根据购物车项有选择地显示/隐藏链接等用例。
以下步骤显示如何开发实现与“Additional Request information”特性有关的自定义所需的自定义 ADF 构件,以及如何将其作为 oracle.iam.ui.custom-dev-starter-pack.war
的一部分一起部署。这些说明是对此特性的官方文档的补充。
按照文档 30.10.1 节中的说明开发一个 ADF View Controller 项目。如果开发受阻,请参考以下步骤/屏幕截图。
oracle.iam.ui.custom
。 adflibAdditionalReqInfoPrj1
)。 到目前为止,我们所执行的步骤与文档 30.10.1 节中相同。
下面一组步骤显示如何创建有界 ADF 任务流,其中包含将在购物车提交时收集的其他信息。作为本次练习的一部分,我们将:
addnl-entitlement-info.xml
”的有界任务流示例。additionalEntitlementInfo.jsff
”的页面片段,它是此任务流的一部分。AddnlEntitlementInfoStateBean
和 AddnlEntitlementInfoRequestBean
。AddnlEntitlementInfoStateBean
在 pageFlowScope
中配置,其中保存 jsff 的状态(Start Date 和 End Date)。AddnlEntitlementInfoRequestBean
在 BackingBean
作用域中配置,它保存与 jsff 中 Save 和 Cancel 按钮对应的操作监听器方法 onSave
和 onCancel
。Util.java
的 Java 类,用于定义任何实用程序方法;创建一个 HelperBean.java
托管 bean,用于自定义逻辑。项目结构如下所示:下面一组步骤显示如何创建 ADF View Controller 项目的每个组成构件。
<Project_dir>/public_html/WEB-INF
下创建一个新的 ADF 任务流。在下面的屏幕截图中,在 <Project_dir>/public_html/WEB-INF/oracle/iam/ui/custom/additionalInfo
目录下创建了任务流 addnl-entitlement-info.xml
。Util
,它拥有实用程序方法。 AddnlEntitlementInfoStateBean
的托管 bean,用于表示任务流的状态。也就是说,它包含任务流域 startDate
和 EndDate
。注意,该类必须实现 Serializable 接口。requestFormContext
和 additionalRequestInfo
,对应于下面在第 8 步中讨论的任务流输入参数。readOnly
是一个布尔变量,用于确定 jsff 中的 start date 和 end date 域是只读还是可编辑。cartItemId
用作 additionalRequestInfo
对象的索引,以提取与所选购物车项对应的其他信息(参见接口)。initialize
方法,使用 requestFormContext
对象确定和初始化 readOnly
和 cartItemId
域,以及使用 additionalRequestInfo
对象确定和初始化 startDate
和 endDate 域。store
的公有方法使用 startDate
和 endDate 域的新/更新值更新 additionalRequestInfo
对象。在 additionalEntitlementInfo.jsff
页面上单击 Save 按钮时,应调用该方法。AddnlEntitlementInfoRequestBean
。它有一个名为 stateBean
的 AddnlEntitlementInfoStateBean
类型成员变量,是因任务流中配置的托管 bean 属性(在下面第 7 步中)而注入的。注意,访问器方法是使用 JDeveloper 为此变量生成的。操作监听器方法 onSave
调用上面在状态 bean 中定义的 store
方法,将状态保存到任务流/jsff。然后使用下述 Util
类隐藏弹出窗口。操作监听器方法 onCancel
隐藏弹出窗口,不保存状态。Util
类,其实用程序方法 findParentComponent
用于上面的请求 bean。addnl-entitlement-info.xml
任务流中将上面创建的状态 bean 和请求 bean 配置为托管 bean,如下面的屏幕截图所示。注意,stateBean
在 pageFlow
作用域中配置,requestBean
在 backingBean
作用域中配置。选择 requestBean
,使用名称 stateBean
、类型 oracle.iam.ui.custom.AdditionalRequestInfo.AddnlEntitlementInfoStateBean
和值 '#{pageFlowScope.stateBean}'
配置托管属性。这是为了将 stateBean
注入 requestBean
。additionalRequestInfo
(类:oracle.iam.ui.common.model.catalog.requestdetails.AdditionalRequestInfo
)和 requestFormContext
(类:oracle.iam.ui.platform.view.RequestFormContext
),如图 18 所示。将这些输入参数存储在上面创建的 AddnlEntitlementInfoStateBean
中对应的成员变量中。这可以使用 EL 表达式 #{pageFlowScope.stateBean.additionalRequestInfo}
和 #{pageFlowScope.stateBean.requestFormContext}
实现。注意,EL 表达式中使用的 stateBean
对应于上面配置的托管 bean。addnl-entitlement-info.xml
任务流,拖放一个 Method 调用活动,并为其命名(如 initialize
)。要将其标记为默认活动,请右键单击 Mark Activity > Default Activity。双击该活动,将其与 stateBean
中的 initialize 方法关联。additionalEntitlementInfo
。双击该组件,创建一个名为 additionalEntitlementInfo.jsff
的页面片段。initialize
和 additionalEntitlementInfo
活动之间添加一个 Control Flow Case,如下面的 addnl-entitlement-info.xml
设计和源码中所示:注:对于 Start Date inputDate
组件,readOnly
属性设置为 #{pageFlowScope.stateBean.readOnly}
,value 属性设置为 #{pageFlowScope.stateBean.startDate}
。这会将此组件及其属性绑定到 stateBean
(AddnlEntitlementInfoStateBean
) 中的变量。同样的操作也适用于 End Date 组件。还要注意,Save 按钮的 action listener 属性设置为 #{backingBeanScope.requestBean.onSave}
,这将其绑定到 requestBean
的 onSave
方法。
保存所有更改。
HelperBean.java
),以扩展 oracle.iam.ui.platform.view.backing.BaseMB
。该类用于实现文档 30.11.5 和 30.11.6 节中讨论的用例,也就是说,用于动态确定购物车提交页面中的以下内容: initialize
:该方法使用以下代码初始化 oracle.iam.ui.platform.view.RequestFormContext
类型的实例变量 requestFormContext
:requestFormContext = RequestFormContext.newInstance(null).getCurrentContext();
isRenderAdditionalDetailsForRequest
:该方法可用于确定是否必须在请求/购物车级别显示 Additional Information 链接。isRenderAdditionalDetailsForCartItem
:该方法可用于确定是否必须为当前购物车项显示 Additional Information 链接。isRenderUpdateButton
:该方法可用于确定是否在审批详细信息页面上显示 Update 按钮。图 24 捕获几个方法的代码。注意,产品文档的 30.11.5 和 30.11.6 节已经介绍了可用于实现所需自定义的数据。还介绍了 cartItemDataMap
、pageFlowScope
等。
adfc-config.xml
中,将上面创建的 HelperBean
类配置为托管 bean(在 backingBean
作用域中),如图 25 所示。注意,该 bean(及其任何公有方法)可在任何 EL 表达式中用名称 additionalInfoHelperBean
引用。例如:#{backingBeanScope.additionalInfoHelperBean.renderUpdateButton}
adflibAdditionalReqInfoPrj1
进行部署。单击 Finish 完成部署。编译和部署成功后,即创建一个类似以下的 jar:<JDEV_WORKSPACE>/AdditionalReqInfoApp/AdditionalReqInfoPrj/deploy/adflibAdditionalReqInfoPrj1.jar
oracle.iam.ui.custom-dev-starter-pack.war
的一部分部署,如文档 30.10.4 节所述。按照文档 30.5.1 节中的介绍使用 Authorization Policy Manager (APM) 为自定义任务流添加权限。
注意,本练习以上部分所构建的示例任务流为:/WEB-INF/oracle/iam/ui/custom/additionalInfo/addnl-entitlement-info.xml#addnl-entitlement-info
oracle.adf.controller.security.TaskFlowPermission
自定义或查看资源名 /WEB-INF/oracle/iam/ui/custom/.*
是现成内置的,因此无需为示例任务流添加任何新的权限。
在此步骤中,我们将对上面步骤 A 中创建并导出的沙盒进行自定义。在自定义 UI 组件与自定义任务流之间建立链接并作为步骤 B 的一部分将其部署,也需要此步骤。
cart-details.jsff.xml
文件,将看到类似以下的 mds:insert
和 mds:modify
标记:<mds:insert parent="ph1" position="last"> <af:commandLink xmlns:af="http://xmlns.oracle.com/adf/faces/rich" id="e9847224848" shortDesc="Additional Cart Information" text="Additional Cart Information"/> </mds:insert> <mds:insert parent="pgl4" position="first"> <af:commandLink xmlns:af="http://xmlns.oracle.com/adf/faces/rich" id="e2712655339" text="Additional Cart Item Information" shortDesc="Additional Cart Item Information"/> </mds:insert> <mds:modify element="ctb2"> <mds:attribute name="rendered" value="true"/> </mds:modify>
确保文件中包含全部三个自定义:添加两个新 commandLink、修改 Update 按钮。
cart-details.jsff.xml
文件做以下更改: commandLink
的 actionlistener
属性设置为与下面完全相同的值:actionListener="#{catalogRequestBean.launchAdditionalRequestInfoTaskFlow}"
commandLink
的 clientAttribute
。taskFlowId
属性的值应为完全限定任务流名称。在本示例中,我们将 taskflowId
属性设置为 EL 表达式:#{backingBeanScope.additionalInfoHelperBean.additionalInfoTaskFlowIdForCartItem}
getAdditionalInfoTaskFlowIdForCartItem
方法。该方法返回以下 taskflowId
:/WEB-INF/oracle/iam/ui/custom/additionalInfo/addnl-entitlement-info.xml#addnl-entitlement-info
#{backingBeanScope.additionalInfoHelperBean.renderUpdateButton}
isRenderUpdateButton
方法。该方法只对审批更新流返回“true”,因此其他流上不会显示该按钮。<?xml version='1.0' encoding='UTF-8'?> <mds:customization version="11.1.1.64.93" xmlns:mds="http://xmlns.oracle.com/mds" motype_local_name="root" motype_nsuri="http://java.sun.com/JSP/Page"> <mds:insert parent="ph1" position="last"> <af:commandLink xmlns:af="http://xmlns.oracle.com/adf/faces/rich" id="e81172800" text="Additional Cart Information" actionListener="#{catalogRequestBean.launchAdditionalRequestInfoTaskFlow}" rendered="false"/> </mds:insert> <mds:insert parent="pgl4" position="first"> <af:commandLink xmlns:af="http://xmlns.oracle.com/adf/faces/rich" id="e5139681203" text="Additional Cart Item Information" actionListener="#{catalogRequestBean.launchAdditionalRequestInfoTaskFlow}" rendered="#{backingBeanScope.additionalInfoHelperBean.renderAdditionalDetailsForCartItem}"> <af:clientAttribute xmlns:af="http://xmlns.oracle.com/adf/faces/rich" name="taskFlowId" value="#{backingBeanScope.additionalInfoHelperBean.additionalInfoTaskFlowIdForCartItem}"/> <af:clientAttribute xmlns:af="http://xmlns.oracle.com/adf/faces/rich" name="dialogTitleIcon" value="/images/request_ena.png"/> <af:clientAttribute xmlns:af="http://xmlns.oracle.com/adf/faces/rich" name="headerText" value="Additional Cart item Information"/> <af:clientAttribute xmlns:af="http://xmlns.oracle.com/adf/faces/rich" name="dialogTitle" value="#{backingBeanScope.additionalInfoHelperBean.popupTitle}"/> </af:commandLink> </mds:insert> <mds:modify element="ctb2"> <mds:attribute name="rendered" value="#{backingBeanScope.additionalInfoHelperBean.renderUpdateButton}"/> </mds:modify> </mds:customization>
rendered=""#{backingBeanScope.additionalInfoHelperBean.renderAdditionalDetailsForCartItem}
isRenderAdditionalDetailsForCartItem
方法。该方法保存逻辑,仅当角色名称为 role1 时返回“true”。以 xelsysadm 用户身份登录,尝试以下用例:
getRequestDetails
操作获取上面创建的任何请求的请求详细信息。确保 Web 服务方法返回其他信息。本文演示在 OIM (11.1.2.2.0) 中如何实现 Additional Request information 特性。本练习中开发了一个自定义的有界任务流,并使用同一任务流为角色和授权相关请求指定其他信息。可以使用类似方法开发和部署多个自定义工作流,根据需求的不同,实现文档的 30.11.5 和 30.11.6 节中所述自定义。
Nitin Patel 是 Oracle Identity Manager 开发团队的成员,致力于应用服务器安全、与一次性登录解决方案集成、OIM 服务器和 UI 开发等领域。他获得了比尔拉技术与科学学院的技术学士学位。