Struts 2 s:iterator: How to avoid name clashes? - struts2

As far as I see, s:iterator always pushes the current item into the OGNL Value Stack, even if I use the var attribute. This means that all the members of the current item become top-level OGNL variables inside the loop, potentially hiding the properties of the Action:
<s:property value="owner" /> <%-- From the Action --%>
<s:iterator value="projects" var="project">
<s:property value="#project.owner" /> <%-- From the project, obviously --%>
<s:property value="owner" /> <%-- Ops, also from the project! --%>
</s:iterator>
<%-- (Fun(?) fact: #project.owner is still accessible here) --%>
The objects we iterate through (often with multiple levels of nesting) has many properties, and their number can grow later. The danger of accidentally hiding properties is very real, and worse, adding properties to JavaBeans can break pages that were once working.
Am I missing something here? How do you iterate through complex objects with Struts 2 + JSP?

Related

Numbers not formatted properly in Struts 2

I am using following syntax to display a value in a proper number format, e.g. 1,250.00.
<s:property value="%{getText('{0,number,#,##0.00}',#plan.amount)}" />
However, it is not working. The plan is an object with a property amount.
First of all, if you want to display multiple values from a list, you need an iterator;
second, if plan is a list in the action with a getter method
public List<Something> getPlan() { return plan; }
then you don't have to put the # ahead of the variable.
The right code for your case would be:
<s:iterator value="plan">
<s:property value="getText('{0,number,#,##0.00}',{amount})" />
</s:iterator>
There's a related Q&A on the topic.
EDIT
Since you have
<s:iterator value="list" var="plan" status="status">
<div class="values">
$ <s:property value="%{getText('{0,number,#,##0.00}',#plan.amount)}"/>
</div>
</s:iterator>
Then it should be:
<s:iterator value="list">
<s:property value="getText('{0,number,#,##0.00}',{amount})" />
</s:iterator>
If the value is printed like 1250.00 then it's not formatted properly. The method getText() has many overloaded methods and which method is used is determined by the parameter's types and count.
To pass arguments to the getText() method you can use OGNL list construction {}. And the arguments should be listed as single values, not "list of object". Perfectly it should be list of Double with one element inside the list.
<s:set var="amount" value="%{1250.0}"/>
<s:property value="%{getText('{0,number,#,##0.00}',{#amount})}" />

How to display pre-checked checkboxes inside iterator in Struts 2

I need to iterate through List<String>, each element has s:checkbox.
I have defined one list in Action layer to keep selected elements.
Using my code I can submit my form and capture selected values in action layer. But, some of the checkboxes must be pre-checked. I cannot display pre- checked status when loading the page.
Value1 contains list of String objects.
functionCheckBoxList - The list I have defined to keep checked element
While loading, I added some element to functionCheckBoxList that belongs to Value1.
But still does not show pre-checked status in the page.
<s:iterator value="value1" var ="functionName">
<s:checkbox fieldValue="%{#functionName}" name="functionCheckBoxList"
value="%{#functionName}" theme="simple" >
</s:checkbox>
</s:iterator>
Note: I know how to do it using s:checkboxlist but can't here as I need special format in the iteration.
i could find a solution for my problem, i would like to share it with everyone.
<s:iterator value="value1" var ="functionName">
<s:checkbox fieldValue="%{#functionName}" name="functionCheckBoxList"
value="%{#functionName in functionCheckBoxList}" theme="simple" >
</s:checkbox>
</s:iterator>

Preserving objects through actions in Struts2

Can I preserve object across actions in Struts2 without using session?
I'm working on a Struts2 project and curious if there are some ways to preserving object
value once an action is ended.
What I'm trying to do is:
Calling an action to read from an uploaded file and prepare its contents as a list of objects.
Then I display the list as an example for the user.
Then the user can click on a submit button to call an action to process the list which is created from the first action.
Usually the list would be lost once the action is end. So, I have to store the list as a session, but I think it should have some better methods to achieve the I'm working on.
If you want to preserve data across requests the session is the normal mechanism for doing so.
If you don't use the session you'd need to essentially duplicate its functionality to maintain the data associated with the current user/conversation.
If you need to preserve the List, then you have to use the Session.
But if you (if I've understood your problem) just need to handle the List through
ActionOne (that creates the List) ->
JSPOne (thast shows the List to the user) ->
ACtionTwo (that receives the List from JSPOne and does some business with it)
, without having to worry about the fact that the user can change the List client-side (for example manipulating the web page with FireBug), then you don't need the session.
You just need the List object to be declared on ActionOne and ActionTwo (with getters and setters, at least the getter on ActionOne and at least the setter on ActionTwo), and to include List name and index on name attribute of JSP tags.
If you just draw it (like with <s:property/> tag), instad of using some tag that will post the value, like <s:textfield />, then just use an <s:hidden /> to post te value.
For example, if you have:
List<MyObject> myList //with getters and setters
and assuming that MyObject has id and value fields (with getters and setters),
in JSP instead of
<s:iterator value="myList" >
<s:property value="id"/>
<s:textfield name="value"/>
</s:iterator>
use
<s:iterator value="myList" status="ctr" >
<s:hidden name="myList[#ctr.index].id" value="id"/>
<s:property value="id"/> <!-- no need here, you won't post this -->
<s:textfield name="myList[#ctr.index].value" value="value" />
</s:iterator>
You will eventually validate a List like this throught the Visitor Validator (somewhewre in the future after all the rest is done :)
Enjoy

struts2 iterator tag - iterating over a collection of collections

I am new to struts 2 and am losing my mind over iterating a collection of collections in my JSP using the iterator tag.
My action class exposes a List (parent) which in turn contains 4 more lists (children). Each child list contains 5 domain objects (e.g. User).
In my JSP, i need to display the User.Name after iterating over the collections. I am able to iterate over the parent collection but cannot get to the child lists. They are anonymous lists and are not exposed by a specific name (i.e. a getter is not available).
<s:iterator value="usrList" var="refParent">
<ul>
<s:iterator value="#refParent.columns" var="usr">
<li>
<s:property value="#usr.Name"/>
</li>
</s:iterator>
</ul>
</s:iterator>
The outer iterator results in 4 <ul> tags but each of those tags are empty i.e. none of the <li> tags are displayed.
All the examples that i see are accessing specific named Collections (e.g. User.PhoneList) but none of them seem to demonstrate this particular behavior.
Any help is greatly appreciated
I think i finally figured it out from one of the Iterator-tag examples (thanks to Umesh and Quaternion). I totally missed that one and did not read through the entire example using top.
<s:iterator value="usrList">
<ul>
<s:iterator value="top">
<li>
<s:property value="Name"/>
</li>
</s:iterator>
</ul>
</s:iterator>
Please try this example from this link
<table>
<s:iterator value="allCities" id="cities">
<s:iterator value="#city.phoneNumbers" id="number">
<tr>
<td>
<!-- Accessing the city name through the city variable -->
<s:property value="#city.name" />
</td>
<td>
<!-- Accessing the objects inside the phone number object through the number variable -->
<s:property value="#number.prefix" />
</td>
<td>
<s:property value="#number.rate" />
</td>
</tr>
</s:iterator>
</s:iterator>
</table>
Struts2 Iterator tag a simple enough and work in a very simple manner.So if you have Collection of Collection or what ever structure think how you will iterator them in a simple Java application , same will apply for the S2 iterator tag, but at same time it will give you more flexibility as well configurations.
In Short you need nested iterator tag.When S2 iterator tag iterate objects it will place current object on the top of value stack and you can easily access that tag in your JSP code.
Since in your code Top level object will be a Collection you need to iterate that again like
<s:iterator value="firstCollection">
<s:iterator value="firstCollection>
/ do what you want here
</iterator>
Since while iterating object will be at top of stack you can refer to that tag directly without any reference.
i Suggest you to have look at following official documents
iterator
iterator-tag-examples

Struts 2 List of List access

I wonder if someone can help.
Background Architecture:
I have an application which contians many areas which have many specific questions, where these questions contian progress
So at a high-level view there can be many applications. A user is associated to maybe many applications.
So I have a list of applications and I can quite easliy iterate my way through and get its relevant details. But when it comes to accessing each specific area to get question progress for some reason it does not work out form me.
So here is logic I want:
for the applications
display its details
for each area(applicaitonId)
display each its completion progress
so to translate to struts I have this
<s:iterator id="app" value="appList" status="row">
<s:iterator id="qsp" value="questionProgessList[%{#row.index}]" status="status">
so applist is the list of all applications with its own getter/setter && questionSetProgress is defined by:
List<ApplicationQuestionSetProgress> getQuestionProgressList(final int index)
or
List> getQuestionProgressList()
So trying in many ways to access the list has proved futile I have tried:
<s:iterator id="qsp" value="questionProgessList">
<s:property />
</s:iterator>
with this:
List<List<ApplicationQuestionSetProgress>> getQuestionProgressList()
but no joy
I've also tried using the iterator index to call the method but it just does not work out.
List<ApplicationQuestionSetProgress> getQuestionProgressList(final int index)
i.e.
<s:iterator id="qsp" value="questionProgessList[%{#row.index}]" status="status"> or <s:iterator id="qsp" value="questionProgessList(%{#row.index})" status="status">
any hints or tips??
TIA
Considering you have something like
List<ApplicationQuestionSetProgress> getQuestionProgressList(final int index)
Use this
<s:iterator var="qsp" value="questionProgessList[#row.index]" status="status">
You mentioned the following method:
List<List<ApplicationQuestionSetProgress>> getQuestionProgressList()
But you mentioned that the action needed to get a list of "applications" where each contained among its properties a list of "areas".
As such I would name that method:
List Applications getApplications(){
return this.applications;
}
The form of a JSP to extract all properties would be:
<s:iterator value="applications">
<s:property value=applicationsProperty1"/>
<s:property value="applicationsProperty2"/>
...
<s:iterator value="areas">
<s:property value="areasProperty1"/>
<s:property value="areasProperty2"/>
...
<s:iterator value="progress">
<s:property value="progressProperty1"/>
<s:property value="progressProperty2"/>
...
</s:iterator>
</s:iterator>
</s:iterator>

Resources