zoukankan      html  css  js  c++  java
  • Oracle OAF 应用构建基础之实现控制器 (转)

    原文地址: Oracle OAF 应用构建基础之实现控制器 

    设计一个OA Controller

    如OA Framework Page解析中所描述的,OA Controller定义了web beans的行为。具体来说,编写控制器代码的目的是:
    •在运行时处理/初始化UI(包含那些通过编程方式添加的layout)
    •拦截或响应按钮按下之类的用户事件

    控制器不应该包含任何业务逻辑;这应该属于模型类。

    必备知识

    通常来说,在提出如何设计控制器之前,应该思考一下是否需要创建控制器。

    作为一条规则,应该只在绝对必要的情况下才编写控制器。如果可以通过设计的方式创建页面,就不要通过编程的方式实现region和item。编程方式创建的web beans不能被个性化,重用或继承。而且,一些硬编码的layouts可能会丢失BLAF UI样式。

    实现视图中说过,所有位于共同组件中的顶级regions必须与一个控制器关联。

    粒度

    OA Controllers可以与任何region关联(任何实现oracle.apps.fnd.framework.webui.beans.OAWebBeanContainer接口的web beans);不能将控制器与items关联。

    许多OA Framework新手都想知道控制器应该是”多大“。应该一个页面一个,或一个功能region一个(比如“Search” region),或一个复合web bean(比如一个table)一个,或者?答案是要看情况。

    最初,在一个非常简单的页面,你可能不需要任何控制器(如果没有工作要作就不需要创建控制器)。如果需要编写代码,你需要根据下面的条件决定创建什么样的控制器:
    •利于封装,一个web bean实现了它自己的行为
    •组件重用,如果组件被设置为重用,它必须是自包含,自已自足。
    •代码实用性,尽管页面包含了8个regions时可以很容易的添加8个控制器(每个包含少量的代码),这种“纯”OO的观念可以导致代码维护困难,可能导致产品代码文件膨胀。

    有一些方法可以帮助决定如何处理:
    •永远不要从child bean中设置parent/grandparent web bean的属性。
    •为相关联的region定义控制器来设置region和它的子孙region的属性。如果需要主控制器管理多个子/孙web bean,控制器应该与适当的父/祖父bean相关联。
    •对于复杂的beans(比如OATableBean)应该将控制器关联到bean自身,或关联到一个简单的容器bean中(如果它实现功能逻辑单元)。

    通常,应该为页面创建少于满足上面规则和考虑数量的控制器。对于非常简单的页面,通常是为pageLayout区域关联单个的控制器。对于更复杂的 页面,应该为各个功能组件(比如,查询页面中典型的“Search”区域控制器和“Results”区域控制器)创建少量不同的控制器。共享区域应该拥有 自己的适当的控制器。


    模型性/重用

    在同一组相关联的页面中,你有时将找到可以重用代码的机会。下面是创建模块性更强的控制器代码的方法:
    •在控制器中添加私自己的私有方法。
    •创建一个公用的控制器类(它是oracle.apps.fnd.framework.webui.OAControllerImpl),然后为有需要的页面/区域继承这个类。
    •创建辅助的实用工具类,控制器中可以根据需要代理。这些类不需要实现任何OA Framework类或接口,应该被包含在与它们所辅助的控制器类所在的包中。注意,静态方法适合于在这些类中使用,当使用静态方法时,应该考虑下面的问题: ◦不能影响子类中的静态方法。
    ◦封装相关常量和静态方法。(There are packaging implications related to the use of constants and static methods )

    线程安全

    OA Framework被设计为支持多线程web bean访问(尽管还没有实现)。大部分对于你的代码来说是透明的,只有少量规则必须在控制器代码中遵守:
    •如果在控制器或辅助类中使用静态方法,则永远不要包含状态。
    •总是将页面的OAPageContext传递给任何web bean存储器(如果需要可以带OAPageContext)。比如,使用setText(OAPageContext pageContext, String text)代替setText(String text)。


    状态管理

    不要在控制器中或你实例化的辅助类中添加非易失性成员变量。OA Framework不会钝化成员变量,因此一旦虚拟机失效被支持后将不能恢复这些值。可以添加static final成员变量。


    编码规则


    创建一个控制器

    为一个区域创建控制器:
    1.在JDEveloper Structure页面中选择区域
    2.右键选择Set New Controller...
    3.在New Controller对话框中,输入包和类名。选择OK创建与选择区域关联的控制器。注意Inspector中的Controller Class属性值是类的全名,如: oracle.apps.fnd.framework.toolbox.tutorial.webui.HoMESearchCO。

    JDeveloper将创建控制器模板。

    /*===========================================================================+
    | Copyright (c) 2001, 2003 Oracle Corporation, Redwood Shores, CA, USA |
    | All rights reserved. |
    +===========================================================================+
    | HISTORY |
    +===========================================================================*/
    package oracle.apps.fnd.framework.toolbox.tutorial.webui;
    
    import oracle.apps.fnd.common.VersionInfo;
    import oracle.apps.fnd.framework.webui.OAControllerImpl;
    import oracle.apps.fnd.framework.webui.OAPageContext;
    import oracle.apps.fnd.framework.webui.beans.OAWebBean;
    
    /**
    * Controller for ...
    */
    public class OrderSummaryCO extends OAControllerImpl
    {
    public static final String RCS_ID="$Header$";
    public static final boolean RCS_ID_RECORDED =
    VersionInfo.recordClassVersion(RCS_ID, "%packagename%");
    
    /**
    * Layout and page setup logic for a region.
    * @param pageContext the current OA page context
    * @param webBean the web bean corresponding to the region
    */
    public void processRequest(OAPageContext pageContext, OAWebBean webBean)
    {
    super.processRequest(pageContext, webBean);
    }
    
    /**
    * Procedure to handle form. submissions for form. elements in
    * a region.
    * @param pageContext the current OA page context
    * @param webBean the web bean corresponding to the region
    */
    public void processFormRequest(OAPageContext pageContext, OAWebBean webBean)
    {
    super.processFormRequest(pageContext, webBean);
    }
    
    }

    注意: 缺省的模板内容不包含processFormData(OAPageContext pageContext, OAWebBean webBean)方法,这个方法在POST处理的第一个阶段被调用。如果需要(非常少见),可以将它加到控制器中。

    注意: 也可以通过编程的方式将控制器与区域关联。查看OAWebBeanContainer中的setControllerClass(String javaClass)方法。


    处理HTTP GET

    在GET处理过程中,每个控制器的processRequest(OAPageContext pageContext, OAWebBean webBean)方法被按照它们被实例化时的层级结构而依次被调用。处理从pageLayout bean开始,然后递归处理整个层级结构。初始化页面——或影响层级结构中的web bean(通过设置属性,创建web bean等等)——属于processRequest()方法。

    注意: 传递到processRequest()方法中的oracle.apps.fnd.framework.webui.OAWebBean参数是与当前控制器关联的区域。

    下面是一个典型的processRequet的代码。它描绘的是根据从“search”页面传递过来的参数,初始化用于查看的“detail”页面。

    /**
    * Layout and page setup logic for region.
    * @param pageContext the current OA page context
    * @param webBean the web bean corresponding to the region
    */
    public void processRequest(OAPageContext pageContext, OAWebBean webBean)
    {
    // Always call this before adding your own code.
    super.processRequest(pageContext, webBean);
    
    // Get the purchase order number from the request.
    String rderNumber = pageContext.getParameter("headerId");
    
    // We need to set the page header text to include the PO order number for reference.
    MesSageToken[] tokens = { new MessageToken("PO_NUMBER", orderNumber) };
    
    // Always use a translated value from Message Dictionary when setting strings in
    // your controllers.
    String pageHeaderText = pageContext.getMessage("ICX", "FWK_TBX_T_PO_HEADER_TEXT", tokens);
    
    // Set the po-specific page title (which also appears in the breadcruMBS. Since this
    // controller is associated with the page layout region, simply cast the webBean
    // parameter to the right type and set the title.
    
    ((OAPageLayoutBean)webBean).setTitle(pageHeaderText);
    
    // Now we want to initialize the query for our single purchase order with all of its
    // details.
    OAApplicationModule am = pageContext.getApplicationModule(webBean);
    Serializable[] parameters = { orderNumber };
    am.invokeMethod("initDetails", parameters);
    
    } // end processRequest()

    在调用super.processRequest(pageContxt, webBean)后,范例中的代码从request参数中获取名为“headerId(从Search页面传递过来的参数)”。这个值被显示在页面标题和 breadcrumbs上,并且它被传递给模型以便查询。
    使用页面的title值定义页面标题和breadcrumbs:

    由于显示于页面中的值必须被翻译,我们在Oracle应用消息字典(Oracle Application Message Dictionary)中创建了一个名为FWK_TBX_T_PO_HEADER_TEXT的消息,消息内容为“Purchase Order: &PO_NUMBER”。这个代码定义了以令牌PO_NUMBER作为Purchase Order Number的占位符,然后从oracle.apps.fnd.framework.webui.OAPageContext(它将操作委派给 AOL/J)中提取翻译后的版本。然后将翻译后的字符串作为页面标题。

    警告: 不要在用户界面中使用硬编码的文本值。所有以编程方式显示的文本值必须来源于消息字典(Message Dictionary)。也可以在设计时在web bean中使用这种方式(所有显示的bean属性都是被翻译的),或者也可以从多国语言表中查询出值来显示。

    最后,这个只读的”details“页面自动按给定的编号进行查询而不管它是否会被渲染。它通过将编号传递给页面根应用模块的initDetails()方法。然后应用模块将参数传递给适当的视图对象,在那里将参数与WHERE子句绑定并执行查询。


    修改Bean属性

    注意: 作为规则来说,更好的修改web bean属性的方法是使用局部页面渲染(partial page rendering (PPR))和SPEL,在Dynamic User Interface中有描述。在不能通过PPR和SPEL的环境下,也必须在processRequest()方法中修改web bean层级结构(这节被包含在GET处理一章中,也是由于只能在processRequest()方法中才允许修改web bean层级结构)。

    如果需要以编程方式在响应表单提交的事件中修改层级结构,必须forward到同一个页面的processRequest()方法(见下面POST事件处理)。作出这个限制的原因有:
    •确保web bean层级结构能在需要的时候被正确的重建。
    •Beans被适当的初始化。主要是Rendered属性,或影响复杂组件渲染的prepareForRendering()方法。
    •Bean层级结构被放在同一个方法中维护。

    修改web bean的属性时,只需要简单的根据它的名称(在JDeveloper中赋给它的ID)查找到正确的bean,然后按下面的方法调用适当的方法。

    警告: 当获得web bean时,在调用它的任何方法前都需要检查对象是否为空。即使你认为bean被包含于web bean层级结构中,但也有可能在用户使用个性化定制时半它隐藏了。

    processRequest(OAPageContext pageContext, OAWebBean webBean)
    {
    // Always call this before adding your own code.
    super.processRequest(pageContext, webBean);
    
    OATableBean table = (OATableBean)webBean.findIndexedChildRecursive("OrdersTable");
    
    if (table == null)
    {
    MessageToken[] tokens = { new MessageToken("OBJECT_NAME", "OrdersTable")};
    throw new OAException("ICX", "FWK_TBX_OBJECT_NOT_FOUND", tokens);
    }
    
    // Set the purchase-order specific "control bar" select text:
    // "Select Purchase Order(s) and..."
    
    String selectPOText = pageContext.getMessage("ICX", "FWK_TBX_T_SELECT_PO", null);
    table.setTableSelectionText(selectPOText);
    
    }

    使用findIndexedChildRecursive(String name)方法可以在整个web bean层级结构中查找到第一个与名称匹配的被索引的子对象。如果如果要修改的web bean是一个被命名的UIX子对象(或,如果你不确定它是否“被命名(named)“或”被索引(indexed)“),则使用 findChildRecursive(String name)方法。
    如果需要修改控制器区域的属性,只需要将processRequest()的OAWebBean参数转换为正确的类型并调用需要的方法。


    编程的方式创建Bean

    注意: 本节包含于GET处理部分,因为只允许在processRequest()方法中修改web bean层级结构。

    如果需要在响应表单提交事件中添加web bean到层级结构中,必须forward到同一个页面的processRequest()代码中执行。

    作为规则,如果你可以通过设计的方式产生web bean就不应该通过编程的方式产生web beans。另外,如果你的页面与局部页面渲染相关,则也不能在运行时修改web bean层级结构。

    对于那些极少见的必须手工实例化web bean的情况,则使用OAControllerImpl类中的createWebBean()工厂方法。不要直接使用web bean的构造器,不必担心要直接创建oracle.apps.fnd.framework.webui.OAWebBeanFactory,因为控制器 的createWebBean()方法代理了OAWebBeanFactory。

    注意: 对于这些手工创建的beans,使用工厂方法时可以指定bean的“name”(JDeveloper中的ID属性)。避免使用deprecated的方 法,它允许你在创建web bean时不指定name。web bean的名称(name)在同一个页面中必须是一个唯一标识。另外,bean的名称可能被OA Framework用于BC4J对象实例名(比如应用模块实例),因此不应该包含Java命名中规定的无效字符。

    比如,下面的代码描述了如何创建两个web bean并将它们添加到父区域中。

    OATableLayoutBean tableLayout = (OATableLayoutBean)findIndexedChildRecursive("tableLayout");
    
    // Create a row layout and give it the unique ID "topRow"
    OARowLayoutBean row = (OARowLayoutBean)createWebBean(pageContext,
    OAWebBeanConstants.ROW_LAYOUT_BEAN,
    null, // no need to specify a data type
    "topRow");
    
    // Create a row layout and give it the unique ID "bottomRow"
    OARowLayoutBean anotherRow = (OARowLayoutBean)createWebBean(pageContext,
    OAWebBeanConstants.ROW_LAYOUT_BEAN,
    null, // no need to specify a data type
    "bottomRow");
    
    // Always check to see if a web bean exists.
    if (tableLayout != null)
    {
    
    // Add the two row layout beans to the table so the "topRow" renders above
    // the "bottomRow"
    tableLayout.addIndexedChild(row);
    tableLayout.addIndexedChild(anotherRow);
    }

    也可以通过编程的方式将设计时定制的web bean关联到父区域中。比如,在下面的代码中,名为“HomeSearchRN”的stackLayout区域是在JDeveloper中定义的,但它 必须通过编程的方式创建side navigation component。

    OASideNavBean sideNav = (OASideNavBean)createWebBean(pageContext,
    OAWebBeanConstants.SIDE_NAV_BEAN,
    null, // no need to specify a data type
    "sideNav" // always specify name);
    
    OAStackLayoutBean search =
    (OAStackLayoutBean)createWebBean(pageContext,
    "/oracle/apps/fnd/framework/toolbox/tutorial/webui/HomeSearchRN",
    "HomeSearchRN", // always specify name
    true); // region created in Oracle JDeveloper OA Extension
    
    sideNav.addIndexedChild(search);

    约束

    OA Framework并不能很容易的支持通过编程的方式添加、删除、替换任何“默认(default)”区域中的子对象(比如OA Extension中的defaultSingleColumn区域是 oracle.apps.fnd.framework.webui.beans.layout.OADefaultSingleColumnBean的实 例)。这些区域应该通过设计的方式定义。如果绝对必须替换或删除“默认(default)”区域(不能添加item),则要遵循下面的步骤:
    1.调用webBean.findIndexedChildRecursive()获得要被移除或替换的子web bean。
    2.通过调用子web bean的childWebBean.getAttribute(OAWebBeanConstants.PARENT)方法获取子web bean的父对象。

    注意: OAWebBeanConstants.PARENT属性被用作OA Framework内部开发使用(如果查看OAWebBeanConstants的Javadoc将看到警告信息)。只可以对缺省区域使用这个入口。另 外,缺省区域已经不被推荐使用(deprecated),因此不应该在新的开发中使用这这些。
    1.执行从父bean中替换或移除自己的操作。


    处理HTTP POST(表单提交)

    在HTTP POST处理过程中,OA Framework首先检查页面的web bean层级结构是否位于它的缓存中。如果没有(资源被限制或者用户使用了浏览器的后退按钮),则OA Framework必须在处理前重新创建web bean层级结构。这意味着processRequest()中的代码被重新执行,就好像浏览器发出了一个HTTP GET请求。

    注意: 可能发生的重建web bean层级结构将导致产生了大量编码上的考虑,这些在Chapter 6: Supporting the Brower Back Button和OA Framework View和Controller编码规范中有完整的描述。

    POST的主要处理过程发生在整个web bean层级结构中的两个分开的途径中:
    •首先,OA Framework将在整个web bean层级结构中递归调用web bean的processFormData()方法将form的数据写入模型。任何需要在这个处理阶段执行的代码应该添加到控制器的 processFormData(OAPageContext pageContext, OAWebBean webBean)方法。
    •假设第一阶段的处理过程中没有发生异常,OA Framework处理第二阶段,在每个web bean上调用processFormRequest(OAPageContext pageContext, OAWebBean webBean)。


    processFormData()

    多数情况(并非所有情况)下没有理由要覆盖这个方法。实际上,使用这种方法只会在极端的情况下,而不像是在OA Framework应用中:如果区域的数据源不是一个视图对象,因此没有为各个web bean定义视图实例和属性,这时你可以在区域的processFormData()方法中编码将子web bean的数据写入适当的数据源。

    注意: OA Framework在item级实现了processFormData(),但你只能在region级别覆盖它,因此如果你实现了这个方法则必须处理 region中的所有item。如果是有选择性的修改,则要记得先要调用super.processFormData(OAPageContext pageContext, OAWebBean webBean)。


    processFormRequest()

    任何处理用户表单提交的动作属于processFormRequest()方法。

    下面是一个典型的processFormRequest()的代码。它描述了好何决定是哪个组件的区域表单提交(在这里是“Go“按钮),如果开始 在模型中查询,如何执行一个JSP Forward回到同一个页面以便在processRequest()方法中修改web bean的属性。

    OASideNavBean sideNav = (OASideNavBean)createWebBean(pageContext,
    OAWebBeanConstants.SIDE_NAV_BEAN,
    null, // no need to specify a data type
    "sideNav" // always specify name);
    
    OAStackLayoutBean search =
    (OAStackLayoutBean)createWebBean(pageContext,
    "/oracle/apps/fnd/framework/toolbox/tutorial/webui/HomeSearchRN",
    "HomeSearchRN", // always specify name
    true); // region created in Oracle JDeveloper OA Extension
    
    sideNav.addIndexedChild(search);

    这个例子展示了如何使用setForwardUrl()方法传递请求参数,包括了如休替换一个已经存在的参数值(在这里,“X”将成为目标页面被“忽略(ignore)“的值)。 import 

    com.sun.java.util.collections.HashMap;
    import oracle.bali.share.util.IntegerUtils;
    
    ...
    
    processFormRequest(OAPageContext pageContext, OAWebBean webBean)
    {
    // Always call this before adding your code
    super.processFormRequest(pageContext, webBean);
    
    String poEvent = pageContext.getParameter("poEvent");
    
    HashMap params = new HashMap(2);
    
    // Replace the current poEvent request parameter value with "X"
    params.put("poEvent", "X");
    
    // IntegerUtils is a handy utility
    params.put("poStep", IntegerUtils.getInteger(5));
    
    pageContext.setForwardURL("OA.jsp?page=/oracle/apps/dem/employee/webui/EmpDetailsPG", // target page
    null, // not necessary with KEEP_MENU_CONTEXT
    OAWebBeanConstants.KEEP_MENU_CONTEXT, // no change to menu context
    null, // No need to specify since we're keeping menu context
    params, // request parameters
    true, // retain the root application module
    OAWebBeanConstants.ADD_BREAD_CRUMB_YES, // display breadcrumbs
    OAException.ERROR); // do not forward w/ errors
    }

    注意: 如果视图对象被作为被显示的web bean的数据源,则不要移除视图对象和它的行,以及嵌套包含的应用模块。如果你需要在定向到页面之前移除这些对象,则将不会显示视图对象中数据(出于性 能优化的原因),在作出移除的调用后,确保使用 oracle.apps.fnd.framework.webui.OAPageContext.forwardImmediatelyOAPageContext.setforwardURL 方法定向到新页面。这保证了forward动作将立即发生,当前页面中forward调用后其它的web bean将不会处理;否则,移除视图对象或行实例将导致后续处理产生不良影响。


    使用不同的技术POST到OA Framework页面

    如果你使用不同的技术(比如JTT页面)POST到OA Framework页面,OA Framework只会执行目录页面的processRequest段。它不执行processFormData和processFormRequest段。


    与模型交互

    简单来说,应该只从OA Controller中直接访问应用模块。换言之,在控制器中唯一有效的模型导入代码如下:
    import oracle.apps.fnd.framework.OAApplicationModule;
    不应该访问视图对象直接执行查询、迭代行集或与下层的实体交互。比如,下面的代码(尽管技术上是可行的)是不符合OA Framework Controller Coding Starndards的。 

    import oracle.apps.fnd.framework.OAViewObject;
    ...
    
    // Get the root application module
    OAApplicationModule am = pageContext.getRootApplicationModule();
    
    // Find the view object you want to query
    OAViewObject vo = (OAViewObject)am.findViewObject("<instanceName>");
    
    ...

    如果需要执行视图对象查询,应该按下面在“Search”区域中按下“Go”按钮的事件处理的例子的方式。 
    首先,添加方法到应用模块中(这个例子中,它是页面的根应用模块)它接收查询,然后将它委派给视图对象执行查询(查看

    实现模型获取关于查询的信息)。

    public void search(String orderNumber, String created, String showMyOrders)
    {
    PoSummarySimpleExpVOImpl vo = getPoSummarySimpleExpVO();
    
    // Always check for the null condition if the VO cannot be found/created
    if (vo == null)
    {
    MessageToken[] tokens = { new MessageToken("OBJECT_NAME", "PoSummarySimpleExpVO")};
    throw new OAException("ICX", "FWK_TBX_OBJECT_NOT_FOUND", tokens);
    }
    
    vo.initQuery(orderNumber, created, showMyOrders);
    
    } // end search()

    然后,添加如下的按钮处理代码到控制器中,它调用应用模块中对应的方法。 
    注意,总是应该在processFormRequest()的代码中检查事件源;不要假设浏览器发送的POST请求是由于你的item被选中了(即使是一个只有一个按钮的简单页面)。在后台,OA Framework经常提交页面的表单,而这可能是不是你所期望的。

    processFormRequest(OAPageContext pageContext, OAWebBean webBean)
    {
    
    // Check to see if the "Go" button was pressed...
    if (pageContext.getParameter("gButton") != null)
    {
    // Get the search criteria
    String rderNumber = pageContext.getParameter("SearchOrder");
    String created = pageContext.getParameter("Created");
    String showMyOrders = pageContext.getParameter("MyOrders");
    
    OAApplicationModule am = pageContext.getApplicationModule(webBean);
    
    // All parameters passed using invokeMethod() must be serializable.
    Serializable[] parameters = { orderNumber, created, showMyOrders };
    am.invokeMethod("search", parameters);
    }
    }

    技巧: 不要在服务端BC4J组件中调用invokeMethod(),任何你传递的参数必须是Serializable类型的。上例中展示的的 invokeMethod()方法需要的参数都是字符串。如果需要传递其它对象类型,可以使用带一个类型数组参数版本的invokeMethod()。比 如:
    Class[] parameterTypes = { String.class, Hashtable.class, Number.class ...};
    am.invokeMethod("search", parameters, parameterTypes);
    类似地,由于视图对象是实体对象的导管——不应该在控制器中直接与视图对象交互——也应该通过应用模块来处理实体操作。 
    注意: 如实现模型中描述的,添加到应用模块中的方法命名应该与UI“事件(events)“对应。比如,如果用户按了“Create”按钮,应用模块方法应该命名为“create”等等。

    创建的实例

    processFormRequest(OAPageContext pageContext, OAWebBean webBean)
    {
    OAApplicationModule am = pageContext.getApplicationModule(webBean);
    am.invokeMethod("create", null);
    }

    删除的实例

    这个例子展示了调用共享区域中的嵌套应用模块中的delete方法而不是调用页面根应用模块中的方法。

    processFormRequest(OAPageContext pageContext, OAWebBean webBean)
    {
    
    if (pageContext.getParameter("DeleteYesButton") != null)
    {
    // User has confirmed that she wants to delete this purchase order.
    // Invoke a method on the AM to set the current row in the VO and
    // call remove() on this row.
    
    String poHeaderId = pageContext.getParameter("poHeaderId");
    Serializable[] parameters = { poHeaderId };
    
    OAApplicationModule am = pageContext.getApplicationModule(webBean);
    am.invokeMethod("delete", parameters);
    }
    
    ...

    自定义动作实例(“Approve”)

    processFormRequest(OAPageContext pageContext, OAWebBean webBean)
    {
    if (pageContext.getParameter("Approve") != null)
    {
    OAApplicationModule am = pageContext.getApplicationModule(webBean);
    am.invokeMethod("approve");
    }
    }

    提交操作实例

    processFormRequest(OAPageContext pageContext, OAWebBean webBean)
    {
    // Simply telling the transaction to commit will cause all the Entity Object validation
    // to fire.
    //
    // Note: there's no reason for a developer to perform. a rollback. This is handled by
    // the OA Framework if errors are encountered during the processFormData phase.
    
    OAApplicationModule am = pageContext.getApplicationModule(webBean);
    am.invokeMethod("apply");
    }

    禁用校验

    有多个机会可以屏蔽在处理OA Framework HTTP POST过程中的校验。比如,实现表格中的”Add Another Row“中,在用户添加新行的操作时,可能不需要因为未填写完整的行数据而显示错误信息。同样,你可能在一个多步骤的页面流中想要将校验延时到最后一个预 览提交页面,或者通过tabs导航到同一个下层对象的不同视图上时。


    禁用服务端校验

    为了阻止从模型校验逻辑中抛出异常,在页面中与下面列表对应的bean上调用setServerUnvalidated(true)方法(记住在processRequest()方法中添加修改web bean的代码):
    •OASubmitButtonBean
    •OATableBean
    •OAAdvancedTableBean
    •OASubTabLayoutBean
    •OANavigationBarBean
    •OADefaultHideShowBean
    •OAHideShowHeaderBean

    注意: 也可以在设计时设置组件的Disable Server Side Validation属性为True,也可以为那些配置为提交表单的链接或图标设置禁用校验。查看下面的Javascript. URL一节获得更多信息。

    当用户执行一个由这些bean导致的表单提交时,OA Framework按上面描述的方式执行所有的HTTP POST处理——包括执行属性级别的校验逻辑(实体级别的校验没有被执行)。如果在处理processFormData()过程中抛出了 oracle.apps.fnd.framework.OARowValException或 oracle.apps.fnd.framework.OAAttrValException异常(功它们被deprecated的子类),OA Framework只是简单的忽略这些异常,并继续执行就像没有遇到异常一样。

    注意: OA Framework不会忽略processFormData()中的严重异常(比如NullPointerException)。这些会按正常的方式显示 出来,并且不会继续处理processFormRequest()。而且processFormRequest()中由你或者由BC4J抛出的异常都会被 正常的显示出来。


    禁用客户端校验

    当一个带的客户输入的数据的表单提交时,UIX执行一些基础的onSubmit JavaScript校验(它校验必填字段,数据类型和格式),如果校验通过就提交表单。为了屏蔽校验,也需要在上节“禁用服务端校验”中的bean列表 中的bean上调用setUnvalidated(true)方法。

    注意: 也可以在设计时设置组件的Disable Server Side Validation属性为True,也可以为那些配置为提交表单的链接或图标设置禁用校验。查看下面的Javascript. URL一节获得更多信息。

    技巧: 对于tables和HGrid组件,必须通过设置table和HGrid区域自己的属性启用/禁用客户端校验,因为你不能直接访问OANavigationBarBean的用作数据集导航的子web bean。注意,现在不能禁用这些组件的服务端校验。


    错误处理

    OA Framework自动显示模型层抛出的任何错误信息;不需要在控制器中做什么就能处理。
    •查看Error Handling获取更多关于在控制器中抛出异常和在页面顶端显示错误、警告、确认信息。
    •查看Chapter 4: Dialog Pages获取关于显示模型错误、警告、确认和信息的对话框页面。


    JavaScript

    UIX和OA Framework正在快速的添加新的功能以提供更好的用户体验(区域页面渲染、自动的表格统计等等)。当这些功能发布后,你将受益于这些功能,但是,在这之前你不应该自己实现这些功能。

    简单来说,Javascript在OA Framework开发团队外是被禁止的。


    JavaScript. URL

    以前,如果需要配置链接或图像来提交页面表单(由于你需要在导航到新页面前处理事件),可以将它设置在UIX submitForm. Javascript函数中。

    现在,应该配置fireAction事件来代替使用Javascript. URL。查看Declarative Submit Form文档获取其它信息。

  • 相关阅读:
    s3c2440 nand flash 拷贝实验
    DE270数字系统设计(4)基于Nios的LCD显示
    DE270数字系统设计实验(3)移位寄存器
    s3c2440启动时的内存拷贝过程分析
    s3c2440基本io/ports led点亮
    (转)X11/Xlib.h:没有该文件或目录
    NAND Flash读写技术
    Http中ContentType的取值讲解
    Json对象和Json字符串的区别
    table() function
  • 原文地址:https://www.cnblogs.com/huanghongbo/p/4537045.html
Copyright © 2011-2022 走看看