Serialisierung von Referenzen

Added by timekeeper 10 months ago

Hallo Alex,
ich möchte ein Interface schreiben, welches einem Client erlaubt, vom Server dessen Datenmodell zu laden.
Vereinfacht gesprochen besteht das Modell aus
  • einer Liste von Objektbeschreibungen und
  • einer Liste von Eigenschaften der Objekte

Die Objektbeschreibungen enthalten nun wieder eine Liste von Eigenschaften (aus obiger Liste).

Wie verhindere ich nun, dass (wiederverwendete) Eigenschaften mehrmals übertragen werden?

Beispiel:
Ich definiere eine Eigenschaft "Kommentar" und verwende diese im Objekt "Benutzer", "Firma", "Projekt" usw. In der Eigenschaftenliste kommt der "Kommentar" nur einmal vor und wird von den 3 Objektbeschreibungen referenziert. Wie verhindere ich nun, dass die Eigenschaft nach dem Deserialisieren im Client 4x existiert?

Hermann


Replies (3)

RE: Serialisierung von Referenzen - Added by achristian 10 months ago

Hmm, das ist eine knifflige Frage. Ich hab noch gar nicht ausprobiert um die JVM so schlau ist, und beim deserialisieren "erkennt" ob die mehrfach vom Netz gelesenen Daten ein und demselben Objekt entsprechen... Wenn der ObjectInputStream das nicht von Haus aus kann, dann wüsste ich auf die schnelle nicht wie man das mit technischen Mitteln am besten löst.

Folgendes würde wohl gehen, wäre aber etwas unschön:

Die Objekte Benutzer, Firma und Projekt enthalten nur Kommentar-IDs, und nicht das Kommentar-Objekt. Auf der Clientseite legst du eine Service-Klasse an, die dir die Objekte vom Server holt. Und wenn dann ein Kommentar-Objekt gebraucht wird, geht der Request über die Clientseitige Service-Klasse, welche prüft ob es die Kommentar-Instanz schon einmal geholt hat und ob die bereits geholte Version noch aktuell ist. Ist beides nicht der Fall, wird die Kommentar-Instanz vom Server angefordert.

Wie gesagt, ist etwas unschön... Ich werd' das mit dem ObjectInputStream aber nochmal verifizieren.

Wie ist das denn bei deinen Benutzer, Firma und Projekt-Objekten? Die beinhalten jeweils als Instanzvariable das Kommentar-Objekt, oder?

- Alex

RE: Serialisierung von Referenzen - Added by timekeeper 10 months ago

Hallo Alex,
ich habe es mittlerweile hinbekommen. Man muss

private void writeObject(ObjectOutputStream oos) und
private void readObject(ObjectInputStream ois)

implementieren, dann sind die für die Serialisierung zuständig.

Ich hatte eine dreistufige Hirarchie:

ObjektKlassen enthalten Fragmente und diese wiederum Properties.

Mein zu serialisierendes Objekt enthält 3 Maps aller dieser Instanzen. Deshalb habe ich zunächst nur die Objekte ohne Referenzen auf die untergeordneten Objekte übertragen und dann eine HashMap generiert, und übertragen, welche nur die keys enthielt. Anhand der keys habe ich dann im Empfänger wieder die Referenzen
aufgebaut. Ist sehr mühselig und fehleranfällig, aber jetzt gehts.

Übrigens:
Ich habe jetzt mit dem Lookup-Konstrukt von Netbeans eine Architektur aufgebaut, welche es erlaubt, Module im Server hinzuzufügen, welche eigene Simon-Interfaces benutzen. Die Initialisierung der Interfaces geschieht völlig automatisch. Ich muss bei der Interface-Implementierung nur eine weitere Annotation hinzufügen.

Auch im Client kann jetzt ein Modul ein Interface per Annotation anfordern. Ist das Modul nicht da, wird eben kein lookup gemacht.

Langsam aber sicher bekomme ich die ersten Funktionen hin. Ist alles sehr mühsam, da man viele Komponenten selbst schreiben muss, welche einem ein Tomcat oder Glasfish schenkt, aber man wird mit den Vorteilen von Simon belohnt. Bisher habe ich den Eindruck, dass Simon rattenschnell ist. Ich muss einmal warten, bis ich wirklich grosse Datenmengen übertragen muss.

