How does unmarshalling work in JAXB?

2019-02-19 09:41发布

问题:

I have a getter/setter pair for an element in jaxb:

@XmlElementWrapper(name="requires", required=true) 
@XmlElement(name="equals", required=true)
List<MyObject> getMyObjects() {
    return this.myObject;
}
void setMyObjects(final MyObject... myObjects) {
    //call the regular method for setting the objects 
    //that does not have the required signature type
}

The thing is that the setter method is never getting called. I put a breakpoint on both the getter and setter, and the one by the getter is hit, but not the setter's.

I just found this question, but I don't fully understand the answer. myObjects is initialized at construction time, so it looks like it fits into Scenario 2. What happens in the unmarshalling process after the getter is called?

回答1:

Your setter doesn't match up with the signature of your getter. Instead of:

void setMyObjects(final MyObject... myObjects)

You need

void setMyObjects(List <MyObject> myObjects)


回答2:

You genearlly do not use the setter for list fields in JAXB objects.

In stead, you use the getter for the list and maniuplate the returned list.

Example JAXB object:

class JaxbExample {
    @XmlElement(name="stringList", required = true)
    private List<String> stringList;

    public List<String> getStringList() {
        return stringList;
    }
}

add three strings to stringList:

JaxbExample someObject = ...;

// add three Strings to stringList

someObject.getStringList().add("foo");
someObject.getStringList().add("bar");
someObject.getStringList().add("baz");

// now the list contains 3 new strings and there was
// no need to use a setter.

set stringList to an existing list:

JaxbExample someObject = ...;
List<String> someList = ...;

// set someObject's stringList to someList

someObject.getStringList().addAll(someList);

To clarify further...

We sometimes generate our JAXB Java classes from XML schema files (.XSD files) using the XJC utility.

When a generated class contains a List element, no setter method is generated for the List.

The following comment appears above the getter for each List:

/**
 * Gets the value of the stringList property.
 * 
 * <p>
 * This accessor method returns a reference to the live list,
 * not a snapshot. Therefore any modification you make to the
 * returned list will be present inside the JAXB object.
 * This is why there is not a <CODE>set</CODE> method for the stringList property.
 * 
 * <p>
 * For example, to add a new item, do as follows:
 * <pre>
 *    getStringList().add(newItem);
 * </pre>
 * 
 * 
 * <p>
 * Objects of the following type(s) are allowed in the list
 * {@link String }
 * 
 * 
 */

Hopefully that comment does a better job of explaining than I have!!



回答3:

This doesn't actually explain why JAXB works the way it does, but I was able to get my code to work the way I wanted it to. I don't really know why, but this is what I did:

@XmlElementWrapper(name="requires", required=true) 
@XmlElement(name="equals", required=true)
MyObject[] getMyObjects() { //myObjects is an ArrayList
    return this.myObjects.toArray(EMPTY_OBJECT_ARRAY);
}
void setMyObjects(final MyObject... myObjects) {
    //call the regular method for setting the objects 
    //that does not have the required signature type
}


标签: java jaxb