Friday, July 30, 2010

A short cut to display row numbers for each record on UI

In this post, I'm sharing a tip to display row numbers along with data in each row on UI. Idea is to modify the ViewObject's query to use ROW_NUMBER(). You may need to be measured if the number of records in the table are large in size (because of the obvious performance issues).

SQL for a typical ViewObject may look like as shown below,
SELECT ROW_NUMBER() OVER(ORDER BY  Employees.FIRST_NAME)AS ROW_NUMBER , Employees.EMPLOYEE_ID, 
       Employees.FIRST_NAME, 
       Employees.LAST_NAME, 
       Employees.EMAIL, 
       Employees.PHONE_NUMBER
FROM EMPLOYEES Employees

You can download the sample workspace from here.
[Runs with Oracle JDeveloper 11g R1 PS2 + HR Schema]

Tuesday, July 27, 2010

Tips on using <af:panelCollection>

A couple of tips on using <af:panelCollection>
1. Use space delimiter if you want to turn off multiple 'default features' for the <af:panelCollection>
Example:
<af:panelCollection id="pc1" featuresOff="detach freeze wrap" >

2. If you don't want the end user to hide specific columns using the 'View->Columns' option, set showRequired="true" for those columns. This setting will disable the columns in the 'View' menu.

Monday, July 26, 2010

Enabling LOVs for Dynamic ViewObject attributes

In one of my previous posts, I talked about the model driven approaches for building dynamic User Interfaces. This post is in continuation of the earlier post. This time, I'll discuss about building 'Dynamic Form' containing LOV(List of Values) enabled fields (built using dynamic ViewObject).

Defining Dynamic Entity Objects and View Objects

First step is to to build EntityObject and corresponding ViewObject dynamically, based on the meta-data supplied by the run time. Below given sample code illustrates the APIs used for building EntityObjects and corresponding ViewObject, on the fly.

EntityDefImpl newEntity = new EntityDefImpl(DYNAMIC_EO);
AttributeDefImpl newAttrDef1 =
    newEntity.addAttribute("DepartmentId", "DEPARTMENT_ID",
               Number.class, false, false, true);
//Other attribute defn goes here...
newEntity.resolveDefObject();
newEntity.registerDefObject();
ViewDefImpl newView = new ViewDefImpl(DYNAMIC_VO);
newView.addEntityUsage("e", DYNAMIC_EO, false, false);
newView.addAllEntityAttributes("e");
newView.setFetchSize((short)30);

newView.setSelectClauseFlags(ViewDefImpl.CLAUSE_GENERATE_RT);
newView.setWhereClauseFlags(ViewDefImpl.CLAUSE_GENERATE_RT);
newView.setFromClauseFlags(ViewDefImpl.CLAUSE_GENERATE_RT);
buildLOVForDepartmentId(newView);

Enabling LOVs for Dynamic ViewObject attributes

Cool...Next step is to define LOV for desired attributes programmatically. Apparently, you may need to have following two items defined on the ViewObject to enable LOV for specific attributes.

1. ViewAccessor definition - For accessing Data Source View Object(destination view object) for LOV.
2. ListBinding definition - This defines meta data used for the LOV, such as the columns displayed on the LOV component, return attribute mappings etc.

The following sample code illustrates programmatic definition of LOV for 'DepartmentId' attribute.

