Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 415
  • Last Modified:

using forEach tags with <%=

I have the following code in my jsp:

                  <c:forEach var='doctype' items='${modifyUserFormBean.doctypes}'>
                        <td align="center" valign="middle" class="row_normal">
                        <div><input name="<c:out value='${doctype.doctypeId}' />"
                              type="checkbox" value="checkbox"
                              checked="<%= modifyUserFormBean.getCheckedDoctypes().contains(doctype.getDoctypeId())%>" />
                        <c:out value='${doctype.doctypeName}' /></div>
                        </td>
                  </c:forEach>


In line that says modifyUserFormBean.getCheckedDoctypes().contains(doctype.getDoctypeId())%>"  I get a compilation exception on doctype: doctype cannot be resolved

I've tried different combinations of c: and c_rt: but to no avail.

Please help.
0
aturetsky
Asked:
aturetsky
  • 13
  • 12
  • 7
  • +1
2 Solutions
 
bloodredsunCommented:
This is to do with scopes rather than the forEach tag. The scriptlet does not have access to the expression lanaguage variable "doctype"
0
 
TimYatesCommented:
Does:

               <c:forEach var='doctype' items='${modifyUserFormBean.doctypes}'>
                    <jsp:useBean id="doctype" class="CLASSOFDOCTYPEOBJECT"/>
                    <td align="center" valign="middle" class="row_normal">
                    <div><input name="<c:out value='${doctype.doctypeId}' />"
                         type="checkbox" value="checkbox"
                         checked="<%= modifyUserFormBean.getCheckedDoctypes().contains(doctype.getDoctypeId())%>" />
                    <c:out value='${doctype.doctypeName}' /></div>
                    </td>
               </c:forEach>

help?
0
 
TimYatesCommented:
(replace CLASSOFDOCTYPEOBJECT with the full classname that the "doctype" obejct represents :-)
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
aturetskyAuthor Commented:
Tim, I am sorry for the delayed response.  I ended up doing it differently before I received your message, so I kept putting off my response until I would get to try out your code.

Here's what i don't understand in your code.  Wouldn't <jsp:useBean id="doctype" class="somepackage.Doctype"/>
result in putting a blank bean of Doctype type into the session.  How, in your code, would it get populated with the contents of ${doctype}?  Would you not need a c:set?
0
 
TimYatesCommented:
>> How, in your code, would it get populated with the contents of ${doctype}?  Would you not need a c:set?

  <c:forEach var='doctype' items='${modifyUserFormBean.doctypes}'>

defines a doctype object and stores it in the var called "doctype"

  <jsp:useBean id="doctype" class="CLASSOFDOCTYPEOBJECT"/>

gets this object, and defines it so that it can be used in your JSP scriptlet...

As far as I know anyway...  did you try the code?

Tim
0
 
aturetskyAuthor Commented:
Tim,

Well, I tried running it, but it doesn't seem to work for a different reason - the doctype is of class Doctype, which for some reason is not being treated by the jsp compiler as a bean, so I get a "The value for the useBean class attribute com.talisen.workflow.model.Doctype is invalid" error , even though I made sure that the declaration and everything else is correct.  I'll included the code for that class on the very bottom, in case you can tell me offhand why this class is not being treated as a bean.

But in any case here's what I don't understand in your code:

You suggest that the line <jsp:useBean id="doctype" class="CLASSOFDOCTYPEOBJECT"/>  "gets this object."  Well, I didn't think that was true, and that it would instantiate a brand new bean of  that type, but just to be sure I did some research, and I think I am correct here:
According to http://java.sun.com/products/jsp/syntax/1.2/syntaxref1217.html,

"The <jsp:useBean> element locates or instantiates a JavaBeans component. <jsp:useBean> first attempts to locate an instance of the bean. If the bean does not exist, <jsp:useBean> instantiates it from a class or serialized template.

To locate or instantiate the bean, <jsp:useBean> takes the following steps, in this order:

   1. Attempts to locate a bean with the scope and name you specify.
   2. Defines an object reference variable with the name you specify.
   3. If it finds the bean, stores a reference to it in the variable. If you specified type, gives the bean that type.
   4. If it does not find the bean, instantiates it from the class you specify, storing a reference to it in the new variable. If the class name represents a serialized template, the bean is instantiated by java.beans.Beans.instantiate.
   5. If <jsp:useBean> has instantiated (rather than located) the bean, and if it has body tags or elements (between <jsp:useBean> and </jsp:useBean>), executes the body tags"

