Background
When a collection property is mapped in JAXB it first checks the getter to see if the collection property has been pre-initialized. In the example below I want to have my property exposed as List<String>
, but have the backing implementation be a LinkedList
ready to hold 1000 items.
private List<String> foos = new LinkedList<String>(1000);
@XmlElement(name="foo")
public List<String> getFoos() {
return foos;
}
Why Your Code Used to Work
If you previously had JAXB call the setter on a property mapped to a collection that returned a non-null response from the getter, then there was a bug in that JAXB implementation. Your code should not have worked in the previous version either.
How to Get the Setter Called
To have the setter called you just need to have your getter return null, on a new instance of the object. Your code could look something like:
import java.util.*;
import javax.xml.bind.annotation.*;
@XmlRootElement(name = "Foo")
public class Foo {
private List<CustomObject> list = null;
@XmlElementWrapper(name = "Wrap")
@XmlElement(name = "Item", required = true)
public synchronized void setList(List<CustomObject> values) {
if (null == list) {
list = new ArrayList<CustomObject>();
} else {
list.clear();
}
list.addAll(values);
}
public synchronized List<CustomObject> getList() {
if (null == list) {
return null;
}
return new ArrayList(list);
}
}
UPDATE
If you don't need to perform any logic on the List returned from JAXB's unmarshalling then using field access may be an acceptable solution.
@XmlRootElement(name = "Foo")
@XmlAccessorType(XmlAccessType.FIELD)
public class Foo {
@XmlElementWrapper(name = "Wrap")
@XmlElement(name = "Item", required = true)
private List<CustomObject> list = null;
public synchronized void setList(List<CustomObject> values) {
if(null == list) {
list = new ArrayList<CustomObject>();
} else {
list.clear();
}
list.addAll(values);
}
public synchronized List<CustomObject> getList() {
return new ArrayList(list);
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…