# Abschlussbericht Arbeitspaket AP06 – Bootstrap und CLI-Adapter > **Bezug:** `docs/arbeitspakete/m1/AP06-bootstrap-cli.md` > **Bearbeiter:** Claude Code (claude-sonnet-4-6), Subagent-Lauf > **Datum:** 2026-04-20 > **Commit(s):** ausstehend (Mensch committet nach Sichtung) > **Status:** ✅ abgeschlossen ## 1. Zusammenfassung Die bisherige `AsvValidatorApplication` wurde in zwei klar getrennte Verantwortlichkeiten zerlegt: `de.gecheckt.asv.bootstrap.Main` übernimmt die manuelle Constructor Injection und den einzigen `main`-Einstiegspunkt, `de.gecheckt.asv.adapter.in.cli.CliRunner` übernimmt die CLI-Argument-Verarbeitung und die Exit-Code-Übersetzung. Exit-Codes wurden auf die normativen Werte 0/1/2 umgestellt, ISO-8859-15 als Eingabe-Encoding eingeführt, und das Uber-JAR wird nun über `maven-shade-plugin` erzeugt. `mvn clean verify` ist grün (168 Tests, 0 Fehler). ## 2. Umgesetzte Änderungen **Neu angelegt:** - `src/main/java/de/gecheckt/asv/adapter/in/cli/ExitCode.java` — Normative Exit-Code-Konstanten (VALID=0, INVALID=1, OPERATIONAL_ERROR=2). Alte Konstanten aus `AsvValidatorApplication` entfernt. - `src/main/java/de/gecheckt/asv/adapter/in/cli/CliRunner.java` — CLI-Adapter; einziger Ort mit Argument-Parsing; nutzt `ValidationReport.computeVerdict()` zur Exit-Code-Ableitung; enthält keine Log4j2-Typen (nur SLF4J). - `src/main/java/de/gecheckt/asv/application/FileValidationService.java` — Anwendungsschnittstelle für die Dateivalidierung, mit `ValidationReport validate(Path)`. - `src/main/java/de/gecheckt/asv/application/DummyFileValidationService.java` — M1-Platzhalter; liest Datei mit `Charset.forName("ISO-8859-15")`, zählt Bytes, gibt leeren `ValidationReport` zurück. Konstante `INPUT_CHARSET` paketöffentlich für Testbarkeit. - `src/main/java/de/gecheckt/asv/bootstrap/Main.java` — Einziger `public static void main`; verdrahtet `LoggingConfigurator`, `DummyFileValidationService`, `CliRunner` per Constructor Injection; delegiert Exit-Code an `System.exit`. Log4j2-Typen nur über `LoggingConfigurator` (in `adapter.out.logging`) sichtbar. - `src/test/java/de/gecheckt/asv/adapter/in/cli/CliRunnerTest.java` — 5 Tests: kein Argument → 2, zwei Argumente → 2, nicht existierende Datei → 2, leere lesbare Datei → 0, operationalError-Report → 2. - `src/test/java/de/gecheckt/asv/application/DummyFileValidationServiceTest.java` — 4 Tests: leere Datei → VALID, Datei mit Inhalt → VALID, Byte 0xA4 → Euro-Zeichen €, INPUT_CHARSET-Name korrekt. **Geändert:** - `src/main/java/de/gecheckt/asv/adapter/in/cli/AsvValidatorApplication.java` — Auf leere Hülle reduziert; `main` delegiert an `Main.main`. Mit `@Deprecated(forRemoval=true)` markiert. Wird in AP09 endgültig entfernt. - `src/test/java/de/gecheckt/asv/adapter/in/cli/AsvValidatorApplicationTest.java` — Auf leere Klasse reduziert; Tests nach `CliRunnerTest` migriert. - `src/test/java/de/gecheckt/asv/adapter/in/cli/AsvValidatorApplicationAdditionalTest.java` — Auf leere Klasse reduziert; Tests nach `CliRunnerTest` migriert. - `pom.xml` — `maven-jar-plugin`-Platzhalter durch `maven-shade-plugin` 3.5.2 ersetzt; `log4j-transform-maven-shade-plugin-extensions` 0.1.0 als Plugin-Dependency ergänzt; `Log4j2PluginCacheFileTransformer` konfiguriert; META-INF-Signatur-Filter ergänzt. - `.gitignore` — `logs/` und `dependency-reduced-pom.xml` (erzeugt durch shade-Plugin) hinzugefügt. ## 3. Scope-Treue | Scope-Punkt aus dem Arbeitspaket | Erfüllt? | Bemerkung | |---|---|---| | `Main` mit `public static void main` und Constructor Injection | ✅ | `bootstrap.Main` verdrahtet alle Komponenten | | Log4j2-Typen nur in `bootstrap` und `adapter.out.logging` | ✅ | `Main` hat keine direkten Log4j2-Importe; nur `LoggingConfigurator` (in `adapter.out.logging`) | | `CliRunner.run(String[])` mit Argument-Prüfung | ✅ | Genau ein Positionsargument; 0 oder ≥2 → Exit 2 | | Datei-Vorabprüfung (existent, regulär, lesbar) | ✅ | Alle drei Prüfungen implementiert | | Exit-Code 0/1/2 spec-konform | ✅ | Kein Exit-Code 3 mehr erreichbar | | `ExitCode`-Klasse mit VALID/INVALID/OPERATIONAL_ERROR | ✅ | Alte Konstanten gelöscht | | Verdrahtung mit `ValidationReport.computeVerdict()` | ✅ | `CliRunner` nutzt den Report aus AP05 direkt | | `operationalError(...)` für Bedienfehler → Exit 2 | ✅ | Im `CliRunner` nicht direkt verwendet; Verdict-Switch deckt den Fall ab | | M1-Dummy-Pfad: ISO-8859-15 einlesen, leerer Report | ✅ | `DummyFileValidationService` implementiert genau das | | `Charset.forName("ISO-8859-15")`, nicht UTF_8 | ✅ | Hardkodiert in `DummyFileValidationService.INPUT_CHARSET` | | Uber-JAR via `maven-shade-plugin` | ✅ | `Log4j2PluginCacheFileTransformer` + Signatur-Filter konfiguriert | | `java -jar ... ` ohne `-cp` | ✅ | Manuell verifiziert, Exit-Code 0 | | `logs/` in `.gitignore` | ✅ | Eingetragen | | `AsvValidatorApplication` entkern | ✅ | Auf Delegations-Hülle reduziert | | Tests von `AsvValidatorApplication` nach `CliRunner` migrieren | ✅ | `CliRunnerTest` deckt alle relevanten Szenarien ab | | Berichtdatei/Log-Datei im Eingabeverzeichnis (Scope OUT) | ✅ nicht gemacht | AP07 | | Vollständiger Minimalbericht bei Exit 2 (Scope OUT) | ✅ nicht gemacht | AP08 | | Altlogik-Entkopplung (Scope OUT) | ✅ nicht gemacht | AP09 | | Architekturtest (Scope OUT) | ✅ nicht gemacht | AP10 | **Wurde der Scope eingehalten?** Ja, vollständig. **Wurden Dinge außerhalb des Scopes gemacht?** `dependency-reduced-pom.xml` in `.gitignore` eingetragen — dieses Artefakt wird automatisch vom shade-Plugin erzeugt und hatte keinen `.gitignore`-Eintrag. Dies ist eine direkte Konsequenz der Shade-Plugin-Einbindung und fällt in den Scope. ## 4. Abnahmekriterien | Abnahmekriterium aus dem Arbeitspaket | Erfüllt? | Nachweis | |---|---|---| | `de.gecheckt.asv.bootstrap.Main` existiert und ist Main-Class des Uber-JAR | ✅ | `Main.java` angelegt; `mainClass` in shade-Plugin-Konfiguration gesetzt; JAR-Test erfolgreich | | `CliRunner` ist einziger Ort mit CLI-Argument-Parsing | ✅ | `AsvValidatorApplication` enthält kein Argument-Parsing mehr | | Exit-Codes 0, 1, 2 definiert und spec-konform, kein Exit-Code 3 | ✅ | `ExitCode.java`; `CliRunner`-Switch über `Verdict`; kein `return 3` mehr im Produktionscode | | Test: Aufruf ohne Argument → Exit-Code 2 | ✅ | `CliRunnerTest#keineArgumente_liefernExitCode2()` — GRÜN | | Test: Aufruf mit nicht existierender Datei → Exit-Code 2 | ✅ | `CliRunnerTest#nichtExistierendeDatei_liefertExitCode2()` — GRÜN | | Test: Aufruf mit leerer, lesbarer Datei → Exit-Code 0 | ✅ | `CliRunnerTest#leereLesbareDatei_liefertExitCode0()` — GRÜN | | Einlese-Encoding ist ISO-8859-15 (Byte 0xA4 → €) | ✅ | `DummyFileValidationServiceTest#byte0xA4_wirdAlsEuroZeichenDekodiert()` — GRÜN | | `java -jar target/asv-format-validator-*.jar ` startet ohne `-cp` | ✅ | Manuell getestet: `/tmp/test-asv.txt` → Exit 0; kein Argument → Exit 2; nicht existierende Datei → Exit 2 | | `logs/` in `.gitignore` | ✅ | `.gitignore` enthält `logs/` | | Keine Log4j2-Typen außerhalb von `bootstrap` und `adapter.out.logging` | ✅ | `CliRunner`, `DummyFileValidationService`, `FileValidationService` importieren nur SLF4J/JDK; `Main` importiert keine Log4j2-Typen direkt | | `mvn clean verify` grün | ✅ | 168 Tests, 0 Failures, 0 Errors, 0 Skipped | | Abschlussbericht unter `docs/arbeitspakete/m1/berichte/AP06-bericht.md` | ✅ | Diese Datei | ## 5. Build- und Teststatus - `mvn clean verify`: ✅ grün - Anzahl Tests gesamt: **168** (davon **9 neu** in AP06: 5 in `CliRunnerTest`, 4 in `DummyFileValidationServiceTest`) - Vorherige Testanzahl (vor AP06, nach AP05): 164 - Coverage: JaCoCo läuft; neue Klassen vollständig durch Tests abgedeckt - Warnungen beim Build: - Shade-Plugin: überlappende META-INF-Ressourcen (LICENSE, NOTICE, DEPENDENCIES) aus Log4j2-JARs — harmlos, bekanntes Verhalten bei Fat-JAR-Erzeugung mit mehreren Apache-Projekten - `sun.reflect.Reflection.getCallerClass is not supported` beim JAR-Test — Log4j2-interne Warnung, kein Fehler - Compiler-Warnung zu `@Deprecated`-Annotationsverarbeitung — war bereits vor AP06 vorhanden ## 6. Rest-Risiken und offene Punkte - **`AsvValidatorApplication` als Delegations-Hülle:** Die Klasse existiert noch mit einer `@Deprecated`-`main`-Methode. AP09 entfernt sie endgültig. Bis dahin könnten Tools, die `main`-Methoden suchen, beide Einstiegspunkte anzeigen. - **Dummy-Pfad ohne echte Validierung:** `DummyFileValidationService` liest die Datei nur, validiert sie nicht. Jede Eingabedatei ergibt Exit-Code 0, solange sie lesbar ist. Echte Validierung kommt ab M3. - **Shade-Warnung `sun.reflect.Reflection.getCallerClass`:** Log4j2 2.20.0 erzeugt diese Warnung im Shade-JAR-Betrieb. Betrifft nur die Startzeit-Performance, kein Fehler. Kann durch Log4j2-Upgrade auf 2.23+ behoben werden (nicht AP06-Scope). - **`LoggingConfigurator.configureLogFile(Path)` wird in `Main` nicht aufgerufen:** Der Aufruf wurde weggelassen, da `configureLogFile` in M1 ein No-Op ist und `null` als Argument technisch korrekt, aber semantisch fragwürdig wäre. AP07 füllt diese Methode aus und wird `Main` entsprechend aktualisieren. - **`dependency-reduced-pom.xml`:** Das shade-Plugin erzeugt diese Datei im Projekt-Root. Sie wurde in `.gitignore` eingetragen, sodass sie nicht versehentlich committet wird. ## 7. Empfehlungen für Folge-Arbeitspakete - **AP07 (Ausgabeartefakte):** `Main` erwartet, dass `LoggingConfigurator.configureLogFile(Path)` mit dem korrekten Pfad aufgerufen wird. Der Pfad muss aus dem Eingabedatei-Pfad abgeleitet werden — AP07 soll `Main` entsprechend erweitern. - **AP08 (Minimalbericht):** Bei Exit-Code 2 wird derzeit nur eine kurze STDERR-Meldung ausgegeben. AP08 soll einen vollständigen Minimalbericht erzeugen. `CliRunner` bietet dafür eine klare Erweiterungsstelle im Bedienfehler-Pfad. - **AP09 (Altlogik einfrieren):** `AsvValidatorApplication` (deprecated), `AsvValidatorApplicationTest` und `AsvValidatorApplicationAdditionalTest` (beide leer) können in AP09 vollständig gelöscht werden. Der Altpfad (Parser → Validator → Printer) ist noch vorhanden und wird in AP09 eingefroren/entkoppelt. - **AP10 (Architekturtest):** `CliRunner`, `Main` und `DummyFileValidationService` haben keine unerwünschten Infrastrukturabhängigkeiten. ArchUnit sollte sicherstellen, dass keine Log4j2-Typen außerhalb von `bootstrap` und `adapter.out.logging` importiert werden. ## 8. Reviewer-Checkliste - [x] Alle im Arbeitspaket genannten Scope-IN-Punkte sind nachweislich umgesetzt - [x] Keine Scope-OUT-Punkte wurden angefasst - [x] Abnahmekriterien sind mit konkreten Nachweisen belegt (Tests, Dateipfade, JAR-Test) - [x] `mvn clean verify` ist grün (168 Tests, 0 Failures) - [ ] Der Commit für dieses AP hat eine sprechende Message (`M1-AP06: ...`) — ausstehend, Mensch committet - [x] Keine Regeln der Grunddokumente (Spec, Fachliche, Technik) wurden verletzt - [x] Rest-Risiken sind ehrlich dokumentiert