How to stop recursive composite component from including itself recursively

三世轮回 提交于 2019-12-01 12:33:11
BalusC

Use a view build time tag to stop the recursion instead of a view render time tag. The component tree is built during view build time. The rendered attribute isn't evaluated during view build time, but instead during view render time. So your construct basically keeps including itself in an infinite loop. You should already know that StackOverflowError is caused by a recursion so deep that the memory stack can't handle it anymore (usually around ~1000 iterations).

Replace <h:panelGroup rendered> by a <c:if test> and it'll work as expected. The renderQuestions can by the way be simplified by omitting the check on children. The <ui:repeat> won't render anything anyway if there are no children.

If you happen to use view scoped beans in this construct and you're using Mojarra implementation, then make sure that you upgrade to at least 2.1.18, because binding a view build time tag attribute to a view scoped bean property would in older versions break the view scope.

See also:

Based on the answer of BalusC I created a solution like this.

<composite:interface>
    [..]
    <composite:attribute name="level" required="true" default="0"/>
</composite:interface>
<composite:implementation>

        <c:if test="#{cc.attrs.level == 0}">
            <a4j:repeat value="#{cc.attrs.list}" var="subList" rendered="#{cc.attrs.list != null}">

                    <xx:recursiveComponent list="#{subList}" id="subComponent" level="1"/>

            </a4j:repeat>   
        </c:if>

</composite:implementation>

The level attribute is used at build time to avoid endless recursion and the renered attribute of the a4j:repeat (or ui:repeat in your case) will be evaluated at render time.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!