SimpleListProperty 上的 NotSerializableException [英] NotSerializableException on SimpleListProperty

查看:24
本文介绍了SimpleListProperty 上的 NotSerializableException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Javafx,我将我的对象包装到 ListProperty 中,让 tableview 更新列表对象上的任何更改.现在我正在尝试序列化我的项目和对象的 ListProperty,它向我抛出了这个异常.

I'm using Javafx, and I wrap my objects into ListProperty to let the tableview updates for any changes on the objects of the list. Now I'm trying to serialize my project and the ListProperty of objects and it throw me this exception.

java.io.NotSerializableException: javafx.beans.property.SimpleListProperty
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1181)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1541)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1506)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
at Util.FileManager.serializeProject(FileManager.java:23)
at Controller.FrameworkController.saveProject(FrameworkController.java:549)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:75)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:279)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1435)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:28)
at javafx.event.Event.fireEvent(Event.java:171)
at javafx.scene.control.MenuItem.fire(MenuItem.java:456)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1197)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer$6.handle(ContextMenuContent.java:1148)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer$6.handle(ContextMenuContent.java:1146)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:33)
at javafx.event.Event.fireEvent(Event.java:171)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3328)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3168)
at javafx.scene.Scene$MouseHandler.access$1900(Scene.java:3123)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1563)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2265)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:250)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:173)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:292)
at com.sun.glass.ui.View.handleMouseEvent(View.java:528)
at com.sun.glass.ui.View.notifyMouse(View.java:922)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:73)
at java.lang.Thread.run(Thread.java:724)

我的项目类是这样的,我自己的所有对象都已经实现了可序列化.

My project class is something like this and all my own objects are already implementing serializable.

public class Project implements Serializable{

private String name;
private String standard;
private ListProperty<Equipment> projectEquipments;

private ListProperty<LegendElement> equipmentsLegend;

public Project() {
    this.projectEquipments = new SimpleListProperty<Equipment>(FXCollections.observableArrayList(new ArrayList<Equipment>()));

    this.equipmentsLegend = new SimpleListProperty<>(FXCollections.observableList(new ArrayList<LegendElement>()));}

我该怎么做才能序列化我的项目和其中的设备清单?

What can I do to serialize my project and the list of equipment within it?

推荐答案

这是对我有用的解决方案(Serialize SimpleXXXProperty on a JPA Entity where xxx can be String, Object, etc)

Here is the solution that works for me (Serialize SimpleXXXProperty on a JPA Entity where xxx can be String, Object, etc)

https://gist.github.com/james-d/a7202039b00170256293

你'只'必须:
1) 实现可序列化
2) 将所有属性设置为瞬态
3) 像这样定义 2 个特殊方法:

You 'just' have to :
1) implements Serializable
2) set all Properties as transient
3) define 2 specials methodes like that :

private void writeObject(ObjectOutputStream s) throws IOException {
    s.defaultWriteObject();
    s.writeLong(idProperty().longValue());
    s.writeUTF(aStringProperty().getValueSafe()); // can't be null so use getValueSafe that returns empty string if it's null
    s.writeUTF(anOtherStringPoperty().getValueSafe());
}

private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
    idProperty.set(s.readLong());
    aStringProperty.set(s.readUTF());
    anOtherStringPoperty(s.readUTF());
    // set values in the same order as writeObject()
}

瞧 :) 你可以用

and voilà :) You can serialize your Object with

MyObject o = new MyObject();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();

注意,这些奇怪的私有方法是由Java虚拟机直接调用的,不能是官方文档中提到的Override、public或其他.

Note that these strange private methodes are directly called by the Java Virtual Machine and must not be Override, public or other as mentionned in the official documentation.

已不要将 writeChars 用于 String 而是 writeUTF.
请记住,在反序列化过程中,读取的对象"未实例化(未调用构造函数!)然后所有属性都未初始化,因此 idProperty.set(o) 将抛出 nullPointerException.
所以你必须创建一个 initMethode 来初始化所有的属性.在从 ObjectInputStream 读取数据之前,从构造函数和 readObject 方法调用此方法

Edited : don't use writeChars for String but writeUTF.
And remember that on deserialization process, the "readed object" isn't instanciated (constructor isn't called!) and then all Properties aren't initialized and so idProperty.set(o) will throws nullPointerException.
So you have to create a initMethode where all properties are initialized. Call this methode from your constructor AND from readObject methode before read data from the ObjectInputStream

我制作了自动写入和读取的助手.如果你想使用它,这里是代码:

Edit : I made helpers for automatic write and read. Here is code if you want to use it :

public class WriteObjectsHelper {

// write a StringProperty to ObjectOutputStream
public static void writeStringProp(ObjectOutputStream s, StringProperty strProp) throws IOException {
    s.writeUTF(strProp.getValueSafe());
}

// write a ListProperty to ObjectOutputStream
public static void writeListProp(ObjectOutputStream s, ListProperty lstProp) throws IOException {
    if(lstProp==null || lstProp.getValue()==null) {
        s.writeInt(0);
        return;
    }
    s.writeInt(lstProp.size());
    for(Object elt:lstProp.getValue()) s.writeObject(elt);
}

// automatic write set of properties to ObjectOutputStream
public static void writeAllProp(ObjectOutputStream s, Property... properties) throws IOException {
    s.defaultWriteObject();
    for(Property prop:properties) {
        if(prop instanceof IntegerProperty) s.writeInt(((IntegerProperty) prop).intValue());
        else if(prop instanceof LongProperty) s.writeLong(((LongProperty) prop).longValue());
        else if(prop instanceof StringProperty) s.writeUTF(((StringProperty)prop).getValueSafe());
        else if(prop instanceof BooleanProperty) s.writeBoolean(((BooleanProperty)prop).get());
        else if(prop instanceof ListProperty) writeListProp(s,(ListProperty)prop);
        else if(prop instanceof ObjectProperty) s.writeObject(((ObjectProperty) prop).get());
        else throw new RuntimeException("Type d'objet incompatible : " + prop.toString());
    }
}
}

public class ReadObjectsHelper {

// Read a ListProperty from ObjectInputStream (and return it)
public static ListProperty readListProp(ObjectInputStream s) throws IOException, ClassNotFoundException {
    ListProperty lst=new SimpleListProperty(FXCollections.observableArrayList());
    int loop=s.readInt();
    for(int i = 0;i<loop;i++) {
        lst.add(s.readObject());
    }

    return lst;
}

// automatic fill a set of properties with values contained in ObjectInputStream
public static void readAllProp(ObjectInputStream s, Property... properties) throws IOException, ClassNotFoundException {
    for(Property prop:properties) {
        if(prop instanceof IntegerProperty) ((IntegerProperty)prop).setValue(s.readInt());
        else if(prop instanceof LongProperty) ((LongProperty)prop).setValue(s.readLong());
        else if(prop instanceof StringProperty) ((StringProperty)prop).setValue(s.readUTF());
        else if(prop instanceof BooleanProperty) ((BooleanProperty)prop).setValue(s.readBoolean());
        else if(prop instanceof ListProperty) ((ListProperty)prop).setValue(readListProp(s));
        else if(prop instanceof ObjectProperty) ((ObjectProperty)prop).setValue(s.readObject());
        else throw new RuntimeException("Unsupported object type : " + prop==null?null:prop.toString());
    }
}
}

他们,这是我的(法语)JPA 实体的一部分:

And them, here is part of my (french) JPA entity :

@Entity
@Table(name="articles")
public class Article implements Serializable, IEntity {

private transient LongProperty idArticle;
public LongProperty idArticleProperty() { return idArticle; }

private transient StringProperty descriptionFr;
public StringProperty descriptionFrProperty() { return descriptionFr; }

private transient StringProperty reference;
public StringProperty referenceProperty() { return reference; }

private transient StringProperty constructeur;
public StringProperty constructeurProperty() { return constructeur; }

private transient StringProperty numSAP;
public StringProperty numSAPProperty() { return numSAP; }

private transient StringProperty descriptionEn;
public StringProperty descriptionEnProperty() { return descriptionEn; }

private transient ListProperty<Article> testList;
public ListProperty<Article> articlesProperty() {return testList; }

public Article() {
    initInstance();
}

/**
 * Need for calling by readObject;
 */
private void initInstance() {
    idArticle=new SimpleLongProperty();
    descriptionFr=new SimpleStringProperty();
    descriptionEn=new SimpleStringProperty();
    reference=new SimpleStringProperty();
    constructeur=new SimpleStringProperty();
    numSAP=new SimpleStringProperty();
    testList=new SimpleListProperty<>(FXCollections.observableArrayList());
}

private void writeObject(ObjectOutputStream s) throws IOException {
    WriteObjectsHelper.writeAllProp(s,idArticle,descriptionFr,reference,constructeur,numSAP,descriptionEn,testList);
}

private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
    initInstance();
    ReadObjectsHelper.readAllProp(s, idArticle,descriptionFr,reference,constructeur,numSAP,descriptionEn,testList);
}

@Column(name = "idArticle")
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getIdArticle() {
    return idArticle.get();
}

public void setIdArticle(Long idArticle) {
    this.idArticle.set(idArticle);
}
//...
}

这篇关于SimpleListProperty 上的 NotSerializableException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