Konsolidierte Ansicht

Migration-Gesamthandbuch

Alle 34 Migrationsakten in einer Datei. Die vollständigen Modulakten enthalten zusätzlich farbig formatierte Codeausschnitte und technische Diffs.

34Module
70Rollen-Mappings
204Umsetzungspakete
170Abnahmekriterien
163Produktionsdateien

Inhaltsverzeichnis

  1. 01 · Dependency Injection
  2. 02 · AOP
  3. 03 · REST
  4. 04 · Persistenz
  5. 05 · Transaktionen
  6. 06 · Batch
  7. 07 · Messaging
  8. 08 · XML und JAXB
  9. 09 · Servlet und Web
  10. 10 · SOAP
  11. 11 · Java-Grundlagen
  12. 12 · Collections
  13. 13 · Generics
  14. 14 · Annotations und Reflection
  15. 15 · Lambda und Streams
  16. 16 · Concurrency
  17. 17 · Java I/O und NIO
  18. 18 · Exception Handling und Logging
  19. 19 · JUnit und Testdesign
  20. 20 · HTTP-Client und Webtest
  21. 21 · Maven Properties und Konfiguration
  22. 22 · Spring JDBC
  23. 23 · Hibernate und JPA
  24. 24 · MongoDB
  25. 25 · JNDI und Service-Auflösung
  26. 26 · JMX und Monitoring
  27. 27 · EJB und Services
  28. 28 · JPMS / Jigsaw
  29. 29 · Service Registry und ServiceLoader
  30. 30 · XML Parser
  31. 31 · XSLT
  32. 32 · Kryptografie
  33. 33 · SMTP und Mail
  34. 34 · Patterns und Refactoring

Alle Module

01 · Dependency Injection — Service Locator / manuelle Verdrahtung → Spring Constructor Injection

Fachlicher Vertrag

  • Die Grußfunktion liefert für denselben Namen denselben fachlichen Text.
  • Der fachliche Use Case kennt weder Spring noch einen globalen Registry-Zugriff.
  • Fehlende Implementierungen werden bereits beim Start beziehungsweise Konstruktoraufruf sichtbar.

Risiko / Testfokus

hidden dependencies, global state

constructor-level unit tests and context smoke test

Code-Mapping

LegacyModernBedeutung
ServiceRegistry.javaSpring Context / Constructor InjectionVersteckte globale Auflösung wird durch explizite Verdrahtung ersetzt.
GreetingService.javaGreetingPort.javaFachlicher Servicevertrag wird als Port stabilisiert.
DefaultGreetingService.javaGermanGreetingService.javaKonkrete Implementierung bleibt fachlich gleich.
DiLegacyApplication.javaDiModernApplication.java + GreetingRunner.javaBootstrap und Use-Case-Ausführung werden getrennt.

Umsetzung

  1. GreetingService als fachlichen Port festlegen und Aufrufer dagegen testen.
  2. Direkte Zugriffe auf ServiceRegistry erfassen und durch Konstruktorparameter ersetzen.
  3. DefaultGreetingService funktional in GermanGreetingService überführen.
  4. GreetingRunner als Application Adapter einführen; keine Container-API in den Port aufnehmen.
  5. Spring-Komponenten nur am äußeren Rand annotieren und Context-Smoke-Test ergänzen.
  6. Globalen Registry-Zustand entfernen und Parallelbetrieb über Adapter ermöglichen.

Abnahme

  • Kein Produktionscode ruft ServiceRegistry auf.
  • GreetingPort lässt sich ohne Spring-Kontext unit-testen.
  • Anwendung startet nur mit genau einer passenden Implementierung.
  • Legacy- und Modern-Ausgabe sind für definierte Testfälle identisch.
  • Kein statischer veränderlicher Servicezustand bleibt zurück.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

02 · AOP — JDK Dynamic Proxy → Spring AOP mit @Aspect

Fachlicher Vertrag

  • Rechenergebnisse und Exceptions des Zielobjekts bleiben unverändert.
  • Tracking darf keine fachliche Transaktion starten oder beenden.
  • Sensitive Parameter werden nicht ungefiltert protokolliert.

Risiko / Testfokus

proxy limitations and cross-cutting coupling

aspect activation, exception and ordering tests

Code-Mapping

LegacyModernBedeutung
LoggingProxy.javaTrackingAspect.java + Tracked.javaManueller Proxy wird durch deklarativen Interceptor ersetzt.
SimpleCalculator.javaTrackedCalculator.javaZielobjekt bleibt fachlich, erhält nur explizite Markierung.
AopLegacyApplication.javaAopModernApplication.java + CalculatorRunner.javaComposition Root wird vom Runner getrennt.

Umsetzung

  1. Alle über LoggingProxy abgefangenen Methoden und Nebenwirkungen inventarisieren.
  2. Tracked als explizites Pointcut-Merkmal definieren und unbeabsichtigte Treffer vermeiden.
  3. LoggingProxy-Verhalten in Around-Advice nachbilden, einschließlich Exception-Pfad.
  4. Self-invocation und nur über Proxy erreichbare Methoden explizit testen.
  5. Reihenfolge zu Transaktions-, Security- und Retry-Aspekten festlegen.
  6. Proxy-Implementierung erst entfernen, wenn Ergebnis-, Exception- und Log-Verträge übereinstimmen.

Abnahme

  • Markierte Methoden werden genau einmal gemessen.
  • Nicht markierte Methoden bleiben unbeeinflusst.
  • Originalexception und Stacktrace bleiben erhalten.
  • Keine rekursive Aspect-Ausführung.
  • Pointcut- und Reihenfolgetests sind grün.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

03 · REST — JAX-RS 2.1 mit javax.ws.rs → Spring Boot REST mit jakarta.validation

Fachlicher Vertrag

  • HTTP-Pfade, Verben, Statuscodes und JSON-Felder werden bewusst versioniert.
  • Book-ID und Repository-Semantik bleiben stabil.
  • Ungültige Eingaben liefern ein dokumentiertes, maschinenlesbares Fehlerformat.

Risiko / Testfokus

HTTP contract drift and validation gaps

status codes, validation, error payload and actuator exposure

Code-Mapping

LegacyModernBedeutung
BookResource.javaBookController.java + BookService.javaResource-Verantwortung wird in HTTP-Adapter und Service Layer getrennt.
BookRepository.javaBookRepository.javaDatenzugriffsvertrag bleibt erhalten.
Book.javaBook.javaAPI-/Domain-Datenform bleibt vergleichbar.
RestLegacyApplication.javaRestModernApplication.javaJersey/Grizzly-Bootstrap wird Spring Boot Bootstrap.

Umsetzung

  1. JAX-RS-Vertrag aus BookResource als Contract-Test festhalten.
  2. BookRepository zunächst unverändert hinter BookService verwenden.
  3. BookController mit denselben Pfaden und Medienformaten einführen.
  4. Bean Validation und globale Fehlerabbildung ergänzen; Fehlerpayload versionieren.
  5. Legacy- und Modern-Endpunkt im Parallelbetrieb gegen dieselben Testvektoren ausführen.
  6. Traffic erst nach Contract-, Last- und Observability-Prüfung umschalten.

