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
| Legacy | Modern | Bedeutung |
|---|
| ServiceRegistry.java | Spring Context / Constructor Injection | Versteckte globale Auflösung wird durch explizite Verdrahtung ersetzt. |
| GreetingService.java | GreetingPort.java | Fachlicher Servicevertrag wird als Port stabilisiert. |
| DefaultGreetingService.java | GermanGreetingService.java | Konkrete Implementierung bleibt fachlich gleich. |
| DiLegacyApplication.java | DiModernApplication.java + GreetingRunner.java | Bootstrap und Use-Case-Ausführung werden getrennt. |
Umsetzung
- GreetingService als fachlichen Port festlegen und Aufrufer dagegen testen.
- Direkte Zugriffe auf ServiceRegistry erfassen und durch Konstruktorparameter ersetzen.
- DefaultGreetingService funktional in GermanGreetingService überführen.
- GreetingRunner als Application Adapter einführen; keine Container-API in den Port aufnehmen.
- Spring-Komponenten nur am äußeren Rand annotieren und Context-Smoke-Test ergänzen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LoggingProxy.java | TrackingAspect.java + Tracked.java | Manueller Proxy wird durch deklarativen Interceptor ersetzt. |
| SimpleCalculator.java | TrackedCalculator.java | Zielobjekt bleibt fachlich, erhält nur explizite Markierung. |
| AopLegacyApplication.java | AopModernApplication.java + CalculatorRunner.java | Composition Root wird vom Runner getrennt. |
Umsetzung
- Alle über LoggingProxy abgefangenen Methoden und Nebenwirkungen inventarisieren.
- Tracked als explizites Pointcut-Merkmal definieren und unbeabsichtigte Treffer vermeiden.
- LoggingProxy-Verhalten in Around-Advice nachbilden, einschließlich Exception-Pfad.
- Self-invocation und nur über Proxy erreichbare Methoden explizit testen.
- Reihenfolge zu Transaktions-, Security- und Retry-Aspekten festlegen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| BookResource.java | BookController.java + BookService.java | Resource-Verantwortung wird in HTTP-Adapter und Service Layer getrennt. |
| BookRepository.java | BookRepository.java | Datenzugriffsvertrag bleibt erhalten. |
| Book.java | Book.java | API-/Domain-Datenform bleibt vergleichbar. |
| RestLegacyApplication.java | RestModernApplication.java | Jersey/Grizzly-Bootstrap wird Spring Boot Bootstrap. |
Umsetzung
- JAX-RS-Vertrag aus BookResource als Contract-Test festhalten.
- BookRepository zunächst unverändert hinter BookService verwenden.
- BookController mit denselben Pfaden und Medienformaten einführen.
- Bean Validation und globale Fehlerabbildung ergänzen; Fehlerpayload versionieren.
- Legacy- und Modern-Endpunkt im Parallelbetrieb gegen dieselben Testvektoren ausführen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| CustomerDao.java + JdbcCustomerDao.java | CustomerRepository.java | DAO/SQL-Zugriff wird Repository-Abstraktion. |
| Customer.java | CustomerEntity.java | Datenobjekt wird explizite JPA Entity. |
| PersistenceLegacyApplication.java | PersistenceModernApplication.java + CustomerService.java | Bootstrap und transaktionaler Use Case werden getrennt. |
Umsetzung
- CustomerDao-SQL und ResultSet-Mapping als Golden-Master-Tests sichern.
- CustomerEntity exakt gegen bestehendes Schema mappen; automatische DDL-Erzeugung deaktivieren.
- CustomerRepository zunächst nur für lesende Use Cases aktivieren.
- CustomerService mit expliziten Transaktionsgrenzen einführen.
- Schreibpfad per Shadow Read/Write oder Vergleichslauf validieren.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyTransferService.java | TransferService.java + AccountRepository.java | Manuelle Connection-Transaktion wird deklarativer Service plus Datenadapter. |
| TransactionsLegacyApplication.java | TransactionsModernApplication.java | Bootstrap wechselt auf Spring Transaction Management. |
Umsetzung
- Commit-/Rollback-Pfade des LegacyTransferService mit Datenbanktests festhalten.
- AccountRepository als reinen Datenadapter ohne Transaktionssteuerung gestalten.
- TransferService als einzige Transaktionsgrenze definieren.
- Checked- und Runtime-Exception-Regeln explizit konfigurieren und testen.
- Nebenläufige Transfers mit geeigneter Sperr-/Versionsstrategie prüfen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyBatchImporter.java + CsvOrderParser.java | BatchConfiguration.java | Imperativer Ablauf wird Reader/Processor/Writer-Pipeline. |
| OrderRow.java | OrderRow.java | Fachlicher Datensatz bleibt stabil. |
| BatchLegacyApplication.java | BatchModernApplication.java | Manueller Start wird Spring-Batch-Jobstart. |
Umsetzung
- CSV-Format, Header, Zeichensatz und Dezimalregeln als Input Contract festhalten.
- CsvOrderParser-Logik in Reader/Processor/Writer-Verantwortungen zerlegen.
- JobRepository und persistente Metadaten konfigurieren.
- Idempotenzschlüssel und Duplicate-Policy definieren.
- Skip-, Retry-, Restart- und Abbruchgrenzen mit realistischen Dateien testen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyJmsGateway.java | OrderMessagePublisher.java + OrderMessageListener.java | Ein JMS Gateway wird in Producer und Consumer getrennt. |
| MessagingLegacyApplication.java | MessagingModernApplication.java + MessageDemoRunner.java | Embedded-Broker-Demo wird Spring-Boot-Komposition. |
Umsetzung
- JMS-Header, Payload, Queue-Namen und Acknowledgement-Modus inventarisieren.
- Publisher und Listener hinter fachliche Ports legen.
- Serializer/Deserializer mit Schema- und Versionsprüfung einführen.
- Idempotenzspeicher, Redelivery und DLQ-Regeln konfigurieren.
- Legacy ActiveMQ Classic nur für Vergleich/Übergang nutzen und Broker-Upgrade planen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyCustomer.java | ModernCustomer.java | javax JAXB Model wird Jakarta JAXB Model. |
| LegacyXmlMapper.java | ModernXmlMapper.java | Marshaller/Unmarshaller-Verantwortung bleibt erhalten. |
| XmlLegacyApplication.java | XmlModernApplication.java | Bootstrap wird auf Jakarta Runtime umgestellt. |
Umsetzung
- Repräsentative Legacy-XMLs und XSDs als Golden Master sammeln.
- javax-Modelle auf jakarta-Pakete umstellen, ohne XML-Annotationen semantisch zu ändern.
- Marshaller-/Unmarshaller-Konfiguration explizit machen.
- Round-trip- und Cross-Version-Tests ausführen.
- Unknown-Field- und Versionierungsstrategie festlegen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| StatusServlet.java | StatusController.java | Servlet Adapter wird Spring MVC Controller. |
| ServletLegacyApplication.java | WebModernApplication.java | Embedded Jetty Bootstrap wird Spring Boot. |
Umsetzung
- Servlet-Mappings und Jetty-Startparameter dokumentieren.
- StatusServlet-Verhalten durch Mock-/HTTP-Contract-Tests sichern.
- StatusController mit identischem externem Vertrag implementieren.
- Fehlerbehandlung, CORS und Header zentral konfigurieren.
- Reverse-Proxy- und Context-Path-Verhalten testen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyCalculatorEndpoint.java | ModernCalculatorEndpoint.java | javax JAX-WS Endpoint wird Jakarta Endpoint bei stabilem SOAP-Vertrag. |
| SoapLegacyApplication.java | SoapModernApplication.java | Endpoint-Publishing wechselt Namespace/Runtime. |
Umsetzung
- WSDL/XSD und Beispielnachrichten versioniert sichern.
- javax- zu jakarta-Imports migrieren, ohne Contract-First-Artefakte zu verändern.
- Endpoint-Publishing und Handler/Interceptors getrennt konfigurieren.
- Legacy- und Modern-Service gegen denselben Client-Test ausführen.
- Fault-, MTOM-, Header- und Encoding-Fälle prüfen, soweit verwendet.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyCustomer.java | Customer.java + CustomerStatus.java | Mutable Bean wird Record plus typisierter Status. |
| BasicsLegacyApplication.java | BasicsModernApplication.java | Aufrufer wird auf Value Semantics umgestellt. |
Umsetzung
- Bean-Eigenschaften, Nullregeln und Mutationen inventarisieren.
- Customer als Record nur dort einsetzen, wo Wertsemantik passt.
- Status-Strings durch CustomerStatus mit stabiler externer Repräsentation ersetzen.
- Adapter für Bean-basierte Frameworks oder Mapper ergänzen.
- Equals/hashCode- und JSON/XML-Verhalten vergleichen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyInventory.java | Inventory.java | Legacy Collections werden generisch und defensiv gekapselt. |
Umsetzung
- Verwendung von Vector, Hashtable und Enumeration erfassen.
- Generische Typen einführen und Casts entfernen.
- Inventory mit defensiven Kopien/Views implementieren.
- Nebenläufigkeitsannahmen explizit prüfen; Vector-Synchronisierung nicht blind verlieren.
- Alias-, Reihenfolge- und Duplicate-Tests ergänzen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| RawBox.java | TypedBox.java | Object-Container wird typsicher. |
| RawBox-Anwendungsfall | Repository.java + InMemoryRepository.java + Identifiable.java | Generischer Datenzugriffsvertrag wird ergänzt. |
| untypisierte Domänenwerte | Customer.java | Konkreter typsicherer Repository-Typ. |
Umsetzung
- Alle RawBox-Aufrufer und erwarteten Typen erfassen.
- TypedBox schrittweise mit konkreten Typen einführen.
- Identifiable und Repository-Vertrag definieren.
- InMemoryRepository mit stabiler ID-Semantik implementieren.
- Unchecked-Warnungen auf null reduzieren.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyCommandRegistry.java | CommandRegistry.java + Command.java | String-/Konventionssuche wird explizite Metadatenregistrierung. |
| LegacyCommands.java | ModernCommands.java | Command-Implementierungen erhalten Annotation statt Namenskonvention. |
Umsetzung
- Bisherige Namenskonvention und erlaubte Signaturen dokumentieren.
- Command-Annotation mit Runtime-Retention und Method-Target definieren.
- CommandRegistry beim Start validierend aufbauen.
- Duplikate, falsche Signaturen und Zugriffsfehler hart ablehnen.
- Invocation-Exceptions in stabile Fach-/Technikfehler übersetzen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyOrderAnalytics.java | OrderAnalytics.java | Schleifen werden zu lesbarer Stream-Pipeline. |
| Order.java | Order.java | Fachliches Eingabeobjekt bleibt stabil. |
Umsetzung
- Imperative Schleifen mit ihren Randfällen als Tests sichern.
- Zwischenschritte als benannte Mapper/Predicates extrahieren.
- Stream-Pipeline sequentiell implementieren.
- BigDecimal-/Rundungsregeln explizit erhalten.
- Leere, doppelte und nullhaltige Eingaben testen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyTaskRunner.java | VirtualThreadTaskRunner.java | Fester Pool wird für blockierende Tasks durch Virtual Threads ersetzt. |
Umsetzung
- Thread-Pool-Größe, Queueing und Blocking-Aufgaben inventarisieren.
- Task-Vertrag und Ergebnisreihenfolge festlegen.
- VirtualThreadTaskRunner für blockierende unabhängige Tasks einführen.
- Timeout, Cancellation und InterruptedException korrekt propagieren.
- Last-, Leak- und wiederholte Stress-Tests ausführen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyFileCopy.java | PathFileService.java | File/Streams werden Path/Files und sichere Ressourcenverwaltung. |
Umsetzung
- Legacy File-Verhalten inklusive Overwrite und Encoding testen.
- String/File-Parameter auf Path an der Systemgrenze normalisieren.
- Files-Operationen mit expliziten CopyOptions einsetzen.
- Temporärdatei/atomaren Move für kritische Schreibvorgänge prüfen.
- Berechtigungs-, Symlink-, große Datei- und Fehlerfälle testen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyCustomerLookup.java | CustomerLookupService.java + CustomerNotFoundException.java | null/Catch-all wird explizite Fachexception plus Logging. |
Umsetzung
- Catch-all- und null-Rückgaben inventarisieren.
- CustomerNotFoundException als stabilen Fachfehler definieren.
- Technische Exceptions an der Adaptergrenze übersetzen.
- System.err durch strukturiertes Logging ersetzen.
- Correlation-/Business-Key in Logkontext aufnehmen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| VatCalculator.java | VatCalculator.java | Produktionscode bleibt; Testdesign wechselt von JUnit 4 zu Jupiter/Parameterized Tests. |
Umsetzung
- JUnit-4-Runner, Rules und erwartete Exceptions inventarisieren.
- Dependencies und Imports auf Jupiter umstellen.
- Setup/Teardown auf BeforeEach/AfterEach oder Extensions migrieren.
- Wiederholte Fälle in Parameterized Tests überführen.
- Assertions semantisch überprüfen, nicht nur syntaktisch ersetzen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyHttpClient.java | JavaHttpTransport.java | HttpURLConnection wird Java HttpClient Adapter. |
| direkter Transportaufruf | TextTransport.java + PageTitleService.java | Port trennt Transport von Fachauswertung. |
Umsetzung
- LegacyHttpClient-Verhalten mit lokalem HTTP-Server erfassen.
- TextTransport als Port definieren und PageTitleService davon abhängig machen.
- JavaHttpTransport mit expliziten Timeouts und Headern implementieren.
- Nicht-2xx, Redirect und große Antworten behandeln.
- Deterministische lokale Integrationstests ergänzen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyPropertiesConfig.java | ApplicationConfig.java + ConfigFactory.java | String-Properties werden validiertes Konfigurationsobjekt. |
Umsetzung
- Alle Property-Quellen und Überschreibungsregeln inventarisieren.
- ApplicationConfig als typisiertes unveränderliches Objekt definieren.
- ConfigFactory für Parsing, Defaulting und Validierung einsetzen.
- Build-Time-Filtering von Runtime-Konfiguration trennen.
- Malformed-, Encoding- und fehlende Werte testen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| CustomerDao.java | CustomerRepository.java + Customer.java | Manuelles JDBC wird JdbcClient Repository plus Row Mapping. |
Umsetzung
- CustomerDao-SQL und Mapping mit Testdaten fixieren.
- Customer als stabiles Ergebnisobjekt definieren.
- CustomerRepository mit JdbcClient und parametrierten SQLs implementieren.
- Empty/Multiple-Result-Verhalten explizit abbilden.
- Duplicate-Key- und Constraint-Fehler übersetzen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyBook.java | BookEntity.java | javax Entity wird Jakarta Entity. |
| HibernateBookStore.java | BookRepository.java | Session API/Unit of Work wird Spring Data Repository. |
| Legacy Bootstrap | JpaModernApplication.java | Konfiguration wechselt auf Spring Boot/JPA. |
Umsetzung
- LegacyBook-Mapping und Hibernate-Konfiguration dokumentieren.
- BookEntity auf jakarta.persistence übertragen und Schema validieren.
- BookRepository mit expliziten Query-Namen/Sortierungen einführen.
- Session-spezifische Unit-of-Work-Logik in Service verschieben.
- Lazy/Eager, Cascade, N+1 und Locking mit Integrationstests prüfen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyBook.java | BookDocument.java | BSON-Datenform wird annotiertes Spring-Data-Dokument. |
| LegacyBookMapper.java + LegacyBookRepository.java | BookRepository.java | Manueller Mapper/Driver wird Repository-Abstraktion. |
Umsetzung
- Reale BSON-Dokumentformen und Mapper-Regeln inventarisieren.
- BookDocument mit expliziten Feldnamen und ID-Typ definieren.
- Spring Data Repository zunächst read-only einführen.
- LegacyBookMapper gegen neue Konvertierung mit Golden Documents vergleichen.
- Queries, Null-/fehlende Felder und Indizes testen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| JndiServiceLocator.java + MemoryContext.java | Spring Constructor Injection | Namensdienst/Locator entfällt aus dem Use Case. |
| GreetingPort.java | GreetingPort.java | Fachlicher Port bleibt stabil. |
| GreetingService.java | GreetingService.java | Implementierung bleibt fachlich. |
| LegacyGreetingUseCase.java | GreetingUseCase.java | Lookup wird Konstruktorabhängigkeit. |
Umsetzung
- Alle JNDI-Namen und Lookup-Stellen inventarisieren.
- GreetingPort als fachlichen Vertrag festlegen.
- LegacyGreetingUseCase auf Konstruktorinjektion vorbereiten.
- GreetingUseCase und GreetingService als explizite Komponenten verdrahten.
- JNDI-Adapter nur an der Composition Root für Übergang behalten.
- 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
| Legacy | Modern | Bedeutung |
|---|
| TaskCounterMBean.java + TaskCounter.java + JmxRegistration.java | TaskMetrics.java | MBean-Registrierung wird Micrometer-Metrik/Actuator-Exposition. |
Umsetzung
- MBean-Namen, Attribute und Operationen inventarisieren.
- TaskCounter-Metrik auf Micrometer Counter/Gauge abbilden.
- Actuator-Exposition minimal konfigurieren.
- Dashboards/Alerts auf neue Namen und Einheiten umstellen.
- Doppelzählung im Parallelbetrieb verhindern.
- 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
| Legacy | Modern | Bedeutung |
|---|
| OrderHome.java + OrderRemote.java | OrderController.java | Remote EJB Contract wird HTTP Remote Facade. |
| OrderSessionBean.java | OrderService.java | Session Bean wird containerarmer Service. |
| EJB Container Bootstrap | OrderApplication.java | Deploymentmodell wechselt zu Spring Boot. |
Umsetzung
- Home/Remote-Verträge und Container-Services inventarisieren.
- OrderService als containerunabhängige Session Facade extrahieren.
- Transaktion und Security explizit über Spring-Konfiguration/Annotationen nachbilden.
- OrderController als Remote Facade mit versioniertem Vertrag einführen.
- Client-Adapter und Contract-Tests für beide Endpunkte erstellen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyPluginLoader.java + LegacyGreetingPlugin.java | GreetingProvider.java + GermanGreetingProvider.java | Classpath Plugin wird expliziter Service Provider. |
| globale Classpath-Sichtbarkeit | module-info.java | requires/exports/uses/provides werden deklarativ. |
| Legacy Start | JpmsApplication.java + JpmsSmokeCheck.java | Start und Module-Path-Smoke-Test werden explizit. |
Umsetzung
- Abhängigkeiten und Package-Zyklen mit jdeps/Build analysieren.
- API- und Internal-Pakete trennen.
- module-info mit requires/exports minimal erstellen.
- Service Provider über uses/provides registrieren.
- Tests explizit auf dem Module Path ausführen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| ServiceRegistry.java + PaymentService.java | PaymentProviders.java + PaymentProvider.java | Registry wird Java-SPI-Resolver. |
| registrierte Implementierung | DefaultPaymentProvider.java + META-INF/services | Provider wird über ServiceLoader paketiert. |
Umsetzung
- Benötigte Registry-Funktionen und echte Dynamik-Anforderungen klären.
- PaymentProvider als Java-SPI definieren.
- META-INF/services korrekt paketieren.
- PaymentProviders mit Auswahl-/Fehlerregeln implementieren.
- No-/Multi-provider- und Packaging-Tests ausführen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| DomOrderReader.java | StaxOrderReader.java | Vollständiger DOM-Baum wird Streaming Reader. |
Umsetzung
- DOM-Ausgabe für repräsentative XMLs als Golden Master sichern.
- StaxOrderReader mit Namespace- und Encoding-Regeln implementieren.
- Secure Processing/External Access explizit konfigurieren.
- Malformed-, große Datei- und XXE-Fälle testen.
- Event-/Elementreihenfolge und Missing-Element-Regeln dokumentieren.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyXsltTransformer.java | SecureXsltTemplate.java | Transformer pro Aufruf wird sichere vorkompilierte Templates-Fassade. |
Umsetzung
- Legacy-Ausgaben mit repräsentativen XML/XSLT-Paaren sichern.
- TransformerFactory Security-Features explizit setzen.
- Stylesheet einmal zu Templates kompilieren.
- Pro Aufruf einen Transformer aus Templates erzeugen.
- Concurrency-, Cache- und invalides Stylesheet testen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyAesEcb.java | AesGcmService.java + EncryptedPayload.java | Deterministische Verschlüsselung wird authentifizierte, versionierbare Payload. |
Umsetzung
- Bestandsdaten und AES/ECB-Nutzung inventarisieren; keine stille In-place-Konvertierung.
- EncryptedPayload mit Version, Salt, IV und Ciphertext definieren.
- AesGcmService mit SecureRandom und authentifizierter Verschlüsselung implementieren.
- PBKDF2-Parameter und Key-Management als Betriebsentscheidung dokumentieren.
- Read-old/write-new beziehungsweise expliziten Re-encryption-Job planen.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyMailFactory.java | MailCommand.java + JakartaMailGateway.java | Message-Erzeugung wird validiertes Kommando plus Gateway. |
Umsetzung
- Legacy MimeMessage-Felder und Session-Eigenschaften inventarisieren.
- MailCommand als validiertes Fachkommando definieren.
- JakartaMailGateway als Infrastrukturadapter implementieren.
- Unicode, Multipart/Attachments und Reply-To prüfen, soweit verwendet.
- Timeout-, Auth-, TLS- und Fehlerbehandlung konfigurieren.
- 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
| Legacy | Modern | Bedeutung |
|---|
| LegacyPriceCalculator.java | PriceService.java + PricingStrategy.java + PricingStrategyFactory.java | Switch wird Strategy/Factory-Komposition. |
| String/Branch Customer Type | CustomerType.java | Kundentyp wird expliziter Value/Enum-Vertrag. |
Umsetzung
- Switch-Zweige und Testfälle als Entscheidungstabelle erfassen.
- PricingStrategy als kleinen fachlichen Vertrag definieren.
- Je CustomerType eine Strategie implementieren oder als Lambda registrieren.
- PricingStrategyFactory mit Vollständigkeitsprüfung einführen.
- PriceService nur von Factory/Strategie abhängig machen.
- 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 →