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]