Skip to content

Plugin-System

FinAnalyzer verwendet ein modulares Plugin-System, das Built-in Plugins (im Lieferumfang enthalten) und externe Plugins (als JAR-Dateien nachinstallierbar) unterstützt.

┌──────────────────────────────────────────────────┐
│ FinAnalyzer Backend │
│ │
│ ┌─────────────┐ ┌──────────────────────────┐ │
│ │ Plugin │ │ Built-in Plugins │ │
│ │ Registry │◄──│ • CSV Import │ │
│ │ Service │ │ • Google Sheets │ │
│ │ │ │ • HBCI / FinTS │ │
│ │ (DB sync, │ │ • Tink Open Banking │ │
│ │ lifecycle)│ └──────────────────────────┘ │
│ │ │ │
│ │ │ ┌──────────────────────────┐ │
│ │ │◄──│ External Plugins (PF4J) │ │
│ │ │ │ • /data/plugins/*.jar │ │
│ └─────────────┘ └──────────────────────────┘ │
│ │
│ ┌─────────────┐ ┌──────────────────────────┐ │
│ │ Plugin │ │ Plugin Config │ │
│ │ Admin API │ │ Service │ │
│ │ (Admins) │ │ (pro User, JSON Schema) │ │
│ └─────────────┘ └──────────────────────────┘ │
└──────────────────────────────────────────────────┘

Diese Plugins sind fest im Backend eingebaut und sofort verfügbar:

PluginKategorieBeschreibung
CSV ImportImportBanktransaktionen aus CSV-Dateien importieren
Google SheetsImportTransaktionen aus Google Sheets synchronisieren
HBCI / FinTSImportDirekter Bankzugang über das FinTS-Protokoll (deutsche Banken)
Tink Open BankingImportPSD2-konformer Bankzugang über die Tink-API (europaweit)

Built-in Plugins werden beim Serverstart automatisch erkannt und registriert. Sie können von Admins aktiviert/deaktiviert werden.

Externe Plugins werden als JAR-Dateien bereitgestellt und in das Plugin-Verzeichnis gelegt. Das Backend erkennt neue JARs automatisch zur Laufzeit (Hot-Reload) — kein Neustart nötig.

Plugin-Verzeichnis:

  • All-in-One Image: /data/plugins/
  • Docker Compose (Prod/Dev): gemountet via plugins-data Volume
  • Lokale Entwicklung (IDE): ./plugins/ relativ zum Backend-Arbeitsverzeichnis
  • Konfigurierbar via: Umgebungsvariable FINANALYZER_PLUGINS_DIR

Jedes Plugin durchläuft einen definierten Lebenszyklus — sowohl beim Serverstart als auch bei Hot-Reload (neue JARs zur Laufzeit):

Neu entdeckt: onInstall() → onLoad() → onEnable()
Bereits bekannt: onLoad() → onEnable() (wenn ENABLED)
Deaktiviert: onLoad() (kein onEnable)
CallbackWannZweck
onInstall()Einmalig beim ersten EntdeckenErsteinrichtung (z.B. Default-Konfiguration)
onLoad()Bei jedem Serverstart oder Hot-ReloadRessourcen laden, Caches initialisieren
onEnable()Bei Start/Hot-Reload, wenn Plugin aktivFunktionalität aktivieren
onDisable()Wenn Admin das Plugin deaktiviertFunktionalität deaktivieren, Ressourcen freigeben

Fehlertoleranz: Wenn ein Plugin beim Start einen Fehler wirft, wird es übersprungen — alle anderen Plugins starten normal weiter.

StatusBedeutung
INSTALLEDEntdeckt, aber noch nicht synchronisiert
ENABLEDAktiv — Plugin-Funktionen stehen zur Verfügung
DISABLEDDeaktiviert durch Admin — Plugin wird geladen aber nicht aktiviert
ACTIVEWie ENABLED (Legacy-Kompatibilität)

Admins können über die Admin-API Plugins aktivieren/deaktivieren:

GET /api/v1/admin/plugins → Alle Plugins mit Status
GET /api/v1/admin/plugins/{pluginId} → Plugin-Details
PUT /api/v1/admin/plugins/{id}/status → {"enabled": true/false}

Jeder Benutzer kann Plugins individuell konfigurieren (z.B. API-Keys, Zugangsdaten):

GET /api/v1/plugins → Alle Plugins mit Config-Status
GET /api/v1/plugins/{pluginId}/config-schema → JSON Schema für Config-Formular
GET /api/v1/plugins/{pluginId}/config → Aktuelle Konfiguration
PUT /api/v1/plugins/{pluginId}/config → Konfiguration speichern
DELETE /api/v1/plugins/{pluginId}/config → Konfiguration löschen
GET /api/v1/plugins/configs → Alle eigenen Konfigurationen

Die Konfiguration wird als JSON-Objekt gespeichert und gegen das Config-Schema des Plugins validiert. Sensible Felder (wie API-Keys) werden serverseitig verschlüsselt gespeichert.

Externe Plugins werden als .jar-Dateien verteilt. Achte auf:

  • Kompatibilität: Das Plugin muss zur installierten FinAnalyzer-Version passen (Major-Version muss übereinstimmen)
  • Vertrauenswürdigkeit: Plugins haben vollen Zugriff auf die Backend-Funktionalität — installiere nur Plugins aus vertrauenswürdigen Quellen
  • Dateiformat: Die Datei muss eine .jar-Endung haben und ein gültiges PF4J-Plugin sein

Das Backend erkennt neue JARs automatisch per Hot-Reload — ein Neustart ist nicht nötig.

All-in-One Image:

Terminal window
# Plugin in den laufenden Container kopieren — wird automatisch erkannt
docker cp mein-plugin-1.0.0.jar finanalyzer:/data/plugins/

Docker Compose (Prod/Dev):

Terminal window
# Plugin in das gemountete Volume kopieren — wird automatisch erkannt
docker cp mein-plugin-1.0.0.jar backend-prod:/app/plugins/

Lokale Entwicklung (IDE — Backend läuft direkt):

Terminal window
# JAR in das plugins/-Verzeichnis im Backend-Root legen — wird automatisch erkannt
cp mein-plugin-1.0.0.jar fin-analyzer-backend/plugins/

Tipp: Falls du das Plugin in einen gestoppten Container/Volume platzierst, wird es beim nächsten Start geladen. Bei einem laufenden Container wird es per Hot-Reload innerhalb des nächsten Scan-Intervalls erkannt.

Nach dem Platzieren der JAR-Datei wird das Plugin automatisch erkannt und als ENABLED registriert — kein Server-Neustart nötig. Das Backend scannt das Plugin-Verzeichnis regelmäßig auf neue JARs (Hot-Reload).

  • Erster Scan nach Serverstart: nach 30 Sekunden (konfigurierbar via FINANALYZER_PLUGINS_SCAN_INITIAL_DELAY_MS)
  • Danach: alle 10 Sekunden (konfigurierbar via FINANALYZER_PLUGINS_SCAN_INTERVAL_MS)

Im Admin-Bereich der App ist das Plugin nach dem nächsten Scan sichtbar.

Falls das Plugin eine Konfiguration benötigt (z.B. API-Schlüssel), öffne die Plugin-Einstellungen in der App und fülle das Konfigurationsformular aus.

  1. Plugin über die Admin-API deaktivieren
  2. Container stoppen
  3. JAR-Datei aus dem Plugin-Verzeichnis löschen
  4. Container neu starten

Hinweis: Das Entfernen von Plugins erfordert derzeit einen Neustart. Das Hinzufügen neuer Plugins funktioniert ohne Neustart (Hot-Reload).

ProblemUrsacheLösung
Plugin erscheint nicht nach PlatzierungJAR nicht im richtigen VerzeichnisPrüfe docker exec <container> ls /app/plugins/ bzw. /data/plugins/
Plugin erscheint nicht nach 30 SekundenJAR ist kein gültiges PF4J-PluginPrüfe Container-Logs: docker logs <container> | grep PF4J
Plugin erscheint, aber Status INSTALLEDStartup-Fehler im PluginPrüfe Container-Logs auf failed during startup lifecycle
Plugin-Konfiguration schlägt fehlJSON entspricht nicht dem SchemaPrüfe das Config-Schema via /api/v1/plugins/{id}/config-schema
Plugins verschwinden nach Container-UpdateVolume nicht gemountetStelle sicher, dass das plugins-data Volume korrekt gemountet ist
VariableDefaultBeschreibung
FINANALYZER_PLUGINS_DIRpluginsPfad zum Plugin-Verzeichnis (relativ oder absolut)
FINANALYZER_PLUGINS_SCAN_INTERVAL_MS10000Hot-Reload Scan-Intervall in Millisekunden
FINANALYZER_PLUGINS_SCAN_INITIAL_DELAY_MS30000Verzögerung vor dem ersten Scan (Startup abwarten)

⚠ Hinweis: Wenn du FINANALYZER_PLUGINS_DIR änderst, muss auch der Volume-Mount angepasst werden, damit die JARs im Container am richtigen Pfad liegen. Im All-in-One Image ist /data/plugins/ Teil des /data-Volumes — eine Änderung erfordert einen zusätzlichen Volume-Mount.

Externe Plugins implementieren das FinAnalyzerPlugin-Interface aus dem FinAnalyzer Plugin SDK (fin-analyzer-be-sdk). Plugins werden als PF4J-Plugins verpackt.

  • Java/Kotlin 21
  • Zugang zum fin-analyzer-be-sdk Maven-Artefakt (Gitea Registry oder lokal via mvn install)
  1. Dependency: fin-analyzer-be-sdk als provided-Dependency (wird zur Laufzeit vom Backend bereitgestellt)
  2. Interface: FinAnalyzerPlugin implementieren — definiert:
    • pluginId — Eindeutige ID (z.B. my-custom-import)
    • pluginName, pluginDescription, pluginVersion, pluginAuthor
    • pluginCategoryIMPORT, EXPORT, oder UTILITY
    • configSchemaConnectorConfigSchema mit ConfigField-Liste (definiert das Konfigurationsformular)
    • Lifecycle-Hooks: onInstall(), onLoad(), onEnable(), onDisable()
  3. Extension Point: @Extension Annotation (PF4J) auf der Plugin-Klasse für automatische Erkennung
  4. Packaging: Fat JAR mit PF4J Plugin-Manifest (plugin.properties oder META-INF/extensions.idx)
Terminal window
# 1. SDK lokal installieren (falls nicht aus Registry verfügbar)
cd fin-analyzer-be-sdk
./mvnw install -DskipTests
# 2. Plugin bauen
cd mein-plugin/
./mvnw package -DskipTests
# 3a. IDE-Modus: JAR ins plugins/-Verzeichnis des Backends legen
cp target/mein-plugin-1.0.0.jar ../fin-analyzer-backend/plugins/
# Hot-Reload erkennt das Plugin automatisch — kein Neustart nötig
# 3b. Docker-Modus: JAR ins Volume kopieren
docker cp target/mein-plugin-1.0.0.jar finanalyzer-local:/app/plugins/
# Hot-Reload erkennt das Plugin automatisch — kein Neustart nötig
  • Plugin-IDs müssen global eindeutig sein — Duplikate verursachen einen Startup-Fehler
  • Lifecycle-Hooks dürfen nicht blockieren — lang laufende Initialisierung asynchron auslagern
  • Fehler in Hooks werden isoliert — ein fehlerhaftes Plugin blockiert nicht den Rest
  • Config-Schema-Validierung ist automatisch — ungültige User-Konfigurationen werden vom Backend abgelehnt
  • SECRET-Felder werden verschlüsselt gespeichert — verwende ConfigFieldType.SECRET für API-Keys und Passwörter

Detaillierte SDK-Dokumentation: siehe fin-analyzer-be-sdk/README.md.