Abnahme

  • GET und POST liefern erwartete Statuscodes und Content-Type.
  • Bestehende JSON-Clients funktionieren oder erhalten dokumentierte Versionierung.
  • Validierungsfehler enthalten Feld, Code und verständliche Meldung.
  • Repository-IDs werden nicht doppelt vergeben.
  • Actuator-Endpunkte sind nicht versehentlich öffentlich exponiert.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

04 · Persistenz — JDBC und DAO → Spring Data JPA

Fachlicher Vertrag

  • Tabellen-, Spalten- und Schlüsselstruktur bleibt bis zur kontrollierten Schemaänderung kompatibel.
  • Transaktionsgrenzen liegen im Service und nicht im Controller/Repository.
  • Lazy Loading tritt nicht außerhalb einer aktiven Transaktion auf.

Risiko / Testfokus

schema drift, lazy loading and transaction boundaries

repository slice, service transaction and rollback tests

Code-Mapping

LegacyModernBedeutung
CustomerDao.java + JdbcCustomerDao.javaCustomerRepository.javaDAO/SQL-Zugriff wird Repository-Abstraktion.
Customer.javaCustomerEntity.javaDatenobjekt wird explizite JPA Entity.
PersistenceLegacyApplication.javaPersistenceModernApplication.java + CustomerService.javaBootstrap und transaktionaler Use Case werden getrennt.

Umsetzung

  1. CustomerDao-SQL und ResultSet-Mapping als Golden-Master-Tests sichern.
  2. CustomerEntity exakt gegen bestehendes Schema mappen; automatische DDL-Erzeugung deaktivieren.
  3. CustomerRepository zunächst nur für lesende Use Cases aktivieren.
  4. CustomerService mit expliziten Transaktionsgrenzen einführen.
  5. Schreibpfad per Shadow Read/Write oder Vergleichslauf validieren.
  6. N+1-, Locking- und Rollback-Verhalten messen, bevor DAO entfernt wird.

Abnahme

  • Alle bestehenden Datensätze lassen sich ohne Schemaverlust lesen.
  • Schreiboperationen erzeugen identische Schlüssel und Pflichtfelder.
  • Rollback hinterlässt keine Teildaten.
  • Keine unkontrollierte DDL-Änderung beim Start.
  • Query-Anzahl und Laufzeit bleiben innerhalb definierter Grenzen.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

05 · Transaktionen — manuelles Commit/Rollback → @Transactional

Fachlicher Vertrag

  • Eine Überweisung ist atomar: beide Konten oder keines werden geändert.
  • Rollback-Regeln für fachliche und technische Exceptions sind explizit.
  • Beträge werden ohne Gleitkommafehler verarbeitet.

Risiko / Testfokus

partial writes and incorrect rollback rules

success, checked/unchecked failure and rollback assertions

Code-Mapping

LegacyModernBedeutung
LegacyTransferService.javaTransferService.java + AccountRepository.javaManuelle Connection-Transaktion wird deklarativer Service plus Datenadapter.
TransactionsLegacyApplication.javaTransactionsModernApplication.javaBootstrap wechselt auf Spring Transaction Management.

Umsetzung

  1. Commit-/Rollback-Pfade des LegacyTransferService mit Datenbanktests festhalten.
  2. AccountRepository als reinen Datenadapter ohne Transaktionssteuerung gestalten.
  3. TransferService als einzige Transaktionsgrenze definieren.
  4. Checked- und Runtime-Exception-Regeln explizit konfigurieren und testen.
  5. Nebenläufige Transfers mit geeigneter Sperr-/Versionsstrategie prüfen.
  6. Manuelle Connection-Steuerung erst nach Recovery- und Timeout-Tests entfernen.

Abnahme

  • Saldo-Summe bleibt vor und nach Transfer gleich.
  • Fehler nach erster Buchung führt zum vollständigen Rollback.
  • Unzureichende Deckung erzeugt definierte Fachfehler.
  • Paralleltests zeigen keine Lost Updates.
  • Transaktions-Timeout und Isolation sind dokumentiert.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

06 · Batch — manueller CSV-Ablauf → Spring Batch Pipeline

Fachlicher Vertrag

  • Jede Eingabezeile wird höchstens einmal fachlich wirksam.
  • Restart setzt an einem konsistenten Checkpoint fort.
  • Fehlerhafte Datensätze werden nach klarer Skip-/Fail-Regel behandelt.

Risiko / Testfokus

restartability, duplicate processing and bad-record policy

job launch, restart, skip/retry and idempotency tests

Code-Mapping

LegacyModernBedeutung
LegacyBatchImporter.java + CsvOrderParser.javaBatchConfiguration.javaImperativer Ablauf wird Reader/Processor/Writer-Pipeline.
OrderRow.javaOrderRow.javaFachlicher Datensatz bleibt stabil.
BatchLegacyApplication.javaBatchModernApplication.javaManueller Start wird Spring-Batch-Jobstart.

Umsetzung

  1. CSV-Format, Header, Zeichensatz und Dezimalregeln als Input Contract festhalten.
  2. CsvOrderParser-Logik in Reader/Processor/Writer-Verantwortungen zerlegen.
  3. JobRepository und persistente Metadaten konfigurieren.
  4. Idempotenzschlüssel und Duplicate-Policy definieren.
  5. Skip-, Retry-, Restart- und Abbruchgrenzen mit realistischen Dateien testen.
  6. Scheduler/Operator erst nach identischen Summen- und Fehlerreports umstellen.

Abnahme

  • Erstlauf und Restart ergeben denselben Endbestand.
  • Fehlerzeilen sind vollständig nachvollziehbar.
  • Keine doppelte Verarbeitung nach Prozessabbruch.
  • Chunk-Transaktionen sind konsistent.
  • Jobparameter verhindern versehentliche Doppelstarts.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

07 · Messaging — javax.jms und ActiveMQ Classic → Spring JMS mit jakarta.jms

Fachlicher Vertrag

  • Nachrichtenformat und Destination werden versioniert und rückwärtskompatibel behandelt.
  • At-least-once-Zustellung führt nicht zu doppelter fachlicher Wirkung.
  • Poison Messages gelangen kontrolliert in eine DLQ.

Risiko / Testfokus

duplicate delivery, poison messages and vulnerable legacy broker

redelivery, idempotency, DLQ and serialization tests

Code-Mapping

LegacyModernBedeutung
LegacyJmsGateway.javaOrderMessagePublisher.java + OrderMessageListener.javaEin JMS Gateway wird in Producer und Consumer getrennt.
MessagingLegacyApplication.javaMessagingModernApplication.java + MessageDemoRunner.javaEmbedded-Broker-Demo wird Spring-Boot-Komposition.

