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]

Comments