4.9 KiB
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.
// ✅ 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.
// ✅
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.
import io.quarkus.logging.Log;
@ApplicationScoped
public class SftpService {
public List<String> 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.
// ✅
@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.