Umsetzung

  1. JMS-Header, Payload, Queue-Namen und Acknowledgement-Modus inventarisieren.
  2. Publisher und Listener hinter fachliche Ports legen.
  3. Serializer/Deserializer mit Schema- und Versionsprüfung einführen.
  4. Idempotenzspeicher, Redelivery und DLQ-Regeln konfigurieren.
  5. Legacy ActiveMQ Classic nur für Vergleich/Übergang nutzen und Broker-Upgrade planen.
  6. Produzenten und Konsumenten gestaffelt migrieren; gemischte Versionen testen.

Abnahme

  • Doppelte Nachricht erzeugt nur eine fachliche Änderung.
  • Fehlerhafte Nachricht landet nach definierter Anzahl Versuche in der DLQ.
  • Correlation-ID bleibt erhalten.
  • Shutdown verliert keine bestätigten Nachrichten.
  • Broker- und Clientversion sind security-geprüft.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

08 · XML und JAXB — javax.xml.bind → jakarta.xml.bind

Fachlicher Vertrag

  • Namespace, Elementnamen, Reihenfolge und optionale Felder bleiben schema-kompatibel.
  • Zeichensatz und Datums-/Zahlenformate ändern sich nicht unbemerkt.
  • Externe Entitäten werden nicht aufgelöst.

Risiko / Testfokus

namespace and schema compatibility

round-trip, invalid XML, encoding and XXE-negative tests

Code-Mapping

LegacyModernBedeutung
LegacyCustomer.javaModernCustomer.javajavax JAXB Model wird Jakarta JAXB Model.
LegacyXmlMapper.javaModernXmlMapper.javaMarshaller/Unmarshaller-Verantwortung bleibt erhalten.
XmlLegacyApplication.javaXmlModernApplication.javaBootstrap wird auf Jakarta Runtime umgestellt.

Umsetzung

  1. Repräsentative Legacy-XMLs und XSDs als Golden Master sammeln.
  2. javax-Modelle auf jakarta-Pakete umstellen, ohne XML-Annotationen semantisch zu ändern.
  3. Marshaller-/Unmarshaller-Konfiguration explizit machen.
  4. Round-trip- und Cross-Version-Tests ausführen.
  5. Unknown-Field- und Versionierungsstrategie festlegen.
  6. Legacy Mapper erst nach Partner-/Schemafreigabe entfernen.

Abnahme

  • Legacy-XML wird vom Modern Mapper gelesen.
  • Modern erzeugtes XML erfüllt das bestehende Schema.
  • Round-trip verliert keine Pflichtinformationen.
  • Ungültiges XML wird sauber abgewiesen.
  • XXE-Test bleibt negativ.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

09 · Servlet und Web — javax.servlet → Spring MVC auf jakarta.servlet

Fachlicher Vertrag

  • Pfad, Statuscode, Content-Type und Response-Body bleiben vertragskonform.
  • Container-spezifische Startlogik wird vom Controller getrennt.
  • Statische Inhalte und API-Routen kollidieren nicht.

Risiko / Testfokus

container/API migration and endpoint compatibility

web slice, content type, health and malformed request tests

Code-Mapping

LegacyModernBedeutung
StatusServlet.javaStatusController.javaServlet Adapter wird Spring MVC Controller.
ServletLegacyApplication.javaWebModernApplication.javaEmbedded Jetty Bootstrap wird Spring Boot.

Umsetzung

  1. Servlet-Mappings und Jetty-Startparameter dokumentieren.
  2. StatusServlet-Verhalten durch Mock-/HTTP-Contract-Tests sichern.
  3. StatusController mit identischem externem Vertrag implementieren.
  4. Fehlerbehandlung, CORS und Header zentral konfigurieren.
  5. Reverse-Proxy- und Context-Path-Verhalten testen.
  6. Legacy-Container nach Umschaltung und Beobachtungsphase entfernen.

Abnahme

  • Health-/Status-Antwort ist semantisch identisch.
  • Content-Type und Encoding stimmen.
  • Unbekannte Pfade liefern definiertes 404-Verhalten.
  • Keine unbeabsichtigten Management-Endpunkte sind extern.
  • Graceful Shutdown funktioniert.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

10 · SOAP — javax JAX-WS → Jakarta XML Web Services

Fachlicher Vertrag

  • WSDL, Namespace, Operationen und XML-Schema sind die primären Verträge.
  • SOAP Faults behalten fachliche Codes und Detailstruktur.
  • Endpoint-Adresse ist konfigurierbar und nicht im Fachcode verankert.

Risiko / Testfokus

WSDL/namespace compatibility and fault mapping

contract, SOAP fault and interoperability tests

Code-Mapping

LegacyModernBedeutung
LegacyCalculatorEndpoint.javaModernCalculatorEndpoint.javajavax JAX-WS Endpoint wird Jakarta Endpoint bei stabilem SOAP-Vertrag.
SoapLegacyApplication.javaSoapModernApplication.javaEndpoint-Publishing wechselt Namespace/Runtime.

Umsetzung

  1. WSDL/XSD und Beispielnachrichten versioniert sichern.
  2. javax- zu jakarta-Imports migrieren, ohne Contract-First-Artefakte zu verändern.
  3. Endpoint-Publishing und Handler/Interceptors getrennt konfigurieren.
  4. Legacy- und Modern-Service gegen denselben Client-Test ausführen.
  5. Fault-, MTOM-, Header- und Encoding-Fälle prüfen, soweit verwendet.
  6. Consumer-Freigabe einholen, bevor alte Endpoint-URL abgeschaltet wird.

Abnahme

  • WSDL-Diff enthält nur genehmigte Änderungen.
  • Bestehender Client kann den neuen Endpoint aufrufen.
  • SOAP Faults sind kompatibel.
  • Namespaces und Elementreihenfolge stimmen.
  • Timeout/Transportfehler werden nachvollziehbar protokolliert.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

11 · Java-Grundlagen — mutable JavaBean und Hilfsklassen → Records, Pattern Matching und Value Objects

Fachlicher Vertrag

  • Gleichheit, Hashing und String-Repräsentation werden bewusst definiert.
  • Records bleiben echte Value Objects ohne versteckte Mutable State.
  • Serialisierung wird bei extern verwendeten Modellen explizit geprüft.

Risiko / Testfokus

serialization/equality behavior changes

equals/hashCode, validation and immutability tests

Code-Mapping

LegacyModernBedeutung
LegacyCustomer.javaCustomer.java + CustomerStatus.javaMutable Bean wird Record plus typisierter Status.
BasicsLegacyApplication.javaBasicsModernApplication.javaAufrufer wird auf Value Semantics umgestellt.

Umsetzung

  1. Bean-Eigenschaften, Nullregeln und Mutationen inventarisieren.
  2. Customer als Record nur dort einsetzen, wo Wertsemantik passt.
  3. Status-Strings durch CustomerStatus mit stabiler externer Repräsentation ersetzen.
  4. Adapter für Bean-basierte Frameworks oder Mapper ergänzen.
  5. Equals/hashCode- und JSON/XML-Verhalten vergleichen.
  6. Mutable Bean erst entfernen, wenn alle Integrationen angepasst sind.

