Der AS4 Message Service persistiert die Nachrichten und Bestätigungen, um eine spätere Nachverfolgbarkeit zu ermöglichen. Dieser Service erhält die AS4-Nachrichten und Bestätigungen über den Message-Broker, bietet aber über REST eine Abfragemöglichkeit an.
Hardware Anforderungen
Eine Service-Instanz erfordert mindestens 512 MB RAM.
Wir empfehlen 0,4 CPU-Kerne je Instanz.
Logs werden auf die Festplatte geschrieben, entsprechend muss genügend Speicherplatz vorhanden sein.
Abhängigkeiten
Der Service greift auf einen Message-Broker zu, um Nachrichten zu empfangen und zu versenden.
Der Service greift auf eine SQL Datenbank zu, um Nachrichten zu speichern. Der Speicherverbrauch hängt vom Nachrichtenaufkommen sowie von der Archivierungs-/Löschstrategie ab.
Einfache Konfiguration der as4-message-service.properties
SQL Datenbank Anbindung
Der Einsatz des Microservice erfordert Zugriff auf eine SQL-Datenbank. Im Vorfeld muss ein Schema angelegt worden sein. Die Tabellen werden automatisch vom Microservice angelegt (via flyway).
Diese speziellen Datenbankparameter können je nach Bedarf verändert werden. Das Passwort wird als Environment Variable mit übergeben. Momentan werden die Datenbanksysteme MSSQL, Oracle und Postgresql unterstützt.
#=== JDBC Settings ==='
datasource.url=jdbc:postgresql://as4-database:5432/as4_messages
datasource.username=postgres
datasource.password=${DB_PASSWORD}
datasource.type=postgres
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
Im Fall einer Oracle-DB kann sich an den nachfolgenden Parametern orientiert werden.
datasource.url=jdbc:oracle:thin:@//as4-database-oracle:1521/orclas4
datasource.username=as4_messages
datasource.password=${DB_PASSWORD}
datasource.type=oracle
Es muss mindestens Oracle 12.2 eingesetzt werden, ältere Versionen werden nicht unterstützt.
Message Broker Anbindung
Die Kommunikation zwischen den verschiedene AS4 Services erfolgt über einen Message-Broker.
#=== RabbitMQ Configuration ===#
rabbitmq.host=rabbitmq3
rabbitmq.port=5672
rabbitmq.username=guest
rabbitmq.password=guest
Der Service korreliert Business Message und das dazugehörige Receipt anhand der businessId. Genauer bedeutet es, dass auf die Ankunft beider Nachrichten gewartet wird. Dies passiert mit einem Eintrag der businessId als Key in der Datenbanktablle Lock, um eine Race Condition zu verhindern. Dieser Eintrag besteht nur bis die Verarbeitung und Persistierung der angekommenen Nachricht andauert. Wenn eine Nachricht ankommt, und bereits ein Lock-Eintrag für die vorhandene businessId besteht, wird die Nachricht nochmals eine kurze Zeit später konsumiert. In dieser Zeit sollte die Verarbeitung der verwandten Nachricht fertig und der dazu bestehende Lock-Eintrag gelöscht sein.
consumer.max.retries=3
#interval in ms (1000ms = 1s)
consumer.retry.interval=1000
AMQP Routing Konfiguration
Falls Sie das Standard Routing nutzen, muss das Routing nicht weiter konfiguriert werden. Wenn Sie Ihr Routing anpassen möchten, lesen Sie die folgende Dokumentation.
Der AS4 Message Service empfängt über die Queue as4.messages.default die Business Message vom AS4 Receipt Service und AS4 Outbound Sender.
businessMessageExchangeName=as4.messages
Über die Queue as4.receipt.default erhält der AS4 Message Service die Empfangsbestätigungen (Receipt) vom AS4 Receipt Message und dem AS4 Inbound Endpoint.
receiptExchangeName=as4.receipt
Nach der Speicherung der AS4-Nachricht wird diese je nach ServciceId an den AS4 Address Service oder B2b Message Service per AMQP geroutet.
inboundExchangeName=as4.inbound
Inbound Routing Konfiguration der as4-message-service.properties
Im default wird die Nachricht je nach ServiceId an den AS4 Address Service oder B2B Message Service geroutet. Ist ein anderes Routing gewünscht, so kann dies durch Angabe der RoutingKeyExpression erfolgen. Dazu können Werte aus dem Header verwendet werden. Folgende Werte befinden sich im Header:
- tenant: ILN Nummer des Senders
- partner: ILN Nummer des Empfängers.
- sector: GAS, ELECTRICITY
- serviceId: serviceId Wert
In der application.properties müsste die Eigenschaft wie folgt angegeben werden:
inboundExchangeName=as4.inbound
inboundRoutingKeyExpression=headers.serviceId
Es kann auch eine Kombination aus Header-Werten angegeben werden. Zum Beispiel, wenn nach Tenant und ServiceId geroutet werden soll.
Wichtig ist, dass der Exchange, die Queues und die entsprechenden Bindings vor dem Start des AS4 Message Service erstellt werden müssen, da es sonst sein kann, dass Nachrichten verloren gehen. Eine entsprechende Dokumentation zum Anlegen der Queues ist hier dokumentiert.
Wird der Producer für das Routing konfiguriert muss natürlich auch die Gegenstelle dafür eingerichtet werden. Dem Consumer wird über die Gruppe der Wert (Value) aus der HeaderValues Liste zugewiesen nach welchem gefiltert werden soll. Bitte den Default Wert nur ändern, wenn Routing verwendet werden soll.
businessMessageExchangeName=as4.messages
businessMessageGroup=default
receiptExchangeName=as4.receipt
receiptGroup=default
Outbound Routing Konfiguration der as4-message-service.properties
Im default wird die Nachricht je nach ServiceId an B2B Message Service geroutet. Ist ein anderes Routing gewünscht, so kann dies durch Angabe der RoutingKeyExpression erfolgen. Dazu können Werte aus dem Header verwendet werden. Folgende Werte befinden sich im Header:
- tenant: ILN Nummer des Senders
- partner: ILN Nummer des Empfängers.
- sector: GAS, ELECTRICITY
- serviceId: serviceId Wert
In der application.properties müsste die Eigenschaft wie folgt angegeben werden:
outboundExchangeName=as4.receipt.outbound
outboundRoutingKeyExpression=headers.serviceId
Es ist zudem möglich eine Kombination aus verschiedenen Header-Werten anzugeben. Soll das Routing beispielsweise anhand des Tenants und der ServiceId stattfinden, so kann dies wie folgt angegeben werden:
outboundRoutingKeyExpression=headers.serviceId + '.' + headers.tenant
Max Concurrency - Parallelität
Für jeden Consumer ist es möglich die Eigenschaft max-concurrency
zu setzen. Diese definiert die maximale Anzahl von gleichzeitigen Verarbeitungsthreads, die für einen Consumer gestartet werden können. Der Default steht für jeden Consumer auf 50.
businessMessageMaxConcurrency=50
receiptMaxConcurrency=50
Löschjob
Dieses Feature steht voraussichtlich mit Release CW 21 zur Verfügung.
Um die alten Geschäftsnachrichten und Empfangsnachrichten aus der Datenbank zu entfernen, wurde ein Spring Quartz Scheduler integriert. Um den Scheduler zu aktivieren, muss die folgende Eigenschaft mit einem Wert versehen werden. Wenn kein Wert angegeben wird, wird der Planer nicht ausgelöst.
deletion.older-than=
Die Eigenschaft wird auch verwendet, um zu definieren, wie alt die zu löschenden Nachrichten im Vergleich zur aktuellen Datenzeit sein sollen. Von dieser Eigenschaft zugelassene Muster sind:
deletion.older-than=P1Y3M - 1 Jahr und 3 Monate (P ist nicht obligatorisch)
deletion.older-than=P1Y3M5D - 1 Jahr, 3 Monate und 5 Tage (P ist nicht obligatorisch)
deletion.older-than=P1Y3M5DT12H - 1 Jahr, 3 Monate, 5 Tage und 12 Stunden (T ist nicht zwingend erforderlich, um den Zeitteil zu identifizieren)
deletion.older-than=P1Y3M5DT12H30M40S - 1 Jahr, 3 Monate, 5 Tage und 12 Stunden 30 Minuten und 40 Sekunden (T ist nicht zwingend erforderlich, um den Zeitteil zu identifizieren)
deletion.older-than=T12H30M40S - 12 Stunden 30 Minuten und 40 Sekunden (T ist nicht zwingend erforderlich, um den Zeitteil zu identifizieren)
Konfiguration für die Quartz Scheduler-Datenbankverbindung und den Treiber, es gibt notwendigerweise nur die Konfiguration für die Datenbank, die verwendet wird, nicht alle davon.
Diese Property basiert auf RFC-3339.
#Postgres
datasource.driver=org.postgresql.Driver
datasource.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
#Oracle
datasource.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
datasource.driver=oracle.jdbc.driver.OracleDriver
#MySql
datasource.driverDelegateClass=org.quartz.impl.jdbcjobstore.MSSQLDelegate
datasource.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
Wenn Quartz Scheduler aktiviert ist, müssen auch die folgenden Eigenschaften festgelegt werden. Definiert das Intervall, in dem der Job ausgelöst wird. Beispiel eines Cron-Ausdrucks für Quartz Scheduler. Die Syntax für diesen Cron-Ausdruck unterscheidet sich von der normalen.
Sekunden: 0 – Der Job wird in der 0. Sekunde ausgeführt.
Minuten: 0 – Der Job wird in der 0. Minute ausgeführt.
Stunden: 12 – Der Job wird um 12:00 Uhr (Mittag) ausgeführt.
Tag des Monats: * – Der Job wird jeden Tag des Monats ausgeführt.
Monat: * – Der Job wird jeden Monat ausgeführt.
Wochentag: ? - Es ist kein bestimmter Wochentag erforderlich (es spielt keine Rolle).
deletion.cron=0 33 * * * ? - jede Stunde bei Minute 33
deletion.cron=0 */33 * * * ? - von 33 bis 33 Minuten
Zeitzone
Es wird empfohlen, die Server-Zeitzone auf die gewünschte Zeitzone einzustellen. Alle Server müssen die gleiche Zeitzone nutzen. Die Server-Zeitzone darf nachträglich nicht mehr geändert werden.
REST API Dokumentation
Die API bietet die Möglichkeit zur Abfrage von verarbeiteten AS4 Nachrichten und zugehörigen Quittungen.
Darüber hinaus bietet die API Server-Health Informationen an.
Ein KontextPath Präfix kann über folgende Property konfiguriert werden: server.servlet.contextPath
.
Der Port lässt sich über folgende Property konfigurieren: server.port=8080
.
Swagger
Die Beschreibung der REST API lässt sich, im Fall einer Docker Installation, unter
http://host.docker.internal:8086/aep-as4-message-service/swagger-ui/index.html#/
oder unter
http://localhost:8080/aep-as4-message-service/swagger-ui/index.html#/
finden.
Keycloak
Bei Bedarf kann die REST-API per Keycloak abgesichert werden.
In Keycloak können die Mandanten, auf die der User Zugriff hat, eingeschränkt werden. Weitere Details entnehmen Sie der Doku.
Upgrade zur Version 2024-03-xx
Mit dieser Version wird die Datenbank selbstständig aktualisiert.
Es kann sein, dass eine manuelle Datenbereinigung nötig wird: falls Sie zuvor manuell Testdaten abseits der üblichen Workflows eingespielt haben (z.B. direkt in die Datenbank oder via Messaging an den internen Queues), können diese Daten möglicherweise das Update verhindern, wenn sie das neu eingeführte Unique-Constraint (Tabelle receipt, Spalte business_id) verletzen. In diesem Fall müssen Sie die Daten manuell bereinigen. Testdaten dieser Art werden, wenn überhaupt dann nur in Entwicklungsumgebungen eingespielt.
In jedem Fall empfehlen wir Ihnen, vor der Bereinigung die neue Version auszuführen. Denn das Datenbank-Update beinhaltet auch die Erzeugung von Indexen, die auch die Performance der Bereinigung verbessern.
Die Bereinigung erfolgt, indem unzulässige Duplikate gelöscht werden. Sie können die Datenbank mithilfe des folgenden (Postgres) SQL-Scripts bereinigen:
WITH cte AS (
SELECT business_id, MIN(as4_id) as as4_id
FROM receipt
GROUP BY business_id
HAVING COUNT(business_id) > 1
)
DELETE FROM receipt
WHERE business_id IN (SELECT business_id FROM cte)
AND as4_id NOT IN (SELECT as4_id FROM cte);
Erneute Verarbeitung von AS4-Nachrichten
Um Nachrichten erneut zu verarbeiten, werden AS4-Nachrichten mithilfe eines Filters aus der Datenbank des AS4-Message-Services abgerufen und dann erneut an die entsprechenden Services übermittelt. Mehr Infos gibt es in der folgenden Dokumentation: AS4-Redelivery
Anhang: Gesamtkonfiguration
Folgende Konfiguration reicht in einem Standard-System aus: application.properties
:
#=== JDBC Settings ==='
datasource.url=jdbc:postgresql://as4-database:5432/as4_messages?currentSchema=as4_messages
datasource.username=postgres
datasource.password=${DB_PASSWORD}
datasource.type=postgres
#=== RabbitMQ Configuration ===#
rabbitmq.host=rabbitmq3
rabbitmq.port=5672
rabbitmq.username=guest
rabbitmq.password=${RABBITMQ_PASSWORD}
Allgemeine Hinweise zur Konfiguration finden Sie hier.
View Me Edit Me