javax.servlet.jsp.JspTagException: Don't know how to iterate over supplied "items" in <forEach>
<p>I am trying to do a nested loop. I keep getting a generic error.</p>

<blockquote>
  <p>javax.servlet.jsp.JspTagException: Don't know how to iterate over supplied "items" in &lt;forEach></p>
</blockquote>

<p>No real detail.  Any clue what I am doing wrong here?</p>

<p>Here is the organization model: </p>

<pre><code>import java.util.ArrayList;
import java.util.List;

public class TestOrganization {

private int organizationID, orgStatusID; 
private String organizationName;
private List&lt;TestLocation&gt; locations = new ArrayList&lt;&gt;(); 

public TestOrganization(int organizationID, String organizationName,    List&lt;TestLocation&gt; locations) {
    this.organizationID = organizationID;
    this.organizationName = organizationName;
    this.locations = locations;
}

public int getOrganizationID() {
    return organizationID;
}
public void setOrganizationID(int organizationID) {
    this.organizationID = organizationID;
}
public int getOrgStatusID() {
    return orgStatusID;
}
public void setOrgStatusID(int orgStatusID) {
    this.orgStatusID = orgStatusID;
}
public String getOrganizationName() {
    return organizationName;
}
public void setOrganizationName(String organizationName) {
    this.organizationName = organizationName;
}

public List&lt;TestLocation&gt; getLocations() {
    return locations;
}

public void setLocations(List&lt;TestLocation&gt; locations) {
    this.locations = locations;
}
</code></pre>

<p>}</p>

<p>Here is the location model: </p>

<pre><code>package com.maple.model;

public class TestLocation {

private int locationID, locationNameID, organizationID, activeStatusID;
private String locationName;



/**
 * Constructor used for listing locations
 * @param locationID
 * @param locationNameID
 * @param organizationID
 * @param locationName
 */
public TestLocation(int locationID, int locationNameID, int organizationID, String locationName) {
    super();
    this.locationID = locationID;
    this.locationNameID = locationNameID;
    this.organizationID = organizationID;
    this.locationName = locationName;
}



public int getLocationID() {
    return locationID;
}

public void setLocationID(int locationID) {
    this.locationID = locationID;
}

public int getLocationNameID() {
    return locationNameID;
}

public void setLocationNameID(int locationNameID) {
    this.locationNameID = locationNameID;
}

public int getOrganizationID() {
    return organizationID;
}

public void setOrganizationID(int organizationID) {
    this.organizationID = organizationID;
}

public int getActiveStatusID() {
    return activeStatusID;
}

public void setActiveStatusID(int activeStatusID) {
    this.activeStatusID = activeStatusID;
}

public String getLocationName() {
    return locationName;
}

public void setLocationName(String locationName) {
    this.locationName = locationName;
} 



}
</code></pre>

<p>Here is the organizationDBUtil </p>

<pre><code>package com.maple.DBUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import com.maple.model.TestLocation;
import com.maple.model.TestOrganization;

public class TestOrganizationDBUtil {

private DataSource dataSource;

public TestOrganizationDBUtil(DataSource theDataSource){
    dataSource = theDataSource; 
}

public List&lt;TestOrganization&gt; getOrgDetails() throws Exception {

    List&lt;TestOrganization&gt; organizations = new ArrayList&lt;&gt;(); 

    List&lt;TestLocation&gt; locations = new ArrayList&lt;&gt;(); 

    Connection myConn = null; 
    Statement myStmt = null; 
    ResultSet rSet = null; 

    PreparedStatement myStmt2 = null; 
    ResultSet rSet2 = null; 

    try{
        // get a connection
        myConn = dataSource.getConnection(); 

        // create SQL statement
        String sql = "SELECT * "
                + "FROM maple.organization o "
                + "WHERE o.activeStatusID &lt;&gt; 2 "
                + "Order BY o.organizationName"; 

        myStmt = myConn.createStatement(); 

        // execute query
        rSet = myStmt.executeQuery(sql);

        // process result set
        while(rSet.next()){

            // retrieve data from result set row
            int organizationID = rSet.getInt("organizationID");
            String organizationName = rSet.getString("organizationName");

                String sql2 = "SELECT "
                        + "l.locationID as locationID, "
                        + "l.locationNameID as locationNameID, "
                        + "ln.locationName as locationName "
                    + "FROM maple.location l "
                    + "INNER JOIN maple.locationName ln "
                    + "ON ln.locationNameID = l.locationID "
                    + "WHERE l.activeStatusID &lt;&gt; 2 "
                    + "AND l.organizationID=? "
                    + "Order BY ln.locationName"; 

                // prepare statement
                myStmt2 = myConn.prepareStatement(sql2);

                // set parameters 
                myStmt2.setInt(1, organizationID);

                // execute SQL statement
                rSet2 = myStmt2.executeQuery(); 

                // process result set
                while(rSet2.next()){

                // retrieve data from result set row
                int locationID = rSet2.getInt("locationID");
                int locationNameID = rSet2.getInt("locationNameID");
                String locationName = rSet2.getString("locationName");

                TestLocation tempLocation = new TestLocation(locationID, locationNameID, organizationID, locationName);
                locations.add(tempLocation);    
            }

            // create new member object
            TestOrganization tempOrganization = new TestOrganization(organizationID, organizationName, locations);

            // add it to the list of members
            organizations.add(tempOrganization);    
        }

        return organizations; 
    }
    finally{
        // close JDBC objects
        close(myConn, myStmt, rSet);
    }

}

private void close(Connection myConn, Statement myStmt, ResultSet rSet) {
    try { 
        if(rSet !=null){
            rSet.close(); 
        }
        if(myStmt !=null){
            myStmt.close(); 
        }
        if(myConn !=null){
            myConn.close(); 
        }
    }
    catch(Exception exc){
        exc.printStackTrace();          
    }
}

}
</code></pre>

