以编程方式获取facelets参数(变量)的表达式值

时间:2011-12-15 09:46:52

标签: jsf facelets el converter

以下java代码允许从faces上下文访问任何对象或变量:

ELContext elCtx = facesContext.getELContext();
ExpressionFactory exprFac = facesContext.getApplication().getExpressionFactory();
MyProperty myProperty = (MyProperty) exprFac.createValueExpression(elCtx, "#{somebean.someattr.someproperty}", MyProperty.class).getValue(elCtx);

我使用自定义转换器中的代码从上下文中读取其他转换参数。

如果#{somebean}被定义为JSF上下文中的普通支持bean,则代码可以正常工作。

Facelets允许创建JSF表达式的“快捷方式”。例如:

<ui:param name="shortcut" value="#{somebean.someattr.someproperty}" />
<div>#{somebean.someattr.someproperty} equals #{shortcut}</div>

在这种情况下,#{somebean.someattr.someproperty}#{shortcut}都具有相同的值。

但是,使用上面的java代码无法访问这些“快捷方式”名称。例如:

MyProperty myProperty1 = (MyProperty) exprFac.createValueExpression(elCtx, "#{somebean.someattr.someproperty}", MyProperty.class).getValue(elCtx);
// myProperty1 has expected value

MyProperty myProperty2 = (MyProperty) exprFac.createValueExpression(elCtx, "#{shortcut}", MyProperty.class).getValue(elCtx);
// myProperty2 is null

有没有办法访问facelets上下文并读取当前JSF页面上定义的'shortcut'参数值?

3 个答案:

答案 0 :(得分:3)

我遇到了同样的问题并选择了以下方法:

/**
     * Führt eine Expression im aktuellen Faces EL Context 
     * UND im Facelets El Context aus.
     * 
     * @param facesContext
     * @param expression
     * @return object
     */
    private static Object executeExpressionInUIContext (final FacesContext facesContext, final String expression) {
        final ELContext elContext = facesContext.getELContext();
        final Application application = facesContext.getApplication();

        Object result = executeExpressionInElContext(application, elContext, expression);
        if (null == result) {
            FaceletContext faceletElContext = (FaceletContext) FacesContext.getCurrentInstance().getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
            result = executeExpressionInElContext(application, faceletElContext, expression);
        }
        return result;
    }

    private static Object executeExpressionInElContext (Application application, ELContext elContext, String expression) {
        ExpressionFactory expressionFactory = application.getExpressionFactory();
        ValueExpression exp = expressionFactory.createValueExpression(elContext, expression, Object.class);
        return exp.getValue(elContext);
    }

“ui:param”是Facelet视图处理技术的一部分。 Facelets扩展了JSF。 这两种技术在存储变量时都使用自己的 Context 。 除了Faces El Context之外,还有一个Facelet El Context(FaceletContext)。

陈述的方法在两种情境中评估表达式。请注意,如果在每个上下文中以相同的名称存储两个值,则无法使用此功能。

答案 1 :(得分:1)

在我尝试访问它们的上下文中似乎不存在facelet快捷方式。

我做了以下解决方法:在放置了我的输入元素的JSF页面上,我添加了一个<f:param>元素作为我的转换器输入的子元素。

<h:inputText id="myid" value="#{action.myinput}">
     <f:converter converterId="myConverter" />
     <f:param name="converterParameters" shortcut="#{somebean.someattr.someproperty}"/>
</h:inputText>

然后在转换器中,我能够找到UIParam元素作为输入子节点之一并从中读取我的快捷方式。

public Object getAsObject(FacesContext context, UIComponent component, String value) {

    MyProperty myProperty = null;
    try {
        for (final UIComponent child : component.getChildren()) {
            if ("converterParameters".equals(child.getAttributes().get("name"))) {
                final ELContext elCtx = context.getELContext();
                myProperty = (MyProperty) child.getValueExpression("shortcut").getValue(elCtx);
                break;
            }
        }
        if (myProperty == null) {
            throw new NullPointerException("My property is undefined.");
        }
    } catch (Exception e) {
        LOG.error("Cannot convert " + value + ".  Use <f:param name=\"converterParameters\" "
                + "shortcut=\"#{here.comes.shortcut}\"/> for your input element. ", e);
        throw new ConverterException("Cannot initialize converter.", e);
    }
//...
}

答案 2 :(得分:0)

ui:param的映射不存储在上下文中,它位于每个VariableMapper的{​​{1}}中。 因此,如果您需要以编程方式创建ValueExpression,依赖另一个ValueExpression的varMapper,您可以执行以下操作:

ValueExpression