Search code examples
javajspstruts2jstljsp-tags

How to use nested foreach tag in JSP


I using Struts2 framework with JSP. I want to have nested foreach tag in JSP but I am getting below error at inner foreach tag.

Getting the error while iterating the nested objects from.

<c:forEach var="emp" items="${dept.emplyees}"> 

Exception:

Caused by: javax.servlet.jsp.JspTagException: Don't know how to iterate over supplied "items" in &lt;forEach&gt;
    at org.apache.taglibs.standard.tag.common.core.ForEachSupport.toForEachIterator(ForEachSupport.java:274) ~[jstl-1.2.jar:1.2]
    at org.apache.taglibs.standard.tag.common.core.ForEachSupport.supportedTypeForEachIterator(ForEachSupport.java:238) ~[jstl-1.2.jar:1.2]
    at org.apache.taglibs.standard.tag.common.core.ForEachSupport.prepare(ForEachSupport.java:155) ~[jstl-1.2.jar:1.2]
    at javax.servlet.jsp.jstl.core.LoopTagSupport.doStartTag(LoopTagSupport.java:291) ~[javax.servlet.jsp.jstl-api-1.2.1.jar:1.2.1]
    at org.apache.jsp.views.Home.home_jsp._jspx_meth_c_005fforEach_005f1(home_jsp.java:364) ~[na:na]
    at org.apache.jsp.views.Home.home_jsp._jspService(home_jsp.java:159) ~[na:na]

Below is my sample code with POJO and Struts Action feilds.

JSP Code:

<c:forEach var="dept" items="${deptList}"> 
  <c:out value="${dept.deptname}"/> 
  <c:forEach var="emp" items="${dept.emplyees}"> 
    <c:out value="${emp.name}"/> 
  </c:forEach>
</c:forEach>

Action class: testAction:

class TestAction{
List<Department> deptList

public List<Department> getDeptList() {
        return deptList;
    }

    public void setDeptList(List<Department> deptList) {
        this.deptList = deptList;
    }
}

Deprtment POJO:

class Department{

private String deptname

List<Employee> emplyees;

    public List<Employee> getDeptList() {
        return emplyees;
    }

    public void setDeptList(List<Employee> emplyees) {
        this.emplyees = emplyees;
    }
}

Employee POJO:

class Employee{
    private String name;
}

Solution

  • To iterate over the property of the object it should be not null and have a getter method.

    private List<Employee> emplyees = new ArrayList<>();
    public List<Employee> getEmplyees() { return emplyees; }  
    

    Before displaying this property on the page, it would be nice to have some values. You can do this in the action, or better in prepare() and let your action implement Preparable interface.

    Often the data used to populate a form control is dynamically generated, perhaps from a database. When the user submits the form, the Struts 2 validation interceptor attempts to validate the user's form input. If validation fails the Struts 2 framework returns the value "input" but the "input" action is not re-executed. Rather the view associated with the "input" result is rendered to the user. Usually this view is the page that displayed the original form.

    This work-flow can cause a problem if one or more of the form fields or some other data displayed depends on a dynamic look-up that that is accomplished in the Action class's input method. Since the Action class's input method is not re-executed when validation fails, the view page may no longer have access to the correct information to create the form or other display information.