<h2>Here is the Controller Servlet</h2>

<pre><code>package com.maple.controller;

import java.io.IOException;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import com.maple.DBUtil.TestOrganizationDBUtil;
import com.maple.model.TestOrganization;

/**
* Servlet implementation class OrganizationControllerServlet
*/
@WebServlet("/TestControllerServlet")
public class TestControllerServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

private TestOrganizationDBUtil testOrganizationDBUtil; 

@Resource(name="jdbc/maple")
private DataSource dataSource; 

@Override
public void init() throws ServletException {
    super.init();

    // create our maple db util and pass conn pool
    try{
        testOrganizationDBUtil = new TestOrganizationDBUtil(dataSource);
    }
    catch (Exception exc){
        throw new ServletException(exc); 
    }
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    try {

        // read the "command" parameter
        String theCommand = request.getParameter("command");

        //if the command is missing, then default to login page
        if (theCommand == null) {
            theCommand = "ORG_DETAILS";
        }

        //route to the appropriate method
        switch (theCommand){ 

        case "ORG_DETAILS": 
            listOrgDetails(request, response);
            break;  
        }

    }
    catch (Exception exc) {
        throw new ServletException(exc); 
    }
}


private void listOrgDetails(HttpServletRequest request, HttpServletResponse response) 
        throws Exception {

            // get organizations from db util 
            List&lt;TestOrganization&gt; organizations = testOrganizationDBUtil.getOrgDetails();

            // add organization to request 
            request.setAttribute("ORGANIZATION_DETAILS", organizations);

            // send to JSP page (view)
            RequestDispatcher dispatcher = request.getRequestDispatcher("/test.jsp");
            dispatcher.forward(request, response);
        }

}
</code></pre>

<h2>Here is the JSP page</h2>

<pre><code>&lt;%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %&gt;

&lt;!DOCTYPE html&gt; 
&lt;html lang="en"&gt;
&lt;body&gt;

&lt;c:forEach var="outer" items="${ORGANIZATION_DETAILS}" varStatus="tempOrganization"&gt;

Organization: ${outer.organizationName} &lt;br/&gt; 

&lt;c:forEach var="inner" items="${outer}" varStatus="templocation"&gt;
Location: ${inner.locationName}  
&lt;/c:forEach&gt;

&lt;/c:forEach&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>

<p>The stack trace: </p>

<pre><code>processing JSP page /test.jsp at line 14
type Exception report
message org.apache.jasper.JasperException: An exception occurred processing JSP page /test.jsp at line 14
description The server encountered an internal error that prevented it from fulfilling this request.
exception
javax.servlet.ServletException: org.apache.jasper.JasperException: An exception occurred processing JSP page /test.jsp at line 14

11: 
12:   Organization: ${outer.organizationName} &lt;br/&gt; 
13: 
14:   &lt;c:forEach var="inner" items="${outer}" varStatus="templocation"&gt;
15:     Location: ${inner.locationName}  
16:   &lt;/c:forEach&gt;
17: 
</code></pre>

<h2>Stacktrace:</h2>

<pre><code>    com.maple.controller.TestControllerServlet.doGet(TestControllerServlet.java:65)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause
org.apache.jasper.JasperException: An exception occurred processing JSP page /test.jsp at line 14

11: 
12:   Organization: ${outer.organizationName} &lt;br/&gt; 
13: 
14:   &lt;c:forEach var="inner" items="${outer}" varStatus="templocation"&gt;
15:     Location: ${inner.locationName}  
16:   &lt;/c:forEach&gt;
17: 
</code></pre>

<h2>Stacktrace:</h2>

<pre><code>    org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:579)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:461)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:340)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    com.maple.controller.TestControllerServlet.listOrgDetails(TestControllerServlet.java:81)
    com.maple.controller.TestControllerServlet.doGet(TestControllerServlet.java:59)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause
javax.servlet.ServletException: javax.servlet.jsp.JspTagException: Don't know how to iterate over supplied "items" in &amp;lt;forEach&amp;gt;
    org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:909)
    org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:838)
    org.apache.jsp.test_jsp._jspService(test_jsp.java:144)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:438)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:340)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    com.maple.controller.TestControllerServlet.listOrgDetails(TestControllerServlet.java:81)
    com.maple.controller.TestControllerServlet.doGet(TestControllerServlet.java:59)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause
javax.servlet.jsp.JspTagException: Don't know how to iterate over supplied "items" in &amp;lt;forEach&amp;gt;
    org.apache.taglibs.standard.tag.common.core.ForEachSupport.toForEachIterator(ForEachSupport.java:312)
    org.apache.taglibs.standard.tag.common.core.ForEachSupport.supportedTypeForEachIterator(ForEachSupport.java:276)
    org.apache.taglibs.standard.tag.common.core.ForEachSupport.prepare(ForEachSupport.java:193)
    javax.servlet.jsp.jstl.core.LoopTagSupport.doStartTag(LoopTagSupport.java:291)
    org.apache.jsp.test_jsp._jspx_meth_c_005fforEach_005f1(test_jsp.java:221)
    org.apache.jsp.test_jsp._jspx_meth_c_005fforEach_005f0(test_jsp.java:179)
    org.apache.jsp.test_jsp._jspService(test_jsp.java:128)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:438)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:340)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    com.maple.controller.TestControllerServlet.listOrgDetails(TestControllerServlet.java:81)
    com.maple.controller.TestControllerServlet.doGet(TestControllerServlet.java:59)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
note The full stack trace of the root cause is available in the Apache Tomcat/8.0.38 logs.
________________________________________
Apache Tomcat/8.0.38
</code></pre>