In trying to solve a larger problem using JSF, I noticed that I can't seem use c:forEach to iterate over lists. Research has taught me that there are several different versions now, and I believe I'm using JSF 2.2.
I've tried some different settings on the web.xml and in the xmlns:c tag with no result.
The following is a test file to demonstrate what is not working: index.html includes Content/Content_index.xhtml which includes Content/Recursive_Box.xhtml:
index.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<c:choose>
<c:when test="#{LoginBean.currentUser.loggedOn}">
<ui:include src="#{MainBean.setLayout(0,0,0)}"></ui:include>
</c:when>
<c:otherwise>
<ui:include src="#{MainBean.setLayout(0,6,0)}"></ui:include>
</c:otherwise>
</c:choose>
</html>
Content_index.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<c:choose>
<c:when test="#{LoginBean.currentUser.loggedOn}">
<title>
Bubble Up!
</title>
<!--<c:set value="#{TargetBean.PullStructure(LoginBean.currentUser.userIndex)}" var="tickle"></c:set>-->
<ui:include src="Recursive_Box.xhtml">
<ui:param name="box" value="#{TargetBean.structure}" />
</ui:include>
</c:when>
</c:choose>
</html>
Recursive_Box.xhtml (Only the first 2 tests work: Static and Test1)
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
#{box}<br/>
#{box.boxList}<br/>
#{box.getBoxList()}<br/>
#{box.boxList.get(0)}<br/>
#{box.boxList.size()}<br/>
<c:forEach var = "i" begin = "1" end = "5">
Static<br/>
</c:forEach>
<c:forEach var = "i" begin = "0" end = "#{box.boxList.size()}">
Test1<br/>
</c:forEach>
<c:forEach var = "i" begin = "1" end = "#{box.boxList.size()}">
Test2<br/>
</c:forEach>
<c:forEach var = "i" items = "#{box.getBoxList()}">
Test2<br/>
</c:forEach>
<c:forEach var = "i" begin = "1" end = "#{box.getBoxList().size()}">
Test3<br/>
</c:forEach>
<c:forEach var = "i" begin = "1" end = "${box.boxList.size()}">
Test4<br/>
</c:forEach>
<c:forEach var = "i" items = "${box.getBoxList()}">
Test5<br/>
</c:forEach>
<c:forEach var = "i" begin = "1" end = "${box.getBoxList().size()}">
Test6<br/>
</c:forEach>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
I should be able to iterate over a given list, but the for my tests, I'm getting the following output:
Main.Box@50eb0e0
[Main.Box@2452c4d, Main.Box@5fd03294, Main.Box@4c97b69b, Main.Box@3c6e8659, Main.Box@17e2e2dd]
[Main.Box@2452c4d, Main.Box@5fd03294, Main.Box@4c97b69b, Main.Box@3c6e8659, Main.Box@17e2e2dd]
Main.Box@2452c4d
5
Static
Static
Static
Static
Static
Test1
I eventually figured out that it doesn't actually have to do with the configuration, but it has to do with build vs render time (which is what led me to doing c:forEach as opposed to ui:repeat, needing an ui:include as I did).
Because the TargetBean (where the collection is) is dependent on the LoginBean, the TargetBean must be constructed by using the LoginBean's user id to get the collection from the database. This must also be the first thing that happens so that the c:forEach loops have information to iterate over, and thus must also occur during build time (like c:forEach), so I had to put the call in the first c:forEach as I don't have other build time tags to use for my example.
Here's my test file where I was able get results displayed:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
Test 1:<br/>
<c:forEach var = "i" begin = "0" end = "#{TargetBean.PullStructure(0).boxList.size()-1}">
Result 1!<br/>
</c:forEach>
#{TargetBean}<br/>
#{TargetBean.structure.boxList}<br/>
#{TargetBean.structure.getBoxList()}<br/>
#{TargetBean.structure.boxList.get(0)}<br/>
#{TargetBean.structure.boxList.size()}<br/>
<br/><br/>
Static:<br/>
<c:forEach var = "i" begin = "0" end = "4">
#{i}: #{TargetBean.structure.boxList.get(i)}<br/>
</c:forEach>
Test 2:<br/>
<c:forEach var = "i" begin = "1" end = "#{TargetBean.structure.boxList.size()-1}">
Result 2!<br/>
</c:forEach>
Test 3:<br/>
<c:forEach var = "i" items = "#{TargetBean.structure.getBoxList()}">
Result 3!<br/>
</c:forEach>
Test 4:<br/>
<c:forEach var = "i" begin = "1" end = "#{TargetBean.structure.getBoxList().size()-1}">
Result 4!<br/>
</c:forEach>
Test 5:<br/>
<c:forEach var = "i" begin = "1" end = "${TargetBean.structure.boxList.size()-1}">
Result 5!<br/>
</c:forEach>
Test 6:<br/>
<c:forEach var = "i" items = "${TargetBean.structure.getBoxList()}">
Result 6!<br/>
</c:forEach>
<c:forEach var = "i" begin = "1" end = "${TargetBean.structure.getBoxList().size()-1}">
Test6<br/>
</c:forEach>
Test 7:<br/>
<c:forEach var = "i" begin = "0" end = "${TargetBean.structure.boxList.size()-1}">
#{TargetBean.structure.boxList.get(i)}<br/>
</c:forEach>
</html>