• 将 Oracle Forms 集成到 Oracle ADF Faces 中



    作者:Wilfred van der Deijl

     https://www.oracle.com/technetwork/cn/topics/wilfred-adf-forms-096013-zhs.html

    了解使用 Oracle ADF 组件扩展现有 Forms 应用程序的方法。

    2007 年 6 月发表

    Oracle Forms 已经支持 Web 好多年了。在 Web 浏览器中运行 Oracle Forms 是自然而然的事,Oracle 在其 2005 年的发展方向说明中指出仍将致力于开发和支持 Oracle Forms。

    另一方面,Java/JEE 技术快速发展,其采用也迅猛增长,并且通常向面向服务的体系结构 (SOA) 转变。通过 Oracle JDeveloper 和 Oracle 应用开发框架 (ADF),可以构建功能丰富的 JavaServer Faces (JSF) Web 应用程序。本文将描述可让您集成这两个领域的方法组合。

    Oracle ADF 是 Oracle JDeveloper 提供中的一个创新性 J2EE 开发框架。它通过将编写实现众所周知的设计模式和应用程序基础结构的代码的需求降至最低,简化了 Java 开发。Oracle ADF 将这些实现作为框架的一部分提供。

    本文重点介绍 ADF Faces,它是 ADF 框架的一个组件。ADF Faces 包含一组广泛的 UI 组件,这些组件构建在利用最新技术(包括部分页面呈现和 Ajax)的标准 JSF API 之上,可以提供丰富的交互式用户界面。本文假设使用 ADF Faces,但您也可以使用相同的方法将 Oracle Forms 与其他 Eeb 技术集成,如 PHP、Oracle Application Express 或 .Net ASP。

    在本文中,我将展示一个集成 Oracle Forms 与 Oracle ADF Faces 的极端示例,在该示例中,最终用户不会注意到 Oracle ADF Faces 用户界面与合并了现有 Oracle Forms 表单的页面之间的差异。有关此类集成的简单示例,参见图 1。只有显示订单的多记录块是现有 Oracle Forms 表单。页面的其余部分包含的是 Oracle ADF Faces 组件。

    图 1
    图 1 集成到 Oracle ADF Faces 中的 Oracle Forms 表单

    该示例演示了以下几点:

    • 视觉上,表单与 Oracle ADF Faces 页面紧密集成。没有显示菜单、工具栏和状态栏。该集成将 Oracle Forms 中的典型用户体验更改为较传统的 Web 体验。它使您能够逐步采用 Oracle ADF Faces,同时还可以利用 Oracle Forms 应用程序的特性。在该示例中,使用 Oracle ADF Faces 表替换 Oracle Forms 表单而不引起用户注意很简单。对于某些情况,该极端集成的程度可能过高,如果愿意,您可以为用户保留菜单、工具栏和/或状态栏。您可能还会遇到这样的情况:用户保留众所周知的 Oracle Forms 多文档界面,但调用 Oracle ADF Faces 页面执行特定任务。
    • 您无法在屏幕截图中清楚地看到系统只显示了特定客户的订单。当前选定的客户在(纯 Oracle ADF Faces)Customers 选项卡上,这意味着,系统将选定客户的 ID 传递给 Oracle Forms 以查询相应记录。
    • Oracle Forms 还可以将其上下文传递回 Oracle ADF Faces。当您滚动查看 Orders 多记录块时,显示订单行的 Oracle ADF Faces 从表会自动重新查询。这证明,订单 ID 已传递回 Oracle ADF Faces,并且 Oracle Forms 可以触发 Oracle ADF Faces 中的事件(如刷新从表)。在该示例中,Oracle ADF Faces 表位于同一页面上,但它也可以轻松地显示在其他 Web 页上。关键概念是,Oracle Forms 将上下文传递给 Oracle ADF Faces。
    • Oracle ADF Faces 页面还具有 Save Form 提交按钮。该 Oracle ADF Faces 按钮可将事件发送到 Oracle Forms,指示它执行提交操作,这意味着可以从 Oracle ADF Faces 中引发 Oracle Forms 事件。
    • 该屏幕截图没有显示的另一个情况是:消除了 Oracle Forms 小程序启动时间。Oracle Forms 使用客户端浏览器中的 Java 小程序。启动该小程序需要几秒钟。如果用户在 Oracle ADF Faces 页面间导航,其中某些页面包含 Oracle Forms 表单,您一定不希望用户在包含此类表单的每个页面上都体验这段启动时间。

    包括小程序

    第一个障碍是在 Oracle ADF Faces Web 页面上包含实际的 Oracle Forms 表单。有关 Oracle Forms 表单如何在客户端浏览器中运行的概况,参见图 2。该图在概念上显示 Oracle Forms(绿块)如何作为 Java 小程序(蓝块)在客户端浏览器的 Web 页面(黄块)上运行。

    图 2
    图 2 Web 页面上的 Oracle Forms 小程序

    通常,整个 Web 页面由 Oracle Forms servlet 提供服务。在此概念中,您不再依赖该 servlet 提供必需的 HTML。您需要将启动小程序所需的 HTML 合并到实际的 Oracle ADF Faces Web 页面中。

    您可以创建一个 JSF 组件来呈现该 HTML,并将该组件包括在 Oracle ADF Faces 页面上。现在,我们将使用更简单的方法:定义一个区域,然后在所有 Oracle ADF Faces 页面上重用它。首先,创建一个定义 Oracle ADF Faces 标记的 JSPX 文件,以便将 Oracle Forms HTML 输出到客户端:

         
    <?xml version='1.0' encoding='windows-1252'?>
    <af:regionDef var="regionParams" 
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:af="http://xmlns.oracle.com/adf/faces">
    <f:verbatim>
    . . . { actual HTML and JavaScript goes here } . . .
    </f:verbatim>
    </af:regionDef>     
    

    接下来,在 META-INF/region-metadata.xml 文件中注册该区域:

         
    <component>
    <component-type>com.example.oracleFormRegion</component-type>
    <component-class>oracle.adf.view.faces.component.UIXRegion</component-class>
    <component-extension>
    <region-jsp-ui-def>/regions/oraFormsRegion.jspx</region-jsp-ui-def>
    </component-extension>
    <attribute>
    <attribute-name>formModuleName</attribute-name>
    <attribute-class>java.lang.String</attribute-class>
    </attribute>
    </component>        
    

    最后,可以通过 <af:region> 在需要嵌入 Oracle Forms 表单的每个 Oracle ADF Faces 页面上重用该定义:

      
    <af:region id="oraFormRegion" regionType="com.example.oracleFormRegion">
    <f:attribute name="formModuleName" value="orders.fmx" <//>
    </af:region>        
    

    使用 <af:regionDef> 和 <af:region>,您只需定义一次启动 Oracle Forms 所需的 HTML 和 JavaScript,即可在需要嵌入 Oracle Forms 表单的每个 Oracle ADF Faces 页面上重用它。

    入站 JavaScript API

    关键要求是用来链接 Oracle Forms 与 Oracle ADF Faces 的方法。这两个环境应该能够彼此通信。对于将上下文(如当前选定的记录 ID)传递到其他环境,甚至用其他技术引发事件,该功能是必需的。这可通过基于 JavaScript 的 API 实现。Oracle ADF Faces 可以包括用于调入 Oracle Forms 的 JavaScript,Oracle Forms 应该能够执行与 Oracle ADF Faces 通信的 JavaScript。

    我在这里描述的第一个方法是使用入站 JavaScript API,该 API 允许 Oracle ADF Faces 引发 Oracle Forms 中的事件,从而在 Oracle Forms 中执行 PL/SQL 代码。Oracle ADF Faces 的 Save 按钮就是一个简单示例,该按钮既可以提交 Oracle Forms 表单,又可以在同一页面上提交并保存 Oracle ADF Faces 输入项。

    Oracle Forms 10g 第 2 版以及之前的版本没有原生 JavaScript API。这是 Oracle Forms 11g 计划引入的特性,但您可以使用业界标准的 LiveConnect API(所有主要的浏览器都实现了该 API)在 Oracle Forms 10g 第 2 版(或之前的版本)中自己实现该特性。该 API 允许 JavaScript 调用 Java 类的公共方法。Oracle Forms 小程序是一个 Java 类,如果该类公开了一个公共方法,就可以通过 JavaScript 调用该方法。

    Oracle 提供的 Oracle Forms 小程序没有提供公共方法,但您可以自己添加一个。将 Oracle Forms 小程序类 oracle.forms.engine.Main 划分为子类,然后添加一个 raiseEvent() 公共方法。这个新的公共方法可以通过客户端 JavaScript 调用,并可接收有效负载(消息)以传递到 Oracle Forms(参见图 3 中的步骤 1):

        
    document.formsapplet.raiseEvent('do_key', 'commit_form');        
    

    图 3
    图 3 入站 JavaScript API

    这个公共的 raiseEvent() 方法仍需触发活动 Oracle Forms 表单中的代码。您不能直接执行该操作。幸运的是,Oracle Forms 提供了一个称为可插入式 Java 组件 (PJC) 的框架来执行此类操作。PJC 是一个将 oracle.forms.ui.VBean 划分为子类的 JavaBean,可包括在 Oracle Forms 表单中。我们可以创建一个通用 PJC 来处理这个入站 JavaScript 通信。确保将这个 PJC 嵌入在每个表单中。通过 Java 开发 API (JDAPI),可以轻松地自动执行此任务。扩展的 Oracle Forms 小程序中的公共方法可以在活动表单的 PJC 上获得一个句柄,然后将有效负载传递给该 PJC(参见图 3 中的步骤 2):

         
    public void raiseEvent(String event, String payload) {
    CommunicatorBean communicator = findFirstCommunicator();
    if (null != communicator) {
    communicator.sendMessageToForms(event, payload);
      }
    }        
    

    PJC 可以触发一个名为 WHEN-CUSTOM-ITEM-EVENT 的 Oracle Forms 触发器(参见图 3 中的步骤 3):

    public void sendMessageToForms(String event, String payload) {
    try {
    // set properties to pass to Oracle Forms
    mHandler.setProperty(PROP_EVENT, event);
    mHandler.setProperty(PROP_PAYLOAD, payload);
    // trigger WHEN-CUSTOM-ITEM-EVENT trigger in Forms
    CustomEvent ce = new CustomEvent(mHandler, EVENT_MSG_TO_FORMS);
    dispatchCustomEvent(ce);
    } catch (FException e) {
    e.printStackTrace();
      }
    }
    

    最后,您可以使用 PL/SQL 代码检查事件的有效负载,并采取相应的操作:

               
    declare
    BeanEventDetails  ParamList;
    ParamType         number := text_parameter;
    Event             varchar2(1000);
    Payload           varchar2(1000);
    begin
    BeanEventDetails := get_parameter_list(:system.custom_item_event_parameters);
    get_parameter_attr(BeanEventDetails, 'Event',   ParamType, Event);
    get_parameter_attr(BeanEventDetails, 'Payload', ParamType, Payload);
    if event='do_key' then
    do_key(payload);
    end if;
    end;            
    

    这就完成了从客户端 JavaScript 到 Oracle Forms 端 PL/SQL 代码的过程。首先,客户端 JavaScript 调用扩展的 Oracle Forms 小程序的一个公共方法,并传递有效负载(步骤 1)。然后,该公共方法在活动 Oracle Forms 表单的 PJC 上获得一个句柄,并调用该 PJC 的公共方法以传递有效负载(步骤 2)。随后,PJC 触发 WHEN-CUSTOM-ITEM-EVENT 触发器,再次传递有效负载(步骤 3)。最后,处理触发器的 PL/SQL 代码可以检查有效负载并采取相应的操作。

    出站 JavaScript API

    接下来,您需要 Oracle Forms 能够触发其所在的 Web 页面上的事件。这可用于将从 Oracle Forms 返回的上下文和/或事件传递至 Web 应用程序。一个典型的示例是浏览 Oracle Forms 中的多记录块,同时将所选记录的 ID 传回 Web 应用程序。这可用于在 Web 应用程序中显示所选对象的详细信息。

    该通信可通过出站 JavaScript API 实现,该 API 支持 Oracle Forms 通过 PL/SQL 执行并计算 JavaScript。

    该 API 使用我们用于入站 JavaScript API 的同一 PJC。使用 PL/SQL 的内置 SET_CUSTOM_PROPERTY,可将参数传递至 PJC(参见图 4 中的步骤 1):

            
    begin
    -- set the Order ID
    set_custom_property('BLK_PJC.PJC', 1, 'EvalExpression',
    'document.getElementById(''frm:ordid'').value=' || :ord.ordid);
    end;             
    

    图 4
    图 4 出站 JavaScript API

    在这种情况下,PJC 的属性是要计算或执行的 JavaScript。然后,PJC 可获得其包含的 Java 小程序的句柄(参见图 4 中的步骤 2)。该小程序提供了一种方法,可将 JavaScript 作为 LiveConnect API 的一部分进行计算(参见图 4 中的步骤 3):

         
    public boolean setProperty(ID property, Object value) {
    if (PROP_EVAL_EXPR == property) {
    JSObject appletWindow = JSObject.getWindow(mHandler.getApplet());
    Object evalResult = appletWindow.eval(value.toString());
    // make result available as PJC property
    setProperty(PROP_EVAL_RESULT, evalResult);
    return true;
      }
    }        
    

    该示例仅设置了 Web 页面上一个输入元素(可能是隐藏元素)的值。您可以使用相同的出站 JavaScript API 将 Web 页面提交回 Web 服务器。这实际上与以下操作相同:即,用户在搜索表单中输入订单 ID,然后单击 Submit 按钮。

    挂起和重用小程序

    Oracle Forms 使用一个在 Web 浏览器中运行的 Java 小程序来显示表单和处理用户交互。启动较大的 Java 小程序(如 Oracle Forms 表单)会消耗资源,可能需要几秒钟的时间。在典型的 Oracle Forms 安装中,这没有什么影响,因为您在会话的开始就启动了 Oracle Forms 小程序,并且会继续使用一段时间,而不会导航到其他 Web 页面。然而,在本文介绍的体系结构中,用户可以在 Web 页面之间切换。其中某些页面可能包含 Oracle Forms 表单,而其他页面可能不包含 Oracle Forms 表单。Web 浏览器和 Sun Microsystems 的 Java 虚拟机的默认行为是当您离开该页面时销毁小程序。

    在客户端使用 Java 虚拟机 1.4.2 或更高版本时,您可以在小程序的 HTML 中额外指定一个名为 legacy_lifecycle 的参数。该参数可指示虚拟机在您离开该页面时不销毁小程序。小程序将继续在后台运行,并被放入原有生命周期缓存中。当用户返回包含完全相同的小程序声明的 Web 页面时,该小程序就会被重新激活。这意味着,小程序的 HTML 必须完全相同,生命周期缓存才能恢复以前的小程序。这是您在 JSF 区域或 JSF 自定义组件中只希望声明 HTML 一次的另一个原因。

    使用该特性意味着,针对整个浏览器会话只启动一次小程序。当用户返回包含 Oracle Forms 表单的页面时,完全没有小程序启动时间。

    对小程序重新激活进行操作

    小程序从这个缓存中恢复到挂起时的状态。这意味着,来自上一个 Web 页面的 Oracle Forms 表单仍在运行。您可能希望向小程序的重新激活添加操作。遗憾的是,在小程序重新激活期间不会触发任何 Oracle Forms 触发器。在小程序重新激活期间,将调用 Oracle Forms 小程序的一个有争议的 show() 方法。您可以对该方法进行改写,如下所示:

                
    public void show() {
    super.show();
    raiseEvent("WHEN-APPLET-ACTIVATED", "");
    }                       
    

    该操作使用入站 JavaScript API 向 Oracle Forms 发送事件,并且可在 PJC 的 WHEN-CUSTOM-ITEM-EVENT 触发器中处理:

                               
    declare
    BeanEventDetails  ParamList;
    ParamType         number := text_parameter;
    Event             varchar2(1000);
    Payload           varchar2(1000);
    begin
    BeanEventDetails := get_parameter_list(:system.custom_item_event_parameters);
    get_parameter_attr(BeanEventDetails, 'Event',   ParamType, Event);
    get_parameter_attr(BeanEventDetails, 'Payload', ParamType, Payload);
    if event='WHEN-APPLET-ACTIVATED' then
    -- add handling here
    end if;
    end;
    

    需要登录表单

    应用程序中包含的不同 Oracle ADF Faces 页面都可以包含 Oracle Forms 表单。这些不同的页面可能希望调用不同的表单。您不能将这些表单的名称作为小程序 HTML 中的普通参数进行传输。这要求每个 Web 页面上的 HTML 不同,从而会削弱原有生命周期特性的作用。该特性需要完全相同的 HTML 才能重用挂起的小程序。

    您可以通过始终指定与 Oracle Forms 表单名称相同的“登录表单”来规避此要求。要启动的实际表单的名称可以包含在 Web 页面的隐藏元素中:

         
    <input type="hidden" id="formname" value="orders.fmx"<//>  
    

    登录表单的 WHEN-NEW-FORM-INSTANCE 触发器可以通过计算 document.getElementById('formname').value 来确定实际需要的表单,它使用出站 JavaScript API。然后,登录表单可以启动所请求的表单:

         
    declare
    formName varchar2(1000);
    begin
    while true loop
    -- get the form name
    set_custom_property('BLK_PJC.PJC', 1, 'EvalExpression', 
    'document.getElementById(''frm:oraFormRegion:formname'').value');
    formName := get_custom_property('BLK_PJC.PJC', 1, 'EvalResult');
    -- start the form
    call_form(formName);
    if (get_custom_property('BLK_PJC.PJC', 1, 'AppletActive')='FALSE' then
    -- exit the loop if the user is closing the browser
    exit;
    end if;
    end loop;
    end;      
    

    在生命周期缓存中重新激活小程序时,“实际”表单会运行。该表单将通过自动退出来处理小程序重新激活。这将返回对登录表单中无限循环的控制,然后再次检查寄宿的 Web 页面以确定要启动的表单。由于用户将关闭浏览器,因此终止该循环的唯一方法就是停止小程序。

    将上下文放入 Oracle Forms 中

    原有生命周期特性在将 Web 应用程序的上下文传递到 Oracle Forms 时引入了一个问题。如果您希望结合一个 Oracle Forms 表单以编辑 Oracle ADF Faces 页面中的订单,该怎么办?您可能希望将所选订单 ID 从 Oracle ADF Faces 应用程序传递到 Oracle Forms。而且,您不能像通常将参数添加到 HTML 以包含 Oracle Forms 小程序那样来实现此目的。这意味着每个订单的 HTML 都不一样,从而无法重用挂起的小程序。

    同样,您也可以使用出站 JavaScript API 来规避此问题。您可以将订单 ID(或者您要传递的上下文)作为 Oracle ADF Faces 页面的不可见项进行合并。Oracle Forms 表单可以在 WHEN-NEW-FORM-INSTANCE 触发器中检查该值,并采取相应的动作:

           
    declare
    orderID  number;
    begin
    -- get the order ID
    set_custom_property('BLK_PJC.PJC', 1, 'EvalExpression', 
    'document.getElementById(''frm:orderID'').value');
    customerID := get_custom_property('BLK_PJC.PJC', 1, 'EvalResult');
    :parameter.ordid:=orderID;
    -- execute query (where clause refers :parameter.ordid)
    do_key('execute_query');
    end;
    

    可视化集成

    您可以选择在 Oracle ADF Faces 页面上包含一个表单,并且不允许用户导航到其他 Oracle Forms 表单。甚至可以使用户认为他们没有使用 Oracle Forms。为此,您可能希望移除菜单、工具栏、状态栏和 Oracle Forms 边栏。

    实现以上操作的最简单方法是剪辑 Oracle Forms 小程序。将小程序 HTML 包含在单个 <div> 元素中,这代表一个矩形区域。该 <div> 的高度和宽度可以设置为比所包含的 Oracle Forms 小程序的大小小一些。而且,Oracle Forms 小程序的 x 和 y 位置可以设置成与周边的 <div> 元素相关的负值,这将产生一个较小的查看窗口,只显示 Oracle Forms 表单的相关部分,如图 5 中红色方框的区域所示:

    图 5
    图 5 具有有限视图端口的剪辑的 Oracle Forms 表单

    结论

    如您所见,可以使用 ADF Faces 扩展现有的 Oracle Forms 应用程序。现在,您可以在使用 ADF Faces 的同时保护以前的 Forms 投资。

    您还可以使用该方法从 Oracle Forms 用户体验切换到更经典的 Web 用户体验。在该案例中,您可以从所有 Oracle Forms 表单中以可视方式删除菜单、工具栏和状态栏。最初,您可以将现有的 Oracle Forms 表单作为 Oracle ADF Faces Web 页面上的单个对象重用。所有应用程序流控制均由 Oracle ADF Faces 处理,从而能够即时地为用户提供直观的 Web 体验,同时允许您重用现有的表单。该方法允许您一次使一个 Oracle ADF Faces 前端适应您的应用程序。

    该集成还允许您构建嵌入了 Oracle Forms 表单的 portlet。这些 portlet 可以在 Oracle Portal 环境中使用,也可以与刚发布的 Oracle WebCenter 技术结合使用。

    该技术的另一种用法是将单独的 Oracle Forms 表单嵌入 Web 页面,以完成 BPEL 人工任务。Oracle BPEL 可以监视和控制您的业务流程。业务流程可能在某个阶段包含人工任务,如经理批准或拒绝采购订单。使用本文介绍的技术,您可以重用现有的 Oracle Forms 表单来编辑 BPEL 人工任务中的采购订单。

    如您所见,本文介绍的技术可能是一系列新的可能性的基础。如果您了解该想法并给出一些点子,可能会赶上组织内的其他用户。请访问 www.oratransplant.nl/oracle-forms-as-web-component,获得有关此方法的更多详细信息;您可以获得有关构建您自己的示例集成的分步指南,阅读详细的文章,并获得示例应用程序。


    Wilfred van der Deijl 是 Eurotransplant 的高级系统架构师。他拥有 12 年以上的 Oracle 工具使用经验。他管理一个与 Oracle 有关的网志 ( OraTransplant),并且是 Oracle 开发工具客户咨询部的成员。

    false ,,,,,,,,,,,,,,,,

  • 相关阅读:
    卷积神经网络
    舍弃—Dropout
    池化—Pooling
    Python基础知识点——简单 函数
    同事将excel数据转化为pdf,提前下班了,而我还在苦逼地做表
    怎么才能隐藏的IP?打造超强IP池项目,让你自己都忘记原本的IP
    Python爬取抖音视频(没有水印的哟)
    Python可视化:matplotlib 制作雷达图进行对比分析
    用于GIS(地理信息系统)和三维可视化制图的Python库
    关于如何在文件中调用命令窗口执行代码(以python为例)
  • 原文地址:https://www.cnblogs.com/shuihaya/p/14388116.html
Copyright © 2020-2023  润新知