DefaultTableModel wirft beim Serialisieren Exception :-(

  • Themenstarter Themenstarter Marko2001
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
M

Marko2001

Gast
java.io.NotSerializableException: javax.swing.JTable$CellEditorRemover
at java.i😵bjectOutputStream.writeObject0(ObjectOutputStream.java:1156)
at java.i😵bjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
at java.i😵bjectOutputStream.defaultWriteObject(ObjectOutputStream.java:416)
at javax.swing.JTable.writeObject(JTable.java:5779)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)


Was ist da los? Ich serialisiere wirklich nur das TableModel. Das krasse ist, bei manchen TableModel-Instanzen klappt das serialisieren bei anderen nicht. Es muss irgendwie mit dem Status des TableModel zusammenhaengen.

Kann es sein, dass das TableModel irgendwie von der JTable abhaengig werden kann und dann versucht wird die JTable mitzuserialisieren? Zumindest die Fehlermeldung oben scheint dies anzudeuten: at javax.swing.JTable.writeObject(JTable.java:5779)


Bin mittlerweile am verzeifeln da ich auch keinen Einblick in der Serialisierungsmechanismus von Java habe (ich kann leider keinen anderen Mechanismus verwenden wie XML, glaubt mir).
 
Der Serialisierungs-Mechanismus folgt einfach allen Referenzen. Da eine JTable einige TableModelListener beim TableModel registriert, kann es passieren, dass das JTable gleich mitserialisiert wird (du kannst dir selbst ausrechnen, dass der Rest deines Programmes gleich noch hintendran gehängt wird...).

Mögliche Lösung:
- Sicherstellen, dass das Model von niemandem benutzt wird
- Nur die Daten serialisieren, nicht das ganze Model
- Und mein Liebling: auf Serialisierung verzichten und ein gut durchdachtes, schön dokumentierstes Dateiformat entwerfen und nutzen.
 
Beni hat gesagt.:
Der Serialisierungs-Mechanismus folgt einfach allen Referenzen. Da eine JTable einige TableModelListener beim TableModel registriert, kann es passieren, dass das JTable gleich mitserialisiert wird (du kannst dir selbst ausrechnen, dass der Rest deines Programmes gleich noch hintendran gehängt wird...).

Mögliche Lösung:
1. Sicherstellen, dass das Model von niemandem benutzt wird
2. Nur die Daten serialisieren, nicht das ganze Model
3. Und mein Liebling: auf Serialisierung verzichten und ein gut durchdachtes, schön dokumentierstes Dateiformat entwerfen und nutzen.

zu 1. Am liebsten haette ich ja ein new DefaultTableModel(oldModel) dass das besorgt. Ich habe naemlich keine Ahnung wer da irgendwelche Listener registriert. Wenn ich eine einzelne Zelle editiere (und damit wohl einen CellEditor implizit setze samt Listener) kommt es zur Exception. Auch weiss ich jetzt nicht wie ich den Serialisierungsmechanismus aufbohren koennte dass er beim speichern automatisch sowas wie newModel = new DefaultTableModel(oldModel) aufruft und dann nicht oldModel sondern newModel serialisiert. Geht sowas?

zu 2. Gut. Das TableModel ist nur ein kleiner Bereich einer groesseren (nicht-GUI Bean). Ich serialisiere die ganze Bean. Ich haette jetzt nichts dagegen anstatt dem TableModel nur die Vektor-Daten darin abzuspeichern. Es sollte halt mehr oder minder automatisch gehen.
Hast du vielleicht ein Beispiel wo man fuer einen bestimmten Typ den Serialisierungsmechanismus leicht abaendern kann und dass dann auch fuers Speichern/Laden gut klappt?

zu 3. Ich glaube das uebersteigt meine Faehigkeiten bei weitem. Ich habe frueher XStream benutzt was wirklich sehr gut klappte. Nun musste ich leider die Applikation als unsigniertes Applet umsetzen wodurch XStream aufgrund von Sicherheitsbeschraenkungen nicht mehr funktioniert. Nur der Default-Serialisierungsmechanismus von Java funktioniert noch.


Danke fuer die Hilfe.
 
Ich hab's schon mit XMLEncoder gemacht, aber das hilft dir wohl nix, da du XML pauschal ausschliesst (aus welchem Grund auch immer).
 
André Uhres hat gesagt.:
Ich hab's schon mit XMLEncoder gemacht, aber das hilft dir wohl nix, da du XML pauschal ausschliesst (aus welchem Grund auch immer).

XStream war ja XML aber das kann ich aus oben beschriebenen Gruenden nicht nutzen.

Die hauseigene Java XML-Serialisierung klappt nicht weil die Beans recht komplex sind und nicht dem Beans-Standard folgen.

Also wenn du einen XML-Serialisierer hast der in unsignierten Applets genauso maechtig ist wie der Java ObjectOutputStream oder XStream bin ich entzueckt.
Mit maechtig meine ich, dass er meine sehr komplexen Modelle (die ich uebrigens uebernommen habe und nun nicht mehr aendern darf!) ohne Probleme serialisiert und deserialisiert.
 
Wir müssen das Model als "public class" erweitern,
mit einem "default" Konstruktor und Getter+Setter für die Properties.
Das "DefaultTableModel" muss man zu diesem Zweck übrigens auch
erweitern, weil Getter/Setter fehlen.
Wenn bei dir eine Erweiterung aus irgendeinem Grund nicht zulässig ist,
dann funktioniert XMLEncoder allerdings nicht.

EDIT: Ich hab allerdings keine Erfahrung damit in Verbindung mit Applets.
 
André Uhres hat gesagt.:
Wir müssen das Model als "public class" erweitern,
mit einem "default" Konstruktor und Getter+Setter für die Properties.
Das "DefaultTableModel" muss man zu diesem Zweck übrigens auch
erweitern, weil Getter/Setter fehlen.
Wenn bei dir eine Erweiterung aus irgendeinem Grund nicht zulässig ist,
dann funktioniert XMLEncoder allerdings nicht.

EDIT: Ich hab allerdings keine Erfahrung damit in Verbindung mit Applets.

Wie gesagt ist dieses Erweitern unmoeglich, nicht weil ich faul bin sondern aus diversen anderen Gruenden darunter Kompatibilitaet.

Aehnlich wie XStream wird auch der XMLEnocder von Java wohl nicht funktionieren in einem unsignierten Applet. Das muss ich allerdings auch gar nicht ausprobieren, da ich nicht die bestehenden Modelle veraendern kann. XStream war ja grade so praktisch weil es eben alles serialisiert hat und keinen Beans Standard vorraussetzte. Leider kann ich das nicht nutzen.
 
java.io.NotSerializableException: javax.swing.JTable$CellEditorRemover

In diesem Fall klappte es nicht, weil eine Zelle editiert wurde. Allerdings hast Du die ganze JTable mitserialisiert, was Du ja nicht möchtest.

Ein javax.swing.table.DefaultTableModel kannst Du ohne Listeners so kopieren:
Code:
 public static DefaultTableModel cloneModelWithoutListeners(
        DefaultTableModel orgModel) {
    final Vector<?> clonedData = (Vector<?>) orgModel.getDataVector().clone();
    final int columnCount = orgModel.getColumnCount();
    final Vector<String> columnNames = new Vector<String>(columnCount);
    for (int i = 0; i < columnCount; i++) {
      columnNames.add(orgModel.getColumnName(i));
    }
    return new DefaultTableModel(clonedData, columnNames);
  }

Hilft das? Ebenius
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben