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

发布于 2024-12-21 06:10:05 字数 1217 浏览 2 评论 0原文

以下 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 页面上定义的“快捷方式”参数值?

Following java code allows to access any object or variable from faces context:

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

I use the code from within my custom converter to read additional converting parameters from context.

The code works correctly if #{somebean} is defined as normal backing bean within JSF context.

Facelets allow to create 'shortcut' to JSF expressions. Example:

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

In this case both #{somebean.someattr.someproperty} and #{shortcut} have the same value.

However these 'shortcut' names are not accessible using java code above. For example:

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

Is there a way to access a facelets context and to read 'shortcut' parameter values, defined on the current JSF page?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

神爱温柔 2024-12-28 06:10:05

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

/**
     * 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。
这两种技术在存储变量时都使用自己的上下文
除了Faces El Context之外,还有一个Facelet El Context(FaceletContext)。

所述方法对两种上下文中的表达式求值。请注意,如果两个值在每个上下文中存储在相同的名称下,这将不起作用。

I had the same problem and have chosen the following approach:

/**
     * 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" is part of the Facelet view handling technology. Facelets extends JSF.
Both technologies use their own Context when storing variables.
Beside the Faces El Context there is a Facelet El Context (FaceletContext).

The stated method evaluates expressions in both contexts. Be aware that this will not work if two values are stored under the same name in each context.

末蓝 2024-12-28 06:10:05

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

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

<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);
    }
//...
}

It seems that facelet shortcuts do not exist in the context, where I try to access them.

I have made following workaround: On JSF page where my input element is placed, I have added a <f:param> element as child of the input with my converter.

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

Then in converter I'm able to find UIParam element as one of the input children and read my shortcuts from it.

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);
    }
//...
}
慢慢从新开始 2024-12-28 06:10:05

ui:param 的映射不存储在上下文中,而是存储在每个单独 ValueExpressionVariableMapper 中。
因此,如果您需要以编程方式创建 ValueExpression,并依赖另一个 ValueExpression 的 varMapper,您可以执行以下操作:

VariableMapper varMapper = new DefaultVariableMapper();
varMapper.setVariable(mappingName, component.getValueExpression(mappedAttributeName));
return new ValueExpressionImpl(expression, null, null, varMapper, expectedType);

The mapping of ui:param is not stored in context, it's in the VariableMapper of each individual ValueExpression.
So if you need to create ValueExpression programmatically, relying on another ValueExpression's varMapper, you can do something like this:

VariableMapper varMapper = new DefaultVariableMapper();
varMapper.setVariable(mappingName, component.getValueExpression(mappedAttributeName));
return new ValueExpressionImpl(expression, null, null, varMapper, expectedType);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文