Login
Register

Home

Trainings

Fusion Blog

EBS Blog

Authors

Contact Us

Kishore Ryali
  • Register

Oracle Gold Partners, our very popular training packages, training schedule is listed here
Designed by Five Star Rated Oracle Press Authors & Oracle ACE's.

webinar new Click here to raise Support Ticket. Get reply within 48 hours.

Search Courses

Star InactiveStar InactiveStar InactiveStar InactiveStar Inactive
 

Part II – Extend Application Module and Controller

This is the second article in the series “Custom Defaulting and Validation in iProcurement”. For the readers who jumped into this article directly, I will outline my objective. The objective of the article is to implement custom defaulting and validation in iProcurement using different approaches I learnt, and limitations of each approach. To illustrate each approach I took a sample requirement of copying a DFF attribute value called ‘Fund’ on requisition header to another DFF attribute in requisition line during checkout process.

In the first article, I used POR_CUSTOM_PKG to implement my requirement. Limitation on when por_custom_pkg is invoked during checkout process restricted me to partially achieve my objective. I could copy fund value when the requisition is first created, any change made to fund later is not copied to fund at line level as por_custom_pkg executes only for the first time requisition is created.

In this article I will use OA Framework extension of Application Module and Controller to implement my requirement. If you are not familiar with OA Framework extension, Anil’s articles on OA Framework are great places to start. Recommended readings Extending AM Part 1, Part 2, and Extending Controller.

Approach 2: Extend AM and Controller using OAF extension

The screenshot below shows fund at header level in “Checkout: Requisition Information” page. I’ve to copy fund value entered by user, to fund attribute in requisition line.

The user may go to “Edit Lines” to edit line information or “Save” requisition for later use or “Submit” requisition without bothering to edit lines, during requisition creation process. In order to execute my custom code along with seeded validations/defaulting, I’ve to override the seeded functionality built in the events ‘Save’, ‘Submit’, and ‘Edit Lines’.


How do I do it?
  • Override processFormRequest method by Controller Extension to execute custom code.

 

  • Custom code resides in a new method in extended Application Module. AM is the most logical place to do business validations and defaulting

 

Before I implement above high level steps, I need to find out BC4J components and Controller used in “Checkout: Requisition Information” page. ‘About this Page’ section is a good place to start.

The pointers on the above image, shows controller ‘CheckoutSummaryCO’, application module ‘RequisitionAM’ and view object ‘PoRequisitonHeadersVO' for Fund Number i.e. Attribute15. Also note that most fields use view object ‘ReqSummaryVO’ as source. The view object for line information is ‘PoRequisitionLinesVO’.

I will follow bottom up approach to create underlying BC4J component i.e. extended AM to call it in controller. Looking closely at process flow on clicking “Edit Lines” button, I came up with how interaction happens between seeded classes.

  • ‘Edit Lines’ event is captured in processFormRequest (PFR) method of controller CheckoutSummaryCO. It calls processEditLines method.

 

  • processEditLines calls server command class CheckoutSummarySvrCmd’s method populateAttributesToVOs. This populates VOs PoRequisitionHeadersVO and PoRequisitionLinesVO for requisition header and line respectively from ReqSummaryVO.

 

Below illustration summarizes the interaction, please note Classes are shown in bold to differentiate them from methods.

PFR in CheckoutSummaryCO > processEditLines > CheckoutSummarySvrCmd > populateAttributes > populateAttributesToVOs

Implementation:

Understanding seeded process helps in planning how to write custom code for copying fund from header to line. Fund attribute in header is stored in PoRequisitionHeadersVO, which holds any changes made to fund value. ReqSummaryVO also has DFF attributes information, but Attribute15 is not reflecting the changes I made on the page. Due to this, when the last step of populating header VO from ReqSummaryVO took place new fund value entered is overwritten with old value. This part is crucial as the user is not seeing the changes they made to fund number.

The custom code will fill this gap, by fetching Attribute15 from PoRequisitionHeadersVO and set the new value to ReqSummaryVO. Later when the seeded code executes, new fund value is copied to header and line VOs which in turn stores in the database. The steps for extending application module are:

  • Create XxRequisitionAM to extend oracle.apps.icx.por.req.server.RequisitionAM
  • Create a new method copyFundFromHeader to set Attribute15 value from PoRequisitionHeadersVO to          ReqSummaryVO
 

// Source File Name: XxRequisitionAMImpl.java
package xx.oracle.apps.icx.por.req.server;

import java.io.PrintStream;
import oracle.apps.fnd.common.VersionInfo;
import oracle.apps.fnd.framework.OAException;
import oracle.apps.fnd.framework.server.OADBTransaction;
import oracle.apps.icx.por.common.server.ErrorUtil;
import oracle.apps.icx.por.req.server.*;
import oracle.jbo.domain.Number;
import oracle.jdbc.driver.OracleCallableStatement;

public class XxRequisitionAMImpl extends RequisitionAMImpl
{
    public XxRequisitionAMImpl()
    {
    }

