The transition from the XHTML source code to the generated HTML output is a two-step process.
First, during view build time, the XHTML source code is parsed and turned in a tree of Java
UIComponent
instances representing the JSF UI component tree, as available byFacesContext#getViewRoot()
.Then, during view render time, the JSF UI component tree produces HTML output and writes it to the HTTP resopnse, starting with
UIViewRoot#encodeAll()
method.
Taghandlers like all JSTL <c:xxx>
tags, several JSF <f:xxx>
tags and only a few Facelets <ui:xxx>
tags run during view build time. UI components like all JSF <h:xxx>
tags, several Facelets <ui:xxx>
tags and only a few JSF <f:xxx>
tags run during view render time.
The <c:forEach>
is a taghandler and the <ui:repeat>
is an UI component.
In other words, the UI components which are declared inside <c:forEach>
are recreated multiple times in the JSF component tree based on <c:forEach items>
during view build time which in turn individually produce each their own HTML output during view render time. The UI components which are declared inside <ui:repeat>
are created only once in the JSF component tree during view build time which in turn are reused multiple times based on <ui:repeat value>
to produce HTML output during view render time.
Your concrete problem is caused by the fact that <ui:repeat var="table">
is only available during view render time, not during view build time. The <c:forEach>
is basically retrieving a #{null}
as value when it’s about to run during view build time.
You can solve this by replacing the outer <ui:repeat>
by <c:forEach>
. Although I wonder if you couldn’t better use <ui:repeat><p:dataTable><p:columns>
instead.
See also:
- JSTL in JSF2 Facelets… makes sense?