Modul 13 · Migration Deep Dive · Stufe 2 Java Core

Generics

Raw Types und Casts wird nachvollziehbar in typsichere generische Repositorys überführt. Die Akte zeigt nicht nur das Ziel, sondern die tatsächlichen Dateien, APIs, Dependencies, Codebelege, Tests, Risiken und Cutover-Schritte.

Generic RepositoryType Token
1 → 5Produktionsdateien
15 → 53Java-Zeilen
1 → 2Testdateien
0 / 0Dependencies entfernt / neu
NIEDRIGRisiko · Score 0

Was sich konkret ändert

DimensionLegacyModernMigrationskonsequenz
ProgrammiermodellSuppressWarningsexplizite Java-AbstraktionenAnnotationen und Containerfunktionen werden nur dort eingesetzt, wo sie eine konkrete technische Verantwortung übernehmen.
Abhängigkeiten1 direkte Dependencies1 direkte Dependencies0 neu, 0 entfernt; Versionen und transitive Auswirkungen im erfolgreichen Online-Build prüfen.
Öffentliche API2 erkannte Methoden5 erkannte MethodenMethoden werden nach fachlicher Rolle gemappt; reine Bootstrap- und Framework-Methoden sind kein fachlicher Vertrag.
Datenmodellclass RawBoxclass InMemoryRepository, class TypedBox, interface Identifiable, interface Repository, record CustomerFeldnamen, IDs, Null-Semantik, Gleichheit und Serialisierungsform werden separat regressionstestet.
FehlerverhaltenLegacy-Exceptions und Rückgabewerteexplizitere Fach-/Framework-FehlerabbildungFehler dürfen nicht nur technisch übersetzt werden; Status, Ursache, Retrybarkeit und Client-Vertrag müssen erhalten oder versioniert werden.
TestsBestands- und Golden-Master-TestsUnit-, Slice-, Contract- und IntegrationstestsDer Modern-Pfad wird zuerst gegen denselben fachlichen Vektor geprüft und danach um neue technische Risiken ergänzt.
BetriebLegacy-Start/Lifecyclemodernes Packaging, Health und externe KonfigurationUmstellung über kleine Adapter und Golden-Master-Tests statt Big Bang.
RollbackLegacy-Artefakt bleibt unverändertModern-Artefakt getrennt deploybarKein Rollback über Datenverlust: Schema, Nachrichten und verschlüsselte Daten müssen rückwärtslesbar oder durch Dual-Read abgesichert sein.

Fachlicher Vertrag: unverändert zu erhalten

  • Typfehler werden zur Compile-Zeit statt per ClassCastException sichtbar.
  • Repository-Identität und Optional-Semantik sind stabil.
  • Keine unnötigen Wildcard-/Type-Token-Komplexitäten werden eingeführt.

Hauptrisiko und Testfokus

runtime ClassCastException versus compile-time safety

generic boundaries, absent values and repository identity tests

Die Modernisierung gilt erst als abgeschlossen, wenn der fachliche Vertrag automatisiert belegt ist.

Verbindliches Code- und Rollenmapping

Die Zuordnung ist semantisch: Eine Legacy-Klasse kann in mehrere moderne Rollen zerlegt werden.

Legacy-Rolle / DateiModern-Rolle / DateiBedeutung
RawBox.javaTypedBox.javaObject-Container wird typsicher.
RawBox-AnwendungsfallRepository.java + InMemoryRepository.java + Identifiable.javaGenerischer Datenzugriffsvertrag wird ergänzt.
untypisierte DomänenwerteCustomer.javaKonkreter typsicherer Repository-Typ.

Legacy-Quellinventar

DateiTypAnnotationenöffentliche APIPatternZeilen
RawBox.javaclass RawBoxSuppressWarningsvoid set(Object value)
Object get()
Generic Container (Legacy) – kapselt Werte, verliert durch Raw Types jedoch Typsicherheit.15

Modern-Quellinventar

DateiTypAnnotationenöffentliche APIPatternZeilen
Customer.javarecord Customer4
Identifiable.javainterface Identifiable5
InMemoryRepository.javaclass InMemoryRepositoryT save(T entity)
Optional<T> findById(ID id)
List<T> findAll()
19
Repository.javainterface RepositoryGeneric Repository11
TypedBox.javaclass TypedBoxvoid set(T value)
T get()
Generic Container14

Dependency- und Laufzeitmigration

StatusDependencyVersionScopePrüfung
BEIBEHALTENorg.junit.jupiter:junit-jupiterBOM/Parent → BOM/Parenttest → testGemeinsame Dependency; Version und Scope im effektiven POM prüfen.
Direkte POM-Daten ersetzen keinen erfolgreichen Online-Build mit transitiver SBOM- und CVE-Prüfung.

