Hi,
I have a domain class named Parent as follows
public class Parent {
public List<Child> childList = new ArrayList<Child>();
public void setChildList(List<Child> childList) {
this.childList = childList;
}
public List<Child> getChildList() {
return childList;
}
public void addChild(Child child) {
childList.add(child);
child.setParent(this);
}
// other getters and setters
}
Notice Parent/Child is a bidirectional relationship. A addChild convenience method takes care of the bidirectional references.
And a Child class as follows
public class Child {
private Parent parent;
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
private String descripton;
// other getters and setters
}
I have a Spring form as follows
<form:form method="POST" action="addCommand.xhtml" commandName="command">
<div>
<p>1° child:</p>
<form:input path="childList[0].description"/>
</div>
<div>
<p>2° child:</p>
<form:input path="childList[1].description"/>
</div>
<div>
<p>3° child:</p>
<form:input path="childList[2].description"/>
</div>
<input type="submit"/>
</form:form>
Has someone an idea how to bind a child element through addChild convenience method ? I need it because i want to save a cascace Parent/Child bidirectional relationship in Hibernate.
Added to Jacob's answer:
Hi Jacob,
The purpose of AutoPopulatingList.ElementFactory's createElement(int index) method is sets up each Child created "just in time". Then if you use something as follows:
protected Object formBackingObject(HttpServletRequest request) throws Exception {
Parent parent = new Parent();
parent.setChildList(
new AutoPopulatingList.ElementFactory() {
public Object createElement(int index) {
Child child = new Child();
// You have just added A NEW CHILD to command object
parent.addChild(child);
return child;
}
});
return parent;
}
So if i submit THREE Child objects, my Parent command object will have SIX Child objects instead.
You could TEST it according to:
public class BinderTest {
private Parent parent;
private MockHttpServletRequest request;
private ServletRequestDataBinder binder;
@BeforeMethod
public void setUp() {
parent = new Parent();
parent.setChildList(
new AutoPopulatingList.ElementFactory() {
public Object createElement(int index) {
Child child = new Child();
// You have just added A NEW CHILD to command object
parent.addChild(child);
return child;
}
});
request = new MockHttpServletRequest();
binder = new ServletRequestDataBinder(parent, "parent")
}
@DataProvider(name="bindParameter")
public Object [][] bindParameter() {
return new Object [][] {
{new String [] {"d0", "d1", "d2", "d3", "d4"}}
};
}
@Test(dataProvider="bindParameter")
public void bind(String [] descriptionArray) {
// Notice five childs created (descriptionArray.length)
int i = 0;
for(String description: descriptionArray)
request.addParameter("childList[" + i++ + "].description", description);
// It will fail
// parent.getChildList().size() return TEN Child objects
assertEquals(parent.getChildList().size(), descriptionArray.length);
}
}
So in order to pass it, you need the following
parent = new Parent();
parent.setChildList(
new AutoPopulatingList.ElementFactory() {
public Object createElement(int index) {
Child child = new Child();
// child now reference parent
child.setParent(parent);
return child;
}
});
When the form is submitted, parent comand object will reference Child objects because they has been added to childList. Both bidirectional references have been set up.
Regards
Arthur Ronald F D Garcia (Java programmer)
Natal/RN - Brazil