0

According to https://stackoverflow.com/a/8446728/1797006 using the JSF composite component nested:cif recursively and terminating the recursion with c:if should work:

<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://xmlns.jcp.org/jsf/html"
      xmlns:cc="http://xmlns.jcp.org/jsf/composite"
      xmlns:nested="http://xmlns.jcp.org/jsf/composite/nested"
      xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">
    <cc:interface>
        <cc:attribute name="theAttr"
                type="richtercloud.jsf.avoid.nested.rendered.evaluation.Entity0"
                required="true"/>
    </cc:interface>
    <cc:implementation>
        <h:outputLabel value="Hello World!"/>
        <c:if test="#{cc.attrs.theAttr.reference ne null}">
            <nested:cif theAttr="#{cc.attrs.theAttr.reference}"/>
        </c:if>
        <c:if test="#{cc.attrs.theAttr.reference eq null}">
            <h:outputLabel value="recursion terminated"/>
        </c:if>
    </cc:implementation>
</html>

when called as follows:

<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://xmlns.jcp.org/jsf/html"
      xmlns:nested="http://xmlns.jcp.org/jsf/composite/nested">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <nested:cif theAttr="#{backingBean0.reference}"/>
    </h:body>
</html>

Backing bean:

@Named
@ViewScoped
public class BackingBean0 implements Serializable {
    private Entity0 reference = new Entity0(new Entity0(null));

    public Entity0 getReference() {
        return reference;
    }

    public void setReference(Entity0 reference) {
        this.reference = reference;
    }
}

However, I'm getting a

java.lang.StackOverflowError
    at java.util.HashMap.hash(HashMap.java:339)
    at java.util.HashMap.get(HashMap.java:557)
    at javax.faces.component.ComponentStateHelper.get(ComponentStateHelper.java:174)
    at javax.faces.component.UIComponentBase$AttributesMap.get(UIComponentBase.java:2386)
    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.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:2427)
    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.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:2427)
    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.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:2427)
    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)
[a few more hundred lines]

When I place a debugger breakpoint in Entity0.getReference I see that it's invoked once before the StackOverflowError.

Afaik the only other issue covered in other SO question is using rendered to break the recursion which doesn't work because of view build time vs. view render time.

I expect the recursion to cause the "Hello world!" label to be displayed twice because of the depth of 2 which is defined by private Entity0 reference = new Entity0(new Entity0(null)); (Entity0 is a class without only one property which is a reference to itself) and then the "recursion terminated label".

An SSCCE can be found at https://gitlab.com/krichter/jsf-avoid-nested-rendered-evaluation.

I'm using Primefaces 6.2 on Payara 4.1.2.181.

Kalle Richter
  • 8,008
  • 26
  • 77
  • 177
  • Check http://balusc.omnifaces.org/2016/02/recursive-tree-of-composite-components.html. Need to find the stackoverflow counterpart of it – Kukeltje May 04 '18 at 13:54
  • @Kukeltje Thanks a lot. I proposed to link the blog post in the answer to the question of which this one is a duplicate. – Kalle Richter May 04 '18 at 14:11

0 Answers0