Vorher-/Nachher-Codebelege

Die folgenden Ausschnitte stammen direkt aus den enthaltenen Projekten. Dadurch ist sichtbar, welche Verantwortung tatsächlich verschoben wurde.

Legacy
RawBox.java
Modern
TypedBox.java

Migrationsbedeutung: Object-Container wird typsicher.

Legacy-Code

projects/13-generics/legacy/src/main/java/at/aydin/lab/generics/legacy/RawBox.java

package at.aydin.lab.generics.legacy;

// Design Pattern: Generic Container (Legacy) – kapselt Werte, verliert durch Raw Types jedoch Typsicherheit.
@SuppressWarnings({
    "rawtypes", "unchecked"
}) public final class RawBox {
    private Object value;
    public void set(Object value) {
        this.value = value;
    }

    public Object get() {
        return value;
    }
}

Modern-Code

projects/13-generics/modern/src/main/java/at/aydin/lab/generics/modern/TypedBox.java

package at.aydin.lab.generics.modern;

// Design Pattern: Generic Container
// Zweck: Der gespeicherte Typ wird zur Compile-Zeit festgelegt; Laufzeit-Casts entfallen.
public final class TypedBox<T> {
    private T value;
    public void set(T value) {
        this.value = value;
    }

    public T get() {
        return value;
    }
}
Technischen Unified Diff öffnen
--- RawBox.java
+++ TypedBox.java
@@ -1,15 +1,14 @@
-package at.aydin.lab.generics.legacy;
+package at.aydin.lab.generics.modern;
 
