7

I have following code:

<s:iterator value="reviews">

    <img src="<s:property value="#request.restaurant.portalImage.url"  />" />

    <s:property value="user.firstName" />
    <s:property value="user.lastName" />
    <s:property value="rating" />
    <s:property value="review" />

</s:iterator>

reviews is a list of review objects which contain details of a review, such as rating and name of user.

My problem is that I'm not able to access any of the objects present on the ValueStack within the loop.

Outside the loop <s:property value="#request.restaurant.portalImage.url" /> works correctly. But within the loop it prints null.

AFAIK an iterator pushes it's collection on the ValueStack so that all OGNL expressions resolve against it. But I've used # which means I'm explicitly specifying the root object for resolution.

Why is it still not working?

informatik01
  • 16,038
  • 10
  • 74
  • 104
Monika Michael
  • 1,274
  • 5
  • 13
  • 24

4 Answers4

2

I just spent my whole afternoon fighting against a similar issue. In my case, the issue was that my iterator variable (In your case reviews) had a field with the same name as the outer variable.

No matter how hard I tried to break out of the local stack of the iterator, it would not access the outer variable.

If your reviews iterator has a field called restaurant its going to override the outer restaurant variable, no matter how hard you try :(

The solution I found was to simply rename the outer variable. (eg: theRestaurant)

Once I renamed it, it was no longer clashing with the inner variable, and I was able to access it from within the iterator.

Lenny Markus
  • 3,398
  • 2
  • 24
  • 30
  • 1
    Thanks, this helped a lot ! Another solution is to store the "outer value" in a local variable BEFORE the iterator using the tag , and refering to this local variable instead ( or ${theRestaurant}). – mmuller Feb 20 '14 at 09:15
1

You should change it like below:

 <s:iterator value="reviews" var="varrequest">

   <img src="<s:property value="#varrequest.restaurant.portalImage.url"  />" />

   <s:property value="#varrequest.user.firstName" />
   <s:property value="#varrequest.user.lastName" />
   <s:property value="#varrequest.rating" />
   <s:property value="#varrequest.review" />

 </s:iterator>

Using a iterator reference variable to fetch the unique index object.

MohanaRao SV
  • 1,117
  • 1
  • 8
  • 22
Phani
  • 5,319
  • 6
  • 35
  • 43
  • That is the variable which holds the current indexed object for you to access.Please look at this documentation for more info. http://struts.apache.org/2.0.11/docs/iterator.html – Phani Apr 12 '12 at 11:26
  • The current indexed object will be a review object from the list. I want to access something outside the list. A restaurant object that is stored in request scope. – Monika Michael Apr 12 '12 at 11:28
  • @MonikaMichael Is that the same URL to be mapped for all the entries in the iterator? – Phani Apr 12 '12 at 11:30
  • Yup, one restaurant logo, multiple reviews. – Monika Michael Apr 12 '12 at 11:33
  • Declare a variable outside and use it rather going through the object graph every time in the loop which is costlier. – Phani Apr 12 '12 at 11:36
1

I am not sure what object is contained in the collection you are using in the Iterator.As per the iterator when you iterate the collection using the S2 iterator tag it will push the object on the top of value stack, which means, say you have collection of user object on which you are iterating like

<s:iterator value="userCollection">

</s:iterator>

so when this will iterate, S2 iterator will push the user object on top of value stack and if we want to refer to the name property of user object, all we need to refer to the name property

<s:property name="userName"/>

since OGNL will try to resolve userName in the value stack and we already have user object as top level object in value stack.I suggest to go through the Iterator tag documentation and how it push values

Umesh Awasthi
  • 23,407
  • 37
  • 132
  • 204
  • top level object doesn't matter. # is used for explicitly specifying the object to resolve against no matter whether it's on top or not. – Monika Michael Apr 12 '12 at 11:42
0

I think it resolves your issue

s:iterator value="reviews" status="position">
   <img src="<s:property value="#request.restaurant.portalImage.url"/>"/>
   <s:property value="#position.user.firstName"/>
   <s:property value="#position.user.lastName"/>
   <s:property value="#position.rating"/>
   <s:property value="#position.review"/>
 </s:iterator>

your requirement is little confusing

Daya
  • 724
  • 3
  • 14
  • 32