The ilivalidator web service is a Spring Boot application and uses ilivalidator for the INTERLIS transfer file validation.
- checks INTERLIS 1+2 transfer files: see https://github.com/claeis/ilivalidator for all the INTERLIS validation magic of ilivalidator
- uses remote config files for validation tailoring
- user can upload multiple transfer files at once
- REST-API
- simple clustering for horizontal scaling
Der Benutzer wählt eine oder mehrere INTERLIS-Transferdateien aus und lädt sie hoch. Im Browser erscheint nach erfolgter Prüfung das Resultat und Links zu den Logdateien. Es stehen verschiedene Prüfprofile zur Verfügung, welche die Validierung zusätzlich konfigurieren (z.B. Warnung statt Error, zusätzliche Constraints, etc.).
Weitere Informationen:
- GUI: docs/user-manual-de.md
- Nutzungsplanung: docs/user-manual-de-nplso.md
- REST-API: docs/rest-api-de.md
Die Anwendung besteht aus einer Komponente. Wird ein Datenbankserver für das Speichern der Jobqueue verwendet, gehört das Schema etc. auch als Komponente zur Anwendung. Standardmässig wird eine SQlite-Datenbank verwendet, welche automatisch erstellt wird, falls sie nicht vorhanden ist.
Die Prüfprofile (aka Zusatzkonfiguration) sind nicht Bestandteil der Komponente, sondern sie liegen in eigenen oder fremden ilidata-Repositories.
Die Anwendung kann wie folgt gestartet werden:
java -jar ilivalidator-web-service-server/target/ilivalidator-web-service.jar
respektive mit Docker:
docker run -p 8080:8080 sogis/ilivalidator-web-service
Konfiguration via application.properties im Verzeichnis in dem der Service gestartet wird. Oder entsprechende alternative Konfigurationsmöglichkeiten von Spring Boot.
Die Anwendung beinhaltet bereits eine application.properties-Datei. Siehe application.properties, welche beim obigen Aufruf standardmässig verwendet wird.
Der Dockercontainer verwendet eine leicht angepasste Konfiguration (application-docker.properties), damit das Mounten von Verzeichnissen hoffentlich einfacher fällt und weniger Fehler passieren:
- Die SQLite-Datenbank wird im /work-Verzeichnis angelegt, das im Dockerimage angelegt wird.
- Für
WORK_DIRECTORY
wird das /work-Verzeichnis verwendet, das im Dockerimage angelegt wird.
Die allermeisten Optionen sind via Umgebungsvariablen exponiert und somit veränderbar. Im Extremfall kann immer noch ein neues Dockerimage erstellt werden mit einer ganz eigenen Konfiguration.
Mit Docker wird die Anwendung mit einem docker-Profil gestartet (siehe Dockerfile). Standardwerte gemäss diesem application-docker.properties:
Name | Beschreibung | Standard |
---|---|---|
TZ |
Zeitzone des Dockercontainers. Z.B. Europe/Zurich |
|
MAX_FILE_SIZE |
Die maximale Grösse einer Datei, die hochgeladen werden kann in Megabyte. | 200 |
LOG_LEVEL |
Das Logging-Level des Spring Boot Frameworks. | INFO |
LOG_LEVEL_DB_CONNECTION_POOL |
Das Logging-Level des DB-Connection-Poolsocket. | INFO |
LOG_LEVEL_APPLICATION |
Das Logging-Level der Anwendung (= selber geschriebener Code). | DEBUG |
CONNECT_TIMEOUT |
Die Zeit in Millisekunden, die bis zu einem erfolgreichem Connect gewartet wird. Betrifft sämtliche Methoden, welche sun.net.client.defaultConnectTimeout berücksichtigen. Die Option dient dazu damit langsame INTERLIS-Modellablage schneller zu einem Timeout führen. |
5000 |
READ_TIMEOUT |
Die Zeit in Millisekunden, die bis zu einem erfolgreichem Lesen gewartet wird. Betrifft sämtliche Methoden, welche sun.net.client.defaultConnectTimeout berücksichtigen. Die Option dient dazu damit langsame INTERLIS-Modellablage schneller zu einem Timeout führen. |
5000 |
WORK_DIRECTORY |
Verzeichnis, in das die zu prüfenden INTERLIS-Transferdatei und die Logdateien kopiert werden (in ein temporäres Unterverzeichnis, das im WORK_DIRECTORY erstellt wird). Falls local Storage Service gewählt ist, muss das Verzeichnis, bei einem Betrieb mit mehreren Containern, zwingend geteilt werden muss. Sonst ist nicht sichergestellt, dass man die Logdatei(en) herunterladen kann. Falls s3 Storage Service gewählt ist, muss der Name des Buckets gewählt werden, in den die Daten kopiert werden. |
/work/ |
FOLDER_PREFIX |
Für jede zu prüfende Datei wird im WORK_DIRECTORY -Verzeichnis ein temporäres Verzeichnis erstellt. Der Prefix wird dem Namen des temporären Verzeichnisses vorangestellt. |
ilivalidatorws_ |
CLEANER_ENABLED |
Dient zum Ein- und Ausschalten des Aufräumprozesses, der alte, geprüfte Dateien (INTERLIS-Transferdateien, Logfiles) löscht. | true |
REST_API_ENABLED |
Dient zum Ein- und Ausschalten des REST-API-Controllers und damit der eigentlichen Funktionalität (auch wenn Jobrunr trotzdem initialisiert wird). | true |
JDBC_URL |
Die JDBC-Url der Sqlite-Datei, die dem Speichern der Jobs dient, welche mittels REST-API getriggert wurden. Die Datei wird im Standard-WORK -Verzeichnis gespeichert, da dieses beim Multi-Container-Betrieb geteilt werden muss. Andere JDBC-fähige Datenbanken sind ebenfalls möglich. Dann müssten noch mindestens Login und Password als Option exponiert werden. Und die Anwendung müsste neu mit dem dazugehörigen JDBC-Treiber gebuildet werden. |
jdbc:sqlite:/work/jobrunr_db.sqlite |
JOBRUNR_SERVER_ENABLED |
Dient die Instanz als sogenannter Background-Jobserver, d.h. werden mittels REST-API hochgeladene INTERLIS-Transferdateien validiert. Wird nur eine Instanz betrieben, muss die Option zwingen true sein, da sonst der Job nicht ausgeführt wird. |
true |
JOBRUNR_POLL_INTERVAL |
Es wird im Intervall (in Sekunden) nach neuen Validierungsjobs geprüft. | 10 |
JOBRUNR_WORKER_COUNT |
Anzahl Jobs, die in einem "Worker" gleichzeitig durchgeführt werden können. Im Prinzip nicht sehr relevant, da der Validierungsjob synchronisiert ist (nicht thread safe). | 1 |
JOBRUNR_DASHBOARD_ENABLED |
Das Jobrunr-Dashboard wird auf dem Port 8000 gestartet. | true |
JOBRUNR_DASHBOARD_USER |
Username für Jobrunr-Dasboard. Achtung: Basic Authentication. | admin |
JOBRUNR_DASHBOARD_PWD |
Passwort für Jobrunr-Dasboard. Achtung: Basic Authentication. | admin |
TOMCAT_THREADS_MAX |
Maximale Anzahl Threads, welche die Anwendung gleichzeitig bearbeitet. | 20 |
TOMCAT_ACCEPT_COUNT |
Maximale Grösser der Queue, falls keine Threads mehr verfügbar. | 100 |
TOMCAT_MAX_CONNECTIONS |
Maximale Anzahl Threads des Servers. | 500 |
HIKARI_MAX_POOL_SIZE |
Grösse des DB-Connections-Pools | 10 |
ILIDIRS |
Modell- und Datenrepositorie, die verwendet werden sollen. | https://geo.so.ch/models;https://models.interlis.ch;https://models.geo.admin.ch |
Ein docker-run
-Befehl könnte circa so aussehen:
docker run --rm -p8080:8080 -p8000:8000 -v /shared_storage/work:/work/ sogis/ilivalidator-web-service:3
Es werden zwei Ports gemapped. Der Port 8080 ist der Port der Anwendung und zwingend notwendig. Der Port 8000 dient dazu, dass das Jobrunr-Dashboard verfügbar ist.
Im lokalen Filesystem (oder Kubernetes-PV-Whatever etc.) muss das Verzeichnis /shared_storage/work/ vorhanden sein. Die SQLite-Datenbank, die dazu dient die (REST-API-)Jobs zu koordinieren, befindet sich im /shared_storage/work/-Verzeichnis.
Ein Scheduler löscht jede halbe Stunde (momentan hardcodiert) alle temporären Verzeichnisse, die älter als 60x60 Sekunden sind.
Custom-Funktionen können in zwei Varianten verwendet werden. Die Jar-Datei mit den Funktionen muss in einem Verzeichnis liegen und vor jeder Prüfung werden die Klassen dynamisch geladen. Das hat den Nachteil, dass man so kein Native-Image (GraalVM) mit Custom-Funktionen herstellen kann und man z.B. bei einem Webservice die Klassen nicht einfach als Dependency definierten kann, sondern die Jar-Datei muss in einem Verzeichnis liegen, welches beim Aufruf von ilivalidator als Option übergeben wird. Bei der zweiten (neueren) Variante kann man die Custom-Funktionen als normale Dependency im Java-Projekt definieren. Zusätzlich müssen die einzelnen Klassen als Systemproperty der Anwendung bekannt gemacht werden.
Im vorliegenden Fall wird die zweite Variante gewählt. Das notwendige Systemproperty wird in der Application
-Klasse gesetzt. Falls man die erste Variante vorzieht oder aus anderen Gründen verwenden will, macht man z.B. ein Verzeichnis src/main/resources/libs-ext/
und kopiert beim Builden die Jar-Datei in dieses Verzeichnis. Dazu wird eine Gradle-Konfiguration benötigt. Zur Laufzeit (also wenn geprüft wird) muss man die Jar-Datei auf das Filesystem kopieren und dieses Verzeichnis als Options ilivalidator übergeben.
Sämtliche "Koordinationsaufgaben" wie z.B. das Entpacken der Config-Dateien, das Löschen von alten Files etc. sollte (und in einigen Fällen: darf) nur von einer Instanz ausgeführt werden. Als Beispiel eine einfache docker-compose
Konfiguration:
version: '3'
services:
frontend:
image: sogis/ilivalidator-web-service:3
restart: unless-stopped
environment:
TZ: Europe/Zurich
JOBRUNR_SERVER_ENABLED: "false"
ports:
- 8080:8080
- 8000:8000
volumes:
- type: volume
source: work
target: /work
worker:
image: sogis/ilivalidator-web-service:3
restart: unless-stopped
deploy:
replicas: 2
environment:
TZ: Europe/Zurich
JOBRUNR_DASHBOARD_ENABLED: "false"
REST_API_ENABLED: "false"
UNPACK_CONFIG_FILES: "false"
CLEANER_ENABLED: "false"
volumes:
- type: volume
source: work
target: /work
volumes:
docbase:
work:
Es wird ein "frontend"-Service gestartet, welche als Schnittstelle gegen aussen dient. Es werden mehrere "worker"-Services gestartet (replicas
), die nur für das Validieren einer INTERLIS-Transferdatei zuständig sind. Es sind keine Port exponiert, da keiner dieser Worker-Service von aussen verfügbar sein muss. Es werden verschiedene Applikationsfunktionen ausgeschaltet (sieh Umgebungsvariablen). Das Jobmanagement wird mit Jobrunr gemacht.
Achtung: Mit Docker Compose Version 3 kann im Nicht-Swarm-Mode keine CPU-Limits gesetzt werden.
Die Zusatzkonfigurationen - ini-Dateien für die Optionen --config und --metaConfig - müssen auf ilidata-Repositories liegen. Dies ist ein bewusster Entscheid (single source of truth).
TODO:
- spring boot / maven multimodule
- GWT
- Jobrunr
- rest api
- Max file size: Stand heute an zwei Orten...
- Test und Dockertests
- Wie wird metaConfig etc. getestet? (Weiss ich noch nicht zu 100%: Idee neu wäre wohl mit kleinem lokalen Dockerimage mit ilidata.xml etc. Dann müsste preferred Ili Repo im Test noch anders gestetzt werden.)
- Registrierung Zusatzfunktionen
- --spring.profiles.active=docker
- ./mvnw versions:set -DnewVersion=3.0.1-SNAPSHOT -DprocessAllModules (noch nicht implementiert)
- git-commit-id-plugin -> inkl. Link: http://localhost:8080/actuator/info
First Terminal:
./mvnw spring-boot:run -pl *-server -am -Penv-dev
Second Terminal:
./mvnw gwt:codeserver -pl *-client -am
Or without downloading all the snapshots again:
./mvnw gwt:codeserver -pl *-client -am -nsu
./mvnw -Penv-prod clean package -DexcludedGroups="docker"
In der Package-Phase werden die "Spring pur"-Tests durchgeführt und es wird am Ende ein Dockerimage für die Dockertests erstellt. Die definitiven Dockerimages werden wegen des Multi-Arch-Builds in der Pipeline erstellt und publiziert. Die Tests können auch separat ausgeführt werden.
Maven kennt Integrationtests in der Verify-Phase (nach Package). Wir verwenden jedoch nochmals eine separate Testphase, um die Dockertests durchzuführen (siehe nachfolgendes Kapitel).
./mvnw -Penv-test clean test -DexcludedGroups="docker"
./mvnw -Penv-test clean test -Dgroups="docker"
Einzelner Test ausführen:
./mvnw -Penv-test test -Dtest=SpringJobControllerTests#validate_File_Interlis2_Ok -Dsurefire.failIfNoSpecifiedTests=false
Für die Durchführung der Tests wird ein INTERLIS-Modellrepository benötigt. Um zur Laufzeit der Tests nicht von fremden (dazu gehört auch unser eigenes) Repositories abhängig zu sein und Veränderungen in solchen (z.B. replaced Modelle, Änderungen in den ini-Konfigs), wird ein Dockerimage mit den für die Tests benötigten Modellen hergestellt. Die Modelle liegen im *-server/src/test/docker/models-Ordner. Die ilimodels.xml-Datei wird mit ilimanager hergestellt und sie muss im gleichen Ordner wie die Modelle zu liegen kommen (siehe Befehl unten). Das Dockerimage wird im Maven-Build erzeugt und in den Tests mit Testcontainers hochgefahren.
In Units, Time und CoordSys musste das Metaattribut "precursorVersion" gelöscht werden, weil es im Repo keine geben wird und ili2c solche Modell anschliessend ignoriert.
java -jar ilimanager-0.9.1.jar --createIliModels --repos models --out models/ilimodels.xml
Zusätzlich ist auch ein ilidata.xml notwendig für die ilivalidator-Konfigurationen (ini-Files). Die Datei wurde manuell angelegt und nachgeführt.
Docker image builden:
docker build -t sogis/interlis-repository-test .