146 lines
4.9 KiB
Markdown
146 lines
4.9 KiB
Markdown
|
|
# 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<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`.
|
||
|
|
|
||
|
|
```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.
|