Date: 2004-09-30T15:57:57
Editor: NiallPemberton <[EMAIL PROTECTED]>
Wiki: Apache Struts Wiki
Page: StrutsCatalogLazyList
URL: http://wiki.apache.org/struts/StrutsCatalogLazyList
no comment
New Page:
There are two frequent issues the confront people when dealing with populating a
collection of beans in an ActionForm.
* How can I generate the appropriate html using the struts taglibs?
* I have a request scoped ActionForm and am getting an "index out of range" error
when I submit the form - what do I do?
The ''Indexed Properies'' section below deals with generating the html and the ''Lazy
List'' section shows possible solutions for avoiding the "index out of range" error.
== Indexed Properties ==
Struts html tags have an ''indexed'' attribute which will generate the appropriate
html to populate a collection of beans when the form is submitted.
For example the following jsp...
{{{
<html:iterate name="skillsForm" property="skills" id="skills">
<html:text name="skills" property="skillId" indexed="true"/>
</html:iterate>
}}}
...will generate the following html
{{{
<input type="text" name="skills[0].skillId value="..."/>
<input type="text" name="skills[1].skillId value="..."/>
....
<input type="text" name="skills[n].skillId value="..."/>
}}}
When the form is submitted BeanUtils will first call the getSkills(index) method to
retrieve the indexed bean followed by setSkillId(..) on the retrieved bean.
== Lazy List Behaviour ==
A common problem with indexed properties, is that people then get "index out of range"
errors with ActionForms that are in Request scope. The indexed property (List or
Array) needs to be able to automatically ''grow'' during the ActionForm population
process. The key to achieving this is in the getXXXX(index) method.
The following sections show three examples of how to achieve lazy list processing.
=== Hand Cranking lazy List in the ActionForm ===
{{{
public class SkillActionForm extends ActionForm {
protected List skills = new ArrayList();
public List getSkills() {
return skills;
}
public void setSkills(List skills) {
this.skills = skills;
}
public SkillBean getSkills(int index) {
// automatically grow List size
while (index >= skills.size()) {
skills.add(new SkillBean());
}
return skills.get(index);
}
}
}}}
=== Using Commons Collections for lazy Lists ===
Commons collections have a lazy list decorator which automatically grows the list when
the get(int) method is called. In the example below the ActionForm implements the
Factory interface, providing the create() method to populate an entry in the List.
{{{
import org.apache.commons.collections.Factory;
import org.apache.commons.collections.list.LazyList;
public class SkillActionForm extends ActionForm, implements Factory {
protected List skills = LazyList.decorate(new ArrayList(), this);
public List getSkills() {
return skills;
}
public void setSkills(List skills) {
this.skills = skills;
}
public SkillBean getSkills(int index) {
return skills.get(index);
}
// 'Factory' method for LazyList
public Object create() {
return new SkillBean();
}
}
}}}
=== LazyDynaBean / LazyValidatorForm ===
'''N.B.''' Solutions here require '''Struts 1.2.4''' and '''Bean Utils 1.7.0'''
[http://jakarta.apache.org/commons/beanutils/commons-beanutils-1.7.0/docs/api/org/apache/commons/beanutils/package-summary.html#dynamic.lazy
LazyDynaBean] in [http://jakarta.apache.org/commons/beanutils/ Commons BeanUtils] has
the ''lazy'' List type processing.
[http://www.niallp.pwp.blueyonder.co.uk/#lazydynabean LazyValidatorForm] is built
using the BeanUtils LazyDynaBean and can be used by simply configuring it through the
struts-config.xml.
{{{
<form-beans>
<form-bean name="skillForm" type="org.apache.struts.validator.LazyValidatorForm>
<form-property name="skills" type="java.util.ArrayList"/>
</form-bean>
</form-beans>
}}}
In fact using Arrays (rather than Lists) a LazyDynaBean can be used directly, in the
following way:
{{{
<form-beans>
<form-bean name="skillForm" type="org.apache.commons.beanutils.LazyDynaBean">
<form-property name="skills" type="myPackage.SkillBean[]"/>
</form-bean>
</form-beans>
}}}
Struts 1.2.4 will ''wrap'' the LazyDynaBean in a BeanValidatorForm automatically.
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]