JSTL message: Don't know how to iterate over s

2019-04-24 06:09发布

问题:

I am passing a List to <c:forEach>, yet I get the error stating that it doesn't know how to iterate over it.

@RequestMapping("/viewall")
public String viewAll(Model model) {

    // productService.findAllProducts() returns List<Product> 
    model.addAttribute("everything", productService.findAllProducts());

    // Also tried using iterator, but I get same error
    //model.addAtrribute("everything", productService.findAllProducts().iterator());

    ....
}

The jsp page:

<c:forEach items="${everything}" var="prod">
    <p> ${prod.name} </p>
</c:forEach>

The error:

javax.servlet.ServletException: javax.servlet.jsp.JspTagException: Don't know how to iterate over supplied "items" in &lt;forEach&gt;
    org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:912)
    org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:841)
    org.apache.jsp.WEB_002dINF.jsp.allprod_jsp._jspService(allprod_jsp.java:158)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:238)
    org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:262)
    org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1180)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:950)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)

root cause

javax.servlet.jsp.JspTagException: Don't know how to iterate over supplied "items" in &lt;forEach&gt;
    org.apache.taglibs.standard.tag.common.core.ForEachSupport.toForEachIterator(ForEachSupport.java:255)
    org.apache.taglibs.standard.tag.common.core.ForEachSupport.supportedTypeForEachIterator(ForEachSupport.java:219)
    org.apache.taglibs.standard.tag.common.core.ForEachSupport.prepare(ForEachSupport.java:137)
    javax.servlet.jsp.jstl.core.LoopTagSupport.doStartTag(LoopTagSupport.java:227)
    org.apache.jsp.WEB_002dINF.jsp.allprod_jsp._jspx_meth_c_005fforEach_005f0(allprod_jsp.java:180)
    org.apache.jsp.WEB_002dINF.jsp.allprod_jsp._jspService(allprod_jsp.java:137)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:238)
    org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:262)
    org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1180)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:950)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)

回答1:

The problem seems to be that there is another attribute in Session or ServletContext (application) with the same name. From JspContext#findAttribute (which is the method executed when using ${something}):

Searches for the named attribute in page, request, session (if valid), and application scope(s) in order and returns the value associated or null.

It doesn't explain the specific order about how the attribute is searched, so it could be vendor specific.

In order to avoid problems, just change the name of your attribute.



回答2:

For looping over your list you can do something like this,

<c:forEach var="prod" begin="1" end="5">
        <option value="${prod}" >${prod.name}</option>
    </c:forEach>

you can get the length of your list by adding a library which can be used as jstl apis,

<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

and then in the end attribute you can set the end value as the size of your list,

${fn:length(everything)}

the final code would be something like,

<c:forEach var="prod" begin="1" end="${fn:length(everything)}">
        <option value="${prod.name}" >${l}</option>
    </c:forEach>

this code will set the loop variable to start with begin value as 1 and end value as your list size.