Alex
Alex

Reputation: 1749

How to marshall List of List in JAXB

I have an attribute protected ObservableList<List<Boolean>> selectableMatrix; which is actually an ObservableList<ObservableList<Boolean>>, which is the model for a JavaFX tableView where the user can select certain cells. I would like to marshall / unmarshall this selectableMatrix using JAXB, but I can't find an example how to annotate a List of List or how to implement the related adapter. The naive way of

@XmlElement(name = "selectableMatrix")
public ObservableList<List<Boolean>> getSelectableMatrix() {

    return selectableMatrix;
}

results in an IllegalAnnotationsException as java.util.List is an interface, and JAXB can't handle interfaces.

What do I need to do?

EDIT

I tried, as Scott suggested below, ObservableList<ObservableList>. I got

 org.glassfish.jaxb.runtime.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
javafx.collections.ObservableList ist eine Schnittstelle, und JAXB kann keine Schnittstellen verarbeiten.
    this problem is related to the following location:
        at javafx.collections.ObservableList
        at protected javafx.collections.ObservableList de.levin.domain.SessionFlowModel.selectableMatrix
        at de.levin.domain.SessionFlowModel

as it turns out ObservableList is also "only" an interface.

So I added a @XmlJavaTypeAdapter annotation

@XmlJavaTypeAdapter(ObservableListAdapter.class)    // Since JAXB can't deal with interfaces, use this adapter class 
protected ObservableList<ObservableList<Boolean>> selectableMatrix; // matrix indicating whether a transition between two exercises is possible or not

However I can't get the XMLAdapter class even to compile. Can somebody please provide an XMLAdapter example for List<List<?>>?

EDIT 2 I managed to compile my XmlAdapter and according to my System.out output it is called and converts correctly. BUT in the xml file the data doesn't arrive.

public class ObservableListAdapter extends XmlAdapter<ArrayList<ArrayList<Boolean>>, ObservableList<ObservableList<Boolean>>> {

    @Override
    public ObservableList<ObservableList<Boolean>> unmarshal(ArrayList<ArrayList<Boolean>> v) {
        
        ObservableList<ObservableList<Boolean>> result = FXCollections.observableArrayList();
        System.out.println("unmarshall: " + v.size());
        
        for(List<Boolean> childList: v) {
            ObservableList<Boolean> observableChildList = FXCollections.observableArrayList();
            for (int i = 0; i < childList.size(); i++) {
                observableChildList.add(childList.get(i));
            }
            result.add(observableChildList);
        }
       
        return result;
    }

    @Override
    public ArrayList<ArrayList<Boolean>> marshal(ObservableList<ObservableList<Boolean>> v) {
        
        ArrayList<ArrayList<Boolean>> result = new ArrayList<>();
        System.out.println("marshall in: " + v.size());
        
        for(List<Boolean> childList: v) {
            ArrayList<Boolean> childArray = new ArrayList<Boolean>();
            for (int i = 0; i < childList.size(); i++) {
                childArray.add(childList.get(i));
            }
            result.add(childArray);
           
        }
        System.out.println("marshall out: " + result.size());
        return result;
    }
}

If I run it with a 6x6 matrix the two System.out calls print the correct 6. In other words, the adapter is called and converts correctly. However, in the xml file I only have a single line , so none of the values gets saved.

What am I missing?

Upvotes: 1

Views: 45

Answers (0)

Related Questions