Abnahme

  • Wertegleichheit entspricht fachlicher Erwartung.
  • Keine Mutation nach Konstruktion möglich.
  • Persistenz-/Serialisierungsframeworks können den Typ verarbeiten.
  • Statuswerte sind versionierbar.
  • Null- und Validierungsregeln sind getestet.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

12 · Collections — Vector, Hashtable und Enumeration → generische Collections und unveränderliche Sichten

Fachlicher Vertrag

  • Reihenfolge, Duplikat- und Null-Semantik sind dokumentiert.
  • Aufrufer erhalten keine veränderbare interne Collection.
  • Iteration bleibt deterministisch, wenn fachlich erforderlich.

Risiko / Testfokus

mutation leaks and ordering semantics

aliasing, null, duplicates and ordering tests

Code-Mapping

LegacyModernBedeutung
LegacyInventory.javaInventory.javaLegacy Collections werden generisch und defensiv gekapselt.

Umsetzung

  1. Verwendung von Vector, Hashtable und Enumeration erfassen.
  2. Generische Typen einführen und Casts entfernen.
  3. Inventory mit defensiven Kopien/Views implementieren.
  4. Nebenläufigkeitsannahmen explizit prüfen; Vector-Synchronisierung nicht blind verlieren.
  5. Alias-, Reihenfolge- und Duplicate-Tests ergänzen.
  6. Legacy Wrapper nach Aufrufermigration entfernen.

Abnahme

  • Keine Raw Types oder unchecked Casts im Modern-Code.
  • Externe Änderungen beeinflussen internen Zustand nicht.
  • Reihenfolge und Duplikate entsprechen Vertrag.
  • Null-Verhalten ist explizit.
  • Nebenläufige Zugriffe sind entweder sicher oder verboten/dokumentiert.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

13 · Generics — Raw Types und Casts → typsichere generische Repositorys

Fachlicher Vertrag

  • 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.

Risiko / Testfokus

runtime ClassCastException versus compile-time safety

generic boundaries, absent values and repository identity tests

Code-Mapping

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

Umsetzung

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

Abnahme

  • Build ist ohne unchecked-Warnungen.
  • Falscher Typ ist nicht mehr kompilierbar.
  • Find-by-ID liefert eindeutig Optional.
  • Speichern überschreibt/ergänzt nach dokumentierter Regel.
  • Generische API bleibt für Aufrufer verständlich.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

14 · Annotations und Reflection — Namenskonventionen und Reflection-Strings → Annotation-gesteuertes Command Registry

Fachlicher Vertrag

  • Command-Namen sind eindeutig und stabil.
  • Nur explizit markierte Methoden werden registriert.
  • Reflection-Fehler führen zu klarem Startup-Fehler statt spätem Laufzeitfehler.

Risiko / Testfokus

illegal access, duplicate commands and startup failures

duplicate annotation, missing method and invocation failure tests

Code-Mapping

LegacyModernBedeutung
LegacyCommandRegistry.javaCommandRegistry.java + Command.javaString-/Konventionssuche wird explizite Metadatenregistrierung.
LegacyCommands.javaModernCommands.javaCommand-Implementierungen erhalten Annotation statt Namenskonvention.

Umsetzung

  1. Bisherige Namenskonvention und erlaubte Signaturen dokumentieren.
  2. Command-Annotation mit Runtime-Retention und Method-Target definieren.
  3. CommandRegistry beim Start validierend aufbauen.
  4. Duplikate, falsche Signaturen und Zugriffsfehler hart ablehnen.
  5. Invocation-Exceptions in stabile Fach-/Technikfehler übersetzen.
  6. String-basierte Registry nach vollständiger Command-Abdeckung entfernen.

Abnahme

  • Jeder Command ist genau einmal registriert.
  • Falsche Signatur stoppt den Start mit verständlicher Meldung.
  • Unbekannter Command liefert definierten Fehler.
  • Private/unerlaubte Methoden werden nicht geöffnet.
  • Invocation erhält Ursache und Kontext.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

15 · Lambda und Streams — imperative Schleifen und anonyme Klassen → Stream Pipeline mit Records und Collectors

Fachlicher Vertrag

  • Ergebnis, Reihenfolge, Rundung und Null-Semantik bleiben identisch.
  • Streams erzeugen keine versteckten Seiteneffekte.
  • Parallelisierung wird nur nach Messung aktiviert.

Risiko / Testfokus

ordering, short-circuit and null semantics

empty input, duplicates, precision and parallel-safety tests

Code-Mapping

LegacyModernBedeutung
LegacyOrderAnalytics.javaOrderAnalytics.javaSchleifen werden zu lesbarer Stream-Pipeline.
Order.javaOrder.javaFachliches Eingabeobjekt bleibt stabil.

Umsetzung

  1. Imperative Schleifen mit ihren Randfällen als Tests sichern.
  2. Zwischenschritte als benannte Mapper/Predicates extrahieren.
  3. Stream-Pipeline sequentiell implementieren.
  4. BigDecimal-/Rundungsregeln explizit erhalten.
  5. Leere, doppelte und nullhaltige Eingaben testen.
  6. Imperativen Pfad erst nach Ergebnisvergleich entfernen.

Abnahme

  • Golden-Master-Ergebnisse sind identisch.
  • Encounter Order ist dokumentiert und getestet.
  • Keine Mutation externer Collections.
  • Leere Eingaben liefern definiertes Ergebnis.
  • Parallelstream wird nicht unbewusst verwendet.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

16 · Concurrency — plattformgebundener Thread Pool → Virtual Threads und sichere Aggregation

Fachlicher Vertrag

  • Task-Ergebnisse, Timeout- und Abbruchsemantik sind definiert.
  • Executors/Threads werden zuverlässig geschlossen.
  • Fehler eines Tasks gehen nicht verloren.

Risiko / Testfokus

race conditions, leaks and nondeterministic tests

timeouts, cancellation, interruption and repeated stress tests

Code-Mapping

LegacyModernBedeutung
LegacyTaskRunner.javaVirtualThreadTaskRunner.javaFester Pool wird für blockierende Tasks durch Virtual Threads ersetzt.

Umsetzung

  1. Thread-Pool-Größe, Queueing und Blocking-Aufgaben inventarisieren.
  2. Task-Vertrag und Ergebnisreihenfolge festlegen.
  3. VirtualThreadTaskRunner für blockierende unabhängige Tasks einführen.
  4. Timeout, Cancellation und InterruptedException korrekt propagieren.
  5. Last-, Leak- und wiederholte Stress-Tests ausführen.
  6. Plattformthread-Pool erst nach Ressourcenmessung entfernen.

Abnahme

  • Kein Thread-/Executor-Leak nach wiederholten Läufen.
  • Timeout beendet offene Tasks nach Regel.
  • Unterbrechung wird nicht verschluckt.
  • Ergebnisse sind vollständig und korrekt zugeordnet.
  • Lasttest zeigt keine unkontrollierte externe Ressourcenüberlastung.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

