How to serialize ObservableList

Abdullah picture Abdullah · Jan 14, 2016 · Viewed 10.5k times · Source

I am working on a javaFx project where we have to use ObservableList to add Listners. ObservableList includes Model of persons. But I want to store the whole ObservableList Object in a file through serialization. But it gives me an Exception. I also implimented Serialization on the object Model but no luck. Is there any method to serialize ObservableList?

EmployeeModel

package com.company.Model;

import javax.persistence.*;
import java.io.Serializable;

/**
 * Created by Sunny on 1/8/2016.
 */
@Entity
@Table(name = "Employee", schema = "", catalog = "PUBLIC")
public class EmployeeEntity implements Serializable {
    private String empId;
    private String empAddress;
    private String empNumber;
    private String empFirstName;
    private String empLastName;

    public EmployeeEntity(String empId, String empAddress, String empNumber, String empFirstName, String empLastName) {
        this.empId = empId;
        this.empAddress = empAddress;
        this.empNumber = empNumber;
        this.empFirstName = empFirstName;
        this.empLastName = empLastName;
    }

    public EmployeeEntity() {

    }

    @Id
    @Column(name = "emp_ID")
    public String getEmpId() {
        return empId;
    }

    public void setEmpId(String empId) {
        this.empId = empId;
    }

    @Basic
    @Column(name = "emp_address")
    public String getEmpAddress() {
        return empAddress;
    }

    public void setEmpAddress(String empAddress) {
        this.empAddress = empAddress;
    }

    @Basic
    @Column(name = "emp_number")
    public String getEmpNumber() {
        return empNumber;
    }

    public void setEmpNumber(String empNumber) {
        this.empNumber = empNumber;
    }

    @Basic
    @Column(name = "emp_firstName")
    public String getEmpFirstName() {
        return empFirstName;
    }

    public void setEmpFirstName(String empFirstName) {
        this.empFirstName = empFirstName;
    }

    @Basic
    @Column(name = "emp_lastName")
    public String getEmpLastName() {
        return empLastName;
    }

    public void setEmpLastName(String empLastName) {
        this.empLastName = empLastName;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        EmployeeEntity that = (EmployeeEntity) o;

        if (empId != null ? !empId.equals(that.empId) : that.empId != null) return false;
        if (empAddress != null ? !empAddress.equals(that.empAddress) : that.empAddress != null) return false;
        if (empNumber != null ? !empNumber.equals(that.empNumber) : that.empNumber != null) return false;
        if (empFirstName != null ? !empFirstName.equals(that.empFirstName) : that.empFirstName != null) return false;
        if (empLastName != null ? !empLastName.equals(that.empLastName) : that.empLastName != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = empId != null ? empId.hashCode() : 0;
        result = 31 * result + (empAddress != null ? empAddress.hashCode() : 0);
        result = 31 * result + (empNumber != null ? empNumber.hashCode() : 0);
        result = 31 * result + (empFirstName != null ? empFirstName.hashCode() : 0);
        result = 31 * result + (empLastName != null ? empLastName.hashCode() : 0);
        return result;
    }
}

Serialization

 public void write(ObservableList<EmployeeEntity> personObservalble) {
        try {
            // write object to file
            FileOutputStream fos = new FileOutputStream("Objectsavefile.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(personsObservable);
            oos.close();


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

Exception

java.io.NotSerializableException: com.sun.javafx.collections.ObservableListWrapper
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    at FileWriter.write(FileWriter.java:14)
    at Main.main(Main.java:12)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

Process finished with exit code 0

Answer

James_D picture James_D · Jan 14, 2016

ObservableList implementations are not Serializable (Essentially there's no sensible way to define the behavior for serializing the listeners, and not serializing the listeners at all is just the same as serializing a non-observable list with the same data, which I think is what you want to do here.) Assuming your Person class is Serializable (and that instances can actually be serialized), you can do:

 public void write(ObservableList<EmployeeEntity> personObservalble) {
    try {
        // write object to file
        FileOutputStream fos = new FileOutputStream("Objectsavefile.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(new ArrayList<EmployeeEntity>(personsObservable));
        oos.close();


    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

To read it back in, you would do:

ObjectInputStream ois = ... ;
List<EmployeeEntity> list = (List<EmployeeEntity>) ois.readObject();
personsObservable = FXCollections.observableList(list);

Here is a complete test. I ran this and it worked (I removed the persistence annotations, as I didn't have javax.persistence on the classpath in my test environment, but that should make no difference).

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

public class SerializeObservableListTest {

    public static void main(String[] args) throws IOException {
        EmployeeEntity bill = new EmployeeEntity("1000", "Seattle, WA", "1000", "Bill", "Gates");
        EmployeeEntity tim = new EmployeeEntity("2000", "Mobile, AL", "2000", "Tim", "Cook");

        ObservableList<EmployeeEntity> staff = FXCollections.observableArrayList(bill, tim);

        Path temp = Files.createTempFile("employees", "ser");
        write(staff, temp);

        ObservableList<EmployeeEntity> listFromFile = read(temp);
        System.out.println("Lists equal? "+listFromFile.equals(staff));
    }

    private static void write(ObservableList<EmployeeEntity> employees, Path file) {
        try {

            // write object to file
            OutputStream fos = Files.newOutputStream(file);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(new ArrayList<EmployeeEntity>(employees));
            oos.close();


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static ObservableList<EmployeeEntity> read(Path file) {
        try {
            InputStream in = Files.newInputStream(file);
            ObjectInputStream ois = new ObjectInputStream(in);
            List<EmployeeEntity> list = (List<EmployeeEntity>) ois.readObject() ;

            return FXCollections.observableList(list);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return FXCollections.emptyObservableList();
    }
}