Tuesday, December 22, 2009

Conditionally displaying search form parameters

ADF helps you to build search forms declaratively using model-driven af:query and af:quickQuery components. To learn more about this topic, please refer Chapter 26 Creating ADF Databound Search Forms in Fusion Dev. Guide.

If you use ADF Business Components for building your business services, ViewCriteria defined on your ViewObject act as the model for the af:query component. af:query component (backed up with ViewCriteria) is smart enough to address most of the common use cases declaratively. However there may be some use case scenarios, where developers need to go beyond the declarative development approach and dirty their hands a bit:) One such scenario is displaying search form prameters, conditionally. In other words, parameters in the query panel needs to be displayed based on certain conditions. Let me try explaining a possible solution for this use case. Please remember that each query parameter displayed in af:query is modeled by a ViewCrieteriaIteminstance. Apparently, you can make use of the ViewCriteriaItemHints to control the display properties. Following piece of code may help you to hide the ViewCriteriaItem programmatically.
viewCrieteriaItem.setProperty(
ViewCriteriaItemHints.CRITERIA_RENDERED_MODE,
ViewCriteriaItemHints.CRITERIA_RENDERED_MODE_NEVER);
Hey, hang on, I’m not finished!

From Fusion Developer's Guide:
If you are changing the value of a view criteria item programmatically, you must invoke the ViewCriteria.saveState() method to prevent the searchRegion binding from resetting the value of the view criteria item to the value that was specified at design time.

So you may need to call ViewCriteria.saveState() to persist the changes.

viewCrieteriaItem.setProperty(
ViewCriteriaItemHints.CRITERIA_RENDERED_MODE,
ViewCriteriaItemHints.CRITERIA_RENDERED_MODE_NEVER);
viewCriteria.saveState();
That’s it...now sit back and relax!

You can download the sample workspace from here. This example illustrates the above mentioned use case -i.e.: hiding search form parameters at runtime. This sample has two pages department.jspx and employee.jspx. User can navigate from department page to employee search page. The employee.jspx is hosting a task flow that in turn contains a query panel + result table. Department Id displayed inside the query panel of the employee page will be hidden from the user if he/she navigates from department page after selecting a specific department (which makes sense too).
[Runs with Oracle JDeveloper 11g R1 PS1 + HR Schema]

Friday, December 11, 2009

Customizing ELResolver to intercept the evaluation of ADF binding values

ELResolver enables customization of variable and property resolution behavior for EL expression evaluation.
In case you are not familiar with this topic, please see one of my previous post to get a feel of this concept. Very recently, I noticed an interesting use case scenario related to this topic. Here the requirement is that, whenever business user modifies a date field displayed on the web UI, the same value needs to be converted to a specific time zone by the system based on certain business rules before saving to database. One possible solution is to use custom ELResolver to intercept the setters for the attribute value. Interestingly, a customized ELResolver created by sub classing javax.el.ELResolver work for EL expressions that use managed beans, but fail for ADF binding values - modified values are not getting passed to model. So, what next? Your friend is javax.el.MapELResolver here.

Why should I specifically use javax.el.MapELResolver ?

Before answering this question, let us take a step back and try to identify the class responsible for binding controls with attribute value when you use ADF binding. Search end up in an internal class, oracle.adfinternal.view.faces.model.binding.FacesCtrlAttrsBinding, who is responsible for binding controls to a single Row object in the business service layer. A closer analysis shows that FacesCtrlAttrsBinding is sub classed from java.util.Map.
+oracle.jbo.common.JboAbstractMap
 +oracle.adf.model.binding.DCControlBinding
  +oracle.jbo.uicli.binding.JUControlBinding
    +oracle.jbo.uicli.binding.JUCtrlValueBinding
      +oracle.jbo.uicli.binding.JUCtrlAttrsBinding
        +oracle.adfinternal.view...FacesCtrlAttrsBinding


MapELResolver API doc. says:
MapELResolver defines property resolution behavior on instances of Map.This resolver handles base objects of type java.util.Map. It accepts any object as a property and uses that object as a key in the map. The resulting value is the value in the map that is associated with that key.

This answers the above question. Apparently you can subclass javax.el.MapELResolver and override the setValue(...) to push the modified value back to the model.


@Override
public void setValue(ELContext context, 
        Object base, Object property,
        Object value) {
  if ( someBusinessCondition(base, property,
                                   value)) {
    super.setValue(context, base, property,
                  manipulatedValue(value));
  }
}
 

You can download the sample workspace from here. This example illustrates the customization of MapELResolver to amend the literal values entered by the user by appending with a 'Modified' string token
[Runs with Oracle JDeveloper 11g R1 PS1 + HR Schema]

Saturday, December 5, 2009

VIewObject based on 'pivot query'

I have seen few posts in ADF discussion forums asking for solutions to transpose database table rows in to columns. Apparently, this turns out to be s a query related to the underlying RDBMS. Attaching a simple demo application that transforms Employee Table in columnar from as shown below.

[If you use Oracle 11g, pivot operator will help you to achieve the same behavior. The above sample is not using pivot operator]
You can download the sample workspace from here.
[Runs with Oracle JDeveloper 11g R1 PS1 + HR Schema]