Multiple-level nesting with <logic:iterate> in Struts

20

I expected multiple-level nesting with the <logic:iterate> tag in Struts to be difficult, but on the contrary it turned out to be an almost trivial exercise.

In my case/this example, we get from the data tier a list of books in a form bean as a collection of BookDTOs (Data Transfer Objects). A BookDTO contains fields such as title, publisher, year and a collection of authors (second iterator!), which in turn contains fields such as first name, last name and initials.

The JSP fragment is as follows:

&lt;%@ page language="java" %&gt;
&lt;!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en"&gt;
&lt;%@ taglib uri="/tags/struts-html" prefix="html"%&gt;
&lt;%@ taglib uri="/tags/struts-bean" prefix="bean"%&gt;
&lt;%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %&gt;
&lt;logic:greaterThan property="numResults"
                   name="publicationsFormBean"
                   value="0" &gt;
  &lt;h3&gt;Books in database:&lt;/h3&gt;
  &lt;ol&gt;
    &lt;logic:iterate
     name="publicationsFormBean"
     property="publications"
     indexId="i"
     id="dummy"&gt;
      &lt;li&gt;
        &lt;i&gt;
          &lt;bean:write
           name="publicationsFormBean"
           property='&lt;%= "publications["+ i +"].title" %&gt;'/&gt;
        &lt;/i&gt;,
        &lt;logic:iterate name="publicationsFormBean"
         property='&lt;%= "publications["+ i +"].authors" %&gt;'
         indexId="j"
         id="dummy2"&gt;
          &lt;bean:write
           name="publicationsFormBean"
           property='&lt;%= "publications["+ i +"].authors["+ j +"].initials" %&gt;'/&gt;
          &lt;bean:write
           name="publicationsFormBean"
           property='&lt;%= "publications["+ i +"].authors["+ j +"].lastName" %&gt;'/&gt;
         (&lt;bean:write
           name="publicationsFormBean"
           property='&lt;%= "publications["+ i +"].authors["+ j +"].firstName" %&gt;'/&gt;
          &lt;bean:write
           name="publicationsFormBean"
           property='&lt;%= "publications["+ i +"].authors["+ j +"].middleNames" %&gt;'/&gt;),
        &lt;/logic:iterate&gt;
        &lt;bean:write
         name="publicationsFormBean"
         property='&lt;%= "publications[" + i + "].publisher" %&gt;'/&gt;,
        &lt;bean:write
         name="publicationsFormBean"
         property='&lt;%= "publications[" + i + "].year" %&gt;'/&gt;
      &lt;/li&gt;
    &lt;/logic:iterate&gt;
  &lt;/ol&gt;
&lt;/logic:greaterThan&gt;

Note how in the second iterator (with indexId=j) the property is desginated a collection in a collection. From there the properties can be addressed straightforwardly by separating them with dots.

This results in an output as follows:

  1. Book title one, J.W. Klaassen (Jan Willem), My Publisher, 2004
  2. Book title two, J.W. Klaassen (Jan Willem), P. Puk (Pietje), My Publisher, 2004
Share.

About Author

