# CLAUDE.md — Dateieingang Service ## Projektbeschreibung Quarkus-Backend-Service, der einen n8n-Workflow bei Galabau ersetzt. Empfängt einen HTTP-Trigger von der APEX Automation, holt ZIP-Dateien von einem SFTP-Server, entpackt sie, lädt die Dateien in OCI Object Storage hoch und benachrichtigt die Oracle-Datenbank via ORDS. ## Dokumentation Nur bei Bedarf lesen — nicht automatisch in den Kontext laden: | Dokument | Inhalt | |---|---| | `SETUP.md` | Installation (WSL, Java 25, Quarkus CLI), Build, Dev-Server, Umgebungsvariablen | | `docs/Architecture.md` | Pipeline-Steps, Service-Mapping, Konfigurationsstruktur | | `docs/Logging.md` | Logging-Stack (LGTM), MDC-Felder, Log-Events pro Step | | `docs/Plan.md` | Vollständiger Architektur- und Migrationsplan | | `docs/SFTP-Integration.md` | SSHJ-Architektur, Host-Key-Verification, Fehlerbehandlung | Datenbankspezifische Dokumente: `../database/` ## Tech-Stack | Komponente | Technologie | |---|---| | Framework | Quarkus (Java 25) | | Build | Maven (Maven Wrapper `./mvnw`) | | SFTP | SSHJ (`com.hierynomus:sshj`) | | ZIP-Verarbeitung | Apache Commons Compress | | OCI Object Storage | OCI Java SDK (`oci-java-sdk-objectstorage`) | | ORDS-Client | MicroProfile REST Client | | Fehlertoleranz | SmallRye Fault Tolerance (`@Retry`, `@Timeout`) | | Async | Quarkus Managed Executor (`quarkus-smallrye-context-propagation`) | | Logging | Quarkus + OTLP → Loki/Grafana (Dev: `quarkus-observability-devservices-lgtm`) | | JSON | Jackson | ## Paketstruktur ``` src/main/java/de/galabau/dateieingang/ ├── api/ # REST Endpoint (eingehend von APEX Automation) ├── sftp/ # SSHJ: list, download, rename ├── zip/ # ZIP-Entpacken (Apache Commons Compress) ├── oci/ # OCI Object Storage Upload + Marker ├── ords/ # Oracle ORDS REST-Client (process_incoming) ├── pipeline/ # Orchestrierung des Gesamtworkflows ├── model/ # ProcessingContext, FileEntry, DTOs ├── config/ # @ConfigMapping Interfaces └── exception/ # Domain-Exceptions ``` ## Externe Abhängigkeiten | Service | Konfiguration | Zweck | |---|---|---| | SFTP-Server | `galabau.sftp.*` | ZIP-Dateien abholen | | OCI Object Storage | `galabau.oci.*` | Dateien + Marker ablegen | | Oracle ORDS | `galabau.ords.*` | DB-Verarbeitung auslösen | | APEX Automation | ruft `/api/process-incoming` auf | Trigger (stündlich) | ## Konventionen - **Sprache**: Dokumentation auf Deutsch, Code auf Englisch - **Konfiguration**: Alle URLs, Ports, Benutzernamen in `application.properties`; Passwörter und Keys via `${ENV_VAR}` aus Umgebungsvariablen - **Kein eigenes Scheduling**: Trigger kommt von APEX Automation via HTTP POST - **Async**: Pipeline läuft im Hintergrund, APEX bekommt sofort 202 Accepted - **Cleanup**: Lokale Arbeitsdateien immer im `finally`-Block löschen - **Einzelinstanz**: Kein Clustering — `AtomicBoolean`-Guard verhindert gleichzeitige Läufe ## Java Code Guidelines ### Sprache Dokumentation und Kommentare auf Deutsch, Code (Klassen-, Methoden-, Variablennamen) auf Englisch. ### Javadoc Javadoc für alle öffentlichen Methoden der Service-Klassen und alle Klassen in `model/`. Nicht nötig für triviale Getter, Test-Methoden oder selbsterklärende Signaturen. ```java // ✅ Javadoc sinnvoll /** * Lädt alle Dateien aus dem ProcessingContext in OCI Object Storage hoch * und schreibt danach den Marker für die DB-Verarbeitung. * * @param context enthält die Liste der hochzuladenden Dateien und den Ziel-Prefix * @throws OciException bei persistenten OCI-Fehlern (4xx) */ public void upload(ProcessingContext context) throws OciException { ... } ``` ### Exceptions Eigene Domain-Exceptions pro Integrationsbereich. Möglichst nicht `Exception` oder `RuntimeException` fangen. ```java // ✅ throw new SftpException("SFTP rename failed for: " + filename, cause); // ❌ throw new RuntimeException("something went wrong"); ``` ### Logging `io.quarkus.logging.Log` — statische API, kein Field-Boilerplate. ```java import io.quarkus.logging.Log; @ApplicationScoped public class SftpService { public List listZipFiles() throws SftpException { Log.infof("Listing ZIP files on SFTP: %s", config.remotePath()); Log.errorf(e, "SFTP list failed on %s", config.host()); } } ``` Immer mit MDC-Kontext loggen (wird automatisch angehängt, siehe `docs/Logging.md`). Nie sensible Daten loggen (Passwörter, Keys, Key-Dateipfade). ### Konfiguration Keine hardcodierten Werte — alles via `@ConfigMapping`. ```java // ✅ @ConfigMapping(prefix = "galabau.sftp") public interface SftpConfig { ... } // ❌ private static final String HOST = "sftp.lieferant.de"; ``` ### CDI / Services Services als `@ApplicationScoped`. Keine manuelle Instanziierung mit `new`. ### Paketgrenzen Kein direkter Zugriff auf interne Klassen fremder Pakete — nur über die öffentliche Service-API.