Umsetzung von M1
This commit is contained in:
@@ -1,13 +1,22 @@
|
||||
---
|
||||
model: sonnet
|
||||
---
|
||||
# AP06 – Bootstrap und CLI-Adapter
|
||||
|
||||
> **Meilenstein:** M1
|
||||
> **Vorgänger:** AP05 ✅ erforderlich
|
||||
> **Nachfolger:** AP07, AP09
|
||||
> **Grundlage:** `docs/specs/technik-und-architektur.md` v5, §§ „CLI-Zuschnitt", „Laufzeit- und Betriebsmodell", „Gültigkeitsentscheidung und Exit-Codes", „Zeichensätze"
|
||||
> **Entscheidungsprotokoll:** `docs/arbeitspakete/m1/E00-entscheidungsprotokoll.md` (E-05 fat JAR)
|
||||
|
||||
## Ziel
|
||||
|
||||
Die bestehende `AsvValidatorApplication` wird in zwei klar getrennte Verantwortlichkeiten zerlegt:
|
||||
|
||||
1. **Bootstrap** (`de.gecheckt.asv.bootstrap.Main`) — verdrahtet die Komponenten manuell per Constructor Injection und ist der einzige `public static void main`.
|
||||
2. **CLI-Adapter** (`de.gecheckt.asv.adapter.in.cli.CliRunner` oder ähnlich) — nimmt CLI-Argumente entgegen, ruft die Application-Schicht auf, übersetzt das Ergebnis in einen Exit-Code.
|
||||
1. **Bootstrap** (`de.gecheckt.asv.bootstrap.Main`) — verdrahtet alle Komponenten manuell per Constructor Injection, ist der einzige `public static void main`
|
||||
2. **CLI-Adapter** (`de.gecheckt.asv.adapter.in.cli.CliRunner`) — nimmt CLI-Argumente entgegen, ruft Application-Schicht auf, übersetzt Ergebnis in Exit-Code
|
||||
|
||||
Zusätzlich werden die **Exit-Codes spec-konform** auf `0/1/2` umgestellt.
|
||||
Zusätzlich werden Exit-Codes spec-konform auf `0/1/2` umgestellt, ISO-8859-15 als Eingabe-Encoding eingeführt, und das Uber-JAR via `maven-shade-plugin` gebaut.
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
@@ -15,82 +24,146 @@ Zusätzlich werden die **Exit-Codes spec-konform** auf `0/1/2` umgestellt.
|
||||
|
||||
## Scope IN
|
||||
|
||||
### Bootstrap
|
||||
- Klasse `de.gecheckt.asv.bootstrap.Main` mit `public static void main(String[] args)`
|
||||
- verdrahtet manuell:
|
||||
- Logging-Konfigurator
|
||||
- CLI-Runner
|
||||
- (Application-Service — Platzhalter, wird in AP09 feingeschnitten)
|
||||
- ruft `CliRunner.run(args)` auf, gibt den zurückgegebenen Exit-Code an `System.exit` weiter
|
||||
### Bootstrap (`de.gecheckt.asv.bootstrap.Main`)
|
||||
|
||||
- `public static void main(String[] args)`
|
||||
- Verdrahtet manuell per Constructor Injection:
|
||||
- `LoggingConfigurator`
|
||||
- `CliRunner`
|
||||
- Application-Service (in M1 noch Dummy-Pfad — Datei lesen, leeren `ValidationReport` zurückgeben)
|
||||
- Ruft `CliRunner.run(args)` auf und gibt den Exit-Code an `System.exit` weiter
|
||||
- Log4j2-Typen dürfen **nur** hier und in `adapter.out.logging` sichtbar sein
|
||||
|
||||
### CLI-Adapter (`de.gecheckt.asv.adapter.in.cli.CliRunner`)
|
||||
|
||||
### CLI-Adapter
|
||||
- Klasse `CliRunner` im Paket `adapter.in.cli`
|
||||
- Methode `int run(String[] args)`
|
||||
- akzeptiert **genau ein Positionsargument**: den Pfad zur Eingabedatei
|
||||
- bei 0 oder ≥2 Argumenten → Exit-Code `2`, Minimalbericht-Vorbereitung (vollständige Minimalbericht-Logik kommt in AP08)
|
||||
- bei nicht existierender, nicht lesbarer oder nicht regulärer Eingabedatei → Exit-Code `2`
|
||||
- bei erfolgreichem Lauf ohne Spec-Fehler → Exit-Code `0`
|
||||
- bei erfolgreichem Lauf mit Spec-Fehlern → Exit-Code `1`
|
||||
- Akzeptiert **genau ein Positionsargument**: Pfad zur Eingabedatei
|
||||
- Bei 0 oder ≥ 2 Argumenten → Exit-Code `2`, kurze deutsche Fehlermeldung auf STDERR (vollständiger Minimalbericht kommt in AP08)
|
||||
- Bei nicht existierender, nicht lesbarer oder nicht regulärer Eingabedatei → Exit-Code `2`
|
||||
- Bei erfolgreichem Lauf ohne Spec-Fehler → Exit-Code `0`
|
||||
- Bei erfolgreichem Lauf mit Spec-Fehlern → Exit-Code `1`
|
||||
|
||||
### Exit-Code-Konstanten
|
||||
- Konstanten **nur noch in einer Klasse** (z.B. `ExitCode` im Paket `adapter.in.cli`)
|
||||
- Werte:
|
||||
- `0` = gültig, keine Fehler-Befunde
|
||||
- `1` = ungültig, mindestens ein Spec-Fehler
|
||||
- `2` = Bedienfehler
|
||||
- Die alten Konstanten (`EXIT_CODE_INVALID_ARGUMENTS=1`, `EXIT_CODE_FILE_ERROR=2`, `EXIT_CODE_VALIDATION_ERRORS=3`) werden **gelöscht**
|
||||
|
||||
Konstanten **nur noch in einer Klasse** (z.B. `ExitCode` im Paket `adapter.in.cli`):
|
||||
|
||||
```java
|
||||
public final class ExitCode {
|
||||
public static final int VALID = 0;
|
||||
public static final int INVALID = 1;
|
||||
public static final int OPERATIONAL_ERROR = 2;
|
||||
private ExitCode() {}
|
||||
}
|
||||
```
|
||||
|
||||
Die alten Konstanten (`EXIT_CODE_INVALID_ARGUMENTS=1`, `EXIT_CODE_FILE_ERROR=2`, `EXIT_CODE_VALIDATION_ERRORS=3`) werden **gelöscht**.
|
||||
|
||||
### Verdrahtung mit Befundmodell (AP05)
|
||||
- `CliRunner` gibt am Ende einen `ValidationReport` aus AP05 weiter oder erzeugt selbst einen Minimal-`ValidationReport` mit einem `Finding` des Kinds `SPEC`, Severity `ERROR`, Layer `ARTIFACT` im Bedienfehlerfall
|
||||
- das eigentliche Einlesen und Verarbeiten der Datei kann für M1 noch ein **Dummy-Pfad** sein: die Datei wird gelesen, die Bytes gezählt, ein leerer `ValidationReport` mit `fileName` und `timestamp` zurückgegeben. Echte Validierung gehört nicht in M1.
|
||||
|
||||
- `CliRunner` nutzt `ValidationReport.computeVerdict()` zur Exit-Code-Ableitung
|
||||
- Im Bedienfehlerfall: `ValidationReport.operationalError(...)` → Exit-Code `2`
|
||||
- Der eigentliche M1-Dummy-Pfad: Datei wird gelesen (ISO-8859-15), Bytes gezählt, leerer `ValidationReport` mit `fileName` und `timestamp` zurückgegeben. **Keine echte Validierung in M1.**
|
||||
|
||||
### Zeichensatz-Korrektur
|
||||
- beim Einlesen der Eingabedatei wird **ISO 8859-15** verwendet, nicht UTF-8. Das ist eine harte Spec-Vorgabe aus `fachliche-anforderungen.md` §5.1 und muss ab jetzt dauerhaft so bleiben.
|
||||
```java
|
||||
Files.readString(path, StandardCharsets.ISO_8859_1); // nicht ideal — besser Charset.forName("ISO-8859-15")
|
||||
```
|
||||
Achtung: Java kennt `StandardCharsets.ISO_8859_1`, aber **nicht** `ISO_8859_15`. Daher `Charset.forName("ISO-8859-15")` verwenden.
|
||||
|
||||
Beim Einlesen der Eingabedatei wird **ISO-8859-15** verwendet:
|
||||
|
||||
```java
|
||||
// Korrekt:
|
||||
Charset iso = Charset.forName("ISO-8859-15");
|
||||
// NICHT: StandardCharsets.UTF_8
|
||||
// NICHT: Charset.defaultCharset()
|
||||
```
|
||||
|
||||
JDK-21-Verfügbarkeit per Test belegen: Eine Datei mit Byte `0xA4` ergibt beim Einlesen das Euro-Zeichen `€`, weil `0xA4` in ISO-8859-15 auf Euro-Zeichen liegt.
|
||||
|
||||
### Uber-JAR via `maven-shade-plugin`
|
||||
|
||||
`maven-jar-plugin`-Platzhalter aus AP02 ersetzen durch `maven-shade-plugin`:
|
||||
|
||||
```xml
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version><!-- aktuell stabil --></version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals><goal>shade</goal></goals>
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer implementation=
|
||||
"org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>de.gecheckt.asv.bootstrap.Main</mainClass>
|
||||
</transformer>
|
||||
<!-- Log4j2 PluginCache zusammenführen -->
|
||||
<transformer implementation=
|
||||
"org.apache.maven.plugins.shade.resource.Log4j2PluginsCacheFileTransformer"/>
|
||||
</transformers>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
```
|
||||
|
||||
`java -jar target/asv-format-validator-*.jar <datei>` muss ohne `-cp` funktionieren.
|
||||
|
||||
### `.gitignore` — `logs/` ergänzen
|
||||
|
||||
`logs/` zum `.gitignore` hinzufügen (gemäß E-04 aus Entscheidungsprotokoll). Der statische Dateipfad aus AP04 wird nach AP07 durch dynamische Logdatei ersetzt.
|
||||
|
||||
## Scope OUT
|
||||
|
||||
- Berichtdatei und Log-Datei im Eingabeverzeichnis (AP07)
|
||||
- vollständiger Minimalbericht bei Exit-Code `2` (AP08)
|
||||
- Vollständiger Minimalbericht bei Exit-Code `2` (AP08)
|
||||
- Entkopplung der Altlogik (AP09)
|
||||
- Architekturtest (AP10)
|
||||
|
||||
## Schritte
|
||||
|
||||
1. Branch `m1/ap06-bootstrap-cli`
|
||||
2. `de.gecheckt.asv.bootstrap.Main` anlegen mit `public static void main`
|
||||
3. `CliRunner` in `adapter.in.cli` anlegen
|
||||
4. `ExitCode`-Konstantenklasse anlegen
|
||||
5. `AsvValidatorApplication` schrittweise entkernen: Code wandert nach `CliRunner` und `Main`
|
||||
6. Einlese-Encoding auf `Charset.forName("ISO-8859-15")` umstellen
|
||||
7. `maven-jar-plugin` in `pom.xml` auf `de.gecheckt.asv.bootstrap.Main` setzen (Platzhalter aus AP02 konkretisieren)
|
||||
8. Alle Tests, die auf `AsvValidatorApplication` direkt zeigen, auf `CliRunner` umziehen
|
||||
9. `mvn clean package` laufen lassen, das erzeugte JAR manuell mit `java -jar target/asv-format-validator-*.jar <test-datei>` prüfen
|
||||
1. `de.gecheckt.asv.bootstrap.Main` anlegen
|
||||
2. `CliRunner` in `adapter.in.cli` anlegen
|
||||
3. `ExitCode`-Konstantenklasse anlegen
|
||||
4. `AsvValidatorApplication` schrittweise entkernen: Code wandert nach `CliRunner` und `Main`
|
||||
5. Einlese-Encoding auf `Charset.forName("ISO-8859-15")` umstellen
|
||||
6. `maven-shade-plugin` in `pom.xml` einbinden, `maven-jar-plugin`-Platzhalter entfernen
|
||||
7. `logs/` in `.gitignore` ergänzen
|
||||
8. Alle Tests die auf `AsvValidatorApplication` direkt zeigen auf `CliRunner` umziehen
|
||||
9. `mvn clean package` — erzeugtes JAR mit `java -jar target/asv-format-validator-*.jar <testdatei>` manuell prüfen
|
||||
10. `mvn clean verify` grün bekommen
|
||||
11. Commit `M1-AP06: Bootstrap, CLI-Adapter, Exit-Codes 0/1/2, ISO 8859-15`
|
||||
12. Abschlussbericht schreiben
|
||||
11. Abschlussbericht schreiben
|
||||
|
||||
## Abnahmekriterien
|
||||
|
||||
- `de.gecheckt.asv.bootstrap.Main` existiert und ist `Main-Class` des JAR
|
||||
- `CliRunner` ist der einzige Ort mit CLI-Argument-Parsing
|
||||
- Exit-Codes `0`, `1`, `2` sind definiert und spec-konform eingesetzt
|
||||
- **Test:** Aufruf ohne Argument → Exit-Code `2`
|
||||
- **Test:** Aufruf mit nicht existierender Datei → Exit-Code `2`
|
||||
- **Test:** Aufruf mit leerer, lesbarer Datei → Exit-Code `0` (Dummy-Pfad, leerer `ValidationReport`)
|
||||
- Einlese-Encoding ist ISO 8859-15 (per Test belegt: eine Datei mit Byte `0xA4` ergibt beim Einlesen `€`, weil `0xA4` in ISO 8859-15 auf Euro-Zeichen liegt)
|
||||
- ausführbares JAR unter `target/` ist manuell startbar
|
||||
- `mvn clean verify` ist grün
|
||||
- Abschlussbericht liegt vor
|
||||
- [ ] `de.gecheckt.asv.bootstrap.Main` existiert und ist `Main-Class` des Uber-JAR
|
||||
- [ ] `CliRunner` ist der einzige Ort mit CLI-Argument-Parsing
|
||||
- [ ] Exit-Codes `0`, `1`, `2` sind definiert und spec-konform eingesetzt, kein Exit-Code `3` mehr erreichbar
|
||||
- [ ] Test: Aufruf ohne Argument → Exit-Code `2`
|
||||
- [ ] Test: Aufruf mit nicht existierender Datei → Exit-Code `2`
|
||||
- [ ] Test: Aufruf mit leerer, lesbarer Datei → Exit-Code `0`
|
||||
- [ ] Einlese-Encoding ist ISO-8859-15 (per Test belegt: Byte `0xA4` → `€`)
|
||||
- [ ] `java -jar target/asv-format-validator-*.jar <datei>` startet ohne `-cp`
|
||||
- [ ] `logs/` in `.gitignore`
|
||||
- [ ] Keine Log4j2-Typen außerhalb von `bootstrap` und `adapter.out.logging`
|
||||
- [ ] `mvn clean verify` grün
|
||||
- [ ] Abschlussbericht unter `docs/arbeitspakete/m1/berichte/AP06-bericht.md`
|
||||
|
||||
## Rest-Risiken und offene Punkte
|
||||
|
||||
- Der Dummy-Pfad (Datei wird gelesen, leerer Report zurückgegeben) ist bewusst dünn. Die Einbindung der alten Parser-Logik passiert in AP09.
|
||||
- Es ist verlockend, schon hier in AP06 die bestehende Parser-/Validator-Kette mit dem neuen Modell zu verknüpfen. **Nicht tun.** AP06 soll nur die äußere Hülle geradeziehen.
|
||||
- Der Dummy-Pfad (Datei lesen, leerer Report) ist bewusst dünn. Echte Parser-/Validator-Einbindung kommt in M3+.
|
||||
- Nicht versuchen, in AP06 schon die alte Parser-/Validator-Kette mit dem neuen Modell zu verknüpfen — das ist AP09-Scope.
|
||||
- `maven-shade-plugin` mit Log4j2 benötigt den `Log4j2PluginsCacheFileTransformer`, sonst werden Log4j2-Plugins nicht korrekt geladen.
|
||||
|
||||
## Bericht
|
||||
|
||||
`docs/arbeitspakete/m1/berichte/AP06-bericht.md` nach `templates/ap-bericht.md`.
|
||||
`docs/arbeitspakete/m1/berichte/AP06-bericht.md` nach `docs/arbeitspakete/m1/templates/ap-bericht.md`.
|
||||
|
||||
Reference in New Issue
Block a user