Wednesday, July 18, 2012

ValidateEntity, NewRowState and Commit


Below is stated from Developer's Guide:

 

Entity Object Initial / New State

By default, entity objects are created with the row state of STATUS_NEW, and BC4J adds them to its validation and post listener lists. In this case, any event that triggers a validation or database post sequence includes these entity objects.

As stated in the OA Framework Model Coding Standards, always circumvent this behavior by explicitly calling the setNewRowState(STATUS_INITIALIZED) method on its containing ViewRowImpl immediately after you insert the newly created row. This sets the state of any associated entity objects to STATUS_INITIALIZED.

When you do this, BC4J removes the corresponding entity objects from the transaction and validation listener lists, so they will not be validated or posted to the database. As soon as the user makes a change (an attribute "setter" is called), the entity object's state changes to STATUS_NEW, and BC4J returns it to the validation/post lists. You can also call setNewRowState(STATUS_NEW) on the ViewRowImpl to change the state manually at any time.

Code Behaviour:

Case 1: Row has been modified in the UI before submit. Row State could be anything. 
  • The RowState becomes New.
  • ValidateEntity will get called before processFormRequest().
Case 2: Called row.setNewRowState(Row.STATUS_NEW) after inserting a new row. Row has not been modified from UI.
ValidateEntity will not get called before processFormRequest() but will get called on commit and postChanges.
Case 3: Called row.setNewRowState(Row.STATUS_INITIALISED) after inserting a new row. Row has not been modified from UI.
  • ValidateEntity will not get called before processFormRequest() or on commit or postChanges.
  • The Row will be ignored by the Framework and removed from the Cache.
  • Even the mandatory fields in the Entity Object are not checked.
Please note setting the row state (row.setNewRowState) should be done after adding the row to VO as recommended in the OAF Standard.

Though if you set the row state before adding it to the VO, it'll also work fine as long as you don't call any setter. The moment any setter is called row state changes to NEW.

Saturday, May 12, 2012

Common Mistakes in OAF

I have conducted a few corporate trainings, it was a good experience. I received positive feedback, which encouraged me further. On introspection I remembered a saying, “A poor student has good chance of becoming a good teacher”.

Poor students have to struggle hard to learn things, and excel. They can easily relate to participant's problems. They have less chances of taking things for granted and assuming that one would at least know this much. They can ensure that one feels comfortable sharing less intelligent thoughts, they may even relate to many of them. He can understand its not uncommon to do common and silly mistakes while on the learning curve.

Debatable !! Certainly when one of the best teachers I know is my dear friend Deepak Srivastava, who is a topper in School, College, and University. There are exceptions

We are diverting here.
So, following are some of the mistakes I have done over the years and I am totally cool about it. Given a chance I don't mind making more mistakes and learn from them:


1. Calling ProcessRequest from ProcessFormRequest.

This was during my first OAF search page was around 7.5 yrs back. Search page was different from the traditional search pages. This was done in an attempt to write less code. Later realized that significance and semantics of these methods and took corrective measures.


2. Traversing VO Rows directly without any iterator.

Ideally one should prefer using a RowSetIterator for navigating the rows.
If we choose to directly use the VO for navigating the rows using vo.first(), vo.hasNext(), vo.next(), etc methods, this would result in current row getting changed. If same VO is being used to display the result on the webpage, the change in current row will result in different rows being displayed in result table or form.


3. Using of getRowCount()

Worst reason to use getRowCount() could be
if(getRowCount() > 0)
getRowCount() always executes the VO.

4. Calling setters from getters.

Get Methods are not expected to change the value of the property and state of the object.


5. Coding PPR without CO and AM code

This might be a surprise to few but there is a terrible way to code PPR, following are the steps:
a) Enable PPR on the UI widget.
b) Don't handle anything in CO, no capturing the event.
c) Don't write any code for PPR in AM
d) All code in VO getters. Whenever a PPR event is fired, getters of all the fields being displayed will be fired.

Please don't follow above steps for the PPR.


6. Went overboard with generic APIs.

A good programmer writes the logic with KISS principle in mind. Too many generic APIs will make more slightly difficult to read. They are important but one shouldn't write an API for every piece of logic needed.

