Abkündigung zum 31.12.2022
Nach dem 31.12.2022 wird es keinen Support mehr für den DEMIS-Importer geben. Eine einwandfreie Funktionsweise über diesen Zeitpunkt hinaus kann nicht garantiert werden.
Der DEMIS-Importer stellte eine Übergangslösung dar. Softwarehersteller sind daher angehalten, direkt die FHIR Schnittstelle von DEMIS zu verwenden. Zur Integration in Ihre Software stellen wir Ihnen auf Anfrage gern die Sourcen des DEMIS-Importers zur Verfügung.
Die aktuellste Dokumentation befindet sich immer in der README des DEMIS Importer Projekts. Die hier enthaltenen Informationen werden in regelmäßigen Abständen aktualisiert.
Java Projekt zur Umsetzung einer Komponente, die Meldungen für die jeweiligen Gesundheitsämter importiert.
Hinweis: Bei einigen JDKs kann es zu Problemen bei der Entschlüsselung kommen (HmacPBESHA256). Getestet wurden folgende JDKs (höhere Versionen sollten ebenfalls funktionieren):
Oracle JDK Version 13.0.2
OpenJdk Version 11
AdoptOpenJdk 11.0.7.10
Nutzung
Dieses Kapitel beschreibt wie der DEMIS Importer als Kommandozeilenwerkzeug verwendet werden kann.
Kompilieren und Starten
Der DEMIS Importer ist als Java-Projekt umgesetzt, das mit Hilfe von Maven kompiliert wird (mvn clean install
). Maven erstellt eine Jar-Datei welche im Verzeichnis ./target/demis-importer-0.1.jar
gefunden werden kann. ./
bezeichnet hier das Verzeichnis in dem das DEMIS Importer Projekt liegt.
Über die Kommandozeile kann die Jar-Datei mit Hilfe von Java ausgeführt werden. Wenn man sich im selben Verzeichnis wie die Jar-Datei befindet, lässt sich diese wie folgt ausführen:
java -jar demis-importer-0.1.jar
Beim ersten Ausführen wird wahrscheinlich der Fehler MissingConfigurationFileException
auf der Kommandozeile ausgegeben. Das liegt daran, dass der DEMIS Importer bestimmte Parameter benötigt, um erfolgreich ausgeführt werden zu können. Der nächste Teil beschreibt die benötigte Konfigurationsdatei, um diese Parameter bereit zu stellen.
Konfigurationsdatei
Die Konfigurationsdatei enthält notwendige Parameter für die Ausführung. Folgende Angaben werden in der Konfigurationsdatei benötigt, wobei die mit einem $
-Zeichen markierten Variablen durch richtige Werte angepasst werden müssen:
debuginfo.enabled=false fhir.basepath=https://demis.rki.de/notification-clearing-api/fhir/ idp.tokenendpoint=https://demis.rki.de/auth/realms/OEGD/protocol/openid-connect/token idp.oegd.clientid=demis-importer idp.oegd.secret=secret_client_secret idp.oegd.username=$USERNAME idp.oegd.truststore=$PATH_TO_TRUSTORE_FILE idp.oegd.truststorepassword=$PASSWORD_FOR_TRUSTORE_FILE idp.oegd.authcertkeystore=$PATH_TO_KEY_STORE_FILE idp.oegd.authcertpassword=$PASSWORD_FOR_KEY_STORE_FILE idp.oegd.authcertalias=$ALIAS # Define an alternative keystore & password (optional) idp.oegd.outdated.authcertkeystore= idp.oegd.outdated.authcertpassword= # Define custom values for timeouts in milliseconds (optional) - defaults are 2000ms, 2000ms, 20000ms respectively connect.timeout.ms= connection.request.timeout.ms= socket.timeout.ms=
Die Datei-Pfade in der Konfigurationsdatei (z.B. Parameter $PATH_TO_TRUSTORE_FILE
und $PATH_TO_KEY_STORE_FILE
) sind entweder absolut oder relativ zum Arbeitsverzeichnis
zu setzen (z.B. idp.oegd.truststore=C:/demis/demis-importer/certs/truststore.p12
oder idp.oegd.truststore=certs/truststore.p12
).
Alternativer Keystore
idp.oegd.outdated.authcertkeystore
und idp.oegd.outdated.authcertpassword
sind optionale Parameter der Konfigurationsdatei, die den Pfad zu einem alternativen Keystore angeben können. Die Zertifikate zum Ver- und Entschlüsseln von Meldungen laufen nach einiger Zeit ab und müssen durch neue ersetzt werden. Beim Austausch der Zertifikate könnte es vorkommen, dass der Demis-Importer bereits
das neue Zertifikat hat, aber noch Meldungen in der notification-clearing-api existieren, die über das alte Zertifikat verschlüsselt sind. Durch die Angabe des alten Keystores unter den beiden Parametern kann der Demis-Importer das für die Meldung passende Zertifikat auswählen und entschlüsseln.
Laden der Konfigurationsdatei
Damit der DEMIS Importer die Konfigurationsdatei lesen kann muss diese ihm übergeben werden. Das geht auf zwei Arten:
Die Konfigurationsdatei wird unter dem Name
app.properties
im selben Verzeichnis gespeichert von wo man auch die Jar-Datei ausführt. Der Demis-Importer wird anschließend in genau diesem Verzeichnis nach einer Datei mit dem Namenapp.properties
suchen. Wenn er sie findet, wird er die Datei laden und die darin enthaltenen Parameter nutzen.Man übergibt die Konfigurationsdatei mit dem Kommandozeilenparameter
-config
. Z.b. wenn man die Konfigurationsdatei unter "C:/demis/configuration.txt" gespeichert hat, kann man diese Datei an den DEMIS Importer wie folgt übergebenjava -jar demis-importer-0.1.jar -config C:/demis/configuration.txt
Wenn die Parameter in der Konfigurationsdatei richtig sind, sollte der DEMIS Importer sämtliche Meldungen von der notification-clearing-api herunterladen und unter dem Verzeichnis .\results
als JSON-Dateien und als XML-Dateien speichern.
Zeit-Konfigurationsdatei
Bei der ersten Ausführung des DEMIS Importers wird die "Zeit"-Konfigurationsdatei app.time-properties
erstellt:
#Updating query dates in format yyyy-MM-dd HH:mm:ss:SSS (For explanation of abbreviations see: <https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html)> #Wed Aug 26 12:59:58 CEST 2020 notification.last.update.date=2020-08-26 10:41:05:654
Diese Datei enthält den Parameter notification.last.update.date
, welcher verwendet wird, um sich den aktuellsten Zeitstempel der bereits heruntergeladenen Meldungen über mehrere Ausführungen des DEMIS Importers zu merken. Beim Herunterladen neuer Meldungen wird der Parameter für die Unterscheidung zwischen alten und neuen Meldungen auf dem Server verwendet. Nur Meldugen mit einem _lastUpdated
Feld, dessen Wert größer oder gleich (= aktuelleres oder zeitgleiches Datum) als der Parameter ist, werden
vom Importer heruntergeladen. Das Datum des _lastUpdated
Felds erfolgreich heruntergeladener Meldungen wird anschließend für die Aktualisierung des Parameters genutzt.
Das Datum kann manuell auf die Millisekunde genau angepasst werden und muss lediglich dem Format yyyy-MM-dd HH:mm:ss:SSS
(hier beschrieben) entsprechen.
Der oben beschriebene Vorgang nur aktuelle Meldungen (= neuer als der Zeitstempel in der app.time-properties
) herunterzuladen ist das Standardverhalten des DEMIS Importers. Dieses Verhalten kann mit dem Kommandozeilenparameter -all
umgangen werden. Fügt man -all
hinzu werden sämtliche Meldungen heruntergeladen.
Kommandozeilenparameter
Der DEMIS Importer bietet einige Parameter, um dessen Funktionsweise anzupassen. Über die Hilfe-Option -help
können diese auf der Kommandozeile mit englischer Beschreibung ausgegeben werden. Im folgenden werden die existierenden Parameter erklärt und einige Anwendungsbeispiele gegeben:
Optionen:
nobinary
Die Meldungen werden ohne Binärdateien heruntergeladen und enthalten nur eine Zusammenfassung des Inhalts der ursprünglichen Labormeldungen. Durch die kleinere Dateigröße sollten Meldungen schneller geladen werden können. Das interne Datum inapp.time-properties
wird durch Aufrufe mit diesem Parameter nicht aktualisiert.all
Lade sämtliche Meldungen vom Server unabhängig von ihrem_lastUpdate
Wert und dem internen in derapp.time-properties
gespeicherten Datum. Das interne Datum inapp.time-properties
wird durch Aufrufe mit diesem Parameter nicht aktualisiert.timedir <arg>
Diese Option erlaubt es ein alternatives Verzeichnis für die Dateiapp.time-properties
anzugeben. Als Standardwert wird die Datei immer im Arbeitsverzeichnis gespeichert. Sollteapp.time-properties
in dem angegebenen Verzeichnis noch nicht vorhanden sein wird die Datei einfach neu erstellt.timereset
Löscht die gespeicherten Daten in der geladenenapp.time-properties
.perpetual
Der DEMIS Importer kann mit dieser Option in einer Dauerschleife ausgeführt werden, um ständig Meldungen abzurufen.frequency <arg>
Mit Hilfe dieser Option kann die Frequenz in Minuten bestimmt werden, in dem im "Schleifen-Modus" (aktiviert über die Optionperpetual
) die Meldungen abgerufen werden. Der Standardwert für das Abrufen liegt bei 20 Minuten.config <arg>
Übergabe der Konfigurationsdatei an den DEMIS Importer.dir <arg>
Festlegen eines anderen Verzeichnisses zum Abspeichern der Meldungen. Die Standardeinstellung ist./results
.help
Gebe Informationen über die Kommandozeilenparameter aus.verbose
Aktiviert die zusätzliche Ausgabe von Informationen über die getätigten HTTP Anfragen und Antworten.json
Speichert die abgerufenen Meldungen als JSON Dateien. In der Standardeinstellung werden die Meldungen doppelt, als JSON und XML abgespeichert.xml
Speichert die abgerufenen Meldungen als XML Dateien.
Beispiele:
Rufe alle Meldungen als XML-Dateien ab:
java -jar demis-importer-0.1.jar -all -xml
Rufe alle 10 Minuten sämtliche neue Meldungen ab:
java -jar demis-importer-0.1.jar -perpetual -frequency 10
Ändere die Verzeichnisse, aus denen die Konfigurationsdatei gelesen und die Meldungen abgelegt werden und rufe alle neuen Meldugen ab:
java -jar demis-importer-0.1.jar -config C:/demis/app.properties -dir C:/results
Hintergrundinformationen
Dieses Kapitel beschreibt die Technischen Hintergründe und Umsetzungen.
Grundlagen des HAPI FHIR Client
Der DEMIS Importer verwendet zum Abrufen der Meldungen den Client von HAPI FHIR. Die Dokumentation von HAPI FHIR zum Client kann man hier finden.
Im Folgenden werden ein paar Grundlagen zur Verwendung des Client aufgelistet.
Der Client von Hapi Fhir kann wie folgt erstellt werden:
// Erstelle einen Client mit dem FhirContext Version R4 String serverBase = "https://demis.rki.de/notification-clearing-api/fhir/" IGenericClient client = FhirContext.forR4().newRestfulGenericClient(serverBase); // Erstelle und registriere einen Interceptor, der einen validen Token zur Anfragen hinzufügt // Der Token wird durch die Klasse de.rki.demis.importer.mtls.TLSManager bereitgestellt BearerTokenAuthInterceptor authInterceptor = new BearerTokenAuthInterceptor(token); client.registerInterceptor(authInterceptor); // Erstelle und registriere einen Interceptor zum Loggen LoggingInterceptor loggingInterceptor = new LoggingInterceptor(); loggingInterceptor.setLogRequestSummary(true); loggingInterceptor.setLogRequestBody(true); client.registerInterceptor(loggingInterceptor);
In folgender Weise können mit dem Client Meldungen für ein bestimmtes Gesundheitsamt abgerufen werden:
String TAG_NAME = "https://demis.rki.de/fhir/CodeSystem/ResponsibleDepartment"; String exampleID = "1.0.01.1." Bundle responseBundle = client.search() .forResource(Bundle.class); .withTag(TAG_NAME, exampleID) .encodedJson() .returnBundle(Bundle.class) .execute();
Der Server sucht nach Meldungen, welche mit dem passenden Tag versehen sind. Anschließend gibt er die Klasse Bundle
zurück, welche die gefundenen Meldungen enthält.
Die Anzahl der zurückgegebenen Meldungen bei einer Anfrage ist begrenzt. Sollten mehr Meldungen zur Anfrage gefunden worden sein, als auf einer einzelnen Seite zurückgegeben werden können, wird ein Link gesetzt, der auf eine andere Seite mit weiteren Meldungen verweist. Dieses Verhalten wird "paging" genannt. Die verlinkte Seite kann wiederum einen weiteren Link auf die nächste Seite beinhalten und so fort. Folgender Code lädt eine Seite mit weiteren Meldungen , wenn der Link im responseBundle gesetzt wurde:
Bundle nextPageResponseBundle = null; if (responseBundle.getLink(IBaseBundle.LINK_NEXT) != null) { nextPageResponseBundle = client.loadPage().next(responseBundle).execute(); }
Die Methode fetchResourcesFromServer
in der Klasse de.rki.demis.importer.QueryExecutor
setzt das "paging" um.
Die Meldungen liegen als Typ Bundle
im responseBundle unter entries
vor. Folgendes Beispiel iteriert durch alle Einträge und gibt den Geburtstag der Patienten aus:
// Iterieren der Einträge des ResponseBundles, dass die Meldungen enthält for (BundleEntryComponent entry : responseBundle.getEntry()) { // Hier erhalten wir die eigentliche Meldungen Bundle notification = (Bundle) entry.getResource(); // Iterieren der Elemente der Meldungen (Komposition, Organization, ...) for (BundleEntryComponent entry : responseBundle.getEntry()) { if (entry instanceof Patient) { Patient patient = (Patient) patient; System.out.println(patient.get } } }
Erweiterte notwendige Umsetzung
Das zuvor erklärte "paging" ist nur begrenzt verwendbar für große Datenmengen, da der Server die Seiten extra bereitstellen muss. Aus diesem Grund ist die Anzahl an Meldungen , die über das "paging" abgerufen werden können, ebenfalls begrenzt (der Default-Wert sollte bei etwa 250 Meldungen liegen). Um dennoch mehr Meldungen abrufen zu können nutzt der DEMIS Importer die Eigenschaft der notification-clearing-api die Meldungen sortiert nach dem _lastUpdate
Feld zurückzugeben. Jede Anfrage wird um ein _lastUpdate
Feld erweitert, dass anhand der heruntergeladenen Meldungen aktualisiert wird. Zusammen mit dem "paging" können so sehr große Mengen an Meldungen abgerufen werden. Die Methoden fetchAndStoreAllNotifications
und fetchAndStoreNotificatons
im de.rki.demis.importer.DemisImporter
setzen dieses Verhalten um. Hilfklassen für das Verwalten des internen _lastUpdate
Feldes sind die Klassen de.rki.demis.importer.DateHandler
und de.rki.demis.importer.helper.QueryDates
.