Now, l'll go through it in order.  Step 1 attempt would result in nothing, because the var doctype in <c:forEach var='doctype' items='${modifyUserFormBean.doctypes}'> is invisible since it only has nested visibility (see bellsouthpwp.net/b/i/billsigg/jstl-quick-reference.pdf).  Therefore, after defining the object reference variable in Step 2, it would not go into Step 3, since such bean does not exist.   Rather, it would go into step 4 and instantiate a new one.  That means the value of the var from the loop will never get into that bean.

Am I wrong?

As promised here' s the code for the Doctype class - and I am increasing the point value.

package com.talisen.workflow.model;

import java.io.Serializable;

public class Doctype implements Serializable, Comparable {

      private Integer doctypeId = null;
      private String doctypeName;
      private String doctypeDesc;
      private String doctypeAbbr;
      private Status status;
    private int hashValue = 0;

    /**
     * @return Returns the doctypeDesc.
     */
    public String getDoctypeDesc()
    {
        return this.doctypeDesc;
    }
    /**
     * @param doctypeDesc The doctypeDesc to set.
     */
    public void setDoctypeDesc(String doctypeDesc)
    {
        this.doctypeDesc = doctypeDesc;
    }
    /**
     * @param doctypeId The doctypeId to set.
     */
    public void setDoctypeId(Integer doctypeId)
    {
        this.doctypeId = doctypeId;
    }
    /**
     * @param doctypeUsers The doctypeUsers to set.
     */

    /**
     * @return Returns the doctypeName.
     */
    public String getDoctypeName()
    {
        return this.doctypeName;
    }

      /**
       * No-arg constructor for JavaBean tools.
       */
      Doctype() {}

      /**
       * Simple constructor.
       */
      public Doctype(String name) {
            this.doctypeName = name;
      }
      public Doctype(Integer doctypeId) {
            this.doctypeId = doctypeId;
      }

      // ********************** Accessor Methods ********************** //

      public Integer getDoctypeId() { return doctypeId; }

      public void setDoctypeName(String name) { this.doctypeName = name; }


      // ********************** Common Methods ********************** //

      public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof Doctype)) return false;

            final Doctype doctype = (Doctype) o;

            if (doctypeName != null ? !doctypeName.equals(doctype.doctypeName) : doctype.doctypeName != null) return false;

            return true;
      }

    public int hashCode()
    {
        if (this.hashValue == 0)
        {
            int result = 17;
            int userIdValue = this.getDoctypeId() == null ? 0 : this.getDoctypeId().hashCode();
            result = result * 37 + userIdValue;
            this.hashValue = result;
        }
        return this.hashValue;
    }

      public String toString() {
            return  "Doctype_Id ('" + getDoctypeId() + "'), " +
                        "Doctype_Name: '" + getDoctypeName() + "'";
      }

      public int compareTo(Object o) {
            if (o instanceof Doctype) {
                  return this.getDoctypeName().compareTo( ((Doctype)o).getDoctypeName() );
            }
            return 0;
      }

      // ********************** Business Methods ********************** //

      /**
       * @return Returns the doctypeAbbr.
       */
      public String getDoctypeAbbr() {
            return doctypeAbbr;
      }
      /**
       * @param doctypeAbbr The doctypeAbbr to set.
       */
      public void setDoctypeAbbr(String doctypeAbbr) {
            this.doctypeAbbr = doctypeAbbr;
      }
      /**
       * @return Returns the status.
       */
      public Status getStatus() {
            return status;
      }
      /**
       * @param status The status to set.
       */
      public void setStatus(Status status) {
            this.status = status;
      }
}
0
 
aturetskyAuthor Commented:
Tim, I realize my previous posting might be too long to read, but could you at least please respond to this part of it, so I can go ahead and give you points.
-------------------
But in any case here's what I don't understand in your code:

You suggest that the line <jsp:useBean id="doctype" class="CLASSOFDOCTYPEOBJECT"/>  "gets this object."  Well, I didn't think that was true, and that it would instantiate a brand new bean of  that type, but just to be sure I did some research, and I think I am correct here:
According to http://java.sun.com/products/jsp/syntax/1.2/syntaxref1217.html,

"The <jsp:useBean> element locates or instantiates a JavaBeans component. <jsp:useBean> first attempts to locate an instance of the bean. If the bean does not exist, <jsp:useBean> instantiates it from a class or serialized template.

To locate or instantiate the bean, <jsp:useBean> takes the following steps, in this order:

   1. Attempts to locate a bean with the scope and name you specify.
   2. Defines an object reference variable with the name you specify.
   3. If it finds the bean, stores a reference to it in the variable. If you specified type, gives the bean that type.
   4. If it does not find the bean, instantiates it from the class you specify, storing a reference to it in the new variable. If the class name represents a serialized template, the bean is instantiated by java.beans.Beans.instantiate.
   5. If <jsp:useBean> has instantiated (rather than located) the bean, and if it has body tags or elements (between <jsp:useBean> and </jsp:useBean>), executes the body tags"