7. Keeping constants in a separate utility java file (for using it at many places in multiple java files) Compiling only this file after changing value of constant.

Java replaces the reference of constants to actual value of the constants in the .class file.
When you change the value of the constant in the utility java file, and compile, it doesn't replace the value of constant in existing compiled class files where this constant is being used. Existing class files will continue to use the old value of the constants.

8. Creating more transient attributes in VORowImpl than using calculated attributes and keeping code in SQL Queries.

Many times you have a choice to either create a transient variable in VO and calculate the value in VORowImpl or modify the SQL of the VO and calculated the value in SQL.
Both approaches are fine but doing it in SQL is better practice, makes code more readable and easy to maintain.

9. Ignoring the sequence of Form Value and other fields 

At times we have form values and other fields on a page, all binded to same VO Instance and VO Attribute.
Read Only widgets like MessageStyleText don't submit their data, we need Form Values to submit the data to BC4J. 

We need form values in case of dependent LOVs or other dependent widgets. 
We also need form values to submit the data shown to users as readonly which is returned by LOVs.

Now what is more important is to know how and in what order the values in the UI widgets gets transferred to BC4J. The sequence is from top to bottom. In case if there are more than one field in UI for a VO Attribute, then the last UI widget that can submit the value will set the value the last time and thus this will get saved in DB.
I ignored this and in a rare but a badly coded page of mine, this was cause of a bug.


10. Not enabling Passivation on AM

Please do not forget to enable Passivation on your AM.

11. Ignoring the Tuning Tab in VO

In VO properties, there is tuning tab, setting the properties helps improve the performance, and shouldn't be ignored.


12. Not writing re-enterable processRequest Code

The processRequest() method may be re-entered to synchronize UIX with BC4J. Any initialization logic (VO execution, session variables, transaction variables based logic) must keep this in mind.



13. Prefer Oracle-style binding (:1, :2) over JDBC Style(?)

      Oracle Style binding avoids parsing SQL at runtime to do String replacement.

Friday, April 6, 2012

OAF Page Processing Part #1 - Key Terms

There are lot of terms that you'll encounter while learning about the OAF Page Processing, Request Handling etc. 
Following are some key terms that should help one understand OAF and Web development in quick time:

PAGE:

  • A hierarchy of regions that is accessible using a URL. Pages generally represent a cohesive unit of functionality that may stand on its own, or work in concert with other pages.

REGION:

  • Rectangular area that determines layout and UI component presentation in the user interface. Regions are containers which can contain both regions and items. Common region examples include tables, flow layouts, headers and so on.

PAGE LAYOUT REGION:

  • A region that is a high-level layout element that is a template for the entire page. It supports several navigation and content areas for the creation of pages.

RENDER:

  • To furnish; to contribute, to make available, to interpret, represent 
  • When web beans are "rendered," UIX includes them in the web bean hierarchy. Furthermore, HTML is generated for the component and sent to the browser.

ORACLE E-BUSINESS SUITE USER SESSION

  • A mechanism for keeping track of key Oracle E-Business Suite context information for a login.
  • When the user logs in to an OA Framework application, the OA Framework creates an AOL/J oracle.apps.fnd.comon.WebAppsContext object and a browser session-based cookie that together keep track of key Oracle E-Business Suite context information like the current responsibility, organization id and various user attributes (user name, user id, employee id and so on). The Oracle E-Business Suite user session is associated with a servlet session, however, it has its own life cycle and time-out characteristics. 

CONTROLLER:

  • In the context of a Model-View-Controller application (MVC), the controller responds to user actions and directs application flow.
  • In an OA Framework application, this term is often used to specifically refer to the Java UI Controller associated with one or more regions in a page.

 PAGE CONTEXT:

  • Each time a request is received for a page, OA Framework creates an OAPageContext that persists until a new page finishes processing. 
  • This object contains parameters from the requesting page
  • It also contains form fields if the request is a POST
  • The OAPageContext object provides:
  • Access to the server Application Module Class
  • Methods to perform JSP forwards and client redirects\
  • Access to session level Application context for
    • User name
    • Id
    • Current responsibility and so on

