title: StackOverflowError in JSF composite component recursion
body: <p>According to <a href="https://stackoverflow.com/a/8446728/1797006">https://stackoverflow.com/a/8446728/1797006</a> using the JSF composite component <code>nested:cif</code> recursively and terminating the recursion with <code>c:if</code> should work:</p>
  
  <pre><code>&lt;?xml version='1.0' encoding='UTF-8' ?&gt;
  &lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
  &lt;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"&gt;
      &lt;cc:interface&gt;
          &lt;cc:attribute name="theAttr"
                  type="richtercloud.jsf.avoid.nested.rendered.evaluation.Entity0"
                  required="true"/&gt;
      &lt;/cc:interface&gt;
      &lt;cc:implementation&gt;
          &lt;h:outputLabel value="Hello World!"/&gt;
          &lt;c:if test="#{cc.attrs.theAttr.reference ne null}"&gt;
              &lt;nested:cif theAttr="#{cc.attrs.theAttr.reference}"/&gt;
          &lt;/c:if&gt;
          &lt;c:if test="#{cc.attrs.theAttr.reference eq null}"&gt;
              &lt;h:outputLabel value="recursion terminated"/&gt;
          &lt;/c:if&gt;
      &lt;/cc:implementation&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>when called as follows:</p>
  
  <pre><code>&lt;?xml version='1.0' encoding='UTF-8' ?&gt;
  &lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
  &lt;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"&gt;
      &lt;h:head&gt;
          &lt;title&gt;Facelet Title&lt;/title&gt;
      &lt;/h:head&gt;
      &lt;h:body&gt;
          &lt;nested:cif theAttr="#{backingBean0.reference}"/&gt;
      &lt;/h:body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>Backing bean:</p>
  
  <pre><code>@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;
      }
  }
  </code></pre>
  
  <p>However, I'm getting a</p>
  
  <pre><code>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]
  </code></pre>
  
  <p>When I place a debugger breakpoint in <code>Entity0.getReference</code> I see that it's invoked once before the <code>StackOverflowError</code>.</p>
  
  <p>Afaik the only other issue covered in other SO question is <a href="https://stackoverflow.com/questions/17923220/how-to-stop-recursive-composite-component-from-including-itself-recursively">using <code>rendered</code> to break the recursion</a> which doesn't work because of view build time vs. view render time.</p>
  
  <p>I expect the recursion to cause the "Hello world!" label to be displayed twice because of the depth of 2 which is defined by <code>private Entity0 reference = new Entity0(new Entity0(null));</code> (<code>Entity0</code> is a class without only one property which is a reference to itself) and then the "recursion terminated label".</p>
  
  <p>An SSCCE can be found at <a href="https://gitlab.com/krichter/jsf-avoid-nested-rendered-evaluation" rel="nofollow noreferrer">https://gitlab.com/krichter/jsf-avoid-nested-rendered-evaluation</a>.</p>
  
  <p>I'm using Primefaces 6.2 on Payara 4.1.2.181.</p>