Skip to main content

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

Popular posts from this blog

Happy New Year 2018 !

We can't go back and change the beginning, but we always can start where we are and change the ending. Believe in yourself and you will be unstoppable!

Wishing you and your family a very happy new year 2018 !!!

How to set Bind Variable Values at runtime ?

In this post I'm sharing a couple of approaches for programmatically setting bind variables values at run time. This post is an attempt to explain 'When to use what ?'[ In case if you are familiar with 'Bind Variables' in ADF BC, please refer Section 5.10, Working with Bind Variables in Fusion Developer's Guide ]

1. Set the Bind Variable value using RowSet::setNamedWhereClauseParam(...)

You can use use the setNamedWhereClauseParam(...) method on the ViewObject interface (which extends oracle.jbo.RowSet) to set the value for bind variables. Please note this sets the value on default RowSet. In other words, this doesn't have any effect on the secondary RowSets that you/system generates.
ViewObject vo = am.findViewObject("EmployeesView1"); vo.setNamedWhereClauseParam("bindVarDeptId", new Number(10)); vo.executeQuery();
2. Set the Bind Variable value using ViewObject's VariableValueManager::setVariableValue(...)

VariableValueManager Ma…