Search code examples
serializationjavafxxstream

JavaFX Collections and JavaFX properties - XStream serialization problems


I am writing app in Java FX and I used Java FX Properties and Java FX Collections in my classes. I read that I can't serialize Java FX Collections, so i made it in this way:

public class PurchaseContainer implements Serializable{

 List<Purchase> listOfPurchases;
  @XStreamOmitField
  ObservableList<Purchase> observableListOfPurchases =  FXCollections.observableArrayList(); 
  private Date actualDate;
  int PurchaseID;

and I have here the method

  public void copyListForSerialization()
{
listOfPurchases = new ArrayList<Purchase>(observableListOfPurchases);

}

But it doesn't work. I suppose that problem can be Purchase class when I have properties like this:

public class Purchase implements Serializable{
  private IntegerProperty purchaseID;
  private IntegerProperty productID;
  private StringProperty specificProductName;
  private DoubleProperty cost; 
  private DoubleProperty discount;
  private StringProperty descriptionOfPurchase;
  private Date purchaseDate;

I read lots of tutorial but I haven't any idea to solve my problem. I've "Exception in thread "JavaFX Application Thread" java.lang.OutOfMemoryError: Java heap space". But this is very short list, only 4 records. So, I don't think it's caused by memory. Have you any ideas?


Solution

  • XStream does not provide any converters for the JavaFX collections and properties. See the discussion on the XSteam github issue tracker. There is however the XStreamFX project that tries to fill that gap. However I found that especially the collection implementation for XStreamFX does not work, so I had to implement my own converter:

    public class ObservableListConverter extends CollectionConverter implements Converter {
    
        public ObservableListConverter(Mapper mapper) {
            super(mapper);
        }
    
        @Override
        public boolean canConvert(Class type) {
            return ObservableList.class.isAssignableFrom(type);
        }
    
        @Override
        protected Object createCollection(Class type) {
            if (type == ObservableListWrapper.class) {
                return FXCollections.observableArrayList();
            }
            if (type.getName().indexOf("$") > 0) {
                if (type.getName().equals("javafx.collections.FXCollections$SynchronizedObservableList")) {
                    return FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
                }
            }
            return new SimpleListProperty<>(FXCollections.observableArrayList());
        }
    }
    

    The implementation of createCollection may vary depending on your needs. All you have to do then is to add this converter to your XStream instance:

    XStream xstream = new XStream();
    xstream.registerConverter(new ObservableListConverter(xstream.getMapper()));
    

    I'm not sure if that resolves the issue with OutOfMemory, but this is the way to convert an ObservableList using XStream.