WEBBEAN HIERARCHY:

  • At page development time, we specify the bean hierarchy. Structure window shows the bean hierarchy at development time.
  • The sequence in which region and items appear in structure window determines their position in web bean hierarchy.
  • OA Framework reads the page's declarative metadata definition to create the web bean hierarchy.
  • At page rendering time, the UIX framework processes the web bean hierarchy to generate the page HTML

PASSIVATION:

  • The process of saving client state to a secondary medium (in the case of the OA Framework, database tables).

ACTIVATION:

  • The process of restoring client state from a secondary medium (in the case of the OA Framework, database tables).
Passivation and activation are two phases of a resource management technique that reduces the number of bean instances needed to service all clients.

SERIALIZABLE:

  • Process of saving an object's state to a sequence of bytes, as well as the process of rebuilding those bytes into a live object at some future time
Serialization is one way to save data, Passivation is a more generic concept.

PAGE BOUNDARY:

  • The boundary between the completion of page processing for one page, and the start of page processing for another. When OAPageBean finishes processing a page.

REQUEST BOUNDARY:

  • Once a response is returned, it is the end of the request processing or the boundary between one request/response pair and the next.
A page boundary is equal to request boundary except for JSP forward case where a single request can span multiple pages. 

Request parameters exists throughout the life span of a request, which can span across multiple page boundaries. Request parameters will be hanging around in case of JSP Forward.

JBO:

  • Java Business Object
  • BC4J was originally named JBO.

JRAD:

  • Java Rapid Application Development
  • Originally UI Level was called JRAD.

Thursday, April 5, 2012

Multple Transactions in One OAF Page

Date: 20-May-2010  (I am little late for posting this article)

Background:

