2

my ask is similar to the one asked here: JSTL - Using forEach to iterate over a user-defined class However, the (obvious and simple) solution does not work for me, so I am asking again looking for any advice.

I have a simple class implementing Iterable interface, like:

public class Lizt implements Iterable<String> {

  private ArrayList<String> inner = new ArrayList<>();

  public Lizt(){
    this.inner.add("A");
    this.inner.add("B");
  }

  @Override
  public Iterator<String> iterator() {
    return inner.iterator();
  }

  public Iterable<String> getInner(){
    return this.inner;
  }
}

(Ignore "getInner()" function for now). Then I have a simple JSP page:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<jsp:useBean id="lst" scope="session" class="model.Lizt"/>
<html>
<body>
<ul>
<c:forEach var="item" items="${lst}">
    <li>${item}</li>
</c:forEach>
</ul></body></html>

So, I am trying to iterate over an instance implementing Iterable. However, the server returns me (among the others)

javax.servlet.ServletException: org.apache.jasper.JasperException: An exception occurred processing JSP page [/forEachTest.jsp] at line [7]
...
Caused by: javax.servlet.ServletException: javax.servlet.jsp.JspTagException: Don't know how to iterate over supplied "items" in &lt;forEach&gt;

If I replace the JSP expression to access directly the internal inner field, like

<c:forEach var="item" items="${lst.inner}">

... everything works fine. Where is the difference between "my" Iterable and ArrayList's Iterable?

Thanks for any advice in advance.

Engin
  • 98
  • 6

2 Answers2

3

The difference is that ArrayList is a Collection, and your class is not. Here's what the specification of the JSTL says:

Collections Supported & Current Item The data types listed below must be supported for items [...]

  • Arrays [...]
  • Implementation of java.util.Collection [...]
  • Implementation of java.util.Iterator [...]
  • Implementation of java.util.Enumeration [...]
  • Implementation of java.util.Map [...]
  • String

As you can see, Iterable is not listed.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
3

As the comment by Adam Gent to the accepted answer there states:

Caveat to that is that JSTL forEach does not support iterable (extremely annoying) as forEach type. So you need to do ${projectSet.iterator()}

The forEach simply does not support Iterable, as counter-intuitive as it may be. It does support iterator though, which I assume should be easy for you to use instead.

You can find evidence for this in source code of ForEachSupport, in method supportedTypeForEachIterator().

Jiri Tousek
  • 12,211
  • 5
  • 29
  • 43