Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Using nested tags

Status
Not open for further replies.

doubledown32

Programmer
Sep 19, 2001
9
US
Hello everybody-

This is officially my first post. I'm new to developing with struts and am trying to use nested tags without a form.

In my action, I have a sql statement that returns a list of objects. Within each object in the list, there can be a number of child objects some of which can be other Lists of objects. Once the original list of objects has been returned, I put it into scope like this:

request.setAttribute("resultsList", resultListObj);

So now in my jsp what I want to do is iterate through the List of objects and then iterate through the child objects as well. After I set the root nested object to be this request attribute (List), how do I begin to iterate through the list? In other words, how do I get access to the first object in the list in order to serve as the point of reference for any subsequent iteration calls within this root nested tag? When I try to use the <nested:iterate> tag on the List, a get a nullPointerException. When I simply set the request attribute to be an object instead of a list, I don't have any problems. But I need this attribute to be a list as there can be 1 to many objects returned by the sql statement. Here is a dried out version of what I have (unnecessary table tags removed for simplicity)
Code:
<nested:root name="resultsList">
<nested:iterate name="resultsList">

<nested:write property="num" /> /* a property of parent obj in list */
<nested:iterate property="line"> /* a line child object */
<nested:write property="lineNum" /> /* a prop of child object */
</nested:iterate>

</nested:iterate>
</nested:root>
Any help would be much appreciated...thanks!!!

Kris
 
You do not need the nested:root tag in your case, you can either take out the nested:root tag

Code:
<nested:iterate name="resultsList">

<nested:write property="num" /> /* a property of parent obj in list */
<nested:iterate property="line"> /* a line child object */
<nested:write property="lineNum" /> /* a prop of child object */
</nested:iterate>

</nested:iterate>

or keep the nested:root tag, but the first nested:iterate tag should be refereing the parent, which is the root in this case:

Code:
<nested:root name="resultsList">
<nested:iterate name="./">

<nested:write property="num" /> /* a property of parent obj in list */
<nested:iterate property="line"> /* a line child object */
<nested:write property="lineNum" /> /* a prop of child object */
</nested:iterate>

</nested:iterate>
</nested:root>
 
Thanks for the prompt response.

I've tried both solutions, but am still receiving errors. If I omit the <nested:root ...> tag and only leave the <nested:iterate ...> tag, I still receive the nullPointerException error. When I keep both tags, but changed the reference in the iterate tag to <nested:iterate name="./">, I receive an error saying that the bean "./" could not be found in any scope.

When I simply use <nested:root> without trying to iterate, I am able to pull back the values in the first object. I know that the bean is populated correctly. Is there anything else I can try?

I'm not even going down any levels...I'm just trying to display the properties in the parent object just to get started. It doesn't seem like the iterate tag can find the first object in the list. Any ideas?

Code:
<nested:iterate name="POLineResults">
<tr>
<td colspan=6 align="right">
<table border=0 cellpadding=1 cellspacing=1 width=520>
<tr bgcolor="cccccc" >	
<td width="260" align="left">&nbsp;&nbsp;NESTED NUM</td>
<td width="260" align="left">&nbsp;&nbsp;NESTED SENT DATE</td>
</tr>
<tr>
<td width="260" align="left" valign="top">&nbsp;&nbsp;<nested:write property="num" /></td>
<td width="260" align="left" valign="top">&nbsp;&nbsp;<nested:write property="sentDate" format="MM/dd/yyyy" /></td>
</tr>
<tr>
<td colspan=5 align="right">
</td>
</tr>
</table>
</td>
</tr>
</nested:iterate>

Thanks!

Kris
 
For "iterate" to work, the property must implement Collection, e.g. ArrayList, Set, LinkedList...

In order word, your "POLineResults" must implements Collection.

Is you "POLineResults" is an ArrayList or an Object that implements Collection?
 
Hi-

POLineResults is a List.

The weird thing is that I can use the <logic:iterate> tag just fine, but when I try to use the <nested:iterate> tag, I receive the nullPointerException.

One thing that I have been able to do is set the <nested:root> to be a PO object. POLineResults is basically a List of PO objects. If I just reference one po object as my root, all other calls to <nested:iterate> for child objects that may be lists are performed successfully. So my only problem is being able to successfully iterate through the parent POLineResult list of objects.

Do I need to reference the original list in some special way. The only thing I can think of is that any other list within this hierarchy of objects has a getter that returns the list. This isn't true with the parent POLineResults object because I'm not referencing an object before I try to get access to this list. I'm just really confused at this point.

Any ideas?

Here is what I have been able to do:

Code:
		<!-- Need to Iterate through the POs -->
        <!-- Set one PO Object as root just to test -->
		<nested:root name="purchaseOrderObj">
			<tr>
				<td colspan=6>
					<table border=0 cellpadding=1 cellspacing=1 width=520>
						<tr bgcolor="cccccc" >	
							<td width="260">NESTED NUM</td>
							<td width="260">NESTED SENT DATE</td>
						</tr>
						<tr>
							<td width="260"><nested:write property="num" /></td>
							<td width="260"><nested:write property="sentDate" /></td>
						</tr>
						<nested:nest property="line">
							<tr bgcolor="cccccc">
								<td width="260">NESTED LINE QTY</td>
								<td width="260">NESTED LINE NUM</td>
							</tr>
							<tr>
								<td width="260"><nested:write property="qty" /></td>
								<td width="260"><nested:write property="lineNum" /></td>
							</tr>
							<nested:iterate property="invoiceList">
								<tr bgcolor="cccccc">
									<td width="260">NESTED VEND INV NUM</td>
									<td width="260">NESTED VEND INV NUM ALPHA</td>
								</tr>
								<tr>
									<td width="260"><nested:write property="num" /></td>
									<td width="260"><nested:write property="numAlpha" /></td>
								</tr>
								<nested:nest property="invLine">
									<tr bgcolor="cccccc">
										<td width="260">NESTED VEND INV LINE NUM</td>
										<td width="260">NESTED VEND INV LINE PART</td>
									</tr>
									<tr>
										<td width="260"><nested:write property="lineNum" /></td>
										<td width="260"><nested:write property="partNumber" /></td>
									</tr>
								</nested:nest>
							</nested:iterate>
						</nested:nest>
						<tr>
							<td colspan=5></td>
						</tr>
					</table>
				</td>
			</tr>
		</nested:root>