By the way: Gibt es auch die Möglichkeit, beim Dateitransfer einen InputReader zu verwenden? Es wäre doch schön, wenn man direkt aus der DB streamen könnte, oder?

Wie immer: Danke für die Mühe
Hermann

RE: Serialisierung von Referenzen - Added by achristian 10 months ago

Ja, stimmt. Mit Externalize (so nennt sich das) geht das. Wäre da jetzt gar nicht auf die Idee bekommen :-)

Hab vorhin noch etwas mit der standardserialisierung herum gespielt. Ergebnis: geht nicht. Auch nicht wenn man hashCode und equals überschreibt. Wenn man mit == Vergleicht sind's, egal wie man's dreht, immer verschiedene Instanzen.
Das einzige was evtl. gehen würde ist, den ObjectStream vom Client zum Server durchzuziehen, und vor allem am leben lassen würde. Da NIO kein Streaming-Interface bietet, wird der ObjectStream für jedes Objekt einzeln erzeugt und genutzt. Gäbe es das Streaminterface, dann könnte man den ObjectStream recyceln und vor allem dessen Cache-Funktion nutzen. Dann hätte man nur noch ein problem: Wann den Cache aufräumen? Denn das kann das System nicht automatisch. Man muss selbst reset() aufrufen um an eine geänderte Instanz dran zu kommen. Aber gut, wir haben hier ja kein Streaminterface, also steht das erstmal ach nicht wirklich zur Debatte. RMI macht's übriugens, trotz Streaminterface, genauso. Ohne Cache ...

Langsam aber sicher bekomme ich die ersten Funktionen hin. Ist alles sehr mühsam, da man viele Komponenten selbst schreiben muss, welche einem ein Tomcat oder Glasfish schenkt, aber man wird mit den Vorteilen von Simon belohnt. Bisher habe ich den Eindruck, dass Simon rattenschnell ist. Ich muss einmal warten, bis ich wirklich grosse Datenmengen übertragen muss.

Jepp. hab hier auch ein ähnliches System angefangen. Nur eben ohne Netbeans. Bin/war schon ziemlich weit: Module lassen sich zur Laufzeit deployen und nutzen, und auch wieder aus dem System entfernen. JPA Unterstützung (so nett wie mit den Annotations in Jboss und Co.) hab ich auch rudimentär drin. War ein ziemliches gefrickel mit den Classloadern und der benötigten ByteCode-Manipulation. Aber jetzt geht's.

Als ich dann das Netbeans Platform 7 Buch bestellt hab kam mir nach wenigen Seiten die Idee: Mensch, wieso so kompliziert, könnte ja auch mit der Netbeans-Platform gehen.
JBoss und Co. sind zwar toll, aber für mein befinden passt das nicht auf alle Client-Server-Architekturen. Geht zwar prinzipiell für alles, aber man muss sich schon seeeeeeehr an die vorgegebenen Konstrukte halten. Ist irgendwie nicht so mein Fall.

Du hast nicht zufällig vor den Source für deine selbstgestrickte Serverplattform zu veröffentlichen, oder?

Zur Geschwindigkeit von SIMON: Meine Performance-Tests im Wiki hast du schon gesehen, oder?
Wenn du deine zu serialisierende Objekthierarchie flach hälst, oder eben Externalize benutzt um es flach zu halten, dann solltest du keine großartigen Performance-Probleme bekommen, auch bei großen Daten nicht (bezogen auf den Overhead durch SIMON)

By the way: Gibt es auch die Möglichkeit, beim Dateitransfer einen InputReader zu verwenden? Es wäre doch schön, wenn man direkt aus der DB streamen könnte, oder?

Steht auf der ToDo Liste für 1.2.0: http://dev.root1.de/versions/show/13 --> http://dev.root1.de/issues/85
Bis dato gibt's nur die RawChannels mit einer Write-Methode auf der einen Seite, und einem entsprechended Listener auf der anderen Seite.

- Alex

(1-3/3)