You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by bu...@apache.org on 2003/02/27 11:57:58 UTC

DO NOT REPLY [Bug 17473] New: - Problem to include a jsp into an iterate tag

DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=17473>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=17473

Problem to include a jsp into an iterate tag

           Summary: Problem to include a jsp into an iterate tag
           Product: Struts
           Version: 1.1 Beta 3
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: Major
          Priority: Other
         Component: Custom Tags
        AssignedTo: struts-dev@jakarta.apache.org
        ReportedBy: lecerffreddy@fr.ibm.com


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>

---------------------------------------------------------------------
To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-dev-help@jakarta.apache.org