Apps To Fusion

.......contents copyright protected by FocusThread UK Ltd

 
  • Increase font size
  • Default font size
  • Decrease font size
We are glad to announce the launch of Forum for Customizations and Extensions. Click here to visit http://apps2fusion.com/forums
Our OA Framework, BPEL Development & Apps DBA Trainings from USD 299 only [on weekends] . Click here for details.
Also see here fully verifiable feedbacks/testimonials


Nested Application Modules in OA Framework

In one of my old articles on OA Framework extension, I briefly mentioned about Nested Application modules. Today I will explain how Nested Application module can be used. Nested AM is an application module which is under the scope of root application module. 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.

Root AM can contain one or more nested AMs which can themselves nest children to any arbitrary level. In this scenario, the root AM has access to all the data/objects held by its children, and all children participate in the same transaction established by the root.

How do you create nested application module?
Nested application module is created in a similar fashion as any application module. You can create it using wizard in JDeveloper by selecting view objects it uses and code any custom methods in AMImpl class. You can nest an instance of an application module inside another application module in design time or run time.

Design-Time

Suppose you have two application modules XxRootAM and XxNestedAM in your project. To make XxNestedAM nested to XxRootAM, you reference XxNestedAM in Application Module section of XxrootAM Editor. Below screenshot shows editor and how XxrootAM.xml is added with AppModuleUsage tag to reference XxNestedAM.

 

Run-Time

You use createApplicationModule() method in oracle.jbo.ApplicationModule Interface, to create an instance of application module on another application module. For the above example,
assuming ram is instance of XxRootAM, below command creates instance nam for XxNestedAM.

OAApplicationModule nam = (OAApplicationModule)ram.createApplicationModule("XxNestedAM", "xxa2f.oracle.apps.icx.icatalog.shopping.server.XxNestedAM");

You have to give full-qualified name of application module as second parameter. You can then access view objects attached to root application module, in nested application module. Suppose XxRootAM has view object XxVO, you can get instance of it in XxNestedAM using

ViewObject vo = nam.findViewObject("XXVO");

Note that XxNestedAM should be created declaratively before it can be nested using createApplicationModule() in run-time.


Why use nested application module?
Nested application module promotes reusablility and modularizing business logic into smaller and specific business components. It helps to prevent root application module in growing bigger and become nightmare for maintenance and concurrent development. Starting with release 11.5.10, nested application modules are instantiated on an "as needed" basis (in previous releases, BC4J instantiated all the nested application modules when the containing application module was created). For example, if you do a findApplicationModule , BC4J will instantiate the object. If a nested application module is never accessed, it is not created.

More importantly than usual, you can use nested application module to put custom business logic in root application module for seeded pages. It is not advisable to extend root application module. You can still get away with extending root AM until your seeded page doesn't have LOV fields. If page has LOV fields, root AM extension will cause session time out when clicked on LOV. The error looks similar to

"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 was stuck up with the same error when I extended root AM in the Part-2 article of Custom Defaulting and Validation in iProcurment. So solution for root AM extension is to use nested application module. They come really handy in such scenarios
.

Give me an example?
In iProcurement, I will add custom logic to print "Requisition Header Id" in console when "Add to Cart" button is pressed during requisition creation. Some details of 'About this Page' for Non-Catalog Request page.

Page Name: NonCatalogRequestPG
Controller: NonCatalogRequestCO
AM: RequisitionAM

To implement above requirement, I will create custom application module and make it nested to RequisitionAM in Controller. Then I will create printReqHeaderId() method to access PoRequisitionHeadersVO in custom application module and print Requisition Header Id in console.

Steps to use nested application module

  • Create application module XxNestedAM in JDeveloper.
  • Create a method printReqHeaderId in XxNestedAM to get instance of PoRequisitionHeadersVO via root application module. Use getter method to print requisition header id in console.


package xxa2f.oracle.apps.icx.icatalog.shopping.server;
import oracle.apps.fnd.framework.server.OAApplicationModuleImpl;
import oracle.apps.icx.icatalog.shopping.server.*;
import oracle.apps.icx.por.req.server.*;
import oracle.apps.fnd.framework.*;
import oracle.apps.fnd.common.VersionInfo;

public class XxNestedAMImpl extends OAApplicationModuleImpl
{
public XxNestedAMImpl()
{
}

public void printReqHeaderId()
{
System.out.println("Start > XxNestedAM.printReqHeaderId");
OAApplicationModule rootAM = (OAApplicationModule)getRootApplicationModule();
PoRequisitionHeadersVOImpl poh = (PoRequisitionHeadersVOImpl) rootAM.findViewObject("PoRequisitionHeadersVO");
PoRequisitionHeadersVORowImpl pohr = (PoRequisitionHeadersVORowImpl) poh.getCurrentRow();
System.out.println("POHeaderId=" + pohr.getRequisitionHeaderId());
System.out.println("End > XxNestedAM.printReqHeaderId");
}

public static final String RCS_ID = "$Header: XxNestedAMImpl.java 115.30 2009/05/13 21:40:39 kryali noship $";
public static final boolean RCS_ID_RECORDED = VersionInfo.recordClassVersion("$Header: XxNestedAMImpl.java 115.30 2009/05/13 21:40:39 kryali noship $", "xxa2f.oracle.apps.icx.icatalog.shopping.server");
}


  • Create extension NonCatalogRequestCO controller by naming it as xxNonCatalogRequestCO. In processFormRequest() method for AddToCart event, use createApplicationModule() to create instance of XxNestedAM and call method in nested application module using invokeMethod() method.