    public void copyFundFromHeader()
    {
        OADBTransaction oadbtransaction = getOADBTransaction();
        if(oadbtransaction.isLoggingEnabled(1))
            oadbtransaction.writeDiagnostics(this, "*** Custom Code for coping Fund Number from Req Header to Line ***", 1);
        try
        {
            // Fetch new fund value from header VO
            PoRequisitionHeadersVOImpl porequisitionheadersvoimpl = getPoRequisitionHeadersVO();
            PoRequisitionHeadersVORowImpl porequisitionheadersvorowimpl = (PoRequisitionHeadersVORowImpl)porequisitionheadersvoimpl.getCurrentRow();
            String headerFund = porequisitionheadersvorowimpl.getAttribute15();

            Number reqHeaderId = null;
            String reqSumAtt15 = null;

            ReqSummaryVOImpl reqsummaryvoimpl = getReqSummaryVO();
            ReqSummaryVORowImpl reqsummaryvorowimpl = (ReqSummaryVORowImpl)reqsummaryvoimpl.getCurrentRow();
            reqHeaderId = reqsummaryvorowimpl.getRequisitionHeaderId();
            reqSumAtt15 = reqsummaryvorowimpl.getAttribute15();
            if(oadbtransaction.isLoggingEnabled(1))
                oadbtransaction.writeDiagnostics(this, "BEFORE> reqHeaderId=" + reqHeaderId + ",reqSumAtt15=" + reqSumAtt15, 1);

            // set new fund value to Attribute15 of ReqSummaryVO
            reqsummaryvorowimpl.setAttribute15(headerFund);
            reqHeaderId = reqsummaryvorowimpl.getRequisitionHeaderId();
            reqSumAtt15 = reqsummaryvorowimpl.getAttribute15();
            if(oadbtransaction.isLoggingEnabled(1))
                oadbtransaction.writeDiagnostics(this, "AFTER> reqHeaderId=" + reqHeaderId + ",reqSumAtt15=" + reqSumAtt15, 1);
        }
        catch(Exception exception)
        {
            if(oadbtransaction.isLoggingEnabled(1))
                oadbtransaction.writeDiagnostics(this, "Error=" + exception, 1);
            ErrorUtil.handleFatalException(getOADBTransaction(), exception, this);
        }
        if(oadbtransaction.isLoggingEnabled(1))
            oadbtransaction.writeDiagnostics(this, "*** End of Custom Code for coping Fund Number from Req Header to Line ***", 1);
    }

    public static final String RCS_ID = "$Header: XxRequisitionAMImpl.java 115.30 2008/11/18 16:40:39 kryali noship $";
    public static final boolean RCS_ID_RECORDED = VersionInfo.recordClassVersion("$Header: XxRequisitionAMImpl.java 115.30 2008/11/18 16:40:39 kryali noship $", "xx.oracle.apps.icx.por.req.server");
}


  • Substitute RequisitionAM with XxRequisitionAM in ‘Edit Business Components Project’.
  • Create controller XxCheckoutSummaryCO which extends oracle.apps.icx.por.req.webui.CheckoutSummaryCO. Override PFR to call copyFundFromHeader method in extended AM, during Edit Lines, Save, and Submit events.
 

// Source File Name:   XxCheckoutSummaryCO.java
package xx.oracle.apps.icx.por.req.webui;

import oracle.apps.fnd.common.VersionInfo;
import oracle.apps.fnd.framework.OAApplicationModule;
import oracle.apps.fnd.framework.webui.OAPageContext;
import oracle.apps.fnd.framework.webui.beans.OAWebBean;
import oracle.apps.icx.por.req.webui.CheckoutSummaryCO;

public class XxCheckoutSummaryCO extends CheckoutSummaryCO
{
    public XxCheckoutSummaryCO()
    {
    }
    public void processFormRequest(OAPageContext oapagecontext, OAWebBean oawebbean)
    {
        OAApplicationModule oaapplicationmodule = oapagecontext.getApplicationModule(oawebbean);
        String s = oapagecontext.getParameter("event");
        if(oapagecontext.isLoggingEnabled(1))
            oapagecontext.writeDiagnostics(this, "processRequest().begin", 2);
        if(oapagecontext.isLoggingEnabled(1))
            oapagecontext.writeDiagnostics(this, "event=" + s, 2);
        if("editLines".equals(s))
            customDefault(oapagecontext, oaapplicationmodule);
        if("save".equals(s))
            customDefault(oapagecontext, oaapplicationmodule);
        if("submit".equals(s))
            customDefault(oapagecontext, oaapplicationmodule);
        if("goto".equals(s))
            customDefault(oapagecontext, oaapplicationmodule);
        if(oapagecontext.isLoggingEnabled(1))
            oapagecontext.writeDiagnostics(this, "processRequest().end", 2);
        super.processFormRequest(oapagecontext, oawebbean);
    }

    protected void customDefault(OAPageContext oapagecontext, OAApplicationModule oaapplicationmodule)
    {
        oaapplicationmodule.invokeMethod("copyFundFromHeader");
    }

