Fachlicher Vertrag: unverändert zu erhalten
- Dateiinhalte, Attribute und Überschreibregeln sind bewusst festgelegt.
- Ressourcen werden in allen Fehlerpfaden geschlossen.
- Pfadvalidierung verhindert Traversal außerhalb erlaubter Wurzeln.
File und manuelles Ressourcenmanagement wird nachvollziehbar in Path, Files und Try-with-resources überführt. Die Akte zeigt nicht nur das Ziel, sondern die tatsächlichen Dateien, APIs, Dependencies, Codebelege, Tests, Risiken und Cutover-Schritte.
| Dimension | Legacy | Modern | Migrationskonsequenz |
|---|---|---|---|
| Programmiermodell | imperativ / ohne Framework-Annotationen | explizite Java-Abstraktionen | Annotationen und Containerfunktionen werden nur dort eingesetzt, wo sie eine konkrete technische Verantwortung übernehmen. |
| Abhängigkeiten | 1 direkte Dependencies | 1 direkte Dependencies | 0 neu, 0 entfernt; Versionen und transitive Auswirkungen im erfolgreichen Online-Build prüfen. |
| Öffentliche API | 1 erkannte Methoden | 3 erkannte Methoden | Methoden werden nach fachlicher Rolle gemappt; reine Bootstrap- und Framework-Methoden sind kein fachlicher Vertrag. |
| Datenmodell | class LegacyFileCopy | class PathFileService | Feldnamen, IDs, Null-Semantik, Gleichheit und Serialisierungsform werden separat regressionstestet. |
| Fehlerverhalten | Legacy-Exceptions und Rückgabewerte | explizitere Fach-/Framework-Fehlerabbildung | Fehler dürfen nicht nur technisch übersetzt werden; Status, Ursache, Retrybarkeit und Client-Vertrag müssen erhalten oder versioniert werden. |
| Tests | Bestands- und Golden-Master-Tests | Unit-, Slice-, Contract- und Integrationstests | Der Modern-Pfad wird zuerst gegen denselben fachlichen Vektor geprüft und danach um neue technische Risiken ergänzt. |
| Betrieb | Legacy-Start/Lifecycle | modernes Packaging, Health und externe Konfiguration | Umstellung über kleine Adapter und Golden-Master-Tests statt Big Bang. |
| Rollback | Legacy-Artefakt bleibt unverändert | Modern-Artefakt getrennt deploybar | Kein Rollback über Datenverlust: Schema, Nachrichten und verschlüsselte Daten müssen rückwärtslesbar oder durch Dual-Read abgesichert sein. |
resource handling, overwrite and atomicity
permissions, missing files, overwrite and large-file tests
Die Zuordnung ist semantisch: Eine Legacy-Klasse kann in mehrere moderne Rollen zerlegt werden.
| Legacy-Rolle / Datei | Modern-Rolle / Datei | Bedeutung |
|---|---|---|
| LegacyFileCopy.java | PathFileService.java | File/Streams werden Path/Files und sichere Ressourcenverwaltung. |
| Datei | Typ | Annotationen | öffentliche API | Pattern | Zeilen |
|---|---|---|---|---|---|
| LegacyFileCopy.java | class LegacyFileCopy | — | long copy(File source, File target) | Adapter – kapselt streambasiertes Kopieren hinter einer kleinen Datei-API. | 29 |
| Datei | Typ | Annotationen | öffentliche API | Pattern | Zeilen |
|---|---|---|---|---|---|
| PathFileService.java | class PathFileService | — | long copy(Path source, Path target) List<Path> find(Path root, String suffix) void zip(Path source, Path zip) | Adapter | 30 |
| Status | Dependency | Version | Scope | Prüfung |
|---|---|---|---|---|
| BEIBEHALTEN | org.junit.jupiter:junit-jupiter | BOM/Parent → BOM/Parent | test → test | Gemeinsame Dependency; Version und Scope im effektiven POM prüfen. |
Die folgenden Ausschnitte stammen direkt aus den enthaltenen Projekten. Dadurch ist sichtbar, welche Verantwortung tatsächlich verschoben wurde.
Migrationsbedeutung: File/Streams werden Path/Files und sichere Ressourcenverwaltung.
projects/17-io-nio/legacy/src/main/java/at/aydin/lab/io/legacy/LegacyFileCopy.java
package at.aydin.lab.io.legacy;
// Design Pattern: Adapter – kapselt streambasiertes Kopieren hinter einer kleinen Datei-API.
import java.io.*;
public final class LegacyFileCopy {
public long copy(File source, File target) throws IOException {
InputStream in = null;
OutputStream out = null;
long bytes = 0;
try {
in = new FileInputStream(source);
out = new FileOutputStream(target);
byte[] buffer = new byte[4096];
int read;
while ((read = in.read(buffer)) >= 0) {
out.write(buffer, 0, read);
bytes += read;
}
return bytes;
} finally {
if (in != null) try {
in.close();
} catch (IOException ignored) {
}
if (out != null) out.close();
}
}
}
projects/17-io-nio/modern/src/main/java/at/aydin/lab/io/modern/PathFileService.java
package at.aydin.lab.io.modern;
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.zip.*;
// Design Pattern: Adapter
// Zweck: Fachliche Dateioperationen werden hinter der modernen Path-/Files-API gebündelt.
public final class PathFileService {
public long copy(Path source, Path target) throws IOException {
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
return Files.size(target);
}
public List<Path> find(Path root, String suffix) throws IOException {
try (var paths = Files.walk(root)) {
return paths.filter(Files::isRegularFile).filter(p -> p.getFileName().toString().endsWith(suffix)).sorted()
.toList();
}
}
public void zip(Path source, Path zip) throws IOException {
try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(zip))) {
out.putNextEntry(new ZipEntry(source.getFileName().toString()));
Files.copy(source, out);
out.closeEntry();
}
}
}
--- LegacyFileCopy.java
+++ PathFileService.java
@@ -1,29 +1,30 @@
-package at.aydin.lab.io.legacy;
+package at.aydin.lab.io.modern;
-// Design Pattern: Adapter – kapselt streambasiertes Kopieren hinter einer kleinen Datei-API.
import java.io.*;
+import java.nio.file.*;
+import java.util.*;
+import java.util.zip.*;
-public final class LegacyFileCopy {
- public long copy(File source, File target) throws IOException {
- InputStream in = null;
- OutputStream out = null;
- long bytes = 0;
- try {
- in = new FileInputStream(source);
- out = new FileOutputStream(target);
- byte[] buffer = new byte[4096];
- int read;
- while ((read = in.read(buffer)) >= 0) {
- out.write(buffer, 0, read);
- bytes += read;
- }
- return bytes;
- } finally {
- if (in != null) try {
- in.close();
- } catch (IOException ignored) {
- }
- if (out != null) out.close();
+// Design Pattern: Adapter
+// Zweck: Fachliche Dateioperationen werden hinter der modernen Path-/Files-API gebündelt.
+public final class PathFileService {
+ public long copy(Path source, Path target) throws IOException {
+ Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
+ return Files.size(target);
+ }
+
+ public List<Path> find(Path root, String suffix) throws IOException {
+ try (var paths = Files.walk(root)) {
+ return paths.filter(Files::isRegularFile).filter(p -> p.getFileName().toString().endsWith(suffix)).sorted()
+ .toList();
+ }
+ }
+
+ public void zip(Path source, Path zip) throws IOException {
+ try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(zip))) {
+ out.putNextEntry(new ZipEntry(source.getFileName().toString()));
+ Files.copy(source, out);
+ out.closeEntry();
}
}
}
| ID | Ebene | Prüfung | erforderlicher Nachweis |
|---|---|---|---|
| 17-IO-NIO-A01 | Integration/Contract | Kopie ist byte-identisch. | Automatisierter Test und CI-Protokoll |
| 17-IO-NIO-A02 | Integration/Contract | Fehlende Quelle und bestehendes Ziel liefern definierte Fehler. | Automatisierter Test und CI-Protokoll |
| 17-IO-NIO-A03 | Integration/Contract | Keine offenen File Descriptors. | Automatisierter Test und CI-Protokoll |
| 17-IO-NIO-A04 | Integration/Contract | Traversal/Symlink-Risiken sind behandelt. | Automatisierter Test und CI-Protokoll |
| 17-IO-NIO-A05 | Integration/Contract | Große Dateien werden ohne unnötige Vollspeicherung verarbeitet. | Automatisierter Test und CI-Protokoll |
| 17-IO-NIO-T01 | Unit | Fachlogik ohne Container oder externen Dienst testen. | Unit-Test |
| 17-IO-NIO-T02 | Regression | Legacy- und Modern-Ergebnis für denselben Golden-Master-Vektor vergleichen. | Vergleichsreport |
| 17-IO-NIO-T03 | Negative | Fehlerhafte, leere und grenzwertige Eingaben prüfen. | Negativtest |
| 17-IO-NIO-T04 | Operations | Start, Health, Shutdown und Konfigurationsfehler prüfen. | Deployment-/Startprotokoll |
| 17-IO-NIO-F01 | Fokus | permissions, missing files, overwrite and large-file tests | Modulspezifischer Testreport |
| Risiko | Auswirkung | Gegenmaßnahme | Gate |
|---|---|---|---|
| resource handling, overwrite and atomicity | NIEDRIG | permissions, missing files, overwrite and large-file tests | vor Cutover |
Keine zusätzlichen Ressourcen.
PathFileService kann intern auf den Legacy-Pfad delegieren; Dateiformat und Zielpfad bleiben unverändert.