package xxa2f.oracle.apps.icx.icatalog.shopping.webui;

import oracle.apps.fnd.common.*;
import oracle.apps.fnd.framework.*;
import oracle.apps.fnd.framework.webui.*;
import oracle.apps.fnd.framework.webui.beans.*;
import oracle.apps.icx.por.req.webui.*;
import oracle.jbo.ViewObject;
import oracle.apps.icx.icatalog.shopping.webui.NonCatalogRequestCO;
import oracle.apps.icx.icatalog.shopping.server.*;
import oracle.apps.icx.por.req.server.*;
import oracle.apps.fnd.common.VersionInfo;

public class xxNonCatalogRequestCO extends NonCatalogRequestCO
{
public xxNonCatalogRequestCO()
{
}

public void processFormRequest(OAPageContext oapagecontext, OAWebBean oawebbean)
{
try
{
if(oapagecontext.getParameter("AddToCart") != null)
{
System.out.println("*** XX Custom Code Start ***");
OAApplicationModule ram = oapagecontext.getApplicationModule(oawebbean);
// Create Nested Application Module
OAApplicationModule nam = (OAApplicationModule)ram.findApplicationModule("XxNestedAM");
if (nam == null)
nam = (OAApplicationModule)ram.createApplicationModule("XxNestedAM", "xxa2f.oracle.apps.icx.icatalog.shopping.server.XxNestedAM");
nam.invokeMethod("printReqHeaderId");
System.out.println("*** XX Custom Code End ***");
}
}
catch (Exception e)
{
System.out.println("Error=" + e);
}

super.processFormRequest(oapagecontext, oawebbean);
}

public static final String RCS_ID = "$Header: xxNonCatalogRequestCO.java 115.30 2009/05/13 21:40:39 kryali noship $";
public static final boolean RCS_ID_RECORDED = VersionInfo.recordClassVersion("$Header: xxNonCatalogRequestCO.java 115.30 2009/05/13 21:40:39 kryali noship $", "xxa2f.oracle.apps.icx.icatalog.shopping.webui");
}



I've used findApplicationModule() method to check if nested AM is already created, before creating another instance with the same name.

  • Personalize NonCatalogRequestPG page to provide extended Controller XxNonCatalogRequestCO as controller.
  • Run NonCatalogRequestPG in JDeveloper. Enter details in Non-Catalog Request page and hit Add to Cart button. This prints requisition header id in console output in JDeveloper.



This demonstrates how nested application module can be used to add custom business logic in seeded OA Framework pages.

Any other approach?

You can create a custom region say xxCustomRN with application module XxNestedAM and attach the region using OAF Personalization. So the application module XxNestedAM becomes nested to root application module via region. This involves more steps as you have to load custom region definition into MDS repository using XMLImporter utility and create flexible layout to attach custom RN to seeded page. I'll create my next article on this topic.

Update: I've implemented alternate approach in the article How to extend root AM using nested AM. I did not seem bad as I expected.

Comments (6)add
Very userful Information!
written by AnilSharma , May 15, 2009
Hi Kishore,

Just want to confirm that this is useful when we want to extend the AM i.e Root AM then we can create another AM and make it nested AM.

So through Nested AM we can achieve the business need.

Thanks
--Anil
report abuse
vote down
vote up
Votes: +0
Re: NestedAM to extend rootAM business need
written by Kishore Ryali , May 15, 2009
Hi Anil,

You are right. You can use nestedAM to extend rootAM, without the LOV issue.

Kishore
report abuse
vote down
vote up
Votes: +0
Re: NestedAM to extend rootAM business need
written by Kishore Ryali , May 15, 2009
Anil,
One thing that still bothers me is ... According to OAF User Guide, Nested AM shares same transaction and context with root AM. So I should be able to get instance of VOs attached to root AM in Nested AM using statement

PoRequisitionHeadersVOImpl poh = (PoRequisitionHeadersVOImpl) nestedAM.findViewObject("PoRequisitionHeadersVO");
But for some reason, I'm always getting null even when I extend nested AM from root AM in design-time. So for this reason, I got handle to root AM in nested AM using getRootApplicationModule() in the tutorial.

Kishore
report abuse
vote down
vote up
Votes: +0
Re: NestedAM to extend rootAM business need
written by AnilSharma , May 18, 2009
Thanks Kishore,

You mean to say always do with....
PoRequisitionHeadersVOImpl poh = (PoRequisitionHeadersVOImpl) rootAM.findViewObject("PoRequisitionHeadersVO");

and if we will test with nestedAM.findViewObject("PoRequisitionHeadersVO"); then we will get NULL.

--Anil

report abuse
vote down
vote up
Votes: +0
Re: NestedAM to extend rootAM business need
written by Kishore Ryali , May 18, 2009
Anil,

Yes. I meant the same. Also check another article http://apps2fusion.com/at/kr/4...ion-module for extending root AM.

Kishore
report abuse
vote down
vote up
Votes: +0
Add filed global header in oaf Customization
written by Lakshminarayana , October 14, 2009
Hi All,

I need add two fields in global header and data display from data base table.

how to slove the issue..

Narayana
report abuse
vote down
vote up
Votes: +0
Write comment
quote
bold
italicize
underline
strike
url
image
quote
quote
smile
wink
laugh
grin
angry
sad
shocked
cool
tongue
kiss
cry
smaller | bigger

security image
Write the displayed characters


busy
 

Related Items

Search apps2fusion