Tuesday, 12 October 2010

ADF BC - Read Only View Objects and missing PK attributes – A Passivation Issue

A recommended ADF development best practice from Oracle is to check your applications are Activation Safe. In recent testing of an ADF 11g application we discovered the following scenario where our application failed Activation Safe testing, documented for others to read-but-not-experience-first-hand.

Problem Scope

Consider an application displaying employee details. The first screen contains a table of employees, and on selecting a specific row, the 2nd screen shows the details of the selected employee.

Note in the screen shots, selecting employee ID 106 in the table, displays employee ID 106 in the form screen. Essentially the expected behaviour.

In this example from the ADF BC point of view the employees data is backed by a Read Only View Object (VO) based on the employees table from Oracle's HR schema. By default the employees VO contains the following attributes. Note the PK employee ID:

By chance if we disable the PK and run the application, it performs in the same way as described in the first picture above on the developer's PC. Selecting employee ID 106 in the table results in the same record 106 shown in the second page.

Interestingly in the JDev console, as we select the employee in the table, the following message is displayed:

<CurrencyRowKeySet><_computeCurrentRowKey> ADFv: Rowkey does not have any primary key attributes. Rowkey: oracle.jbo.Key[], table: oracle.jbo.server.ViewObjectImpl@e48114.

Yet as stated the application works correctly. Can we ignore this error?

Activation Safe testing teases out the problem in more detail. Activation Safe testing requires us to right click the Application Module -> then select Configurations -> AppModuleLocal -> Pooling and Scalability, and then *disable* the Enable Application Module property:

On re-running our application we see the following behaviour:

...that is on selecting employee ID 105, and navigating to the next page, oddly the record shown is employee ID 100. Selecting the back button, on returning to the table page, it still shows employee ID 100 as the selected record regardless of our original selection.

On looking at the JDev console window when selecting employee ID 105, we see that the log message has expanded:

<CurrencyRowKeySet><_computeCurrentRowKey> ADFv: Rowkey does not have any primary key attributes. Rowkey: oracle.jbo.Key[], table: oracle.jbo.server.ViewObjectImpl@9ddef9.
<FacesCtrlHierBinding$FacesModel><makeCurrent> ADFv: No row found for rowKey: [oracle.jbo.Key[]].

If you turn on the -Djbo.debugoutput=console option when running the program the problem is revealed in more detail:

[978] Warning! Binding:noCtrl_oracle_adfinternal_view_faces_ model_binding_FacesCtrlHierNodeBinding_1 requires key attributes to be able to locate nodes in the hierarchy.


From identifying this problem the natural conclusion is in order to build an Activation Safe application, amongst other issues your View Objects require a primary key. Typically this isn't an issue as most VOs are based on EOs, where the IDE enforces each EO has at least one primary key attribute that is shared to the VO. But in the case of Read Only VOs not based on an EO, it's fairly easy to create a VO without a PK attribute. In the simple example from this blog, of course the employees table has a PK attribute, but, if we're building a customised VO based around some complex query, in particular if we use the expert-mode VO option, no PK is defined by default. Thus our application becomes Activation unsafe.


Tested under JDev build 5536.

No comments: