Saturday 15 December 2012

11. PPR (Partial Page Rendering) in OAF

While developing pages, we may face some scenarios where the requirement is to make modifications on the current page itself, instead of navigating to different page. Such as selecting an item from a choice list might result in modifications to other fields or clicking a button to add a new row in table region and many more like these.
All these tasks can be performed by simply refreshing the page however this could result in performance issues. Another alternative is to use javaScript which will give faster results but implementing complex functions can be a tough job using javaScript.

UIX Framework provides a solution for this: Partial Page Rendering i.e. to re-render only a limited portion of a page.

Working of PPR :-
==========================
PPR is a three step process:

1) Partial page event

Partial page events are quite similar to full page events. However, there are two important differences between partial and full page events. First, partial page events specify partial page rendering-specific event parameters which are not present on the full page event equivalents. For example, partial page events may include an event parameter which identifies the set of partial targets, or nodes that should be re-rendered.
The second difference between partial page events an full page events is how the events are sent. Unlike full page events, partial page events must be sent in a way which does not force the browser to reload the current page. To implement this capability, UIX PPR uses a hidden iframe as a communication channel between the browser and the web application running on the middle-tier. Partial page events are sent by forcing a navigation in the hidden iframe, which in turns causes a request to be sent to the application on the middle-tier. Since the iframe is hidden, the process of sending a partial page event and rendering partial page contents can take place behind the scenes, without discarding the contents of the current page.

2) Partial Page Rendering Pass

When the partial page event is received by the application, the application responds by determining the set of partial targets to render and performing the partial page rendering pass. The partial page rendering pass is similar to a full page rendering pass. In both cases, the UINode tree is traversed by calling render() on each node in the tree. However, in the PPR case, only the contents generated by the partial targets are actually sent back to the browser. All other contents are dropped. So, the partial page response is generally much smaller, since only the modified contents are sent back to the browser.

3) Partial Page Replacement

When the browser receives the partial page response, the new contents for each partial target node are copied from the hidden iframe into the main browser window, replacing the existing contents for each target node. For example, in the table navigation case, rather than replacing the entire page, just the contents of the table itself are replaced.

Now lets create a simple page to implement PPR. In this page, there are 3 items (employee number, employee name & job). I have attach a PPR event on employee number field. Hence, user will enter the emp number and as soon as he tabs out, name and job will populate on their respective fields without refreshing the page.


1) Create a new OA page:
==========================
Right click on project (xxcus) --> New --> Web Tier --> OA Components --> select 'Page' item. Click OK. (This will open a popup window)
We are creating a page for implementing PPR, so specify the details of page as below:
          Name: XxPprDemoPG
          Package: xxcus.oracle.apps.fnd.pprdemo.webui

2) Create a new view objects (VO):
==========================
Right click --> New View Object (This will open a wizard having 7 steps).

Step 1
         Package: xxcus.oracle.apps.fnd.pprdemo.server
         Name: XxPprDemoVO
         Choose the radio button 'Read-only Access' (as no DML operation).
         Click Next.

Step 2
         Enter the below query in 'Query Statement':
               select EMPNO, ENAME, JOB from employee

Keep defaults for step3, 4, 5, 6 & 7 and click Finish. Save All.

3) Create a new Application Module (AM):
==========================
Step 1
         Package: xxcus.oracle.apps.fnd.pprdemo.server
         Name: XxPprDemoAM. Click Next.

Step 2
    Here we will add an instance of the VO created in (2). Select XxPprDemoVO from 'Available View Objects' and shuttle it to 'Data Model' using ">" button.

Keep defaults for all other steps (3, 4). Click Finish.

4) Create a new Controller (CO):
==========================
Right click on pageLayout region and create a new controller:
          Name: XxPprDemoCO
          package: xxcus.oracle.apps.fnd.pprdemo.webui

5) Creating the Page Layout & Setting its Properties :-
==========================
The page will appear as below:



1) Create a new region under pageLayout of type defaultSingleColumn.
2) Create 3 items under defaultSingleColumn region (messageTextInput, messageStyledText, messageStyledText).

Now change the properties for each field from property inspector as shown below:

pageLayout:
             ID: pageLayoutRN
             AM Definition: xxcus.oracle.apps.fnd.pprdemo.server.XxPprDemoAM
             Window Title: PPR Demo Page
             Title: PPR Demo

defaultSingleColumn:
             ID: singleColRN
             Text: Enter Employee Number

messageTextInput (applied PPR event on this item):
             ID: Empno
  Prompt: Employee Number
  Action Type: firePartialAction
     Event: populateFields
 
messageStyledText (for Employee Name): 
             ID: Ename
             Prompt: Employee Name
 View Instance: XxPprDemoVO1
     View Attribute: Ename
 
messageStyledText (for Job):
             ID: Job
             Prompt: Job
     View Instance: XxPprDemoVO1
     View Attribute: Job
 
The declarative page structure in jDev will be similar to as shown below:




We will capture populateFields event (PPR event) in PFR method of controller and call the appropriate method from AMImpl class as shown in below code snippet:

public void processFormRequest(OAPageContext pageContext,
                               OAWebBean webBean) {
 super.processFormRequest(pageContext, webBean);

 OAApplicationModule am = pageContext.getRootApplicationModule();

 if ("populateFields".equals(pageContext.getParameter(EVENT_PARAM))) {
    String empNum = pageContext.getParameter("Empno");
    if (!("".equals(empNum.trim()))) {
       Serializable[] param = { empNum };
       String result = 
         am.invokeMethod("firePprEvent", param).toString();
         if ("N".equals(result)) {
            throw new OAException("Please enter valid employee number.",
                                 OAException.ERROR);
        }
    } else {
        String empnum = null;
        Serializable[] param = { empnum };
        am.invokeMethod("firePprEvent", param);
        throw new OAException("Please enter employee number",
                        OAException.ERROR);
    }
 }
}


Code for firePprEvent method in XxPprDemoAMImpl.java file:

public String firePprEvent(String empNum) {
  try {
      XxPprDemoVOImpl vo = getXxPprDemoVO1();
      vo.setWhereClause(null);
      vo.setWhereClauseParams(null);
      vo.setWhereClause("EMPNO = :1");
      vo.setWhereClauseParam(0, empNum);
      vo.setMaxFetchSize(-1);
      vo.executeQuery();
      XxPprDemoVORowImpl row = (XxPprDemoVORowImpl)vo.first();
      if (row == null) {
          return "N";
      }
  } catch (Exception e) {
      e.printStackTrace();
  }
  return "Y";
}

User will enter employee number and tabs out. This will auto-populate the other two fields without full page refresh as shown below:










1 comment:

  1. the processform request is not getting called on changing the text field.

    ReplyDelete