I have a Home
. Each Home
has a list of Room
s. Each Room
has zero or more Person
s.
I would like to count total persons of each home. But I can't add a new variable to record person count in any backing beans or entity. So I'd like to count it in the view only via <c:set>
.
My first attempt look like:
<c:set var="personCount" value="${0}" />
<ui:repeat var="home" value="#{mybackingBean.homes}">
<ui:repeat var="room" value="#{home.rooms}">
${personCount += room.persons.size()}
</ui:repeat>
<h:panelGrid columns="2">
<h:outputLabel value="#{home.id}" />
<h:outputLabel value="#{personCount}" />
</h:panelGrid>
</ui:repeat>
How can I achieve it?
There are several mistakes.
First,
In EL, the
+=
is the string concatenation operator. So, this will give you basically the result ofString.valueOf(personCount) + String.valueOf(size)
. If the count is initialized to0
and there are3
persons, then this will print03
.You basically want to re-assign the result of
personCount + size
back to variablepersonCount
. You need to re-set the variable using<c:set>
as below.Second,
The
personCount
is initialized with0
outside both iterations. So, for each home you'll this way count the persons of all previous homes as well. You want to declare it inside the first iteration.This is not EL related. This is just a logic error which would cause the same problem in "plain vanilla" Java as well.
Third,
JSTL tags like
<c:set>
run during view build time (during conversion from XHTML template to JSF component tree). JSF components like<ui:repeat>
run during view render time (during conversion from JSF component tree to HTML output). So, the<c:set>
doesn't run during<ui:repeat>
iteration. Thus, it cannot see the iteration variablevar
. You basically need to iterate during view build time as well. You can use JSTL<c:forEach>
for this.So, all in all, your intented solution look like this:
For an in depth explanation, see also JSTL in JSF2 Facelets... makes sense?
However, as the
+=
operator apparently doesn't cause an EL exception in your case, this means that you're already using EL 3.0. This in turn means that you can use the new EL 3.0 lambda and stream features.No need for a counting loop anymore. No, this does not require Java 8, it works on Java 7 as good.