private void buildLOVForDepartmentId(ViewDefImpl newEmpViewDef) {
  String viewAccessorName = "DepartmentIdVA";
  String lovName = "LOV_DepartmentId";
  String listDataSourceViewDefName = "model.DepartmentsView";

  ViewAccessorDef vdef = new ViewAccessorDef();
  vdef.setName(viewAccessorName);
  vdef.setViewDefFullName(listDataSourceViewDefName);
  vdef.setRowLevelBinds(true);

  newEmpViewDef.addViewAccessorDef(vdef);

  ListBindingDef listBindingDef =
    buildListBindingDef(newEmpViewDef.getDefManager(),
    viewAccessorName, lovName,
    new String[] { "DepartmentId" },
    new String[] { "DepartmentId" },
    new String[] { "DepartmentName" });
  newEmpViewDef.addListBindingDef(listBindingDef);
  int clmnIndex = newEmpViewDef.getAttributeIndexOf("DepartmentId");
  AttributeDefImpl _voAttrDef =
  (AttributeDefImpl)newEmpViewDef.getAttributeDef(clmnIndex);
  _voAttrDef.setLOVName(lovName);
  _voAttrDef.setProperty(AttributeHints.ATTRIBUTE_CTL_TYPE,
       AttributeHints.CTLTYPE_COMBO);

}

Build the User Interface

Our model is in place, now you may need to wire the model with <dynamic:form> as shown below.

You can download the sample workspace from here.
[Runs with Oracle JDeveloper 11g R1 PS2 + HR Schema]

How to run this sample?

Run the main.jspx. Main page display a drop down list. Select the 'Employee' item from the list, and then click on the action button displayed below. This action invokes 'dynamicEntityBased-tf' task flow. The default activity for this task flow is to set up the required ViewObjects used by the view. As the next step in the sequence, control moves to 'dynamicForm' page and data is being rendered using <dynamic:form> component. This UI is generated on the fly based on the item selected from the drop down. Please check out the 'dynamicEntityBases-tf' task flow to understand the underlying execution path.


Learn More ...

There are a lot more points like this. If  you are curious to learn the internals of the ADF Business Components and ADF Binding Layer,  the following book is for you - Oracle ADF Real World Developer’s Guide.
More details about this book can be found in this post- http://jobinesh.blogspot.in/2012/07/pre-order-your-copy-of-oracle-adf-real.html

Friday, July 9, 2010

Running ApplicationModule using an external JDBC connection

Use case

This post discusses a bit odd use case. This requirement arose while migrating a huge system built on Java to ADF technology stack. When choosing modules for migration(in a step by step manner), there are chances that a specific service may need to compose business methods from existing legacy system and newly build ADF BC modules. Now the fun starts, functional testing team may not be aware of the underlying migration phases. So there may be cases where existing java code and partially migrated ADF BC modules needs to participate in the same database transaction. This is an easy task if the existing system is based on XADataSource to access database. You may just need to make sure that your ApplicationModule is configured to use the same XADatasource. What if that's not the case? You may need to share same raw JDBC Connection between two implementations. This post discusses a possible solution for this scenario. Please note that, I'm not recommending this approach/solution for a production system. However, this may be useful for certain scenarios as explained above( to carry out an end to end intermediate functionality testing while migrating existing Java applications to use ADF in multiple stages).

Solution

Idea is to store the java.sql.Connection used by the POJO caller in the ThreadLocal instance and customize DBTransactionImpl class from the ApplicationModule to use this Connection. This in turn ensures that ViewObjects/EntityObjects are using the same connection instance supplied by the POJO caller. Please note ADF BC layer let you to override the default DBTransactionImpl using custom DatabaseTransactionFactory class. The customized bc4.xcfg file used for building the attached sample is listed in the following diagram. Please refer the sample project source to learn more.


<AppModuleConfig DeployPlatform="LOCAL" jbo.project="test.Model" JDBCName="DeleteMeLater"
   name="AppModuleLocal" SessionClass="fmwk.extension.CustomSessionImpl"
   TransactionFactory="fmwk.extension.CustomDatabaseTransactionFactory"
   ApplicationName="test.AppModule">
  <AM-Pooling jbo.ampool.connectionstrategyclass="fmwk.extension.CustomDatabaseConnectionStrategy"/>
  <Security AppModuleJndiName="test.AppModule"/>
</AppModuleConfig>

You can download the sample workspace from here.
Run TestAM.java
[Runs with Oracle JDeveloper 11g R1 PS2 + HR Schema]