Gibt es gute Alternativen für das Serialisieren von Enums in Java?

7

Die Java-Sprache profitierte sehr davon, dass sie enums hinzugefügt wurde; aber leider funktionieren sie nicht gut, wenn serialisierte Objekte zwischen Systemen mit unterschiedlichen Code-Ebenen gesendet werden.

Beispiel: Angenommen, Sie haben zwei Systeme A und B. Beide starten mit den gleichen Code-Ebenen, aber irgendwann beginnen die Code-Aktualisierungen zu verschiedenen Zeitpunkten. Nun gehe davon aus, dass es einige gibt %Vor%

Und es gibt andere Objekte, die Referenzen auf Konstanten dieser Enumeration behalten. Diese Objekte werden serialisiert und von A nach B oder umgekehrt gesendet. Bedenke nun, dass B eine neuere Version von Whatever

hat %Vor%

Dann:

%Vor%

wird instanziiert ...

%Vor%

und dann serialisiert und an A gesendet (zum Beispiel als Ergebnis eines RMI-Aufrufs). Was ist schlecht, denn jetzt wird bei der Deserialisierung auf A ein Fehler auftreten: A kennt die Whatever enum-Klasse, aber in einer Version, die nicht SECOND hat.

Wir haben das auf die harte Tour gemerkt; und jetzt bin ich sehr bestrebt, Enums für Situationen zu verwenden, die eigentlich "perfekt für Enums" wären; einfach weil ich weiß, dass ich ein existierendes enum später nicht einfach erweitern kann.

Nun frage ich mich: Gibt es (gute) Strategien, um solche Kompatibilitätsprobleme mit Enums zu vermeiden? Oder muss ich wirklich zurück zu "Prä-Enum" Zeiten gehen; und verwende keine Enums, sondern musst dich auf eine Lösung verlassen, bei der ich überall einfache Strings verwende?

Update: Bitte beachten Sie, dass die Verwendung der serialversionuid hier überhaupt nicht hilft. Dieses Ding hilft dir nur dabei, eine inkompatible Veränderung "offensichtlicher" zu machen. Aber der Punkt ist: Es ist mir egal, warum die Deserialisierung fehlschlägt - weil ich es vermeiden muss. Und ich bin auch nicht in der Lage, unsere Art der Serialisierung unserer Objekte zu verändern. Wir machen RMI; und wir serialisieren zu binär; Ich habe keine Möglichkeit, das zu ändern.

    
GhostCat 01.08.2016, 13:34
quelle

2 Antworten

0

Nachdem ich zu verschiedenen Lösungen hin und her gegangen bin, habe ich eine Lösung gefunden, die auf dem Vorschlag von @GuiSim basiert: Man kann eine Klasse erstellen, die einen Enum-Wert enthält. Diese Klasse kann

  1. benutzerdefinierte Deserialisierung durchführen; somit kann ich verhindern, dass es während des Deserialisierungsprozesses keine Ausnahmen gibt
  2. bietet einfache Methoden wie isValid () und getEnumValue () : Der erste Befehl sagt Ihnen, ob die Enumerierung des Enumerierens tatsächlich funktioniert hat; und die zweite gibt die deserialisierte enum zurück (oder löst eine Ausnahme aus)
GhostCat 03.08.2016, 07:59
quelle
6

Wie @Jesper in den Kommentaren erwähnt, würde ich etwas wie JSON für Ihre dienststellenübergreifende Kommunikation empfehlen. Dadurch können Sie besser steuern, wie unbekannte Enum-Werte gehandhabt werden.

Zum Beispiel könnt ihr mit dem immer tollen Jackson das Deserialisierungsfunktionen READ_UNKNOWN_ENUM_VALUES_AS_NULL oder READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE . Beides ermöglicht Ihrer Anwendungslogik, unbekannte Enum-Werte so zu verarbeiten, wie Sie es für richtig halten.

Beispiel (direkt aus dem Jackson-Dokument)

%Vor%     
GuiSim 01.08.2016 14:12
quelle

Tags und Links