-// Design Pattern: Generic Container (Legacy) – kapselt Werte, verliert durch Raw Types jedoch Typsicherheit.
-@SuppressWarnings({
-    "rawtypes", "unchecked"
-}) public final class RawBox {
-    private Object value;
-    public void set(Object value) {
+// Design Pattern: Generic Container
+// Zweck: Der gespeicherte Typ wird zur Compile-Zeit festgelegt; Laufzeit-Casts entfallen.
+public final class TypedBox<T> {
+    private T value;
+    public void set(T value) {
         this.value = value;
     }
 
-    public Object get() {
+    public T get() {
         return value;
     }
 }
Legacy
RawBox-Anwendungsfall
Modern
Repository.java + InMemoryRepository.java + Identifiable.java

Migrationsbedeutung: Generischer Datenzugriffsvertrag wird ergänzt.

Legacy-Code

projects/13-generics/legacy/src/main/java/at/aydin/lab/generics/legacy/RawBox.java

package at.aydin.lab.generics.legacy;

// Design Pattern: Generic Container (Legacy) – kapselt Werte, verliert durch Raw Types jedoch Typsicherheit.
@SuppressWarnings({
    "rawtypes", "unchecked"
}) public final class RawBox {
    private Object value;
    public void set(Object value) {
        this.value = value;
    }

    public Object get() {
        return value;
    }
}

Modern-Code

projects/13-generics/modern/src/main/java/at/aydin/lab/generics/modern/Repository.java

package at.aydin.lab.generics.modern;

import java.util.*;

// Design Pattern: Generic Repository
// Zweck: Wiederverwendbarer, typsicherer Datenzugriffsvertrag für unterschiedliche Entitäten.
public interface Repository<ID, T extends Identifiable<ID>> {
    T save(T entity);
    Optional<T> findById(ID id);
    List<T> findAll();
}

Modern-Code

projects/13-generics/modern/src/main/java/at/aydin/lab/generics/modern/InMemoryRepository.java

package at.aydin.lab.generics.modern;

import java.util.*;

public final class InMemoryRepository<ID, T extends Identifiable<ID>> implements Repository<ID, T> {
    private final Map<ID, T> data = new LinkedHashMap<>();
    public T save(T entity) {
        data.put(entity.id(), entity);
        return entity;
    }

    public Optional<T> findById(ID id) {
        return Optional.ofNullable(data.get(id));
    }

    public List<T> findAll() {
        return List.copyOf(data.values());
    }
}
Legacy
untypisierte Domänenwerte
Modern
Customer.java

Migrationsbedeutung: Konkreter typsicherer Repository-Typ.

Legacy-Code

projects/13-generics/legacy/src/main/java/at/aydin/lab/generics/legacy/RawBox.java

package at.aydin.lab.generics.legacy;

// Design Pattern: Generic Container (Legacy) – kapselt Werte, verliert durch Raw Types jedoch Typsicherheit.
@SuppressWarnings({
    "rawtypes", "unchecked"
}) public final class RawBox {
    private Object value;
    public void set(Object value) {
        this.value = value;
    }

    public Object get() {
        return value;
    }
}

Modern-Code

projects/13-generics/modern/src/main/java/at/aydin/lab/generics/modern/Customer.java

package at.aydin.lab.generics.modern;

public record Customer(Long id, String name) implements Identifiable<Long> {
}
Technischen Unified Diff öffnen
--- RawBox.java
+++ Customer.java
@@ -1,15 +1,4 @@
-package at.aydin.lab.generics.legacy;
+package at.aydin.lab.generics.modern;
 
-// Design Pattern: Generic Container (Legacy) – kapselt Werte, verliert durch Raw Types jedoch Typsicherheit.
-@SuppressWarnings({
-    "rawtypes", "unchecked"
-}) public final class RawBox {
-    private Object value;
-    public void set(Object value) {
-        this.value = value;
-    }
-
-    public Object get() {
-        return value;
-    }
+public record Customer(Long id, String name) implements Identifiable<Long> {
 }

Umsetzungsplan mit Qualitäts-Gates

  1. Arbeitspaket 1
    Alle RawBox-Aufrufer und erwarteten Typen erfassen. Nachweis: Commit/PR, automatisierter Test und aktualisierte Betriebsdokumentation.
  2. Arbeitspaket 2
    TypedBox schrittweise mit konkreten Typen einführen. Nachweis: Commit/PR, automatisierter Test und aktualisierte Betriebsdokumentation.
  3. Arbeitspaket 3
    Identifiable und Repository-Vertrag definieren. Nachweis: Commit/PR, automatisierter Test und aktualisierte Betriebsdokumentation.
  4. Arbeitspaket 4
    InMemoryRepository mit stabiler ID-Semantik implementieren. Nachweis: Commit/PR, automatisierter Test und aktualisierte Betriebsdokumentation.
  5. Arbeitspaket 5
    Unchecked-Warnungen auf null reduzieren. Nachweis: Commit/PR, automatisierter Test und aktualisierte Betriebsdokumentation.
  6. Arbeitspaket 6
    Alte Cast-Pfade nach vollständiger Kompilierung entfernen. Nachweis: Commit/PR, automatisierter Test und aktualisierte Betriebsdokumentation.

Konkreter Test- und Abnahmekatalog

IDEbenePrüfungerforderlicher Nachweis
13-GENERICS-A01Integration/ContractBuild ist ohne unchecked-Warnungen.Automatisierter Test und CI-Protokoll
13-GENERICS-A02Integration/ContractFalscher Typ ist nicht mehr kompilierbar.Automatisierter Test und CI-Protokoll
13-GENERICS-A03Integration/ContractFind-by-ID liefert eindeutig Optional.Automatisierter Test und CI-Protokoll
13-GENERICS-A04Integration/ContractSpeichern überschreibt/ergänzt nach dokumentierter Regel.Automatisierter Test und CI-Protokoll
13-GENERICS-A05Integration/ContractGenerische API bleibt für Aufrufer verständlich.Automatisierter Test und CI-Protokoll
13-GENERICS-T01UnitFachlogik ohne Container oder externen Dienst testen.Unit-Test
13-GENERICS-T02RegressionLegacy- und Modern-Ergebnis für denselben Golden-Master-Vektor vergleichen.Vergleichsreport
13-GENERICS-T03NegativeFehlerhafte, leere und grenzwertige Eingaben prüfen.Negativtest
13-GENERICS-T04OperationsStart, Health, Shutdown und Konfigurationsfehler prüfen.Deployment-/Startprotokoll
13-GENERICS-F01Fokusgeneric boundaries, absent values and repository identity testsModulspezifischer Testreport

Risikoregister des Moduls

RisikoAuswirkungGegenmaßnahmeGate
runtime ClassCastException versus compile-time safetyNIEDRIGgeneric boundaries, absent values and repository identity testsvor Cutover

Konfiguration und Ressourcen

Keine zusätzlichen Ressourcen.

Rollback und Koexistenz

Ein begrenzter Adapter kann Object akzeptieren und intern validieren; er darf nicht zur dauerhaften neuen Raw-Type-Schicht werden.

Abbruchkriterien

  • Fachlicher Golden-Master weicht ab.
  • Daten-, Nachrichten- oder API-Kompatibilität ist ungeklärt.
  • Fehlerquote, Latenz oder Ressourcenverbrauch überschreiten das vereinbarte Limit.
  • Monitoring oder Rückfallpfad ist nicht funktionsfähig.

Definition of Done

Direkte Arbeitslinks

⌂ Cockpit