Jsf 以编程方式实例化ValueExpressions

Jsf 以编程方式实例化ValueExpressions,jsf,dynamic,components,el,Jsf,Dynamic,Components,El,我使用以下方法在PreRenderViewEvent上动态添加组件 对于添加组件的部件来说,它工作得很好,但是当我尝试动态实例化ValueExpression-s时,我遇到了一个问题 更具体地说,当我尝试使用动态传递的参数伪造动态ValueExpression时,我遇到了一个问题 让我们试着解释一个例子 在顶层,我使用标记组件(标记文件中描述的组件,而不是复合组件和自定义组件) <my:topComponent param=#{toto}"/> <my:nestedCompo

我使用以下方法在PreRenderViewEvent上动态添加组件

对于添加组件的部件来说,它工作得很好,但是当我尝试动态实例化ValueExpression-s时,我遇到了一个问题

更具体地说,当我尝试使用动态传递的参数伪造动态ValueExpression时,我遇到了一个问题

让我们试着解释一个例子

在顶层,我使用标记组件(标记文件中描述的组件,而不是复合组件和自定义组件)

<my:topComponent param=#{toto}"/>
<my:nestedComponent param2=#{param}/>
然后,我使用以下helper函数实例化我的动态值表达式:

public static ValueExpression createValueExpression(String expression, Class clazz) {
        FacesContext fc = FacesContext.getCurrentInstance();
        ELContext elContext = fc.getELContext();
        ExpressionFactory expFactory = fc.getApplication().getExpressionFactory();
        ValueExpression ret = expFactory.createValueExpression(elContext, expression, clazz);
        return ret;
    }
例如:

ValueExpression dynExpression = JSFUtils.createValueExpression("#{" + varName + ".code" + "}"), Object.class);
在本例中,值表达式为“#{param2.code}”

然后,我可以将此valueExpression设置为我的组件:

this.setValueExpression("rowKey", dynExpression);
所有这些代码都在自定义组件类中。我使用基类的渲染器

但是,在呈现期间,以编程方式实例化的ValueExpression没有正确计算。例如,当primefaces datatable呈现程序尝试计算rowKey时,#{param2.code}被计算为“null”,因为param2似乎是未知的

在调试时,我注意到getValueExpression(“finalParam”)有一个VariableMapper集,而dynExpression没有(空值)

如果我没有弄错,这个VariableMapper用于将param2转换为param

如何实例化动态表达式以保留VariableMapper链?FunctionMapper的问题也是如此

提前谢谢

更新 我同意理查德·肯纳德(Richard Kennard)的回答:这似乎是同一个bug

由于我无法等待数年的修复,所以我使用下面的kludge递归地解析变量。它适用于MyFaces 2.1.9/CODI 1.0.5/OWB 1.1.6/Tomcat 7堆栈的简单情况

    public static String getValueExpressionExpression(ValueExpression valueExpression) {
        return valueExpression.getExpressionString().replace("#{", "").replace("}", "");
    }

    public static String getMappedValueExpression(ValueExpression valueExpression) {
        ContextAwareTagValueExpression ctxAware = (ContextAwareTagValueExpression)valueExpression;
        if(ctxAware != null) {
            return getMappedValueExpression((WrappedValueExpression)ctxAware.getWrapped());
        }
        return getValueExpressionExpression(valueExpression);
    }

    public static String getMappedValueExpression(WrappedValueExpression wrappedExpression) {
        String exprString = wrappedExpression.getExpressionString().replace("#{", "").replace("}", "");
        String ret = exprString;
        try {

            Field valueExpression = WrappedValueExpression.class.getDeclaredField("valueExpression");
            valueExpression.setAccessible(true);
            ValueExpressionImpl vei = (ValueExpressionImpl) valueExpression.get(wrappedExpression);
            Field varMapper = ValueExpressionImpl.class.getDeclaredField("varMapper");
            varMapper.setAccessible(true);
            VariableMapperImpl vmi = (VariableMapperImpl) varMapper.get(vei);
            if(vmi != null) {
                String[] components = exprString.split("\\.");
                components[0] = getMappedValueExpression(vmi.resolveVariable(components[0])); 
                ret = "";
                for(int i = 0 ; i < components.length ; i++) {
                    if(i != 0) {
                        ret += ".";
                    }
                    ret += components[i];
                }
            }
        } catch (Exception ex) {
            logger.error("Exception lors du mapping de l'expression EL " + exprString, ex);
        } finally {
            return ret;
        }
    }