17 · Java I/O und NIO — File und manuelles Ressourcenmanagement → Path, Files und Try-with-resources

Fachlicher Vertrag

  • Dateiinhalte, Attribute und Überschreibregeln sind bewusst festgelegt.
  • Ressourcen werden in allen Fehlerpfaden geschlossen.
  • Pfadvalidierung verhindert Traversal außerhalb erlaubter Wurzeln.

Risiko / Testfokus

resource handling, overwrite and atomicity

permissions, missing files, overwrite and large-file tests

Code-Mapping

LegacyModernBedeutung
LegacyFileCopy.javaPathFileService.javaFile/Streams werden Path/Files und sichere Ressourcenverwaltung.

Umsetzung

  1. Legacy File-Verhalten inklusive Overwrite und Encoding testen.
  2. String/File-Parameter auf Path an der Systemgrenze normalisieren.
  3. Files-Operationen mit expliziten CopyOptions einsetzen.
  4. Temporärdatei/atomaren Move für kritische Schreibvorgänge prüfen.
  5. Berechtigungs-, Symlink-, große Datei- und Fehlerfälle testen.
  6. LegacyFileCopy nach Betriebsvergleich entfernen.

Abnahme

  • Kopie ist byte-identisch.
  • Fehlende Quelle und bestehendes Ziel liefern definierte Fehler.
  • Keine offenen File Descriptors.
  • Traversal/Symlink-Risiken sind behandelt.
  • Große Dateien werden ohne unnötige Vollspeicherung verarbeitet.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

18 · Exception Handling und Logging — Catch-all, null und System.err → Domain Exceptions und System.Logger

Fachlicher Vertrag

  • Root Cause und Stacktrace bleiben erhalten.
  • Fachliche Nicht-gefunden-Fälle sind von technischen Fehlern getrennt.
  • Logs enthalten Kontext, aber keine Secrets/PII.

Risiko / Testfokus

lost root cause and unstable error contracts

cause preservation, log context and negative-path tests

Code-Mapping

LegacyModernBedeutung
LegacyCustomerLookup.javaCustomerLookupService.java + CustomerNotFoundException.javanull/Catch-all wird explizite Fachexception plus Logging.

Umsetzung

  1. Catch-all- und null-Rückgaben inventarisieren.
  2. CustomerNotFoundException als stabilen Fachfehler definieren.
  3. Technische Exceptions an der Adaptergrenze übersetzen.
  4. System.err durch strukturiertes Logging ersetzen.
  5. Correlation-/Business-Key in Logkontext aufnehmen.
  6. Legacy-Swallowing erst nach negativen Pfadtests entfernen.

Abnahme

  • Kein leerer Catch-Block.
  • Root Cause ist über cause zugänglich.
  • Nicht gefunden ist reproduzierbar und dokumentiert.
  • Sensitive Daten erscheinen nicht im Log.
  • Fehlercodes bleiben an API-Grenzen stabil.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

19 · JUnit und Testdesign — JUnit 4 und einzelne Beispielwerte → JUnit 5 Parameterized Tests

Fachlicher Vertrag

  • Tests prüfen Fachverhalten und nicht Implementierungsdetails.
  • Lifecycle und Testdatenisolation bleiben korrekt.
  • Fehlermeldungen sind aussagekräftig.

Risiko / Testfokus

test lifecycle and assertion migration

parameter boundaries, lifecycle and failure-message tests

Code-Mapping

LegacyModernBedeutung
VatCalculator.javaVatCalculator.javaProduktionscode bleibt; Testdesign wechselt von JUnit 4 zu Jupiter/Parameterized Tests.

Umsetzung

  1. JUnit-4-Runner, Rules und erwartete Exceptions inventarisieren.
  2. Dependencies und Imports auf Jupiter umstellen.
  3. Setup/Teardown auf BeforeEach/AfterEach oder Extensions migrieren.
  4. Wiederholte Fälle in Parameterized Tests überführen.
  5. Assertions semantisch überprüfen, nicht nur syntaktisch ersetzen.
  6. JUnit Vintage erst nach vollständiger Jupiter-Abdeckung entfernen.

Abnahme

  • Alle bisherigen Tests laufen unter Jupiter.
  • Keine versehentlich deaktivierten Tests.
  • Parameterized Tests decken Grenzwerte ab.
  • Tests sind unabhängig von Ausführungsreihenfolge.
  • Build enthält keine JUnit-4-Runtime mehr, sofern nicht bewusst benötigt.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

20 · HTTP-Client und Webtest — HttpURLConnection → Java HttpClient mit Transport-Port

Fachlicher Vertrag

  • Timeout, Redirect, Encoding und Nicht-2xx-Verhalten sind Teil des Vertrags.
  • Fachlogik hängt nur vom TextTransport-Port ab.
  • Tests benötigen keinen externen Internetdienst.

Risiko / Testfokus

timeouts, redirects and encoding

timeout, non-2xx, headers, redirect and body-size tests

Code-Mapping

LegacyModernBedeutung
LegacyHttpClient.javaJavaHttpTransport.javaHttpURLConnection wird Java HttpClient Adapter.
direkter TransportaufrufTextTransport.java + PageTitleService.javaPort trennt Transport von Fachauswertung.

Umsetzung

  1. LegacyHttpClient-Verhalten mit lokalem HTTP-Server erfassen.
  2. TextTransport als Port definieren und PageTitleService davon abhängig machen.
  3. JavaHttpTransport mit expliziten Timeouts und Headern implementieren.
  4. Nicht-2xx, Redirect und große Antworten behandeln.
  5. Deterministische lokale Integrationstests ergänzen.
  6. HttpURLConnection erst nach Vertragsvergleich entfernen.

Abnahme

  • Timeout tritt innerhalb definierter Grenze ein.
  • Nicht-2xx wird nicht als Erfolg interpretiert.
  • Unicode-Titel werden korrekt gelesen.
  • Tests laufen offline gegen lokalen Server.
  • Transport kann in Unit-Tests ersetzt werden.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

21 · Maven Properties und Konfiguration — String-Properties und Build-Filterung → typisierte Konfiguration mit Validierung

Fachlicher Vertrag

  • Konfigurationspriorität und Defaults sind dokumentiert.
  • Pflichtwerte werden früh validiert.
  • Secrets gelangen nicht in Build-Artefakte oder Logs.

Risiko / Testfokus

missing keys, precedence and environment drift

default, override, malformed and encoding tests

Code-Mapping

LegacyModernBedeutung
LegacyPropertiesConfig.javaApplicationConfig.java + ConfigFactory.javaString-Properties werden validiertes Konfigurationsobjekt.

Umsetzung

  1. Alle Property-Quellen und Überschreibungsregeln inventarisieren.
  2. ApplicationConfig als typisiertes unveränderliches Objekt definieren.
  3. ConfigFactory für Parsing, Defaulting und Validierung einsetzen.
  4. Build-Time-Filtering von Runtime-Konfiguration trennen.
  5. Malformed-, Encoding- und fehlende Werte testen.
  6. Direkte Properties-Zugriffe schrittweise entfernen.

