Stephans Blog

Morphium 6.2.0 — Was ist neu?

Morphium 6.2.0 — Was ist neu?

Nach Monaten intensiver Arbeit ist Morphium 6.2.0 fertig. Dieses Release bringt einige fundamentale Änderungen mit — allen voran die Extraktion von PoppyDB als eigenständiges Modul. Aber der Reihe nach.

Multi-Module Maven-Build

Morphium war bisher ein einzelnes Maven-Projekt. Das hat funktioniert, aber es bedeutete auch, dass jeder, der nur den MongoDB-Client brauchte, automatisch Netty und den gesamten Server-Code mitgeschleppt hat. Ab 6.2.0 ist Morphium ein Multi-Module-Projekt:

  • morphium-parent — Parent POM
  • morphium (artifactId bleibt gleich!) — der Core-Client
  • poppydb — der Server, jetzt eigenständig

Für bestehende Projekte ändert sich nichts an den Maven-Koordinaten:

<dependency>
    <groupId>de.caluga</groupId>
    <artifactId>morphium</artifactId>
    <version>6.2.0</version>
</dependency>

PoppyDB: Der Server wird erwachsen

Der bisher als "MorphiumServer" bekannte In-Memory-MongoDB-Server hat einen eigenen Namen bekommen: PoppyDB (Poppy = Mohnblume, die Quelle von Morphium). Details dazu gibt's in einem eigenen Blog-Post.

@Reference Cascade & Cycle Detection

Referenzen in Morphium können jetzt kaskadiert werden:

@Entity
public class Order {
    @Id private MorphiumId id;

    @Reference(cascadeDelete = true)
    private Customer customer;

    @Reference(orphanRemoval = true)
    private List<OrderItem> items;
}
  • cascadeDelete = true — Löscht referenzierte Objekte mit, wenn das Eltern-Objekt gelöscht wird
  • orphanRemoval = true — Entfernt Referenzen, die nach einem Update nicht mehr in der Collection sind

Zirkuläre Referenzen (A→B→A) werden erkannt und sauber aufgelöst — bei der Serialisierung und Deserialisierung.

@AutoSequence — Sequenznummern ohne Boilerplate

Bisher musste man den SequenceGenerator manuell verwenden. Jetzt reicht eine Annotation:

@Entity
public class ImportRecord {
    @Id private MorphiumId id;

    @AutoSequence(name = "import_number", startValue = 1000, inc = 1)
    private Long importNumber;
}

Explizit gesetzte Werte werden nicht überschrieben — nur null (oder 0 bei Primitiven) wird durch den nächsten Sequenzwert ersetzt. Bei storeList() werden alle Sequenznummern in einem einzigen Roundtrip geholt.

@Version — Optimistic Locking

Endlich eingebaut: Optimistic Locking via @Version. Beim Insert wird die Version auf 1 gesetzt, bei jedem Update atomar inkrementiert. Versucht jemand, eine veraltete Version zu speichern, fliegt eine VersionMismatchException:

@Entity
public class Account {
    @Id private MorphiumId id;
    @Version private Long version;
    private double balance;
}

CosmosDB Auto-Detection

Morphium erkennt jetzt automatisch, ob es mit MongoDB, CosmosDB oder PoppyDB spricht. Die Erkennung erfolgt über die hello-Handshake-Response. Damit kann Morphium Backend-spezifische Eigenheiten berücksichtigen:

if (morphium.isCosmosDB()) {
    // CosmosDB-spezifische Logik
}

Unterstützt werden auch Azure Sovereign Cloud Domains.

MorphiumDriverException ist jetzt unchecked

MorphiumDriverException erweitert jetzt RuntimeException statt Exception. Das folgt der Konvention von MongoDB Java Driver (MongoException), JPA, jOOQ und Spring Data.

Migration: Bestehende catch-Blöcke funktionieren weiter. Nur catch (RuntimeException | MorphiumDriverException e) muss vereinfacht werden zu catch (RuntimeException e).

@CreationTime / @LastChange Verbesserungen

  • LocalDateTime-Support als vierter Feldtyp
  • Nur Feld-Annotation nötig — die Klassen-Annotation ist nicht mehr erforderlich
  • Preset-Werte bleiben erhalten — explizit gesetzte @CreationTime-Werte werden beim Insert nicht mehr überschrieben

Weitere Highlights

  • MONGODB-X509 Client-Zertifikat-Authentifizierung
  • mongodb+srv:// Connection Strings für MongoDB Atlas
  • Konfigurierbare LocalDateTimeMapper — Speicherung als Date oder ISO-8601 String
  • SequenceGenerator.getNextBatch(int) für Bulk-Sequenz-Allokation
  • resetThreadLocalOverrides() — Aufräumen aller Thread-lokalen Overrides in einem Aufruf

Bugfixes

  • Enum-Deserialisierung in Maps und Collections funktioniert jetzt korrekt
  • Custom TypeMappers werden in Queries berücksichtigt
  • BufferedWriter Concurrent Double-Write behoben
  • Quarkus/OSGi ClassLoader — alle Class.forName()-Aufrufe nutzen jetzt den Context ClassLoader
  • WriteConcern auf Standalone MongoDB — graceful Downgrade von w>1 auf w:1

Upgrade

<dependency>
    <groupId>de.caluga</groupId>
    <artifactId>morphium</artifactId>
    <version>6.2.0</version>
</dependency>

Wer PoppyDB für Tests nutzt:

<dependency>
    <groupId>de.caluga</groupId>
    <artifactId>poppydb</artifactId>
    <version>6.2.0</version>
    <scope>test</scope>
</dependency>

Die vollständigen Release Notes gibt's im CHANGELOG auf GitHub.