Chris Smith
Chris Smith

Reputation: 3012

JAXB marshall Properties

Using JAXB, I cannot figure out how to marshal Properties. In particular, I am trying to marshal a SimpleObjectProperty but I assume it won't work with other properties either. In some other classes, I was able to manage getters/setters, but that will not work in this case of the HashMap of SimpleObjectProperties

Here is my code snippet:

..
@XmlRootElement(name = "derby")
@XmlAccessorType(XmlAccessType.FIELD)
public class Derby extends Observable {
    @XmlElement(name = "cars")
    private final ArrayList<Car>                                cars;
    @XmlTransient
    private final ObservableList<Car>                           carsObservable;
    @XmlElement(name = "schedule")
    private final SimpleObjectProperty<Schedule>                scheduleProperty;
    @XmlElement(name = "settings")
    private final HashMap<String, SimpleObjectProperty>         settings;//This is not marshalling correctly
..

And here is the output XML snippet:

...
<settings>
    <entry>
        <key>track.lanecount</key>
        <value/> //No value???
    </entry>
    <entry>
        <key>general.cardisplay</key>
        <value/>
    </entry>
    <entry>
        <key>track.orientation</key>
        <value/>
    </entry>
    <entry>
        <key>general.derbytitle</key>
        <value/>
    </entry>
</settings>
...

I am creating the variables and not leaving them uninitialized. I also tested if the settings actually have a value before marshalling, and they do.

The reason I am using Properties instead of just the real object I am trying to store is because I want to add listeners to my settings so when a single setting changes, all of the things that rely on it will update automatically.

Upvotes: 4

Views: 1853

Answers (1)

StefanHeimberg
StefanHeimberg

Reputation: 1465

i see you are using @XmlAccessorType(XmlAccessType.FIELD) that means that the class fields are used to marschal / unmarshal values...

you could change it to @XmlAccessorType(XmlAccessType.PROPERTY) and then put all @XmlElement onto the getter of the property.

see documentation for more: XmlAccessType

your code sipped then look something like this:

..
@XmlRootElement(name = "derby")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Derby extends Observable {

    private final ArrayList<Car>                                cars;

    private final ObservableList<Car>                           carsObservable;

    private final SimpleObjectProperty<Schedule>                scheduleProperty;

    private final HashMap<String, SimpleObjectProperty>         settings;//This is not marshalling correctly

    @XmlElement(name = "cars")
    public List<Car> getCars() {
        return cars;
    }

    public void setCars(final ArrayList<Car> cars) {
        this.cars.clear();
        this.cars.addAll(cars);
    }

    @XmlElement(name = "schedule")
    public Schedule getSchedule() {
        return this.scheduleProperty.get();
    }

    public void setSchedule(final Schedule schedule) {
        this.scheduleProperty.set();
    }

    @XmlElement(name = "settings")
    public Map<String, Object> getSettings() {
        // do your mapping logic here...
        // convert your HashMap<String, SimpleObjectProperty> to Map<String, Object>
    }

    public void setSettings(final Map<String, Object> settings) {
        // do your mapping logic here...
        // convert your Map<String, Object> to HashMap<String, SimpleObjectProperty>
    }

    @XmlTransient
    public ObservableList<Car> getCarsObservable() {
        return carsObservable;
    }
..

Upvotes: 3

Related Questions