But I can have 1 to many POs so I will need to iterate through that list... :-
Thanks so much!

Kris
 
This is because POLineResults is alreay a list, you don't need to use nested tag to get it. If there this is a container that holds POLineResults, then you can use nested tag. e.g. say you have a Result bean that holds POLineResuts, then you can do
Code:
<nested:root name="Result">
   <nested:iterate property="POLineResults">
      .....
   </nested:iterate>
</nested:root>

nested tag reference property of the current bean. If there is no current bean being referenced, there is no point to use nested. you just use regular logic:iterate and set POLineResults as the current bean. Then within of the loop logic:iterate tag, you can use nested tag to get it child property. The problem that you have is trying to set a List as current bean for nested, but there is no getter method for a List to return itself. If a there is getMyself() that return itself in List, then you can do:
Code:
<nested:root name="POLineResults">
   <nested:iterate property="./myself">
   </nested:iterate>
</nested:root>

Assuming your POLineResutls is a list of PurchaseOrderObj, then you would do something like:
Code:
<table>
<logic:iterate id="purchaseOrderObj" name="POLineResults">
  <tr>
    <td width="260"><nested:write property="num" /></td>
    <td width="260"><nested:write property="sentDate" /></td>
  </tr>
  <nested:nest property="line">
    <tr bgcolor="cccccc">
      <td width="260">NESTED LINE QTY</td>
      <td width="260">NESTED LINE NUM</td>
    </tr>
    <tr>
     <td width="260"><nested:write property="qty" /></td>
     <td width="260"><nested:write property="lineNum" /></td>
    </tr>
    <nested:iterate property="invoiceList">
      ...
    </nested:iterate>
</logic:iterate>
Hope that clear your problem.
 
Hi-

I thought that last post would have cleared my problem...it definitely made sense to me. When I tried to iterate using <logic:iterate> and then nest the other properties I'm trying to get at, I receive an error saying:

[Servlet Error]-[Cannot find bean in any scope]: javax.servlet.jsp.JspException: Cannot find bean in any scope

It seems like the original bean being referenced in the logic:iterate tag is not recognized and therefore cannot be used as a reference for the nested property.

I also tried wrapping the the block of code with a <nested:root name="POLineResults"> like this:

Code:
<nested:root name="POLineResults">
<logic:iterate name="POLineResults" id="POLine">
	<tr>
		<td colspan=6 align="right">
			<table border=0 cellpadding=1 cellspacing=1 width=520>
				<tr bgcolor="yellow" >	
					<td width="260">PARENT NUM</td>
					<td width="260">PARENT SENT DATE</td>
				</tr>
				<tr>
					<td width="260"><bean:write name="POLine" property="num" /></td>
					<td width="260"><bean:write name="POLine" property="sentDate" /></td>
				</tr>
				<nested:nest property="line">
					<tr>	
						<td width="260">NESTED LINE NUM</td>
						<td width="260">NESTED SENT QTY</td>
					</tr>
					<tr>
						<td width="260"><nested:write property="lineNum" /></span></td>
						<td width="260"><nested:write property="qty" /></td>
					</tr>						
				</nested:nest>
			</table>
		</td>
	</tr>		
</logic:iterate>
</nested:root>

That didn't work either. I received an error reading:

[Servlet Error]-[No getter method for property line.lineNum of bean POLineResults]: javax.servlet.jsp.JspException: No getter method for property line.lineNum of bean POLineResults

Could something else be wrong? Thanks for your help on this.

-Kris
 
Sorry for the confusion. I myself was confused as well. After did some experiment, this code should work

Code:
<logic:iterate name="POLineResults" id="POLine">
<nested:root name="POLine">
  <tr>
    <td colspan=6 align="right">
       <table border=0 cellpadding=1 cellspacing=1 width=520>
         <tr bgcolor="yellow" >    
            <td width="260">PARENT NUM</td>
            <td width="260">PARENT SENT DATE</td>
         </tr>
         <tr>
            <td width="260"><nested:write property="num" /></td>
            <td width="260"><nested:write property="sentDate" /></td>
         </tr>
      <nested:nest property="line">
         <tr>    
           <td width="260">NESTED LINE NUM</td>
           <td width="260">NESTED SENT QTY</td>
         </tr>
         <tr>
            <td width="260"><nested:write property="lineNum" /></span></td>
            <td width="260"><nested:write property="qty" /></td>
         </tr>                        
      </nested:nest>
      </table>
    </td>
  </tr>        
</nested:root>    
</logic:iterate>
 
This works great, thanks. I knew it had to be something close to what we were talking about. I actually think I had something similar to this before, but incorrectly referenced the original logic:iterate tag therefore it wouldn't work. Thanks for all of your help! [thumbsup]

-Kris
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top