One very respected gentleman (who's blog we all would have visited while working on OAF.. keep guessing !!) asked a question in interview to a dear friend of mine.
How can we have two regions in a page in such a way that if you commit data in one region it shouldn't commit the data in other regions of the page?
In other words the requirement is to have two transactions in one OAF page.

First Reaction:

Shock!!
Root Application Module provides transaction context.
We can have only one Root Application Module in a page, then how can we have two transactions?

Why we need it?
I don't think we need it at all.
We can handle scenarios like this using combinations of Read-Only and Updatable VOs.
My strict recommendation is you try this only at home and never at work. You'll not be always available for your code's maintenance.

An observation that led to answer:

Application Behavior:
After some brainstorming, I remembered an observation while navigating between pages with retainAM=Y and with different Root AM, state of the page is getting retained.

Learning:
Somewhere system was retaining both Root AMs.
Two Root AMs means two transactions.

Test Case Tried:
On a relatively free day at work. I discussed this testcase with my colleague, one of the better technical resources I have ever worked with.
Tried passing AM object of one page to next page using Request and Session scope. Tried out things with both AMs in second page. 
It worked like magic.

Snippet:
------------

Page 1: Empty Page
Controller 1:

pageContext.putSessionValueDirect("xxfirstAM", pageContext.getApplicationModule(webBean));
//You can try passing it in Request also.
//We'll get this value in second CO and update data in VO's in this AM, call APIs by getting OADBTransaction

pageContext.forwardImmediately(<url of second page>);



Page 2: Transaction Page
Controller 2:

OAApplicationModule secondPageAM = pageContext.getRootApplicationModule();
OAApplicationModule firstPageAM =             (OAApplicationModule)pageContext.getSessionValueDirect("xxfirstAM");

// This way we'll be having two AMs in our Controller.
// Both these AMs will have their own transactions.
// Changes commited from one of them will not commit changes in other. 

Monday, March 26, 2012

OABodyBean


oracle.apps.fnd.framework.webui.beans.OABodyBean


public class OABodyBean
extends oracle.cabo.ui.beans.BodyBean
implements OAWebBeanContainer, OAWebBeanConstants

This bean is a container for the body of a document. It provides many supporting APIs for OAF.

Some Key APIs supported by this:

1. Blocking on Submit (Refer Dev Guide)

Whenever a submit action takes place on a page, subsequent submits can be blocked. When using a blocking on submit technique, when the submit action takes place, the cursor becomes busy and prevents any other submit action until the current submit event has been handled. The block on submit behavior is not enabled by default on a page. However, For Partial Page Refresh (PPR) events alone, it is enabled by default.

OABodyBean bodyBean = (OABodyBean)pageContext.getRootWebBean();  
bodyBean.setBlockOnEverySubmit(true);

2. PPR Event Queuing (Refer Dev Guide)

By default, when a PPR event fires, all subsequent events on the page are queued and processed. For example, lets say you have a search page and one of the item in search panel is a textbox with the PPR. If you enter some information in the textbox and click on Go. It'll first execute the PPR and then it'll process the Go button click.

To disable this feature at site level, set the value of the profile FND: Disable PPR Event Queuing (FND_PPR_EVENT_QUEUE_DISABLED) to Y. In this case, when a PPR event fires, all subsequent events on the page are ignored.

To implement event queuing on a specific page or to update the behavior of event queuing on a specific page, add the following code to the processRequest of that page.


This will enable the event queuing.

bodyBean.setFirstClickPassed(true); 

 

3. Setting Initial Focus on a Field
Setting the initial focus removes the use of mouse to start typing and saves time in certain pages.
bodyBean.setInitialFocusId("FirstName");



4. Setting Page Dirty

bodyBean.setDirty(true);
To mark a page as Dirty.

bodyBean.setDirty(false);
To mark a page as non-Dirty.


bodyBean.isDirty(false);
To get if a page is dirty or non-Dirty.


5. Setting Javascript

body.setOnLoad("<JS>"); (To call JS function on page load.)
body.setOnKeyPress("<JS>"); (Sets an onkeypress JS handler.)

There are more similar APIs that support Javascript.


bodyBean.setFirstClickPassed(true); This will disable the event queuing.

Sunday, March 25, 2012

UIX Bean and OA Webbean hierarchy

Behind every OAWebBean, there is a UIX webbean working behind the scene. 


Wednesday, November 16, 2011

Disable Right Click in OAF page

Following code in controller will block the Right Click, Context Menu Options for IE and Netscape both:

  pageContext.putJavaScriptFunction("click()",
    "var message=\"Due to security reason, Right Click is not allowed\";"+
      "function right2(){\n"+
           "if (event.button==2){\n"+
                "alert(\"Right Click is not allowed.\");\n"+
                "return false;\n"+
            "}\n"+
       "}\n"+
 "function rightClickTest (e) \n" +
 "{\n" +
      "if (document.layers||document.getElementById&&!document.all){ \n"+
        "if (e.which==2||e.which==3){\n"+
            "alert(\"You do not have permission to right click.\");\n" +
            "return false;\n" +
        "}\n"+
      "}\n"+
  "}\n"+
  "if (document.layers) {" +
      "document.captureEvents(Event.MOUSEDOWN);\n" +
      "document.onmousedown=rightClickTest;\n"+
  "}\n"+
  "else if (document.all&&!document.getElementById){" +
      "document.onmousedown=right2;\n"+
  "}\n"+
  "document.oncontextmenu=new Function(\"alert(message);return false;\")"
 );


Following scenarios have been tested and worked fine:
  • Switching the Buttons (Left-Right) has no impact because it doesn't change the event raised.
  • Context Menu from the keyboard is getting blocked as expected.

Why is it needed?

This is one question that I have not been able to find the answer. I can't think of any valid logical reason for disabling the right click. I have seen it in following places:
  • Bank has disabled right click on pages that shows account information.
  • Companies disable right click on page that displays the payslips.

How to enable the right click?

1.  Copy following javascript code in your browser and hit enter.
javascript:void(document.onmousedown=null);void(document.onmouseup=null);void(document.onclick=null);void(document.oncontextmenu=null)

Above seems to be working for OAF pages that have right click blocked and other websites including my bank's website as well.

2.  Disabling the javascript in browser also enable the Right click in websites.


Whether we should do that or not?

NO, its very annoying, and incomplete solution. We should find better way to restrict and protect information that we need to protect.