Implementing a custom EL resolver

In Runtime-defined properties in EL expressions, I described how to implement beans with dynamic properties accessible from an EL expression, so that the property which is accessed can be defined at runtime rather than at compile time through corresponding getter and setter methods. The approach was to implement the Map interface which lets the ADF runtime use the MapELResolver to lookup the properties by their names.

There is also another approach which is more flexible: JSF allows to define Custom EL resolvers through a pluggable resolver mechanism. These resolvers are then used when looking up properties, in addition to the existing resolvers. In ADF, the same mechanism is also available.

To implement a custom EL resolver, we first need to implement a Java class which will serve as the resolver. The simplest approach is to inherit from ELResolver and overwrite the following abstract methods:

public Object getValue(ELContext elContext, Object base, Object property);
This method is called by the framework whenever it needs to retrieve the value of a property. base is the parent object for which to retrieve the property, and can also be null for the very first part of the EL. Assume we have the following EL: #{bean.property}. Then, base will be null when the framework is resolving “bean”, but base will point to the previously resolved “bean” object when the framework is resolving “property”. elContext provides access to data which is relevant in the current resolving context – the most important method is setPropertyResolved(). This method needs to be called each time the resolver could successfully handle a property – the framework will then stop with the resolving process instead of proceeding to the next resolver in its resolver chain.

public void setValue(ELContext elContext, Object base, Object property, Object value);
This method is called by the framework whenever it needs to set the value of a property.

public Class getType(ELContext elContext, Object base, Object property);
This method is used by the framework to return the type of a specific property.

public boolean isReadOnly(ELContext elContext, Object base, Object property);
This method is called by the framework to determine whether a property is read-only or not.

In addition, there are two methods which can be used by design time tools like JDeveloper to retrieve information about objects which are handled by this resolver: getFeatureDescriptors(ELContext eLContext, Object object) and getCommonPropertyType(ELContext eLContext, Object object). If they are not needed, they can either simply return null or throw an UnsupportedOperationException (which I prefer because it allows me to verify if they are called at all).