    public static final String RCS_ID = "$Header: XxCheckoutSummaryCO.java 115.30 2008/10/16 13:31:39 kryali noship $";
    public static final boolean RCS_ID_RECORDED = VersionInfo.recordClassVersion("$Header: XxCheckoutSummaryCO.java 115.30 2008/10/16 13:31:39 kryali noship $", "xx.oracle.apps.icx.por.req.webui");

}


  • Upload custom files in $JAVA_TOP or $XX_TOP (if it is CLASSPATH, jserv.properties, zone.properties). Run JPXImporter to load substitution into MDS repository and verify it with JDR_UTILS.listdocuments. Bounce Middle-Tier.

 

  • In Checkout: Requisition Information page, Personalize page is used to substitute XxCheckoutSummaryCO.


The above approach of extending AM and CO, copies header fund value to line successfully even if changes are made to it after requisition creation.


Limitations:

My triumphal celebrations for solving this issue, lasted a couple of days until I observed an odd behavior with Chart of Accounts KFF Lov in iProcurement. When I clicked on it, KFF page showed up error message with details.



"Error: Cannot Display Page

You cannot complete this task because one of the following events caused a loss of page data:

Your login session has expired.
A system failure has occurred. 

I first reaction was blame it on any patches applied by DBAs, but I later came to know this is happening with all list of values in requisition creation process. I turned off all personalizations and removed substitutions, to realize the hard truth that it was my customization which caused this catastrophe. Putting all emotions aside, thinking rationally and referring OAF developer guide, I came to my conscience that this session state expiration is caused by extending root application module. RequisitionAM is root Application module for most pages in requisition creation process. Root Application module is the AM attached to top region of the page during design time. It maintains the session state and retention level for requests between client and server.


Extending root AM is not advisable, unless you know what you are doing. Since I extended root AM, I was loosing session state between main page and Lov region. I tried creating nested Application modules and call it from extended controller, it did not work either because I couldn't get reference to VOs. I read nested AMs are in the same transaction state as root AM, so it may have worked if I had stretched myself to research more. I will cover this in separate article, on how to use nested AMs.

After my failed attempts with nested AMs, iProcurement Architecture Overview document (Metalink Note: 313195.1) came to rescue. It has a section on extending helper classes to do custom validations in iProcurement. My third approach is based on this, which I will cover in the next article.

Update: Writing this article kept me thinking of Application Module Retention Level property. This property indicates how AM should be retained between requests until it is explicitly released. RequisitionAM has retention level as "MANAGE_STATE". I believe I have not set this property for extended application module, when I implemented the above solution. This may be the cause for Lov issue. I will retest it and share the results.

I tested it by setting retention level property for extended AM, I still face the same Lov issue. So there is genuinely something wrong with extension of root AM. If I can get nested AMs working properly, I will have another solution for my requirement.


Kishore Ryali

Comments   

0 #1 jakkula 2009-03-19 09:51
Hi Kishore,
Very good presentation and good thought to extend server cmnds/helper calsses.

Quick question.
Can't we execute code of CopyFundFromHea der() in PFR of CheckoutSummary CO?
I'm just thinking alternative for extending Root AM RequisitionAmIm pl.java .
Quote
0 #2 kishore Ryali 2009-03-19 09:57
Hi Jakkula,

It is not advisable to access and manipulate VOs/EOs in controller, for sanity sake of MVC architecture.

Kishore
Quote
0 #3 Raghavendra Ravilla 2009-09-01 06:48
Hello,

I am not able to see 'About this Page’ in iProcument. How can i enable this? Please advice

I am using 11.5.9

Thanks
Raghavendra Ravilla
Quote
0 #4 Kishore Ryali 2009-09-02 10:09
Hi

I'm not sure with 11.5.9. For 11.5.10, setting profiile "FND: Diagnostics Enabled" will show about this page.

Kishore
Quote
0 #5 http://fluidims.com 2014-04-22 00:54
There's nothing http://www.fluidims.com wrong with making
$100 to $500 a month extra on the side. Many people place advertisements at
the top spots on search engines prompted Danny Sullivan to coin the term Search engine optimization, contextual advertising, paid placement, and design.
You'll find it next to impossible to index your site.


Here is my page :: http://fluidims.com: http://fluidims.com
Quote
0 #6 Nandu 2014-05-28 02:03
Hi Kishore,

I am facing problem in checkoutsummary Page to enable the Task lov. I set the lov bean rendered true,passed the spell true and used the boundvalueutl but no use. Can you please help me in this regard...
Quote
0 #7 Claudioabogy 2021-06-13 03:39
Hello,

Best music download private server: https://0daymusic.org/premium.php
MP3/FLAC, Label, LIVESETS, Music Videos, TV Series.

Best regards,
0day MP3s
Quote

Add comment


Security code
Refresh

Search Trainings

Fully verifiable testimonials

Apps2Fusion - Event List

<<  Aug 2021  >>
 Mon  Tue  Wed  Thu  Fri  Sat  Sun 
        1
  2  3  4  5  6  7  8
  9101112131415
16171819202122
23242526272829
3031     

Enquire For Training

Fusion Training Packages

Get Email Updates


Powered by Google FeedBurner