Now, l'll go through it in order.  Step 1 attempt would result in nothing, because the var doctype in <c:forEach var='doctype' items='${modifyUserFormBean.doctypes}'> is invisible since it only has nested visibility (see bellsouthpwp.net/b/i/billsigg/jstl-quick-reference.pdf).  Therefore, after defining the object reference variable in Step 2, it would not go into Step 3, since such bean does not exist.   Rather, it would go into step 4 and instantiate a new one.  That means the value of the var from the loop will never get into that bean.

Am I wrong?
0
 
rrzCommented:
>${modifyUserFormBean.doctypes}    
What type of collection is returned ?          rrz
0
 
rrzCommented:
Try something like the following.       rrz

<c:forEach var='doctype' items='${modifyUserFormBean.doctypes}'>
         <td align="center" valign="middle" class="row_normal">
         <div><input name="<c:out value='${doctype.doctypeId}' />"
                     type="checkbox" value="checkbox"
  <%
     com.talisen.workflow.model.Doctype  currentType  =  
                 (com.talisen.workflow.model.Doctype)pageContext.getAttribute("doctype");
     String checkValue =
            modifyUserFormBean.getCheckedDoctypes().contains(currentType.getDoctypeId());
  %>
                     checked="<%=checkValue%>" />
                    <c:out value='${doctype.doctypeName}' /></div>
                    </td>
               </c:forEach>
0
 
aturetskyAuthor Commented:
thanks, rrz - well, I mean I ended up doing earlier in a similar way, except I had to put the attribute "doctype" into the request context.

How would your way work, however - that is, how can you, in the following line, expect the doctype to be an attribute in pageContext if you never put it there?

com.talisen.workflow.model.Doctype  currentType  =  
                 (com.talisen.workflow.model.Doctype)pageContext.getAttribute("doctype");
0
 
rrzCommented:
>how can you, in the following line, expect the doctype to be an attribute in pageContext if you never put it there?            
you put it there with  
><c:forEach var='doctype'        
Please try the following page.     rrz  

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  
<c:forEach items="1,2,3,4,5,6" var="current">
<%
  String current = (String)pageContext.getAttribute("current");
%>
<%=current%>
</c:forEach>
0
 
rrzCommented:
I guess when it comes down to it having a scriptlet in a JSTL tag is an ugly solution.
Are you using JSP 2.0 ? If so then we can clean it up some.      rrz
0
 
rrzCommented:
My solution is a variation of Tim's solution.
Right  ?  
0
 
aturetskyAuthor Commented:
Cool.  Thanks.  You the man.
Before I reward points, I want to make sure that my problem with Tim's answer was justified.  That is, that using  <jsp:useBean id="doctype" class="CLASSOFDOCTYPEOBJECT"/> would not help since doctype was never instantiated as a bean, only as an attribute of the page context.  Is that accurate?
0
 
aturetskyAuthor Commented:
Also, I just saw your response above.  Yes.  I am using 2.0.   I'd love to know how can we clean it up and not use scriplets.
0
 
rrzCommented:
> I'd love to know how can we clean it up and not use scriplets.  
No, I didn't say that. I meant to say that we could get rid of  the display tags.
><c:out value='${doctype.doctypeName}' /></  
could be just  EL  
${doctype.doctypeName}  

>Is that accurate?  
I don't think so. But let's get Tim's response.    
I would try Tim's idea like below.      rrz    

<jsp:useBean id="doctype" class="com.talisen.workflow.model.Doctype"/>
<c:forEach var='doctype' items='${modifyUserFormBean.doctypes}'>
   <td align="center" valign="middle" class="row_normal">
   type="checkbox" value="checkbox"
   checked="<%= modifyUserFormBean.getCheckedDoctypes().contains(doctype.getDoctypeId())%>" />
   ${doctype.doctypeName}</div>
   </td>
</c:forEach>
0
 
rrzCommented:
No, that won't work ( Tim please help ).
0
 
aturetskyAuthor Commented:
Thanks for all this.  If I don't get the response from Tim today, I'll go ahead and reward the points, since I posted my question to him a while ago.  Speaking of EL ... I am posting a following question, that I am sure you can answer.  The link is below.