Abnahme

  • Fehlende Pflichtwerte stoppen den Start verständlich.
  • Default und Override folgen dokumentierter Priorität.
  • Ungültige Zahlen/Enums werden nicht still akzeptiert.
  • Keine Secrets in gefilterten Ressourcen.
  • Konfiguration ist in Unit-Tests ohne Maven reproduzierbar.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

22 · Spring JDBC — Statement, ResultSet und manuelles Mapping → JdbcClient und RowMapper

Fachlicher Vertrag

  • SQL, Parameterbindung und Row-Mapping bleiben fachlich identisch.
  • Connections und Statements werden vom Framework sicher verwaltet.
  • Transaktionen liegen außerhalb des Repositorys.

Risiko / Testfokus

SQL mapping, transaction and resource handling

row mapping, empty result, duplicate key and rollback tests

Code-Mapping

LegacyModernBedeutung
CustomerDao.javaCustomerRepository.java + Customer.javaManuelles JDBC wird JdbcClient Repository plus Row Mapping.

Umsetzung

  1. CustomerDao-SQL und Mapping mit Testdaten fixieren.
  2. Customer als stabiles Ergebnisobjekt definieren.
  3. CustomerRepository mit JdbcClient und parametrierten SQLs implementieren.
  4. Empty/Multiple-Result-Verhalten explizit abbilden.
  5. Duplicate-Key- und Constraint-Fehler übersetzen.
  6. DAO nach Integrations- und Rollbacktests entfernen.

Abnahme

  • Keine SQL-Konkatenation mit Nutzereingaben.
  • Row-Mapping deckt Null-/Typfälle ab.
  • Leere Ergebnisse haben definierte Semantik.
  • Constraint-Fehler sind stabil übersetzt.
  • Repository beteiligt sich korrekt an Service-Transaktionen.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

23 · Hibernate und JPA — proprietäres Hibernate Session API → Jakarta Persistence und Spring Data Repository

Fachlicher Vertrag

  • Entity-Identität, Tabellenmapping und Cascade-Regeln bleiben bewusst.
  • Transaktionen werden nicht durch Open-Session-in-View versteckt.
  • Queries liefern gleiche Ergebnismengen und Sortierung.

Risiko / Testfokus

entity lifecycle, schema and query differences

entity mapping, repository query, transaction and N+1 checks

Code-Mapping

LegacyModernBedeutung
LegacyBook.javaBookEntity.javajavax Entity wird Jakarta Entity.
HibernateBookStore.javaBookRepository.javaSession API/Unit of Work wird Spring Data Repository.
Legacy BootstrapJpaModernApplication.javaKonfiguration wechselt auf Spring Boot/JPA.

Umsetzung

  1. LegacyBook-Mapping und Hibernate-Konfiguration dokumentieren.
  2. BookEntity auf jakarta.persistence übertragen und Schema validieren.
  3. BookRepository mit expliziten Query-Namen/Sortierungen einführen.
  4. Session-spezifische Unit-of-Work-Logik in Service verschieben.
  5. Lazy/Eager, Cascade, N+1 und Locking mit Integrationstests prüfen.
  6. Native Hibernate API erst nach Query- und Performancevergleich entfernen.

Abnahme

  • Schema-Diff enthält keine ungewollten Änderungen.
  • Bestehende IDs und Beziehungen bleiben lesbar.
  • Transaktionen schließen vor API-Serialisierung sauber ab.
  • Keine LazyInitializationException im vorgesehenen Pfad.
  • Query-Anzahl/Performance ist akzeptiert.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

24 · MongoDB — MongoDB Document und manueller Mapper → Spring Data MongoDB Document/Repository

Fachlicher Vertrag

  • Collection-Name, _id und Dokumentfeldnamen bleiben kompatibel.
  • Fehlende/zusätzliche Felder werden versionstolerant behandelt.
  • Indexannahmen werden explizit geprüft.

Risiko / Testfokus

document shape and mapping compatibility

mapping, missing fields, query and index assumptions

Code-Mapping

LegacyModernBedeutung
LegacyBook.javaBookDocument.javaBSON-Datenform wird annotiertes Spring-Data-Dokument.
LegacyBookMapper.java + LegacyBookRepository.javaBookRepository.javaManueller Mapper/Driver wird Repository-Abstraktion.

Umsetzung

  1. Reale BSON-Dokumentformen und Mapper-Regeln inventarisieren.
  2. BookDocument mit expliziten Feldnamen und ID-Typ definieren.
  3. Spring Data Repository zunächst read-only einführen.
  4. LegacyBookMapper gegen neue Konvertierung mit Golden Documents vergleichen.
  5. Queries, Null-/fehlende Felder und Indizes testen.
  6. Schreibpfad erst nach Backfill-/Kompatibilitätsprüfung umstellen.

Abnahme

  • Bestehende Dokumente werden ohne Datenverlust gelesen.
  • Neue Dokumente bleiben für Legacy-Leser kompatibel oder sind versioniert.
  • ID-Typ ändert sich nicht unbemerkt.
  • Kritische Queries nutzen erwartete Indizes.
  • Unknown Fields brechen die Deserialisierung nicht unnötig.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

25 · JNDI und Service-Auflösung — InitialContext und Service Locator → Constructor Injection und explizite Ports

Fachlicher Vertrag

  • Fachcode kennt keine Namensdienst-API.
  • Abhängigkeiten sind im Konstruktor vollständig sichtbar.
  • Fehlende Bindings werden beim Start statt im ersten Request erkannt.

Risiko / Testfokus

runtime lookup failure and hidden dependency

binding failure, constructor contract and context startup

Code-Mapping

LegacyModernBedeutung
JndiServiceLocator.java + MemoryContext.javaSpring Constructor InjectionNamensdienst/Locator entfällt aus dem Use Case.
GreetingPort.javaGreetingPort.javaFachlicher Port bleibt stabil.
GreetingService.javaGreetingService.javaImplementierung bleibt fachlich.
LegacyGreetingUseCase.javaGreetingUseCase.javaLookup wird Konstruktorabhängigkeit.

Umsetzung

  1. Alle JNDI-Namen und Lookup-Stellen inventarisieren.
  2. GreetingPort als fachlichen Vertrag festlegen.
  3. LegacyGreetingUseCase auf Konstruktorinjektion vorbereiten.
  4. GreetingUseCase und GreetingService als explizite Komponenten verdrahten.
  5. JNDI-Adapter nur an der Composition Root für Übergang behalten.
  6. MemoryContext/JndiServiceLocator nach Aufrufermigration entfernen.

Abnahme

  • Kein Use Case importiert javax.naming.
  • Unit-Test erstellt Use Case mit Fake-Port.
  • Fehlende Implementierung stoppt Context-Start.
  • JNDI-Name ist nicht mehr Teil des fachlichen Vertrags.
  • Parallelbetrieb liefert identische Ergebnisse.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