20 Comments

  1. Pingback: Another Blog Title

  2. Hi, Could anybody been able to retrieve values back from inner loop.
    I tried hard but couldn’t got the solution, though i’m able to retrieve values
    back from outer loop. What about the tag , could it be succesfully
    developed and impleneted?

  3. I used the tag in my code, but getting exception as:
    javax.servlet.ServletException: Cannot create iterator for this collection

    Can you please suggest the possible causes for this exception???

  4. freekyfashions on

    Nice tip to learn abt the iteration.
    I would like to add few more points which will give a very clear picture to others.

    Here it is:
    ————
    Create an arraylistContainer.
    Create a bean book – [‘data1′,’data2′,’arrayList’]
    ‘arrayList’ – has another bean details – [‘bean1′]
    ‘bean1′ – has some attributes [‘data3′,’data4′]
    Add the bean to ArrayListContainer.

    Now start your iteration as followed:
    —————————————

    Hope this helps you all still better.

  5. hi….
    i am facing a problem regarding logic:itearate. i am getting the error
    “cannot create iterator for the collection. i have made a multiple Select box as
    my collection by declaring it as object of type java.util.string[] in my struts config

    i am badly struck.

    any help…..

    ankur

  6. Rajamani David on

    Hi Perogi,
    Good to see the solution for IndexedTextTag. I downloaded it from your website.
    Do you have sample jsp to test IndexedTextTag? I could not find anything inside the zip file.

    Thanks
    Rajamani David

  7. Jose Tharail Raphael on

    Hi,

    I am having a problem with the logic:iterate tags.Below is the jsp code


    id="fundingOrganization"
    type="org.digijava.module.aim.helper.FundingOrganization">

    type="org.digijava.module.aim.helper.Funding">

    type="org.digijava.module.aim.helper.FundingDetail">



    td>

    When the page is loaded i get a compile error

    [ServletException in:/repository/aim/view/addFunding.jsp] Unable to compile class for JSP An error occurred at line: 112 in the jsp file: /repository/aim/view/addFunding.jsp Generated servlet error: G:\jboss\server\default\work\jboss.web\localhost\digijava\org\apache\jsp\repository\aim\view\addFunding_jsp.java:343: incompatible types found : java.lang.String required: org.digijava.module.aim.helper.FundingDetail _jspx_fundingDetail_2 = fundingDetail; ^ An error occurred at line: 112 in the jsp file: /repository/aim/view/addFunding.jsp Generated servlet error: G:\jboss\server\default\work\jboss.web\localhost\digijava\org\apache\jsp\repository\aim\view\addFunding_jsp.java:349: incompatible types found : org.digijava.module.aim.helper.FundingDetail required: java.lang.String fundingDetail = (org.digijava.module.aim.helper.FundingDetail) _jspx_page_context.findAttribute(“fundingDetail”); ^ An error occurred at line: 112 in the jsp file: /repository/aim/view/addFunding.jsp Generated servlet error: G:\jboss\server\default\work\jboss.web\localhost\digijava\org\apache\jsp\repository\aim\view\addFunding_jsp.java:358: incompatible types found : org.digijava.module.aim.helper.FundingDetail required: java.lang.String fundingDetail = (org.digijava.module.aim.helper.FundingDetail) _jspx_page_context.findAttribute(“fundingDetail”); ^ An error occurred at line: 112 in the jsp file: /repository/aim/view/addFunding.jsp Generated servlet error: G:\jboss\server\default\work\jboss.web\localhost\digijava\org\apache\jsp\repository\aim\view\addFunding_jsp.java:362: incompatible types found : org.digijava.module.aim.helper.FundingDetail required: java.lang.String fundingDetail = _jspx_fundingDetail_2; ^ 4 errors ‘

    When the page is loaded fundings and fundingDetails Collection is null.

    I am stumped for now.

    Any ideas.

    Thanks in advance.

  8. Hi all, this is an emergency, HELP PLEASE !
    I have the following issue with loginc:iterate, does’n wokr properly, I mean doesn’t show anything in my browser..
    mi logs doesn’t have any error message and everything seems to be fine…

    Here the code:
    /*******
    < %
    views= (request.getAttribute("getViewRecordSet") != null ? (Vector) request.getAttribute("getViewRecordSet") : null);
    pageContext.setAttribute("views", views);
    %>

    ********/

    ite name=”viewCollection” property=”itProcessDesc” /> ite name=”viewCollection” property=”scenarioDesc” />     ite name=”viewCollection” property=”name” />

    erate>

    I guess the property value are the gettes methods fom my action class…

    So somebody can help ?
    Thanks advanced !

  9. I am planning on making a indexedTextTag.war file to display its usage but for now, you can download the file at
    IndexedTextTag. The link is on the left of the page under downloads, I hesitate to
    include a direct link to the file in case I decide to add different downloads.

    Hope this helps those, I know it helped me!
    perogi.

  10. I created a strutsish tag to enable this system. I am testing it atm and I will post a link to download it asap.

    Hope this helps everyone!
    perogi.

  11. Doh! I just read Rajamani’s post. It appears that we have the same problem. If I locate a solution, I will post it.

    Thanks again.
    Perogi.

  12. Hello! I currently am using ‘Leon’s’ technique. It displays perfectly but I have one major problem; the values for
    the second iterated List are not being propagated back into the Object when ‘submit’ is clicked. Anyone else have this problem
    and fixed it or have ideas on how to fix it?

    Thanks in advance.
    Perogi.

  13. Rajamani David on

    Its great! Am using html:text in the second iterate. How do I capture the values after the submit. I tired all the different ways but its not working. Please help me to fix it.

  14. However, should we not move to the JSTL c:foreach and c:out tags soon as possible?

  15. Zeger Hendrikse on

    I reworked my JSP according to Leon’s suggestions, and it worked flawlessly the first time! I’m impressed :-)

  16. Oops, i think this is a classic case of spreading bad code by copy-paste: in the BR-App the “[+i+]”-style indexing was neccesary while testing the struts indexed-properties, but it isn’t anymore. I forgot to remove it, sorry bout that..
    By replacing the id attribute in the iterate tag by a meaningfull name, you can simply access the fields if you use that id as the name-attribute in the nested bean:write..
    Will change the code in CVS right now

  17. Leon van Tegelen on

    An alternative which in my opinion is a bit more readable is something like this:

    &lt;logic:greaterThan property="numResults" name="publicationsFormBean" value="0" &gt;
      &lt;h3&gt;Books in database:&lt;/h3&gt;
      &lt;ol&gt;
        &lt;logic:iterate name="publicationsFormBean" property="publications" id="publication"&gt;
          &lt;li&gt;
            &lt;i&gt;
              &lt;bean:write name="publication" property="title"/&gt;
            &lt;/i&gt;,
            &lt;logic:iterate name="publication" property="authors" id="author"&gt;
              &lt;bean:write name="author" property="initials" /&gt;
              &lt;bean:write name="author" property="lastName" /&gt;
              &lt;bean:write name="author" property="firstName" /&gt;
              &lt;bean:write name="author" property="middleNames" /&gt;
            &lt;/logic:iterate&gt;
            &lt;bean:write name="publication" property="publisher" /&gt;,
            &lt;bean:write name="publication" property="year" /&gt;,
          &lt;/li&gt;
        &lt;/logic:iterate&gt;
      &lt;/ol&gt;
    &lt;/logic:greaterThan&gt;
    

    this uses the id variables much more effective