JAXB Configuration was broken by upgrading from JDK 1.7 to JDK 1.8 u05 for collections

前端 未结 1 1910
深忆病人
深忆病人 2020-12-11 09:03

The code below used to work under the JAXB implementation used by JDK 1.7, but now under JDK 1.8 it\'s broken. In the code below you will find the key change that seems to

相关标签:
1条回答
  • 2020-12-11 09:43

    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);
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题