OAF View Object Extension

OAF View Object Extension

Our business requirement is to add ‘Voucher Number’, ‘Invoice Pay Group’ and ‘Pay Alone Flag’ on the seeded ‘Invoice Approval Notification’ page.    Snap1_OAFV

Analyzing the Page

click on “About this Page” link to check , which View Object is associated with the message component layout [region4]

Snap2_OAFV

Here we can see that message component layout (region 4) has ApInvoiceHeaderVO attached to it. Now click on ‘Business Component References details’ and check the path of ApInvoiceHeaderVO.

Snap4_OAFV

Now, click on ApInvoiceHeaderVO which is an EO based [ApInvoicesAllEO] to check whether it has the additional attributes that need to be added                                                                                 Snap5_OAFV

Here we can see that our VO does not have the attributes – ‘Voucher Number’, ‘Invoice Pay Group’ and ‘Pay Alone Flag’.

So for adding these attribute we need to perform VO Extension.

Now FTP the complete solution package (i.e. oracle.apps.ap) from Application server into myprojects\oracle\apps\ folder.

Open Jdeveloper and create a new OA workspace and project. (Enter the following at each step of the Oracle Application Project Wizard):
Step1: Name workspace as AOAInvNotifEx.jws and the project as AOAInvNotifEx.jpr.
Step2: Check the box for ‘Use Repository for Design Time’ and select the Database connection in use.
Step3: Provide the necessary details:
DBC File Name : <DBC file location>
User Name: <Application – User Name>
Password: <Application- Password>
Application Short Name: < Application_Short_Name >
Responsibility Key: <This is unique for the Application Short Name Entered>

Now right click on AOAInvNotifEx project to open project properties –>Project Content –>Add to include the standard VO package in current project.                                                                      Snap6_OAFV

After adding BC4J package i.e. oracle.apps.ap the project looks like                                               Snap7_OAFV

Creating New View Object (VO): –

Right click on your project and select New–>Adf business Components–>View ObjectSnap8_OAFV

Give the package name as ‘aoa.oracle.apps.ap.invoice.request.negotiation.server’, VO name as ‘AOAApInvoiceHeaderVOEx’ and in the extends property select ‘ApInvoiceHeaderVO’                   Snap9_OAFV

The next screen allows the addition or deletion of Entity Objects. No change is required here for this extension so simply select ‘Next’.
The next pane allows additional attributes to be added or attributes to be removed. In this case add ‘Voucher Num’, ‘Pay Group Lookup Code’ and ‘Exclusive Payment Flag’ attributes to the selected list.

Note 1: On adding the first field we receive the following message:                                                   Snap10_OAFV

Click on ‘OK’ and continue adding the remaining fields.

Note 2: The new attribute you would be adding will be ‘Transient‘Snap11_OAFV

Click on Next

Since our attributes are created as Transient, to fix this issue follow the below steps:

At step 4 of the VO creation Wizard:
Select the newly added attribute – ‘VoucherNum’
Check the box: Mapped to column or SQL
Provide the alias name in the ‘Expression’ field.
(Repeat the above steps for the attributes – ‘Pay Group Lookup Code’ and ‘Exclusive Payment Flag’ as well).                                                                                                                                 Snap12_OAFV

Modify your sql statement to add new created attributes                         Snap13_OAFV

Click on next – >Next
Generate RowImpl and click on finish
Now verify that the newly created attributes are not transient:Snap14_OAFV

Add the new VO (AOAExApInvoiceHeaderVO) to the main Application Module (The AM to which the parent VO (ApInvoiceHeaderVO) has been attached). Also Rename the instance name from ‘AOAExApInvoiceHeaderVO1’ to ‘AOAExApInvoiceHeaderVO’.                                                          Snap15_OAFV

 

 Substitute Your New VO for the Parent VO

Now we need to perform the VO substitution For this we will right click on AOAInvNotifEx project and open project properties–>Business Components–>Substitutions.
Select the ‘ApInvoiceHeaderVO’ in ‘Available’ and ‘AOAExApInvoiceHeaderVO’ in ‘Substitute’ list and click on Add button and then press Ok button.                                                                       Snap16_OAFV

