I have a simple JSF application that iterates over a list.
I know I can use ui:repeat, but just for learning and comparison purposes,
since c:forEach from JSTL is also part of JSF, I'd like to see how it works.
What I do not understand, why does c:forEach evaluate the items for every
iteration. I have a CDI bean that produces the list, and its getter is called
when rendering every row of the c:forEach iteration. And even worse, it calls
the getter even when c:forEach uses a variable that is set before that as
shown below.
This code (part of my index.xhtml JSF file):
Primes (over c:forEach):<br/><br/>
<c:set var="order" value="${0}" />
<c:set var="ps" value="${primeCalculator.primes}" />
<c:forEach items="${ps}" var="p">
<c:set var="order" value="${order + 1}" />
<h:panelGrid columns="2">
<h:outputLabel value="${order}." />
<h:outputLabel value="${p}" />
</h:panelGrid>
</c:forEach>
renders the list of primes properly (n=10):
Primes (over c:forEach):
1. 2
2. 3
3. 5
4. 7
but when I do some logging from the CDI bean (@Named, @RequestScoped):
public List<Integer> getPrimes()
{
System.out.println("getPrimes() n=" + n + ", cnt=" + (cnt++));
ArrayList<Integer> result = new ArrayList<>();
boolean compound[] = new boolean[n + 1];
for (int i = 2; i <= n; i++)
if (!compound[i])
{
result.add(i);
for (int j = 2 * i; j <= n; j += i) compound[j] = true;
}
return result;
}
I see the following in the log:
[2022-03-28T23:06:20.066+0200] (skip...) [[getPrimes() n=0, cnt=0]]
[2022-03-28T23:06:20.067+0200] (skip...) [[getPrimes() n=10, cnt=1]]
[2022-03-28T23:06:20.069+0200] (skip...) [[getPrimes() n=10, cnt=2]]
[2022-03-28T23:06:20.069+0200] (skip...) [[getPrimes() n=10, cnt=3]]
[2022-03-28T23:06:20.069+0200] (skip...) [[getPrimes() n=10, cnt=4]]
[2022-03-28T23:06:20.069+0200] (skip...) [[getPrimes() n=10, cnt=5]]
[2022-03-28T23:06:20.069+0200] (skip...) [[getPrimes() n=10, cnt=6]]
Why is the getter called for every prime that is printed out?
And how could that be avoided? Yes, I have noticed when using
ui:repeat, that it gets called only twice, which is still more
than would make me happy, but it is better than once for each
output item. I am using: Jakarta EE 9, GlassFish 6.2.3, and IntelliJ IDEA 2021.3.2 (that is JSF 3.0.1, inject api 2.0.0, cdi api 3.0, e-api 4.0, implementations weld se 4.0.2) Thanks.