File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Struts and the fly likes Automatic Population of Indexed Fields Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Frameworks » Struts
Bookmark "Automatic Population of Indexed Fields" Watch "Automatic Population of Indexed Fields" New topic
Author

Automatic Population of Indexed Fields

Corey McGlone
Ranch Hand

Joined: Dec 20, 2001
Posts: 3271
Hey folks,

I'm trying to get Struts to automatically populate some data for me from an web form and it's just not working. What I have is this...

A form bean, called CollaborationForm, which has an ArrayList object called comments. The point of this form is for multiple users to collaborate on the data they had entered previously, so there will be more than one comment to display. So, my form bean looks something like this (this is a bit simplified, but it's close):



Now, that ArrayList, allComments, contains nothing but Comment objects. A Comment object isn't very complicated - it only contains a few fields that are all related: the comment, the username of the person who wrote that comment, and whether or not that comment should be saved. So the Comment object looks like this:



Now, in my JSP file, I can easily display all of the comments by doing this:



That prints all of my comments just the way I want. The real problem is when the user submits the form and Struts tries to take this form data and populate my form bean.

The method getAllComments() is being invoked, which returns an empty ArrayList() (because the form bean has not yet been populated). Shortly after that happens, I get an IndexOutOfBoundsException. I assume that Struts is trying to get a given Comment object out of the empty list - causing the exception.

If I add a constructor to my form bean that looks like this:



Then everything works. Of course, this only works if my constructor adds the right number of Comment objects to the ArrayList. Unfortunately, I have no idea how many comments there might be - so this isn't really a solution. I really did it just to help diagnose what's going on.

So any ideas? I'm quite perplexed on this one.

Thanks,
Corey
[ October 12, 2005: Message edited by: Corey McGlone ]

SCJP Tipline, etc.
Vani Bandargal
Ranch Hand

Joined: Oct 06, 2005
Posts: 82
try this getter

let me know if this works or not
[ October 12, 2005: Message edited by: Mark Spritzler ]
Mark Spritzler
ranger
Sheriff

Joined: Feb 05, 2001
Posts: 17250
    
    6

Corey, Corey, Corey.



So if you pass and index to this method that is larger than the size() -1 then you will get an indeax out of bounds exception.

Now to my real comments.

1. Follow Sun's Coding Standards.
2. Put curly braces after the if statement and after the return new Comment(). Second if the index is <= size() you can get the same error because arrays are zero based.
3. Do you really mean >= size()? Because I would assume you would want to pass a valid index that exists, and that second return statement will only run if the index passed is too high for the number of elements in the Array.
4. Why use .toArray()[], when you can just use the get() method of ArrayList.

Mark


Perfect World Programming, LLC - Two Laptop Bag - Tube Organizer
How to Ask Questions the Smart Way FAQ
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4456
    
    6

Corey,

The problem is probably in the setAllComment(int index) method. First check (index >= allComments.size()). If it is, use a loop to add the appropriate number of new Comments. Then you can safely return allComments.get(index). You also might want to write a method resizeAllComments(int newSize) and call it from both the getAllComment and setAllComment methods when the index is out of bounds.


Junilu - [How to Ask Questions] [How to Answer Questions]
Chi Hang Chiu
Greenhorn

Joined: Sep 25, 2004
Posts: 5
Hi Junilu,

You are right. I got your suggestion and create a working example. Thks.

master bean:
public final class A extends ActionForm {
private ArrayList allB = new ArrayList();


public ArrayList getAllBList() {
return allB;
}


public void setAllBList(ArrayList list) {
allB = list;
}


public B getAllB(int index) {
while (index >= allB.size()) {
allB.add(new B());
}
return (B) allB.get(index);
}


public void setAllB(int index, B in) {
if (index >= allB.size()) {
int i = allB.size();
do {
allB.add(new B());
} while (index >= ++i);
}
allB.set(index, in);
}
}

Detail Bean:
public final class B extends ActionForm {
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
private String field = sdf.getInstance().format(new Date());


/**
* Returns the value of field.
*
*@return The field value
*/
public String getField() {
return field;
}


/**
* Sets the value of field.
*
*@param field The value to assign field.
*/
public void setField(String field) {
this.field = field;
}

}

Simple Action:
public final class AAction extends Action {

public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {

A f = (A) form;
B b = new B();
ArrayList al = f.getAllBList();
f.setAllB(al.size(), b);
return (mapping.findForward("input"));
}
}

Simple JSP:

<nested:iterate id="allB" property="allBList" name="AForm">
<nested:text indexed="true" property="field" name="allB"/>
</nested:iterate>

Originally posted by Junilu Lacar:
Corey,

The problem is probably in the setAllComment(int index) method. First check (index >= allComments.size()). If it is, use a loop to add the appropriate number of new Comments. Then you can safely return allComments.get(index). You also might want to write a method resizeAllComments(int newSize) and call it from both the getAllComment and setAllComment methods when the index is out of bounds.
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4456
    
    6

Now that I think about it with a clearer mind (previous post was made early this morning, as you can see, so excuse the brain fart), Struts is probably calling the getAllComment(int index) to get the bean it needs to populate with values from the request parameters. The basic solution is still the same though: you need to resize the allComments list.
Corey McGlone
Ranch Hand

Joined: Dec 20, 2001
Posts: 3271
Hey gang,

I really appreciate the comments, but I'm still having issues. I've updated my method to look like this:



However, I'm still getting the IndexOutOfBoundsException. I should have mentioned it earlier, but my getAllEncounterComment(int index) method isn't actually being called. I've put a breakpoint in that method and it never gets hit. Rather, Struts invokes getAllEncounters() and then throws the exception. According to the stack trace, the exception is being tossed in:

org.apache.commons.beanutils.PropertyUtils.getIndexedProperty(PropertyUtils.java:521)

Any more ideas?

For what it's worth, here's a bit from the stack trace:


[ October 13, 2005: Message edited by: Corey McGlone ]
Corey McGlone
Ranch Hand

Joined: Dec 20, 2001
Posts: 3271
Ok, I think I've found the solution, thanks to this article.

The indexed accessor method needs to match, in name, with the "ID" field of the logic:iterate tag. However, looking back at my original code, my "ID" field actually says allComments, not allComment, so it wasn't hitting my indexed accessor, at all. Rather, it must have been retrieving the entire list (which was empty) and then trying to access the individual object within that list on its own, causing the IndexOutOfBoundsException.

So, anyway, it appears to be working, now that I've changed my JSP to look like this:



For some reason, the checkbox doesn't seem to be populating properly, but I'll look into that. For now, I'm just happy to see that my bean is populating properly.

Thanks again for the help, everyone.
Corey McGlone
Ranch Hand

Joined: Dec 20, 2001
Posts: 3271
I took a quick look at the checkboxes and I can't understand why they're not populating properly. I'm testing with 2 comments in my list. So, based on that, the "setSave" method on my Comment object should be invoked twice - once for each Comment. However, setSave is being invoked only once. The other property methods, setComment and setIdentifiedBy, are being invoked twice, once with each value. Any ideas why my setSave method (which stores the property of the checkbox) would be called only once? It makes no sense to me.
Karthik Jay
Greenhorn

Joined: Apr 09, 2006
Posts: 1
Corey,
Did you find solution to your problem?.

All,
I have strange problem in my struts page. I have 10 text input box but last 2 text are not getting saved. Its returning null all the time. Any help would really be appreciated. Thanks.

<TABLE id="tblHeaderVBY" border="0" width="100%" cellpadding="0"
cellspacing="0" nowrap>
<THEAD>
<TR valign="middle">
<TD nowrap width="40%">Attribute Name</TD>
<TD nowrap width="15%">Default Value</TD>
<TD nowrap width="15%">Behavior Code 1</TD>
<TD nowrap width="15%">Behavior Code 2</TD>
<TD nowrap width="15%">Behavior Code 3</TD>
</TR>
</THEAD>
<TR>
<TD align="left" width="40%" style="a11">attr1<INPUT
type="hidden" name="attr[0].attributeName" value="attr1"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[0].defaultValue" size="10" value=""></TD>

<TD align="left" width="15%"><SELECT
name="attr[0].behaviorCD1">
<OPTION value=""></OPTION>
<OPTION value="1" selected="selected">Value1</OPTION>
<OPTION value="2">Value2</OPTION>
</SELECT></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[0].behaviorCD2" size="10" value="2"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[0].behaviorCD3" size="10" value="0"></TD>
</TR>

<TR>
<TD align="left" width="40%" style="a11">attr2<INPUT
type="hidden" name="attr[1].attributeName" value="attr2"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[1].defaultValue" size="10" value=""></TD>

<TD align="left" width="15%"><SELECT
name="attr[1].behaviorCD1" class="formtext">
<OPTION value=""></OPTION>
<OPTION value="1">Value1</OPTION>
<OPTION value="2">Value2</OPTION>
<OPTION value="3" selected="selected">Value3</OPTION>
</SELECT></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[1].behaviorCD2" size="10" value="2"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[1].behaviorCD3" size="10" value="0"></TD>
</TR>

<TR >

<TD align="left" width="40%" style="a11">attr3<INPUT
type="hidden" name="attr[2].attributeName" value="attr3"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[2].defaultValue" size="10" value=""></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[2].behaviorCD1" size="10" value="0"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[2].behaviorCD2" size="10" value="0"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[2].behaviorCD3" size="10" value="0"></TD>
</TR>

<TR >

<TD align="left" width="40%" style="a11">attr4<INPUT
type="hidden" name="attr[3].attributeName"
value="attr4"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[3].defaultValue" size="10" value=""></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[3].behaviorCD1" size="10" value="0"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[3].behaviorCD2" size="10" value="0"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[3].behaviorCD3" size="10" value="0"></TD>
</TR>

<TR >

<TD align="left" width="40%" style="a11">attr5<INPUT
type="hidden" name="attr[4].attributeName"
value="attr5"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[4].defaultValue" size="10" value=""></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[4].behaviorCD1" size="10" value="0"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[4].behaviorCD2" size="10" value="0"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[4].behaviorCD3" size="10" value="0"></TD>
</TR>

<TR >

<TD align="left" width="40%" style="a11">attr6<INPUT
type="hidden" name="attr[5].attributeName" value="attr6"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[5].defaultValue" size="10" value=""></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[5].behaviorCD1" size="10" value="0"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[5].behaviorCD2" size="10" value="0"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[5].behaviorCD3" size="10" value="0"></TD>
</TR>



<TR >



<TD align="left" width="40%" style="a11">attr7<INPUT
type="hidden" name="attr[6].attributeName" value="attr7"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[6].defaultValue" size="10" value=""></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[6].behaviorCD1" size="10" value="0"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[6].behaviorCD2" size="10" value="0"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[6].behaviorCD3" size="10" value="0"></TD>
</TR>



<TR >



<TD align="left" width="40%" style="a11">attr8<INPUT
type="hidden" name="attr[7].attributeName" value="attr8"></TD>

<TD align="left" width="15%"><SELECT
name="attr[7].defaultValue" class="formtext">
<OPTION value=""></OPTION>
<OPTION value="Value1">Value1</OPTION>
<OPTION value="Value2">Value2</OPTION>
<OPTION value="Value3">Value3</OPTION>
</SELECT></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[7].behaviorCD1" size="10" value="0"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[7].behaviorCD2" size="10" value="0"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[7].behaviorCD3" size="10" value="0"></TD>
</TR>

<TR >

<TD align="left" width="40%" style="a11">attr9<INPUT
type="hidden" name="attr[8].attributeName" value="attr9"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[8].defaultValue" size="10" value=""></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[8].behaviorCD1" size="10" value="0"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[8].behaviorCD2" size="10" value="0"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[8].behaviorCD3" size="10" value="0"></TD>
</TR>

<TR>

<TD align="left" width="40%" style="a11">attr10<INPUT
type="hidden" name="attr[9].attributeName" value="attr10"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[9].defaultValue" size="10" value=""></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[9].behaviorCD1" size="10" value="0"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[9].behaviorCD2" size="10" value="0"></TD>

<TD align="left" width="15%"><INPUT type="text"
name="attr[9].behaviorCD3" size="10" value="0"></TD>
</TR>

</TABLE>
[ April 09, 2006: Message edited by: Karthik Jay ]
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Automatic Population of Indexed Fields