aspose file tools*
The moose likes Struts and the fly likes logic iterate tag for Float array Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Frameworks » Struts
Bookmark "logic iterate tag for Float array" Watch "logic iterate tag for Float array" New topic
Author

logic iterate tag for Float array

Meera Godse
Greenhorn

Joined: Jan 09, 2007
Posts: 28
Hi all,
I have an ActionForm bean which has a 'Float' array declared in it. On my jsp page, i have added a <logic:iterate> tag to display its values. There is no error while displaying the JSP content. But each of the textbox contains the memory address of the array instead of its value (like this: [Ljava.lang.Float;@1503458)
Initially I had taken a 'float' array but I read on the struts site that the logic iterate tag cannot work on primitive arrays but works well on collections. So I modified it to 'Float' Its still giving the same problem. I do not want the array address to be displayed in the textboxes. They should display the individual values.
my code below:

form bean:
public class RatesForm extends ActionForm {
...
private Float[] zones ;

public RatesForm() {
...
this.zones = new Float[4];
for (int i=0; i <zones.length ; i++)
zones[i] = new Float(0);
}

...setter getter...
}


JSP:
<logic:iterate id="zones" property="zones" name="ratesForm">
<html:text property="zones" />
</logic:iterate>

Am I going wrong anywhere. Pls assist.
thanks.
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
You will need to use "Indexed properties" for this. See this link from the JavaRanch Struts FAQ for details.

In your specific case, add the following methods to your ActionForm:

and change your JSP to:


I'm not entirely sure it will work with the object wrapper Float, but if it doesn't, use the primitive float.

One other suggestion: In Struts, it's better to make all input fields Strings, and then convert them to other data types in your Model objects if you need to. While the above code will work for valid data, if the user enters a value that cannot be converted to a float, Struts will throw an exception. If you use Strings, you can validate the values first, and then convert them to floats in your Model. Another point is that with the above code, you're forced to accept the default formatting of your floats. If you use Strings, you can format the output however you want.
[ January 25, 2007: Message edited by: Merrill Higginson ]

Merrill
Consultant, Sima Solutions
Durgaprasad Guduguntla
Ranch Hand

Joined: Oct 20, 2003
Posts: 99
Originally posted by Merrill Higginson:
One other suggestion: In Struts, it's better to make all input fields Strings, and then convert them to other data types in your Model objects if you need to. While the above code will work for valid data, if the user enters a value that cannot be converted to a float, Struts will throw an exception. If you use Strings, you can validate the values first, and then convert them to floats in your Model. Another point is that with the above code, you're forced to accept the default formatting of your floats. If you use Strings, you can format the output however you want.


Merrill, you are right. But apart from coding ActionForms with String properties on one hand and creating DTO classes with same properties with actual data types on the other hand, does not seems to be nice and also doubling the number of classes, eventhough BeanUtils.copyProperties() is helpful for populating the data. Is there any alternate approach to address this issue?


Thanks,<br />Durgaprasad<br />SCJP1.4, SCWCD1.4, SCBCD1.3,<br />SCEA
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
Durgaprasad,

This is one of the weaknesses of Struts 1. The method you mention of having a separate DTO is really the best way to handle this in Struts 1.

Other frameworks such as JSF, Stripes and Struts 2 make this much easier. They will allow you to use numeric data types, and will automatically validate them, returning a nicely formatted error message, rather than just throwing an exception.
Meera Godse
Greenhorn

Joined: Jan 09, 2007
Posts: 28
Thank you for the prompt reply. I tried your suggestion but it still shows the base address in all the textboxes.(for example:- [Ljava.lang.Float;@bf5555). does not give any error. i know that internally its reading the value as just zones instead of zones[i] & so it shows the address.

As per your second suggestion, I am changing the field to String[]. unfortunately I dont have much time to keep on trying with Float. will try to solve this issue some other day.

if the strings thing works, i will post my reply here.
thanks.
[ January 25, 2007: Message edited by: Meera Godse ]
Meera Godse
Greenhorn

Joined: Jan 09, 2007
Posts: 28
its very strange , but String[] is giving me the same problem ! The address is being displayed in all txtboxes. foll is my code:

JSP:
<logic:iterate id="zone" property="zones" name="RatesForm">
<html:text property="zone" indexed="true"/>
</logic:iterate>


form:
public class RatesForm extends ActionForm {
...
private String[] zones ;

public RatesForm() {
this.zones = new String[4];
for (int i=0; i <zones.length ; i++)
zones[i] = "";
}
...
public String[] getZones() { ... }

public void setZones(String[] zones) { ... }

public String getZone(int index) {
return zones[index];
}
public void setZone(int index,String zone) {
this.zones[index] = zone ;
}

pls help.
[ January 25, 2007: Message edited by: Meera Godse ]
Meera Godse
Greenhorn

Joined: Jan 09, 2007
Posts: 28
I had a similar problem a few days back & Merrill gave me the solution. Here is the link
http://www.coderanch.com/t/55423/Struts/Array-inside-Struts-ActionForm

The only difference here was that the collection contained a user defined object class. So in the 'property' tag i could directly specify the name of individual fields & the respective getter method worked. Here, my String array contains strings & so i do not have a specific name to it. all i want is to retrieve it as zones[i]
Hasnt anyone come across this problem anytime ? pls help.
[ January 25, 2007: Message edited by: Meera Godse ]
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
As I thought more about this problem, I realized that in this situation, you really can't use the indexed="true" property. You have to manipulate the property name yourself so that it is property="zone[0]" for the first iteration, property="zone[1]" for the second iteration, etc.

Try it this way:
Meera Godse
Greenhorn

Joined: Jan 09, 2007
Posts: 28
This worked Merrill. Thank you. But I am not very clear with the approach. Why doesnt indexed=true work in this case.
do you know if this problem been solved in struts 2 ?
[ January 25, 2007: Message edited by: Meera Godse ]
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
The indexed=true only works when you have a collection or array of JavaBeans. When you have an array of Strings or primitives, you have to create the indexed property yourself. I've also found that if you have more than one level of nesting, it's also better just to manually create the property name.

This isn't a problem to be fixed, it's just that the indexed=true was only intended for use with JavaBeans. If you understand how indexed properties work, it's not that much more difficult to create the property name you want than it is to use indexed=true.
Meera Godse
Greenhorn

Joined: Jan 09, 2007
Posts: 28
I understand now. Thank you Merrill.
Jobin Mathew
Ranch Hand

Joined: Oct 17, 2006
Posts: 83
So, for doing this we need 4 methods,

private String[] zones ;

public String[] getZones() { ... }

public void setZones(String[] zones) { ... }

public String getZone(int index) {
return zones[index];
}

public void setZone(int index,String zone) {
this.zones[index] = zone ;
}

am I right?
Also do the names must be like this? ie one set of getters/setters with 's' at the end and the other set must be same as the name of textbox?
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
Yes, that's right.. you need four methods. No, they don't have to be named exacly like this, but it's important to realize that Struts ActionForms sometimes have problems with overloaded methods, so it's best to avoid having a getZones() and a getZones(int index) method. Other than that, you can name them anything you want. For me it makes sense to make the getter/setter pair that accesses the array plural and the pair that accesses a single element singular.
Jobin Mathew
Ranch Hand

Joined: Oct 17, 2006
Posts: 83
Thanks Merrill,

I tried this but getting error.

Exception thrown by getter for property name[1] of bean org.apache.struts.taglib.html.BEAN

Here are the codes,

<html:form action="TextBoxes.do">
<%
for(int i=1;i<5;i++)
{
%>
<html:text property='<%="name["+i+"]"%>'></html:text>
<%
}
%>
<br/> <html:submit></html:submit>



FormBeans is given below

public class TextBoxesForm extends ActionForm
{
String[] names;
public String[] getNames()
{
return names;
}

public void setNames(String names[])
{
this.names = names;
}

public String getName(int index)
{
return names[index];
}

public void setName(int index,String name)
{
this.names[index] = name ;
}
}

I dont understand why this error is coming.
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
First of all, arrays in Java are zero based, so you will want to change your code to:

There's another problem, though. The code you've shown us will work only if your Action class calls setNames() prior to the JSP being displayed and if you specified scope="session" when you defined the action mapping. If the scope is request, you will have to make sure the array is initialized in the constructor. Example:
Jobin Mathew
Ranch Hand

Joined: Oct 17, 2006
Posts: 83
When initializing the array it is working.
But the size of array is dynamic.
So if I add the for loop you specified in the constructor it will work one time only since I give scope as session. But the number of textbox varies according to the selection by the user in the previous page. At this context is this a good solution? How I initialize the array every time with the correct number of items.
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
Originally posted by Jobin Mathew:
But the number of textbox varies according to the selection by the user in the previous page.

If the code you've posted is the actual code you're going to use, this is not true. The size of the array will always be 5. The user could choose to leave some of the text boxes empty, but there will always be five of them.

I'm basing my response on this code that you posted:


If you really are going to have a dynamic number of text controls, you shouldn't use an array at all, because when you instantiate an array, you must specify how large it is. In this case it's best to use one of the Collection classes such as ArrayList. You would then use "lazy initialization" in your getters.

For more information on lazy initialization, study Brent Sterling's excellent example of using indexed properties at this link
Jobin Mathew
Ranch Hand

Joined: Oct 17, 2006
Posts: 83
Hi Merrill,
Thanks a lot. I give the type ArrayList in formbean.
But the values are not persisting when i reload the page.

My Jsp is

<c:forEach var="i" begin="1" end="5">
<br><html:text property="subjects" indexed="true"/>
</c:forEach>

This is my form beans

ArrayList subjects = new ArrayList();

public ArrayList getSubjects()
{
return subjects;
}

public void setSubjects(ArrayList subjects)
{
this.subjects = subjects;
}


So make the data persistent, in addition to above methods, i add one more getter/setter like this,

public String getSubjects(int index)
{
return (String)subjects.get(index);
}

public void setSubjects(int index,String subjects)
{
this.subjects.set(index,subjects);
}


Then the page is not loading and giving error like this,

javax.servlet.ServletException: No getter method for property subjects of bean org.apache.struts.taglib.html.BEAN
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
First of all, if you read the other posts in this thread, you will see that I stated in one of them that you can't use indexed="true" in this case. You must construct the proprety name so that it renders "subject[0]", "subject[1]", etc.

Secondly, ActionForms don't handle overloaded methods very well, so it's best to avoid them. Make your second getter/setter pair getSubect() and setSubject() rather than getSubjects() and setSubjects().

Finally, if your JSP code is going to display exactly 5 text boxes as yours does, what's the point of changing to an arrayList? You may as well just leave it as an array.
Jobin Mathew
Ranch Hand

Joined: Oct 17, 2006
Posts: 83
No the number of textboxes are dynamic. For testing purpose, I hardcoded it. Can you please tell me the flow of these 2 pair of setter/getter.
When the form submits which one is first called, which one calls the other one, like that. I dont get the flow of the extra getter/setter ie the one with index as parameter.
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
Originally posted by Jobin Mathew:
I dont get the flow of the extra getter/setter ie the one with index as parameter.

It works like this: suppose you code this in your JSP:

When the page is being rendered (i.e., when the user first calls the page from a URL) Struts calls getSubject(0) on your ActionForm to display a value for the text box. If getSubject(0) returns the value "xxx", the following will be rendered and sent back to the browser:

Now suppose the user changes the value of the text box to "yyy" and presses the submit button. Struts will now call setSubject(0, "yyy") to set the value of "yyy" in your ActionForm. Does this make sense now?
[ February 07, 2007: Message edited by: Merrill Higginson ]
Jobin Mathew
Ranch Hand

Joined: Oct 17, 2006
Posts: 83
Thanks Meril,

So the setXXX(int,String) is called according to the number of textboxes.
But if we are providing getter/setter of only ArrayList type how it will work. On submitting the form how all the values are populated to ArrayList.
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
But if we are providing getter/setter of only ArrayList type how it will work.


Now we're back to where we started! You began this whole thread trying to create a group of text boxes without using indexed getters/setters and wondering why it didn't work. The main point I've been trying to get across to you in all this discussion is that it will not work at all if you provide only a getter and setter of ArrayList type. You must have an indexed getter and setter in order to use indexed properties.

One thing that may not have been clear to you is that Struts will never call setSubjects(ArrayList). You must call it in an action class prior to displaying the JSP. If The ActionForm is in session scope, it persists as long as the same user is signed on, so the same list of subjects will remain. Here's a flow of events in a sample scenario.

1- The user calls the URL http://myserver.com/myapp/PreparePage.do

2- The PreparePage action class has logic to get a list of subjects from a database and calls setSubjects(ArrayList) on the ActionForm. The ActionForm ArrayList now contains however many subjects were in the database. Let's suppose that in this case there are 15 subjects in the database.

3- In your JSP, you put the following code:

The logic:iterate tag calls getSubjects on your ActionForm bean to get the array list of subjects and then iterates over it. Since there are 15 of them in our example, this tag will iterate 15 times, creating text boxes with property names subject[0] through subject[14]. As I mentioned in my last post, struts calls getSubject 15 times using whatever values are currently in the arraylist to populate the text boxes as they are rendered and displayed to the user.

4- The user changes one or more of the text boxes and presses the submit button. Struts then calls setSubject(index, string) 15 times with 15 different indexes, setting 15 different values in the array list.
[ February 07, 2007: Message edited by: Merrill Higginson ]
Jobin Mathew
Ranch Hand

Joined: Oct 17, 2006
Posts: 83
Thank you very much Merrill.
Jobin Mathew
Ranch Hand

Joined: Oct 17, 2006
Posts: 83
Still I am in the middle of certain problems.
As you stated before I use ArrayList for storing values of dynamic textboxes. Do i need to add empty string to it. Otherwise it is showing exception when the page loads first time.
Exception thrown by getter for property subject[0] of bean org.apache.struts.taglib.html.BEAN
So here also I need to add blank values before using this?

Other problem is that once if I add 7 values and at a later time if only 3 textboxes are appearing, still the size of ArrayList is 7. So I cant write my further logic by using the count of ArrayList. Is there any commonly used way to handle these.
Merrill Higginson
Ranch Hand

Joined: Feb 15, 2005
Posts: 4864
If you're going to use indexed properties, you can't just display the Jsp from a URL. You must call an action class that loads the subjects arraylist with data and then forwards to the JSP. So, you create an Action class called "PreparePage" for example, and somewhere in that action class, you call myForm.setSubjects() and provide it with an ArrayList of subjects. Then, when your JSP is rendered, the getSubject(index) method should run without error.

One other thing to check: Make sure that the action specified in the <html:form> has been set up in the action mapping in struts-config.xml to be associated with the right form bean.
Other problem is that once if I add 7 values and at a later time if only 3 textboxes are appearing, still the size of ArrayList is 7. So I cant write my further logic by using the count of ArrayList. Is there any commonly used way to handle these.

This statement makes no sense at all to me. If you start out with an arraylist of 7, never at any time will your JSP show only 3 text boxes. It will always show 7. Please explain more fully what you mean by this.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: logic iterate tag for Float array