公共静态字符串getValueExpressionExpression(ValueExpression){
返回值expression.getExpressionString().replace(“#{”,”).replace(“}”,”);
}
公共静态字符串getMappedValueExpression(ValueExpression-ValueExpression){
ContextAwareTagValueExpression ctxAware=(ContextAwareTagValueExpression)valueExpression;
if(ctxAware!=null){
返回getMappedValueExpression((WrappedValueExpression)ctxAware.getWrapped());
}
返回getValueExpressionExpression(valueExpression);
}
公共静态字符串getMappedValueExpression(WrappedValueExpression wrappedExpression){
String exprString=wrappedExpression.getExpressionString().replace(“#{”,”).replace(“}”,”);
字符串ret=exprString;
试一试{
Field valueExpression=WrappedValueExpression.class.getDeclaredField(“valueExpression”);
valueExpression.setAccessible(true);
ValueExpressionImpl-vei=(ValueExpressionImpl)valueExpression.get(wrappedExpression);
字段varMapper=ValueExpressionImpl.class.getDeclaredField(“varMapper”);
varMapper.setAccessible(true);
variableMapprimpl vmi=(variableMapprimpl)varMapper.get(vei);
如果(vmi!=null){
String[]components=exprString.split(“\\”);
components[0]=getMappedValueExpression(vmi.resolveVariable(components[0]);
ret=“”;
对于(int i=0;i

在MyFaces或Mojarra中有更干净的解决方案将是一件好事。

这是JSF中的一个已知错误

这里是Mojarra团队的文件,这里是MyFaces团队的文件:。我意识到这些错误报告的措辞并不完全符合您的预期,但它是同一个错误。如果您查看评论:

Hi guys,

I just hit this bug again while working on a client's code, and
noticed Manfred had closed it as 'resolved'?

Why was this considered 'resolved'? It's a real problem for me,
stopping me doing things like...

<h:dataTable value="#{companyImport.importFiles}" var="_importFile">
    <h:column>
        <h:outputText value="#{_importFile.name}:"/>
    </h:column>
    <h:column>
        <m:metawidget value="#{_importFile.import}"/>
    </h:column>
</h:dataTable>

...because the m:metawidget cannot 'see' the #{_importFile} var.

Can we please reopen, or at least explain why it is resolved?
大家好,
我只是在处理客户端代码时再次遇到了这个错误
注意到Manfred已将其关闭为“已解决”?
为什么这被认为是“解决的”?这对我来说是一个真正的问题,
阻止我做像。。。
…因为m:metawidget无法“看到”#{u importFile}var。
我们能不能重新打开,或者至少解释一下为什么它被解决了?

这两个bug报告都没有取得多大进展。您可能希望对它们进行评论,对它们进行投票,并对该问题给予重视。

是的,它似乎是同一个bug。我也将对MyFaces问题添加评论,可能建议在几分钟内“干净”地实施我将提供的作为解决方案的kludge。
    public static String getValueExpressionExpression(ValueExpression valueExpression) {
        return valueExpression.getExpressionString().replace("#{", "").replace("}", "");
    }

    public static String getMappedValueExpression(ValueExpression valueExpression) {
        ContextAwareTagValueExpression ctxAware = (ContextAwareTagValueExpression)valueExpression;
        if(ctxAware != null) {
            return getMappedValueExpression((WrappedValueExpression)ctxAware.getWrapped());
        }
        return getValueExpressionExpression(valueExpression);
    }

    public static String getMappedValueExpression(WrappedValueExpression wrappedExpression) {
        String exprString = wrappedExpression.getExpressionString().replace("#{", "").replace("}", "");
        String ret = exprString;
        try {

            Field valueExpression = WrappedValueExpression.class.getDeclaredField("valueExpression");
            valueExpression.setAccessible(true);
            ValueExpressionImpl vei = (ValueExpressionImpl) valueExpression.get(wrappedExpression);
            Field varMapper = ValueExpressionImpl.class.getDeclaredField("varMapper");
            varMapper.setAccessible(true);
            VariableMapperImpl vmi = (VariableMapperImpl) varMapper.get(vei);
            if(vmi != null) {
                String[] components = exprString.split("\\.");
                components[0] = getMappedValueExpression(vmi.resolveVariable(components[0])); 
                ret = "";
                for(int i = 0 ; i < components.length ; i++) {
                    if(i != 0) {
                        ret += ".";
                    }
                    ret += components[i];
                }
            }
        } catch (Exception ex) {
            logger.error("Exception lors du mapping de l'expression EL " + exprString, ex);
        } finally {
            return ret;
        }
    }
Hi guys,

I just hit this bug again while working on a client's code, and
noticed Manfred had closed it as 'resolved'?

Why was this considered 'resolved'? It's a real problem for me,
stopping me doing things like...

<h:dataTable value="#{companyImport.importFiles}" var="_importFile">
    <h:column>
        <h:outputText value="#{_importFile.name}:"/>
    </h:column>
    <h:column>
        <m:metawidget value="#{_importFile.import}"/>
    </h:column>
</h:dataTable>

...because the m:metawidget cannot 'see' the #{_importFile} var.

Can we please reopen, or at least explain why it is resolved?