FTP VO.xml, .class, and the AM.xml, .class files to the respective directories in $JAVA_TOP
(note: FTP the .java files of the VO and AM and compile the files on the server using the ‘javac’ command if the .java file do not compile successfully on ‘JDeveloper’).

Now Import the ‘Substitution’ from the local machine using the following command:

jpximport C:\JDeveloper\jdevhome\jdev\myprojects\ AOAInvNotifEx.jpx -username <user name> -password <password> -dbconnection “(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=<host>)(PORT=<port number>))(CONNECT_DATA=(SID=<SID>)))”

(Run the above command from ‘Command Prompt’)

Personalize the page to create new items:-

On InvPoReqNegoPG, click on personalize page –> complete view –> Expand All, and click on Create Item on Message Component Layout: (region4)                                                               Snap17_OAFV

Set the item style as messageStyledText. Give the id, CSS Class, prompt , View Instance and View Attribute.                                                                                                                                            Snap18-1_OAFV

Snap18-2_OAFV

Create two items for ‘Pay Group Lookup Code’ and ‘Exclusive Payment Flag’ following the above steps.
Click on Apply -> return to application. You can notice that the page has the three columns.    Snap19_OAFV

 

 

 

 

7 thoughts on “OAF View Object Extension

  1. snikam

    Excellent blog on VO extension. Have visited many sites but most of them have given the steps at a high level. This blog gives the detailed steps which helps beginners to quick start with VO extension without any confusion. Thanks for writing and posting it. It would be great if you can also post similar thing on EO and CO extensions.

  2. raj

    Excellet blog on VO extension. I doing the same extension .I followed the steps you have done. Only thing I was not able to add to main Application Module (The AM to which the parent VO (ApInvoiceHeaderVO) has been attached). When I try to open the NegotiationAM I get the error Warning: There are java errors for this object. The wizard will be read-only until they are corrected. I proceed ahead and created the substitution and every thing compiled properly. When I try open the page , I am getting this error…
    ## Detail 0 ##
    java.sql.SQLException: Attempt to set a parameter name that does not occur in the SQL: 1

    Have you come across this error?
    Apprciate your help.
    Thanks
    Raj.

  3. All Oracle Apps Post author

    Hi Raj,

    As far as i understand the issue, the Extended VO was not added to the AM.
    You should get the latest/compatible version of the source java file(NegotiationAM .java) and then add the extended VO to it.
    Using the decompilied version of the AM in JDeveloper might make the file read- only.
    Hence, it is suggested to download the java file for the root AM, add the VO to it and deploy the changes.
    This should resolve the issue.

    Regards,
    All Oracle Apps
    Admin

  4. raj

    Finally I figured out the issue. The Binding Style should be Oracle Positional which is shown under SQL statement. Once that is set , everything seems to work fine. We don’t need to associate the extended VO to AM as mentioned above. Once again thanks for a excellent Blog on VO extension.

    Thanks,
    Raj.

  5. ravinder.gogula

    Good day,

    I’m a newbie to OAF.
    My issue might be wrong topic. I apologize for that.

    Could you please help me with below issues?

    Here is my requirement, need to add “Attachement” item on custom employee form (Navigation: Resp_Name > Search : Create button > Employee form). The issuse is, when it return from add attachment form(strandard form) then controller redirecting to previous page(Employee form) but loosing earlier data which was entered by the user i.e. refreshing the form.

    To resolve that, I have created Transactional variables/flag and checked user has clicked on add attachement item(processFormRequest). By checking value of transactional variable I’m executing VO.

    It’s working fine for Apply button but not on Cancle button i.e. when it return from add attachment form by clicking Cancel button it loosing earlier data which was entered by the user on previous form.

    I have tried following ways to fix the issue but failed:
    1. I have executed VO in controller passing primary key as a parameter.
    2. From controller called “initDetails” method in AM, primary key as a parameter.

    Please find the below code for reference:
    ==========
    Controller
    ==========
    public void processRequest(OAPageContext pageContext, OAWebBean webBean)
    {
    super.processRequest(pageContext, webBean);

    System.out.println(“NonEmpCO- -10”);

    if (!pageContext.isBackNavigationFired(false))
    {

    System.out.println(“NonEmpCO- -20”);
    TransactionUnitHelper.startTransactionUnit(pageContext, “empCreateTxn”);

    if (!pageContext.isFormSubmission())
    {
    System.out.println(“NonEmpCO- -30”);

    OAApplicationModule am = pageContext.getApplicationModule(webBean);
    am.invokeMethod(“createEmployee”, null);

    //”docAttached” and “docAttached” in previous form contoller value is ‘N’
    String docAttached = (String)pageContext.getTransientSessionValue(“docAttached”);
    String voFired = (String)pageContext.getTransientSessionValue(“docAttached”);

    if(docAttached.equals(“N”) && voFired.equals(“N”))
    {
    System.out.println(“NonEmpCO- -40”);
    //Do not execute Your VOs
    System.out.println(“Page Refresh after Attachement Event hence not executing VOs”);

    am.invokeMethod(“createEmployee”, null);
    }

    else
    {

    String voVisitID = (String)pageContext.getTransientSessionValue(“voVisitID”);
    System.out.println(“NonEmpCO- -50”);

    OAViewObject vo = (OAViewObject)am.findViewObject(“NonEmpFullVO1″);

    //”voTVisitID” populated in processFormRequest
    Number voTVisitID = (Number)pageContext.getTransientSessionValue(“voTVisitID”);
    System.out.println(“voTVisitID: “+voTVisitID);

    String employeeNum = String.valueOf(voTVisitID.intValue());

    Serializable[] parameters = { employeeNum };

    System.out.println(“NonEMpCO initDetails”);
    am.invokeMethod(“initDetails”, parameters);

    pageContext.putTransientSessionValue(“voFired”,”Y”);
    System.out.println(“executing VOs”);
    }
    }

    }
    else
    {
    System.out.println(“NonEmpCO- -60”);
    if (!TransactionUnitHelper.isTransactionUnitInProgress(pageContext, “empCreateTxn”, true))
    {
    System.out.println(“NonEmpCO- -70”);
    OADialogPage dialogPage = new OADialogPage(NAVIGATION_ERROR);
    pageContext.redirectToDialogPage(dialogPage);
    }

    }
    }

    /*—————-*/
    public void processFormRequest(OAPageContext pageContext, OAWebBean webBean)
    {

    super.processFormRequest(pageContext, webBean);
    System.out.println(“NonEmpCO- 10”);
    OAApplicationModule am = pageContext.getApplicationModule(webBean);
    Date scoStartDate = null;
    Date scoEndDate = null;

    System.out.println(“NonEmpCO- 20”);

    if ( OA_ADD_ATTACHMENT.equals(pageContext.getParameter(EVENT_PARAM)) )
    {

    System.out.println(“NonEmpCO- 20.5”);

    pageContext.putTransientSessionValue(“docAttached”,”Y”);

    }

    SimpleDateFormat formatter = new SimpleDateFormat(“dd-MMM-yyyy”);
    OAViewObject vo = (OAViewObject)am.findViewObject(“NonEmpFullVO1”);
    s_visit_id = (Number)vo.getCurrentRow().getAttribute(“VisitId”);
    System.out.println(“xxxxx s_visit_id”+s_visit_id);
    String employeeNum = String.valueOf(s_visit_id.intValue());
    pageContext.putTransientSessionValue(“voTVisitID”,s_visit_id);

    System.out.println(“NonEmpCO- 30”);

    if (pageContext.getParameter(“Apply”) != null)
    {

    try
    {
    System.out.println(“NonEmpCO- 40”);
    scoStartDate = formatter.parse(pageContext.getParameter(“StartDate”));
    scoEndDate = formatter.parse(pageContext.getParameter(“EndDate”));
    }
    catch (ParseException e)
    {
    System.out.println(“NonEmpCO- 50”);
    throw new OAException (“Failed to convert String To Date (UpdateNonEmpCO)” ,OAException.ERROR);
    }
    if (scoEndDate.before(scoStartDate))
    {
    System.out.println(“NonEmpCO- 60”);
    throw new OAException (“End date can’t be before start date” ,OAException.ERROR);
    }
    NonEmpUtils utl = new NonEmpUtils();
    if (utl.validate_id(pageContext.getParameter(“IdNumber”))== “INVALID”)
    {
    System.out.println(“NonEmpCO- 70”);
    throw new OAException (“Please enter a valid ID Number” ,OAException.ERROR);
    }

    String employeeName = (String)vo.getCurrentRow().getAttribute(“LastName”) + “, ” + (String)vo.getCurrentRow().getAttribute(“FirstName”);

    System.out.println(“NonEmpCO- 80”);
    am.invokeMethod(“apply”);

    MessageToken[] tokens = { new MessageToken(“EMP_NAME”, employeeName),
    new MessageToken(“EMP_NUMBER”, employeeNum) };
    OAException confirmMessage = new OAException(“FND”, “UNISA_EMP_CREATE_CONFIRM”, tokens,
    OAException.CONFIRMATION, null);

    pageContext.removeTransientSessionValue(“voFired”);
    pageContext.removeTransientSessionValue(“docAttached”);
    System.out.println(“NonEmpCO- 90”);
    pageContext.putDialogMessage(confirmMessage);
    pageContext.forwardImmediately(“OA.jsp?page=/xxunisa/oracle/apps/per/selfservice/nonemp/webui/EmpSearchPG”,
    null,
    OAWebBeanConstants.KEEP_MENU_CONTEXT,
    null,
    null,
    true, // retain AM
    OAWebBeanConstants.ADD_BREAD_CRUMB_NO);

    }
    else if (pageContext.getParameter(“Cancel”) != null)
    {
    System.out.println(“CO Before Rollback Employee”);
    am.invokeMethod(“rollbackEmployee”);
    System.out.println(“NonEmpCO- 100”);

    TransactionUnitHelper.endTransactionUnit(pageContext, “empCreateTxn”);

    pageContext.forwardImmediately(“OA.jsp?page=/xxunisa/oracle/apps/per/selfservice/nonemp/webui/EmpSearchPG”,
    null,
    OAWebBeanConstants.KEEP_MENU_CONTEXT,
    null,
    null,
    true, // retain AM
    OAWebBeanConstants.ADD_BREAD_CRUMB_NO);
    }

    }

    =========================
    Application Module method
    =========================
    public void initDetails(String visit_id)
    {
    NonEmpFullVOImpl vo = getNonEmpFullVO1();
    System.out.println(“AM – initDetails Start”);
    if (vo == null)
    {
    System.out.println(“AM – initDetails vo == null”);
    MessageToken[] errTokens = { new MessageToken(“OBJECT_NAME”, “NonEmpFullVO1”)};
    throw new OAException(“AK”, “FWK_TBX_OBJECT_NOT_FOUND”, errTokens);
    }
    System.out.println(“AM – visit_id: “+visit_id);
    vo.initQuery(visit_id);
    System.out.println(“AM – initDetails End”);
    }
    ==================
    View Object method
    ==================
    public void initQuery(String visit_id)
    {
    if ((visit_id != null) && (!(“”.equals(visit_id.trim()))))
    {
    Number visit = null;
    System.out.println(“initQuery Start”);
    try
    {
    visit = new Number(visit_id);
    System.out.println(“initQuery visit”+visit);

    }
    catch(Exception e)
    {
    throw new OAException(“AK”,”FWK_TBX_INVALID_EMP_NUMBER”);
    }
    setWhereClause(“visit_id = :1”);
    setWhereClauseParams(null);
    setWhereClauseParam(0,visit);
    System.out.println(“initQuery executeQuery”);
    executeQuery();
    int fetchedRowCount = getRowCount();
    System.out.println(“initQuery fetchedRowCount: “+fetchedRowCount);

    }

    }
    ======
    Result
    ======

    14/02/17 13:49:59 NonEmpCO- -10
    14/02/17 13:49:59 NonEmpCO- -20
    14/02/17 13:49:59 NonEmpCO- -30
    14/02/17 13:49:59 NonEmpCO- -40
    14/02/17 13:49:59 Page Refresh after Attachement Event hence not executing VOs
    14/02/17 13:49:59 NonEmpCO- -10
    14/02/17 13:49:59 NonEmpCO- -20
    14/02/17 13:49:59 NonEmpCO- -30
    14/02/17 13:49:59 NonEmpCO- -40
    14/02/17 13:49:59 Page Refresh after Attachement Event hence not executing VOs
    14/02/17 13:50:19 NonEmpCO- 10
    14/02/17 13:50:19 NonEmpCO- 20
    14/02/17 13:50:19 xxxxx s_visit_id604
    14/02/17 13:50:19 NonEmpCO- 30
    14/02/17 13:50:19 NonEmpCO- 10
    14/02/17 13:50:19 NonEmpCO- 20
    14/02/17 13:50:19 xxxxx s_visit_id604
    14/02/17 13:50:19 NonEmpCO- 30
    14/02/17 13:50:22 NonEmpCO- 10
    14/02/17 13:50:22 NonEmpCO- 20
    14/02/17 13:50:22 xxxxx s_visit_id604
    14/02/17 13:50:22 NonEmpCO- 30
    14/02/17 13:50:22 NonEmpCO- 10
    14/02/17 13:50:22 NonEmpCO- 20
    14/02/17 13:50:22 xxxxx s_visit_id604
    14/02/17 13:50:22 NonEmpCO- 30
    14/02/17 13:50:24 NonEmpCO- 10
    14/02/17 13:50:24 NonEmpCO- 20
    14/02/17 13:50:24 NonEmpCO- 20.5
    14/02/17 13:50:24 xxxxx s_visit_id604
    14/02/17 13:50:24 NonEmpCO- 30
    14/02/17 13:50:24 NonEmpCO- 10
    14/02/17 13:50:24 NonEmpCO- 20
    14/02/17 13:50:24 NonEmpCO- 20.5
    14/02/17 13:50:24 xxxxx s_visit_id604
    14/02/17 13:50:24 NonEmpCO- 30
    14/02/17 13:50:26 NonEmpCO- -10
    14/02/17 13:50:26 NonEmpCO- -20
    14/02/17 13:50:26 NonEmpCO- -30
    14/02/17 13:50:26 UnisaNonEmployeesEOImpl- visitId: 605
    14/02/17 13:50:26 NonEmpCO- -50
    14/02/17 13:50:26 voTVisitID: 604
    14/02/17 13:50:26 NonEMpCO initDetails
    14/02/17 13:50:26 AM – initDetails Start
    14/02/17 13:50:26 AM – visit_id: 604
    14/02/17 13:50:26 initQuery Start
    14/02/17 13:50:26 initQuery visit604
    14/02/17 13:50:26 initQuery executeQuery
    14/02/17 13:50:26 initQuery fetchedRowCount: 0
    14/02/17 13:50:26 AM – initDetails End
    14/02/17 13:50:26 executing VOs
    14/02/17 13:50:26 NonEmpCO- -10
    14/02/17 13:50:26 NonEmpCO- -20
    14/02/17 13:50:26 NonEmpCO- -30
    14/02/17 13:50:26 UnisaNonEmployeesEOImpl- visitId: 606
    14/02/17 13:50:26 NonEmpCO- -50
    14/02/17 13:50:26 voTVisitID: 604
    14/02/17 13:50:26 NonEMpCO initDetails
    14/02/17 13:50:26 AM – initDetails Start
    14/02/17 13:50:26 AM – visit_id: 604
    14/02/17 13:50:26 initQuery Start
    14/02/17 13:50:26 initQuery visit604
    14/02/17 13:50:26 initQuery executeQuery
    14/02/17 13:50:26 initQuery fetchedRowCount: 0
    14/02/17 13:50:26 AM – initDetails End
    14/02/17 13:50:26 executing VOs

    —-

    Note: Due to some strange reasons, methods in the controller executing twice.

    Your help is highly appreciated.

    Thanks,
    Ravi

    1. All Oracle Apps Post author

      IN cancel button action, you are calling ‘ am.invokeMethod(“rollbackEmployee”);’ rollback will remove the exisiting data from the VO which is not yet committed to database which is why you were not able to see the data even if you again query the VO.

      You are seeing a blank screen from ‘apply button also earlier because you are calling ‘am.invokeMethod(“createEmployee”, null);’ method which will create a blank row in the VO which will be attached to the page. You should call this method conditionally like when you are not coming from apply button.

Leave a Reply