Sun Java System Application Server Platform Edition 9 Release Notes

JSF 1.1 - 1.2 Spec Violation: Variable and Property Resolvers (ID 6419278)

JavaServer Faces Technology Applications that use the VariableResolver decoration to extend the functionality of the Expression Language may not work properly.

Section 10.4.5 of the JavaServer Faces Technology Specification states:

“When providing a replacement for the default PropertyResolver, VariableResolver, ActionListener, NavigationHandler, ViewHandler, or StateManager, the decorator design pattern is leveraged, so that if you provide a constructor that takes a single argument of the appropriate type, the custom implementation receives a reference to the implementation that was previously fulfilling the role. In this way, the custom implementation is able to override just a subset of the functionality (or provide only some additional functionality) and delegate the rest to the existing implementation.”

In Application Server 9, a custom VariableResolver implementation will receive a “previous” VariableResolver that does not fully fulfill the role of variable resolution.

Solution

Instead of delegating to the “previous” VariableResolver to resolve an expression, we recommend creating an ValueExpression and evaluating it.


Example 3–1 Evaluating a ValueExpression

public class CustomVR extends VariableResolver {

    private VariableResolver previous = null;

    public CustomVR(VariableResolver previous) {
	this.previous = previous;
    }
  
    public Object resolveVariable(FacesContext context, String name)
	throws EvaluationException {
	Object result = null;
	
	// Do some action that may resolve the variable.  If not, you
	// may be tempted to simply do: 

	// result = previous.resolveVariable(context, name);

	// But this would not work due to bug 6419278.  A fix is
	// available, please see the Release Notes.  However, a
	// workaround is the following.

	ValueExpression ve = context.getApplication().getExpressionFactory(). \
createValueExpression(context.getELContext(), "#{" + name + "}", Object.class);
	try {
	    result = ve.getValue(context.getELContext());
	}
	catch (PropertyNotFoundException pnfe) {
	    throw new EvaluationException(pnfe);
	}
	catch (ELException ele) {
	    throw new EvaluationException(ele);
	}
	return result;

    }
}