26 · JMX und Monitoring — Standard MBean und direkte Registrierung → Actuator und Micrometer Counter

Fachlicher Vertrag

  • Metrikbedeutung, Einheit und Label-Kardinalität sind dokumentiert.
  • Managementzugriff ist authentisiert/autorisiert.
  • Monitoring verändert das Fachverhalten nicht.

Risiko / Testfokus

metric/endpoint naming and exposure

endpoint exposure, health detail and unauthorized access tests

Code-Mapping

LegacyModernBedeutung
TaskCounterMBean.java + TaskCounter.java + JmxRegistration.javaTaskMetrics.javaMBean-Registrierung wird Micrometer-Metrik/Actuator-Exposition.

Umsetzung

  1. MBean-Namen, Attribute und Operationen inventarisieren.
  2. TaskCounter-Metrik auf Micrometer Counter/Gauge abbilden.
  3. Actuator-Exposition minimal konfigurieren.
  4. Dashboards/Alerts auf neue Namen und Einheiten umstellen.
  5. Doppelzählung im Parallelbetrieb verhindern.
  6. JMX-Registrierung erst nach Monitoring-Abnahme entfernen.

Abnahme

  • Zählerwerte stimmen für definierte Abläufe überein.
  • Keine unbeschränkte Tag-Kardinalität.
  • Sensitive Endpunkte sind geschützt.
  • Health und Metrics unterscheiden Verfügbarkeit von Fachzustand.
  • Alerting funktioniert nach Umschaltung.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

27 · EJB und Services — EJB-2-artige Home/Remote-Schnittstellen → Spring Service und REST Facade

Fachlicher Vertrag

  • Servicevertrag, Transaktions- und Security-Semantik bleiben explizit.
  • Remote-Ausnahmen werden stabil auf HTTP/Fachfehler abgebildet.
  • Geschäftslogik bleibt im Service, nicht im Controller.

Risiko / Testfokus

transaction/security semantics and remote contract drift

service contract, web adapter and transaction tests

Code-Mapping

LegacyModernBedeutung
OrderHome.java + OrderRemote.javaOrderController.javaRemote EJB Contract wird HTTP Remote Facade.
OrderSessionBean.javaOrderService.javaSession Bean wird containerarmer Service.
EJB Container BootstrapOrderApplication.javaDeploymentmodell wechselt zu Spring Boot.

Umsetzung

  1. Home/Remote-Verträge und Container-Services inventarisieren.
  2. OrderService als containerunabhängige Session Facade extrahieren.
  3. Transaktion und Security explizit über Spring-Konfiguration/Annotationen nachbilden.
  4. OrderController als Remote Facade mit versioniertem Vertrag einführen.
  5. Client-Adapter und Contract-Tests für beide Endpunkte erstellen.
  6. EJB erst nach Consumer- und Betriebsfreigabe abschalten.

Abnahme

  • Fachresultate stimmen zwischen EJB und Service überein.
  • Transaktionsrollback entspricht bisheriger Semantik.
  • Security-Entscheidungen sind mindestens gleich streng.
  • HTTP-Fehlerabbildung ist dokumentiert.
  • Keine EJB-API in der Fachlogik.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

28 · JPMS / Jigsaw — Classpath und globale Sichtbarkeit → module-info, exports und Service Provider

Fachlicher Vertrag

  • Öffentliche Pakete sind minimal und bewusst exportiert.
  • Keine Split Packages.
  • Service Provider funktionieren auf dem Module Path.

Risiko / Testfokus

split packages, exports and readability

module-path compile, forbidden access and service-loading tests

Code-Mapping

LegacyModernBedeutung
LegacyPluginLoader.java + LegacyGreetingPlugin.javaGreetingProvider.java + GermanGreetingProvider.javaClasspath Plugin wird expliziter Service Provider.
globale Classpath-Sichtbarkeitmodule-info.javarequires/exports/uses/provides werden deklarativ.
Legacy StartJpmsApplication.java + JpmsSmokeCheck.javaStart und Module-Path-Smoke-Test werden explizit.

Umsetzung

  1. Abhängigkeiten und Package-Zyklen mit jdeps/Build analysieren.
  2. API- und Internal-Pakete trennen.
  3. module-info mit requires/exports minimal erstellen.
  4. Service Provider über uses/provides registrieren.
  5. Tests explizit auf dem Module Path ausführen.
  6. Classpath-Fallback erst nach Packaging-/Starttests entfernen.

Abnahme

  • Modul kompiliert und startet auf dem Module Path.
  • Interne Pakete sind von außen nicht lesbar.
  • Keine automatischen Module mit instabilen Namen in kritischem Pfad.
  • ServiceLoader findet Provider.
  • Reflection-Zugriffe benötigen nur dokumentierte opens.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

29 · Service Registry und ServiceLoader — dynamische Service Registry → Java SPI mit ServiceLoader

Fachlicher Vertrag

  • PaymentProvider-SPI ist klein, stabil und implementation-neutral.
  • Provider-Auswahl bei mehreren Implementierungen ist deterministisch.
  • Dynamische OSGi-Lifecycle-Semantik wird nicht fälschlich als ServiceLoader-Eigenschaft angenommen.

Risiko / Testfokus

provider discovery, ordering and duplicates

no provider, multiple provider and packaging tests

Code-Mapping

LegacyModernBedeutung
ServiceRegistry.java + PaymentService.javaPaymentProviders.java + PaymentProvider.javaRegistry wird Java-SPI-Resolver.
registrierte ImplementierungDefaultPaymentProvider.java + META-INF/servicesProvider wird über ServiceLoader paketiert.

Umsetzung

  1. Benötigte Registry-Funktionen und echte Dynamik-Anforderungen klären.
  2. PaymentProvider als Java-SPI definieren.
  3. META-INF/services korrekt paketieren.
  4. PaymentProviders mit Auswahl-/Fehlerregeln implementieren.
  5. No-/Multi-provider- und Packaging-Tests ausführen.
  6. Legacy Registry nur entfernen, wenn keine dynamische Nachinstallation benötigt wird.

Abnahme

  • Provider wird im gebauten JAR gefunden.
  • Kein Provider liefert verständlichen Fehler.
  • Mehrere Provider folgen dokumentierter Priorität.
  • SPI enthält keine Implementierungsdetails.
  • Grenze zu echtem OSGi ist in Architektur dokumentiert.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

30 · XML Parser — DOM lädt vollständigen Objektbaum → StAX verarbeitet Streaming-Events

Fachlicher Vertrag

  • Extrahierte Fachwerte bleiben identisch.
  • Externe Entitäten und DTD-Zugriffe sind deaktiviert.
  • Speicherverbrauch skaliert mit Streaming statt Dokumentgröße.

Risiko / Testfokus

XXE, entity expansion and malformed XML

XXE-negative, namespace, large input and error-position tests

Code-Mapping

LegacyModernBedeutung
DomOrderReader.javaStaxOrderReader.javaVollständiger DOM-Baum wird Streaming Reader.