1) my development server supports 2.0, so to use EL syntax such as ${doctype.doctypeName} without the c:out, what should the taglib declaration look like, or do I not need a declaration
2) my production server (Sun Web Server 6.1) only supports 1.2, so I am just curious if I can EL-enable it by dropping in a jar or what not, or is that impossible?

The link for the question is http://www.experts-exchange.com/Web/Web_Languages/JSP/Q_21353601.html.
0
 
rrzCommented:
1) El is part of JSP 2.0   nothing special is needed.  
2)No  
Wait for Tim's response before taking action here.           rrz    
0
 
aturetskyAuthor Commented:
will do
0
 
TimYatesCommented:
Hiya!  Sorry, I was at home, asleep ;-)

Whats the problem?  Didn't rrz's solution fix it?
0
 
rrzCommented:
>Whats the problem?  
Just wondering if your use of useBean tag should work.         rrz
0
 
TimYatesCommented:
I'm not sure if it will work inside a <c:forEach tag...

I know it works inside a <logic:iterate tag for Struts...

But I guess they are completely different :-(

Tim
0
 
aturetskyAuthor Commented:
but even with logic:iterate it would only work for an iteration over a collection of bean objects, correct?  So if my doctype object is, for whatever reason, not classified as a bean (not sure why not in my case, but that's beside the point) it wouldn't work, right?
0
 
TimYatesCommented:
does it have an empty constructor?

if so, it should work as a bean...  (as long as it has getXXX methods for the parameters you want to read...
0
 
aturetskyAuthor Commented:
Thanks.  Could be my problem is the fact that my empty constructor is not declared as public (as you can see in the code above).  I can't get to changing that code right just now to try it out, but what do you think?
0
 
TimYatesCommented:
Sounds like it...  Beans need a public constructor with no args...

good luck with it!!

Tim
0
 
aturetskyAuthor Commented:
Thanks, Tim.  I awarded most of the points to rrz since he gave a complete working solution.  However, I do appreciate the time you put in to answer my questions and for sharing your very helpful expertise.
0
 
rrzCommented:
I spent some time trying Tim's idea.  This works  
-------------------------------------------------------------------
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
  ArrayList list = new ArrayList();
  list.add("joe");
  list.add("sue");
%>
<c:set var="list" value="<%=list%>"/>
<c:forEach items="${list}" var="person">
     <jsp:useBean id="person" class="java.lang.String"/>
     <%=person%>
</c:forEach>
-------------------------------------------------------------------
but you never answered my question  
>>${modifyUserFormBean.doctypes}    What type of collection is returned ?
If, you are returning a Map, then the current element is exposed as a java.util.Map.Entry  .  In that case we are "out of luck" because Entry is just an inerface.      
What do you think Tim ?
0
 
rrzCommented:
<%@ page import="java.util.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
  ArrayList list = new ArrayList();
  list.add("joe");
  list.add("sue");
%>
<c:set var="list" value="<%=list%>"/>
<c:forEach items="${list}" var="person">
     <jsp:useBean id="person" class="java.lang.String"/>
     <%=person%>
</c:forEach>
0
 
aturetskyAuthor Commented:
I have modifyUserFormBean.doctypes as a Set<Doctype>  - I am using Java 1.5 in my development env, so it does typed collections.
So each element should be exposed as a Doctype, which I guess would be a bean once I append "public" modifier to the default constructor - (I didn't get to try that out yet.)

Thanks for all your time, rrz
0
 
aturetskyAuthor Commented:
So let me ask you, then.  If this (your code below) works and bean is anything with a public default constructor, then why would you need <c:set var="list" value="<%=list%>"/>.   If you can access it as an attribute of the pageContext, then why can you not do the same with useBean which would check all contexts for anything that has a public no-arg constructor.  (This is the opposite of what I was asking Tim before - I mean now I would almost think Tim's way should work)

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  
<c:forEach items="1,2,3,4,5,6" var="current">
<%
  String current = (String)pageContext.getAttribute("current");
%>
<%=current%>
</c:forEach>
0
 
rrzCommented:
>Tim's way should work)
I think so.    

>why would you need <c:set var="list" value="<%=list%>"/>.      
Please try the following page and ask question aferwards.  
As Tim has pointed out
the useBean tag is the bridge between the two. It creates both.         rrz        


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
  String scriptVar = "scripting variable";
%>
<c:set var="tag" value="set by tag"/>
Scoped variable can be ${tag}.<br/>
Unscoped variable is <%=scriptVar%>.<br/>
?${scriptVar} No, I can't see that.<br/>
<c:set var="scoped" value="<%=scriptVar%>"/>
Now, I can see the scoped ${scoped}.<br/>
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 13
  • 12
  • 7
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now