I'm going crazy over what should be a simple procedure. I want to add an element to a ListView's model, but when I try, it throws an IndexOutOfBoundsException.
I have a form [1] which contains a ListView and an AjaxSubmitLink which adds items to the ListView. The only funny thing you might notice with the form is that ListView's model is employerInfoModel.contactPoints, while the AjaxSubmitLink is adding items to employerInfoModel.contactPointsSet. This is because employerInfo's collection of contactPoints is actually a set, but ListView needs them as a list. In order to get around this, I have two getters and setters, one that gets the set directly, and one that converts to and from a list [2]. [1] - public class ContactInfoForm extends Form<EmployerInfo> { WebMarkupContainer contactPointsContainer; public ContactInfoForm(String id, CompoundPropertyModel<EmployerInfo> model) { super(id, model); contactPointsContainer = new WebMarkupContainer("contactPointsContainer"); ListView<ContactPoint> contactPointsListView = new ListView<ContactPoint>("contactPoints", new PropertyModel<List<ContactPoint>>(employerInfoModel, "contactPoints")) { @Override protected void populateItem(ListItem<ContactPoint> item) { final ContactPoint cp = item.getModelObject(); item.add(new TextField<String>("contactInfo", new PropertyModel<String>(item.getModel(), "contactInfo"))); item.add(new ContactPointTypesDropDownChoice("contactPointTypeImpl", new PropertyModel<ContactPointType>(item.getModel(), "contactPointTypeImpl"))); item.add(new IndicatingAjaxLink<ContactPoint>("deleteLink", new Model<ContactPoint>(cp)) { @Override public void onClick(AjaxRequestTarget target) { employerInfoModel.getObject().getContactPoints().remove(cp); target.addComponent(ContactInfoForm.this); } }); } }; contactPointsContainer.add(contactPointsListView); contactPointsContainer.setOutputMarkupId(true); add(contactPointsContainer); add(new AjaxSubmitLink("addContactPointLink", this) { @Override public void onSubmit(AjaxRequestTarget target, Form<?> form) { getModelObject().getContactPointsSet().add(new ContactPointImpl()); target.addComponent(contactPointsContainer); } }); } } [2] - public class EmployerInfo extends PersonInfoImpl { ... Set<ContactPoint> contactPointsSet; public List<ContactPoint> getContactPoints() { List<ContactPoint> list = new ArrayList<ContactPoint>(contactPointsSet); Collections.sort(list); return list; } public void setContactPoints(List<ContactPoint> contactPoints) { this.contactPointsSet = new HashSet<ContactPoint>(contactPoints); } public Set<ContactPoint> getContactPointsSet() { return contactPointsSet; } public void setContactPointsSet(Set<ContactPoint> contactPointsSet) { this.contactPointsSet = contactPointsSet; } }