嵌套JSF复合材料元件导致堆栈溢出异常嵌套JSF复合材料元件导致堆栈溢出异常(Nested JSF

2019-05-12 08:26发布

问题

当我在其自身内尝试巢复合部件,其中一些逻辑以结束无限递归我接收堆栈溢出异常。 我的理解是, <c:xxx>标记在视图生成时运行 ,所以我没想到因为我相信一直是这样拥有无限的视图版本。

这是复合部件simpleNestable.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:composite="http://java.sun.com/jsf/composite"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:em="http://xmlns.jcp.org/jsf/composite/emcomp"

  xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">

    <h:head>
        <title>This content will not be displayed</title>
    </h:head>
    <h:body>
        <composite:interface>
            <composite:attribute name="depth" required="true" type="java.lang.Integer"/>
        </composite:interface>

        <composite:implementation>
            <c:if test="#{cc.attrs.depth lt 3}">
                 #{cc.attrs.depth}
                 #{cc.attrs.depth+1}
                 <em:simpleNestable depth="#{cc.attrs.depth+1}" /> 

            </c:if>

        </composite:implementation>
    </h:body>
</html>

这是如何使用它

<h:head>
    <title>Facelet Title</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <h:outputStylesheet name="./css/default.css"/>
    <h:outputStylesheet name="./css/cssLayout.css"/>
</h:head>
<h:body>        
     <emcomp:simpleNestable depth="1"/>

</h:body>

堆栈溢出异常

java.lang.StackOverflowError
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
    at javax.faces.component.UIComponentBase$AttributesMap.get(UIComponentBase.java:2407)
    at com.sun.faces.el.CompositeComponentAttributesELResolver$ExpressionEvalMap.get(CompositeComponentAttributesELResolver.java:393)
    at javax.el.MapELResolver.getValue(MapELResolver.java:199)
    at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
    at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
    at com.sun.el.parser.AstValue.getValue(AstValue.java:140)
    at com.sun.el.parser.AstValue.getValue(AstValue.java:204)
    at com.sun.el.parser.AstPlus.getValue(AstPlus.java:60)
    at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:226)
    at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50)
    at com.sun.faces.facelets.el.ContextualCompositeValueExpression.getValue(ContextualCompositeValueExpression.java:158)
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
    at javax.faces.component.UIComponentBase$AttributesMap.get(UIComponentBase.java:2407)
    at com.sun.faces.el.CompositeComponentAttributesELResolver$ExpressionEvalMap.get(CompositeComponentAttributesELResolver.java:393)
    at javax.el.MapELResolver.getValue(MapELResolver.java:199)
    at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
    at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
    at com.sun.el.parser.AstValue.getValue(AstValue.java:140)
    at com.sun.el.parser.AstValue.getValue(AstValue.java:204)
    at com.sun.el.parser.AstPlus.getValue(AstPlus.java:60)

问题

我怎样才能巢复合部件(或类似的),而不接收堆栈溢出异常自身内(到非预定深度)

为什么我想这个

我有我想从RichFaces的嵌套collapsibleSubTable内代表任意嵌套的数据,替代我的做法是非常欢迎

Answer 1:

问题是在上下文#{cc}和复合属性的有状态。 在#{cc}在嵌套复合引用本身 ,而不是母体的任何属性。 是有状态的属性意味着, #{cc}在每个孩子其进而最终引用本身 ,而不是亲本的重新评估。 因此,堆栈溢出。 它评估在一个无限循环本身的深度。

我使用的背衬部件,如下这立即计算它,并将其指定为一个组件的属性使得它无国籍欺骗属性的有状态:

@FacesComponent("treeComposite")
public class TreeComposite extends UINamingContainer {

    private Integer depth;

    @Override
    public void setValueExpression(String name, ValueExpression binding) {
        if ("depth".equals(name)) {
            setDepth((Integer) binding.getValue(getFacesContext().getELContext()));
        }
        else {
            super.setValueExpression(name, binding);
        }
    }

    public Integer getDepth() {
        return depth;
    }

    public void setDepth(Integer depth) {
        this.depth = depth;
    }

}

这是在界面的中声明componentType如下:

<cc:interface componentType="treeComposite">
    <cc:attribute name="depth" type="java.lang.Integer" />
</cc:interface>

而且,在实施应该在测试参考无状态特性,并在嵌套复合参考母公司的一个(因为#{cc}在嵌套复合材料的属性引用嵌套组合本身):

<cc:implementation>
    <br />We're at depth #{cc.depth}.
    <c:if test="#{cc.depth gt 0}">
        <my:tree depth="#{cc.parent.depth - 1}" />
    </c:if>
</cc:implementation>

我只是改变了这里的“深度”的含义是倒过来,这样它只是声明从客户端上,而无需在实施中进行编辑。 因此,在客户端,你不得不说depth="#{3}" ,如果你想3个嵌套子:

<my:tree depth="#{3}" />

请注意这是一个EL表达式,而不是字面的重要性。 否则setValueExpression()在所述背衬组件将不被调用。



文章来源: Nested JSF Composite Components leading to a Stack Overflow exception