溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

OAF個性化開發(fā)實例(轉(zhuǎn))

發(fā)布時間:2020-08-15 00:26:10 來源:ITPUB博客 閱讀:589 作者:419088217 欄目:建站服務(wù)器

EBS 11.5.10.2

需求

下圖是Oracle標(biāo)準(zhǔn)頁面,有一個簡單的開發(fā)需求,當(dāng)Expense Template等于“管理費用”時,Approver的LOV輸入框默認(rèn)為“XXX”,并且LOV只讀,不能進(jìn)行選擇。

OAF個性化開發(fā)實例(轉(zhuǎn))

分析

這個看似極其簡單的開發(fā),其背后所隱藏的技術(shù)知識卻是不那么簡單的。

當(dāng)Expense Template選擇為“管理費用”時,Approver LOV輸入框只讀,這里牽涉到的開發(fā)基本為給Expense Template加上FireAction的功能,

然后在Expense Template的Value Change事件中去修改Approver LOV的只讀屬性。

因為開發(fā)規(guī)范是不允許直接修改Oracle的代碼,所以此開發(fā)將通過集成標(biāo)準(zhǔn)的控制器類,在客戶化的控制器類中實現(xiàn)添加Expense Template的FireAction功能,和修改Approver LOV只讀屬性,

然后通過個性化,將控制器類替換成客戶化的控制器類。

技術(shù)要點

1,修改Approver LOV的只讀屬性

剛剛進(jìn)行OAF開發(fā)的開發(fā)人員可能覺得這是很簡單的事,只要在客戶化的控制器類的processFormRequest()方法中調(diào)用以下代碼:

OAMessageLovInputBean lovBean = (OAMessageLovInputBean)webBean.findChildRecursive("Approver");
lovBean.setReadOnly(true);
就可以實現(xiàn)了,如果這樣做開發(fā),那么就錯了,在運行時會拋出異常:
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設(shè)為只讀會出錯呢?這是因為OAF在運行時,表現(xiàn)為一棵控件樹。

當(dāng)進(jìn)入頁面時,控件樹被初始化創(chuàng)建,而當(dāng)用戶事件觸發(fā)POST請求時,控件樹并不會被重新生成(提高性能),要改變控件的屬性只有兩個辦法,一個是重新生成控件樹,二是使用PPR。

方法一:重構(gòu)控件樹

重構(gòu)控件樹就意味著在processFormRequest()方法處理事件時,需要Forward到本頁,并通過參數(shù)控制來設(shè)置Approver LOV只讀,這樣會刷新整個頁面,而且對編碼也帶來困難。

方法二:使用PPR

實現(xiàn)方法是利用OAF數(shù)據(jù)綁定機制,將Approver LOV的ReadOnly屬性綁定到視圖對象的屬性,通過改變視圖對象屬性的值來控制Approver LOV的只讀。

這里又引出第2個技術(shù)要點:

2,動態(tài)創(chuàng)建視圖對象

創(chuàng)建視圖對象需要首先創(chuàng)建OAViewDef對象,然后利用OAViewDef對象來創(chuàng)建視圖對象。

這里談一下Oracle的一個開發(fā)規(guī)范,OAViewDef接口在oracle.apps.fnd.framework.server包下,按照Oracle的規(guī)范,任何webui下的類不允許import任何server下的類。我是一個規(guī)范的嚴(yán)格遵守者,這樣就會使開發(fā)變得更復(fù)雜。

要在server包下引用OAViewDef接口,就必須創(chuàng)建應(yīng)用程序模塊,將動態(tài)創(chuàng)建視圖對象的代碼移到應(yīng)用程序模塊中實現(xiàn)。在客戶化控制器類中,動態(tài)創(chuàng)建應(yīng)用程序模塊,然后調(diào)用應(yīng)用程序模塊的方法。

實現(xiàn)步驟

假設(shè)開發(fā)人員對Oracle標(biāo)準(zhǔn)的頁面結(jié)構(gòu)都已經(jīng)非常了解了,包括需要集成哪個標(biāo)準(zhǔn)的控制器,頁面上所使用的視圖對象。

1、創(chuàng)建客戶化應(yīng)用程序模塊cux.oracle.apps.ap.oie.entry.server.CuxPVOAM

2、創(chuàng)建視圖對象cux.oracle.apps.ap.oie.entry.server.CuxPVO,視圖對象中只有一個臨時屬性ReadOnlyFlag,類型為Boolean(此步可選)

3、創(chuàng)建客戶化控制器類,繼承標(biāo)準(zhǔn)的控制器類

4、在CuxPVOAMImpl.java中創(chuàng)建兩個方法:

 

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();
 
    // 創(chuàng)建視圖對象
    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"); //標(biāo)準(zhǔn)的VO
    OAViewObject pvo = (OAViewObject)rootAM.findViewObject("CuxViewPVO");
 
    if () 
    {
      pvo.first().setAttribute("ReadOnlyFlag", Boolean.TRUE);
      vo.first().setAttribute("Xxx", ); // 設(shè)置Approver LOV綁定的視圖對象屬性值
    }
    else
    {
      pvo.first().setAttribute("ReadOnlyFlag", Boolean.FALSE);
    }    
  }
}

5、在客戶化控制器中添加相應(yīng)代碼

processRequest代碼:

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);
 
  // 創(chuàng)建客戶化應(yīng)用程序模塊
  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"));
}

將開發(fā)測試后的代碼發(fā)布到服務(wù)器。(測試可以在本地,將頁面上的控制器類替換成客戶化的控制器來進(jìn)行)

processFormRequest代碼:

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()的代碼如下:

public static OAApplicationModule getNestedAMInstance(OAApplicationModule parentAM, String nestedAMName)
{
  OAApplicationModule am = null;
 
  String[] amNames = parentAM.getApplicationModuleNames();
  for (int i=0; i< 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、進(jìn)入頁面,設(shè)置個性化,替換標(biāo)準(zhǔn)的控制器類為客戶化控制器類。

1.jpg

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI