You are on page 1of 7

Nested Application Modules in OA Framework

Written by Kishore Ryali


Thursday, 14 May 2009 03:59

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.

1/7
Nested Application Modules in OA Framework

Written by Kishore Ryali


Thursday, 14 May 2009 03:59

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("XxNested


AM", "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

2/7
Nested Application Modules in OA Framework

Written by Kishore Ryali


Thursday, 14 May 2009 03:59

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;

3/7
Nested Application Modules in OA Framework

Written by Kishore Ryali


Thursday, 14 May 2009 03:59

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 cr
eateApplicationModule()
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.*;

4/7
Nested Application Modules in OA Framework

Written by Kishore Ryali


Thursday, 14 May 2009 03:59

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);

5/7
Nested Application Modules in OA Framework

Written by Kishore Ryali


Thursday, 14 May 2009 03:59

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?

6/7
Nested Application Modules in OA Framework

Written by Kishore Ryali


Thursday, 14 May 2009 03:59

You can create a custom region say xxCustomRN with application module X
xNestedAM
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.

7/7