Struts 1
  1. Struts 1
  2. STR-1249

[taglib] Problem to include a jsp into an iterate tag

    Details

    • Type: Improvement Improvement
    • Status: Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: Future
    • Fix Version/s: Future
    • Component/s: Tag Libraries
    • Labels:
      None
    • Environment:
      Operating System: All
      Platform: All

      Description

      2 problems have been identified for this type of inclusion :

      Let's start with a sample code :

      Here is a sample main jsp (main.jsp) :
      <%@taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
      <%@taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
      <html:form method="post" action="/submit">
      <html:iterate name="myForm" property="tab" id="tab" indexId ="index"
      scope="request">
      <jsp:include page="/included.jsp" flush="true" />
      </html:iterate>
      </html:form>

      Here is a sample included jsp (included.jsp) :
      <%@taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
      <%@taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
      Personne <bean:write name="index"><br>
      Nom <html:text name="tab" property="firstName" indexed="true" /><br>
      Prenom <html:text name="tab" property="lastName" indexed="true" /><br>

      The first problem is that in the included jsp, it is impossible to access to
      the differents properties given by each iteration : The error message
      is "cannot find bean index in any scope"

      One proposed solution is to use <bean:define> into the <logic:iterate> tag and
      to add the index bean and the tab bean in scope session instead of scope page.
      This solution doesn't seams to work : the error message is the same.

      Another solution could be to modify the doStartTag() and doAfterBody() method
      of the o.a.s.taglib.logic.IterateTag class to store the two bean in request
      instead of page context.

      My tested solution is to redefine the <logic:iterate> tag. I have created a
      <perso:iterate> tag with the class PersoIterateTag wich extends IterateTag,
      redefining his doStartTag() and doAfterBody() method :

      public doStartTag() throws JspException {
      int result = super.doStartTag();

      if (result == EVAL_BODY_TAG) {
      Object o = pageContext.getAttribute(id);
      if (o == null)

      { pageContext.getRequest().removeAttribute(id); }

      else

      { pageContext.getRequest().setAttribute(id,o); }
      o = pageContext.getAttribute(indexId);
      if (o != null) { pageContext.getRequest().setAttribute(indexId,o); }
      }

      return result;
      }

      public doAfterBody() throws JspException {
      int result = super.doAfterBody();

      if (result == EVAL_BODY_TAG) {
      Object o = pageContext.getAttribute(id);
      if (o == null) { pageContext.getRequest().removeAttribute(id); } else { pageContext.getRequest().setAttribute(id,o); }

      o = pageContext.getAttribute(indexId);
      if (o != null)

      { pageContext.getRequest().setAttribute(indexId,o); }

      }

      return result;
      }

      Modifying the first jsp (main.jsp) to use this tag, there is no problem for
      finding the bean anymore.

      But, here comes the second problem : the indexed property of tag <html:text>
      provides a way to generate a <html input="text"> type tag with a name property
      like "tab[0].firstName".
      To do this, when the indexed property is true into the <html:text> tag, the
      method prepareIndex() from o.a.s.taglib.html.BaseHanderTag class is called.
      But into this method the first operation consists in calling the
      findAncestorWithClass() method to get the instance of the IterateTag wich
      correspond to the <logic:iterate>.
      In this case the <logic:iterate> tag isn't in the same page than the
      <html:text> tag, and so an error message comes: "indexed="true" is only valid
      within an enclosing iterate tag"
      This problem seems to be a scope problem : the corresponding instance for
      <logic:iterate> is into the page scope, that's why the included jsp cannot
      recover his instance.

      One solution to fixe this problem can be to add two property to the <html:text>
      (and to similar tag) :

      • indexName : The name of the bean containing the current value of the index
        (in this exemple "index")
      • indexScope : The scope where this bean can be found.

      This properties could be added to the o.a.s.taglib.html.BaseHandlerTag class
      with the corresponding getter and setter method.
      On begining of the prepareIndex() method of this class, the following code
      could be added :
      protected void prepareIndex(StringBuffer handlers, String name) throws
      JspException {
      if (indexName != null) {
      Integer index = (Integer)RequestUtils.lookup
      (pageContext,indexName,indexScope);
      if (index == null)

      { JspException e = new JspException(messages.getMessage ("lookup.bean", indexName, indexScope)); RequestUtils.saveException(pageContext, e); throw e; }

      if (name != null)
      handlers.append(name);
      handlers.append("[");
      handlers.append(index);
      handlers.append("]");
      if (name != null)
      handlers.append(".");
      return;
      }
      ...
      }

      On the end of the release() method of this class, the following code could be
      added :
      indexName = null;
      indexScope = null;

      Finally, the struts-html.tld file has to be modified, addding the following
      line to each tag wich can use it :
      <attribute>
      <name>indexName</name>
      <required>false</required>
      <rtexprvalue>true</rtexprvalue>
      </attribute>
      <attribute>
      <name>indexScope</name>
      <required>false</required>
      <rtexprvalue>true</rtexprvalue>
      </attribute>

      With this modification the folowing jsp code will now work :

      Here is the new main jsp (main.jsp) :
      <%@taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
      <%@taglib uri="/WEB-INF/struts-perso.tld" prefix="logic" %>
      <html:form method="post" action="/submit">
      <logic:iterate name="myForm" property="tab" id="tab" indexId ="index"
      scope="request">
      <jsp:include page="/included.jsp" flush="true" />
      </logic:iterate>
      </html:form>

      Here is the new included jsp (included.jsp) :
      <%@taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
      <%@taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
      Personne <bean:write name="index"><br>
      Nom <html:text name="tab" property="firstName" indexName="index"
      indexScope="request" indexed="true" /><br>
      Prenom <html:text name="tab" property="lastName" indexName="index"
      indexScope="request" indexed="true" /><br>

        Activity

        Mark Thomas made changes -
        Workflow Default workflow, editable Closed status [ 12559113 ] jira [ 12587537 ]
        Mark Thomas made changes -
        Workflow jira [ 12549010 ] Default workflow, editable Closed status [ 12559113 ]
        Mark Thomas made changes -
        Workflow Default workflow, editable Closed status [ 12545701 ] jira [ 12549010 ]
        Mark Thomas made changes -
        Workflow jira [ 12490470 ] Default workflow, editable Closed status [ 12545701 ]
        Jeff Turner made changes -
        Project Import Mon Feb 01 01:03:21 UTC 2010 [ 1264986201992 ]
        pbenedict made changes -
        Assignee Struts Developers [ dev@struts.apache.org ]
        Don Brown made changes -
        Field Original Value New Value
        issue.field.bugzillaimportkey 17473 26540
        Freddy Lecerf created issue -

          People

          • Assignee:
            Unassigned
            Reporter:
            Freddy Lecerf
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:

              Development