VariableResolver 装飾を使用して Expression Language の機能を拡張する JavaServer Faces テクノロジアプリケーションが、正しく機能しない場合があります。
JavaServer Faces 技術仕様の第 10.4.5 項には、次のように記述されています。
「デフォルトの PropertyResolver、VariableResolver、ActionListener、NavigationHandler、ViewHandler、または StateManager の置換値を与えると、デコレータデザインパターンが活用されます。この結果、該当するタイプの単一の引数をとるコンストラクタを与えた場合に、カスタム実装は、以前にロールを実行していた実装への参照を受け取ります。このようにして、カスタム実装は、機能のサブセットだけを変更し、または一部の追加機能だけを提供して、残りを既存の実装に委任することができます。」
Application Server 9 では、VariableResolver のカスタム実装は、変数解決のロールを十分には実行していない「以前」の VariableResolver を受け取ります。
式の解決を「以前」の VariableResolver に委任するのではなく、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;
}
}