Umsetzung

  1. DOM-Ausgabe für repräsentative XMLs als Golden Master sichern.
  2. StaxOrderReader mit Namespace- und Encoding-Regeln implementieren.
  3. Secure Processing/External Access explizit konfigurieren.
  4. Malformed-, große Datei- und XXE-Fälle testen.
  5. Event-/Elementreihenfolge und Missing-Element-Regeln dokumentieren.
  6. DOM-Pfad nach Ergebnis- und Lastvergleich entfernen.

Abnahme

  • Golden-Master-Werte stimmen.
  • XXE-/DTD-Test bleibt blockiert.
  • Große Datei überschreitet definiertes Speicherlimit nicht.
  • Malformed XML enthält brauchbare Position.
  • Namespaces werden korrekt behandelt.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

31 · XSLT — Transformer pro Aufruf mit Defaults → vorkompilierte Templates mit Secure Processing

Fachlicher Vertrag

  • Transformationsergebnis bleibt semantisch identisch.
  • Externe Stylesheets/Dokumente sind standardmäßig gesperrt.
  • Templates-Nutzung ist threadsicher.

Risiko / Testfokus

external access, thread safety and cache invalidation

external resource denial, concurrency and invalid stylesheet tests

Code-Mapping

LegacyModernBedeutung
LegacyXsltTransformer.javaSecureXsltTemplate.javaTransformer pro Aufruf wird sichere vorkompilierte Templates-Fassade.

Umsetzung

  1. Legacy-Ausgaben mit repräsentativen XML/XSLT-Paaren sichern.
  2. TransformerFactory Security-Features explizit setzen.
  3. Stylesheet einmal zu Templates kompilieren.
  4. Pro Aufruf einen Transformer aus Templates erzeugen.
  5. Concurrency-, Cache- und invalides Stylesheet testen.
  6. Legacy Transformer nach Output-Diff und Security-Test entfernen.

Abnahme

  • Output-Diff enthält nur genehmigte Unterschiede.
  • Externer Datei-/Netzzugriff ist blockiert.
  • Paralleltests beeinflussen sich nicht.
  • Ungültiges Stylesheet scheitert früh.
  • Cache-Strategie hat definierte Invalidierung.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

32 · Kryptografie — deterministische AES-ECB-Demo → AES-GCM mit PBKDF2, Salt und IV

Fachlicher Vertrag

  • Neue Verschlüsselung bietet Vertraulichkeit und Integrität.
  • Nonce/IV wird pro Nachricht eindeutig erzeugt.
  • Schlüsselmaterial und Passwörter werden nicht geloggt oder hart codiert.

Risiko / Testfokus

confidentiality/integrity failure and nonce misuse

tamper, wrong key, nonce uniqueness and empty payload tests

Code-Mapping

LegacyModernBedeutung
LegacyAesEcb.javaAesGcmService.java + EncryptedPayload.javaDeterministische Verschlüsselung wird authentifizierte, versionierbare Payload.

Umsetzung

  1. Bestandsdaten und AES/ECB-Nutzung inventarisieren; keine stille In-place-Konvertierung.
  2. EncryptedPayload mit Version, Salt, IV und Ciphertext definieren.
  3. AesGcmService mit SecureRandom und authentifizierter Verschlüsselung implementieren.
  4. PBKDF2-Parameter und Key-Management als Betriebsentscheidung dokumentieren.
  5. Read-old/write-new beziehungsweise expliziten Re-encryption-Job planen.
  6. Tamper-, Wrong-key-, Nonce- und Migrationstests ausführen.

Abnahme

  • Manipulierter Ciphertext wird sicher abgewiesen.
  • Gleicher Klartext erzeugt unterschiedliche Payloads.
  • Legacy-Daten können kontrolliert gelesen/migriert werden.
  • Keine ECB-Neuschreibungen.
  • Key-Rotation und Formatversion sind vorgesehen.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

33 · SMTP und Mail — javax.mail MimeMessage → Jakarta Mail und Mail Gateway

Fachlicher Vertrag

  • Absender, Empfänger, Betreff, Body und Charset bleiben kompatibel.
  • Header Injection wird verhindert.
  • Transportfehler sind wiederholbar und nachvollziehbar.

Risiko / Testfokus

header injection, transport errors and charset drift

recipient validation, Unicode, transport failure and header tests

Code-Mapping

LegacyModernBedeutung
LegacyMailFactory.javaMailCommand.java + JakartaMailGateway.javaMessage-Erzeugung wird validiertes Kommando plus Gateway.

Umsetzung

  1. Legacy MimeMessage-Felder und Session-Eigenschaften inventarisieren.
  2. MailCommand als validiertes Fachkommando definieren.
  3. JakartaMailGateway als Infrastrukturadapter implementieren.
  4. Unicode, Multipart/Attachments und Reply-To prüfen, soweit verwendet.
  5. Timeout-, Auth-, TLS- und Fehlerbehandlung konfigurieren.
  6. javax.mail-Pfad nach Testmail-/Sandbox-Abnahme entfernen.

Abnahme

  • Unicode-Inhalte kommen korrekt an.
  • CR/LF in Headerfeldern wird abgewiesen.
  • Transportfehler enthalten Empfänger-/Correlation-Kontext ohne Body-Leak.
  • TLS/Auth-Konfiguration ist externisiert.
  • Keine javax.mail-Imports im Modern-Modul.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

34 · Patterns und Refactoring — Switch-basierte Preislogik → Strategy, Factory und Value Objects

Fachlicher Vertrag

  • Preisresultate bleiben für alle CustomerTypes identisch.
  • Neue Typen werden ohne wachsenden Switch im Service ergänzt.
  • Unsupported Types liefern definierten Fehler.

Risiko / Testfokus

branch growth and unsupported customer types

all strategies, factory completeness and unknown type tests

Code-Mapping

LegacyModernBedeutung
LegacyPriceCalculator.javaPriceService.java + PricingStrategy.java + PricingStrategyFactory.javaSwitch wird Strategy/Factory-Komposition.
String/Branch Customer TypeCustomerType.javaKundentyp wird expliziter Value/Enum-Vertrag.

Umsetzung

  1. Switch-Zweige und Testfälle als Entscheidungstabelle erfassen.
  2. PricingStrategy als kleinen fachlichen Vertrag definieren.
  3. Je CustomerType eine Strategie implementieren oder als Lambda registrieren.
  4. PricingStrategyFactory mit Vollständigkeitsprüfung einführen.
  5. PriceService nur von Factory/Strategie abhängig machen.
  6. Legacy Switch nach Golden-Master- und Mutations-/Grenztests entfernen.

Abnahme

  • Alle bisherigen Preisfälle sind identisch.
  • Jeder Enum-Wert hat genau eine Strategie.
  • Unbekannter/null Typ scheitert verständlich.
  • Neue Strategie erfordert keine Änderung bestehender Strategien.
  • Factory-Konfiguration ist unit-getestet.

Quellen

Vollständige Akte mit Codeausschnitten und Diffs öffnen →

⌂ Cockpit