Der edi-json.converter Service bietet die Möglichkeit Edifact Nachrichten in ein fachliches JSON der Nachricht zu konvertieren, welches zur Datenübermittlung an ein entsprechendes fachliches Backendsystem geeignet ist.

Grund für die Entwicklung

Das Mapping von Edifact auf JSON und umgekehrt benötigt eine Dependency auf den EdiGenerator. Diese wird in der B2B über den Validation Content geliefert. Wir haben dort somit keine Kontrolle über die vorliegende Version und es kann so zu Versionskonflikten kommen. Daher haben wir uns entschieden hier einen Microservice zu implementieren, der die Abhängigkeit selbstverwaltet ausserhalb des B2B Kontextes nutzen kann.

Aufbau

Der Microservice ist eine eigenständige SpringBoot Applikation, die einen Post Endpunkt pro Konvertierungrichtung anbietet. Streng genommen wäre hier die GET Methode angebrachter, diese übermittelt ihre Daten aber nicht im Request Body, der bei einer Größe von potentiell mehreren Megabytes die bessere Option darstellt. Alternativ wäre eine Datenübermittlung im Rahmen eines File Uploads. Dieser Weg wurde aber hier nicht gewählt.

Unterstützte Formate und Sprache

Ab der Formatumstellung im Oktober 2022 wird das edi-json Mapping von allen EDIFACT Formatversionen des deutschen Strommarktes (definiert durch den BDEW) unterstützt. Die edi-json Datenstruktur liegt dabei ab den Formatversionen zur Umstellung Oktober 2022 in deutscher Sprache vor. Die Benennungen der Felder erfolgen dabei direkt anhand der Spezifikationen des BDEWs aus dem MIG Dokumenten, sodass die edi-json hiermit fachlich leicht lesbar werden.

Für EDIFACT Formatversionen vor der Formatumstellung im Oktober 2022 wird nur das Mapping ausgewählter wichtiger Formate unterstützt, nämlich: UTILMD, MSCONS, ORDERS, ORDRSP, IFTSTA, APERAK. Zudem liegt hier das edi-json in der Regel nur in englischer Sprache vor.

Sollte das edi-json Mapping auch von Gas oder anderen EDIFACT Formaten benötigt werden, so kann dies beauftragt werden.

Datenverarbeitung

Die übermittelten Daten werden synchron konvertiert und die Resultate im Responsebody übertragen.

Konfiguration des Microservice

Der Microservice wird über die Datei application.yml konfiguriert. Relevante Settings dabei

  • server.port - Der Port unter den der Service erreichbar sein soll
  • andere aus SpringBoot bekannte parameter wie logging etc.

Versionsinfo

Die aktuelle Version des Microservice kann mit Hilfe des Endpunkts /actuator/info abgerufen werden.

Artefakt

Der edi-json.converter steht (NLI intern im Nexus) im PrivateDL (mit berechtigtem Zugang) oder als Docker Image docker-nob-erp.next-level-apps.com/edi-json.converter:${EDIC_VER} bezogen werden.

Release

Ein EdiJson-Converter Release ist meistens unabhängig von einem B2B Release, d.h. weder erfolgt er geplant zeitgleich mit einem B2B Release, noch müssen B2B und EdiJson-Converter Versionen aufeinander abgestimmt werden. Die Release Notes zum EdiJson-Converter finden sich im hier.

Deployment (als Docker Container)

Beispiel Eintrag in docker-compose.yml zum Start einer edi-json.converter Instanz.

services:
  edic01:
    image: docker-nob-erp.next-level-apps.com/edi-json.converter:${EDIC_VER}
    hostname: edic01
    container_name: edic01
    restart: always
    command: "-Xmx4g"
    ports:
      - "8090:8080"
      # management server port
      - "9001:9001"
      # debug
#      - "5005:5005"
    environment:
      - TZ=Europe/Berlin
      - JAVA_OPTS= -XX:+ExitOnOutOfMemoryError
      # debug
#      - JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n
    volumes:
      - ./logs_container:/logs
      - /etc/localtime:/etc/localtime:ro

Verwendung zusammen mit der B2B

Schnell-Customizing

Es folgt ein minimales Customizing. Dieses stellt die Edi-Json Grundfunktionalitäten zur Verfügung, die in den folgenden Abschnitten genauer erläutert werden.

globalProperties:
  EDIJSON_CONVERTER_URL: "http://edi-json-converter:8080"

services:
  "ProcessTrigger":
    name: EdiJsonMeta an ProcessTrigger
    class: com.nextlevel.services.outbound.http.ProcessTriggerService
    type: REST
    direction: OUT
    properties:
      URL: "http://sxp-processtrigger-sim:8080"
      MONITOR_OUTPUT: true
  "EdiJsonInbound":
    name: EdiJson Receiver
    type: REST
    channel: OUT_SEP
    direction: IN

actions:
  "SXP-ProcessTrigger #730":
    id: 730
    class: org.b2bbp.runtime.actions.internal.SetPropertyAction
    description: 'Ruft den Service auf, der das EdiJson-Meta an den SXP-ProcessTrigger übergibt.'
    properties:
      B3P_USED_SERVICE_ID:
        value: "ProcessTrigger"
        techMon: true
  "EdiJson-2-Edifact #731":
    id: 731
    class: com.nextlevel.edifactjson.mapping.EdiJson2EdifactMappingAction
    description: 'Action, die das EdiJson in eine Edifact konvertiert.'
    properties:
      URL:
        value: "http://edi-json-converter:8080"
        techMon: true

channels:
  -
    id: IN_SXP
    direction: IN
    actions:
      "ValidatorAction": true
      "Contrl erzeugen": true
      "Aperak erzeugen": true
      "Übergabe an SXP-ProcessTrigger #730": true
      "ErrorMailHandler": false
  -
    id: OUT_SXP
    direction: OUT
    actions:
      "EdiJson-2-Edifact #731": true
      "IndexingService Volltext": true
      "Msg versenden (Mail/AS2)": true
      "ErrorMailHandler": false

Einleitung

Die folgenden zwei Schaubilder zeigen schematisch wie der edi-json.converter Microservice zusammen mit der B2B und einem angeschlossenen Backend (z.B. der SXP Process Engine) konfiguriert werden kann, welches über EdiJsons (mit der B2B) kommuniziert. Dabei sind die folgenden zwei Kommunikationsrichtungen zu beachten:

Markt -> Backend (Edifact -> JSON)

SXP-Inbound

Innerhalb der B2B findet zunächst eine normale Nachrichtenverarbeitung statt. Hier findet keine Push-Kommunikation statt. Es wird nur ein GET Endpoint angeboten, der es erlaubt über die MessageId einer verabeiteten Nachricht diese im JSON-Format abzurufen.

Eine Push-Kommunikation kann jedoch separat über den ProcessTrigger realisiert werden: Am Ende der Verarbeitung wird der ProcessTriggerService im Channel aufgerufen, welches ein MetaDaten-JSON ans Backend-System sendet. Dieses enthält u.a. die MessageId.

Nach Abschluss der Verarbeitung kann die JSON-Representation der verarbeiteten Edifact über den folgenden B2B REST Endpoint (tatsächliche Adresse über Swagger einsehbar) erhalten werden.

GET [b2b]/api/edifactjson/v1/edifact/{messageid}

Dabei wird zunächst die Ursprungsnachricht anhand der messageId aus der Datenbank geladen. Wurden einige Vorgänge der Nachricht per APERAK abgelehnt, so wird nur die “gekürzte” EDIFACT der APERAK-validen Vorgänge geladen. Ist die verarbeitete Ursprungsnachricht keine Edifact, sondern ein EdiJson, so wird dieses direkt zurückgegeben. Im Fall einer Edifact spricht die B2B mit dieser dann den edi-json.converter Microservice an, um diese in ein edi-json zu mappen.

Dieser REST Endpunkt unterscheidet dabei die folgenden Fehlerklassen für den Fall, dass bei der Anfrage kein edi-json erfolgreich zurückgegeben werden kann:

Fehlerfall HTTP Status Fehlerklasse (Response-Body -> details)
Autorisierung an B2B fehlgeschlagen 403 ACCESS_DENIED - Access is denied
MessageId aus Abfrage ist in B2B DB nicht vorhanden oder vorhandener aber hat keine Ursprungsnachricht (BASE_MESSAGE) z.B. Job-Eintrag 404 MESSAGE_ID_NOT_FOUND - MessageId not found
Ursprungsnachricht (BASE_MESSAGE) zu MessageId ist weder eine Edifact oder ein edi-json 404 WRONG_MESSAGE_FORMAT - The message is neither an edifact nor an edi-json
Edifact zur der Nachricht konnte nicht erfolgreich vom edi-json.converter gemappt werden 500 EDIFACT_CONVERSION_FAILURE - Edifact to edi-json conversion failed
edi-json.converter ist (vom B2B) nicht erreichbar 500 CONVERTER_EXCEPTION - Edi-json converter is unavailable or could not handle the requested message
edi-json.converter ist in B2B nicht konfiguriert 500 CONVERTER_NOT_CUSTOMIZED - This service is inoperational because the global property EDIJSON_CONVERTER_URL could not be read
B2B nicht erreichbar 500 kein B2B Fehlercode Body
B2B DB Fehler/nicht erreichbar 503 B2B_DATABASE_UNAVAILABLE - B2B database is not available

Seine Base URL muss dazu in der folgenden GlobalProperty hinterlegt sein.

EDIJSON_CONVERTER_URL = http://<converter_server>:<converter_port>

Der HATEOAS-Wrapper der B2B bei der JSON Convertierung hat die folgende Struktur:

{
  "data": "edi-json",
  "links": []
}

Es können nur nicht archivierte Nachrichten, bei denen das Attribut B3P_BASE_MESSAGE eine Edifact Nachricht enthält abgerufen werden.

Backend -> Markt (JSON -> Edifact)

SXP-Outbound

Die Edifacts werden im definierten JSON Format (gemäß edi-json-model, inklusive Hateoas-Wrapper) mit UTF-8 Encoding per POST an den Endpunkt (tatsächliche Adresse über Swagger einsehbar) gesendet.

POST [b2b]/api/edifactjson/v1/queue/{priority}

Wird keine Priorität angegeben nimmt die B2B als default-Wert LOW an. Dies entspricht dem üblichen Default-Wert. In der B2B muss dazu ein passiver Pseudo-Inbound-Service angelegt werden, der die Nachrichtenverabeitung mit einem bestimmten Channel in Queue leitet.

InboundEdiJsonService

Die ID des Services kann abweichend vom Defaultwert in der folgenden GlobalProperty definiert werden, welche nach Neustart aktiv wird:

INBOUND_EDIJSON_SERVICE = My_Json_Inbound_Service (Default: EdiJsonInbound)

Noch vor der Queue durchläuft das JSON die Formaterkennung, welche aus den unterstützten JSON Formate in der HATEOAS-Wrapper Struktur die entsprechenden Daten auslesen kann. (Im Formatobjekt ist das Attribut UtilRef nicht befüllt.) Nachdem die Nachricht in der Queue abgelegt wurde wird der Request beendet und die Id der neuen Nachricht im ResponseBody zurück geschickt. Die Verarbeitung der Nachricht hat zu diesem Zeitpunkt noch nicht begonnen. Die zurückgegebene ID hat die folgende Form:

<B2BMessageId>_<B2BQueueId>

Die Konvertierung findet hier innerhalb eines Outbound-Channels statt, in welchem die Action EdiJson2EdifactMappingAction konfiguriert werden muss.

Debuggen

  • in der docker-compose.yml die Zeilen unter # debug aktivieren
    • bei ports
    • bei environment
  • Debugger konfigurieren
    • Datei liegt unter: .runConfigurations/localhost_5005.run.xml
    • diese als Debug-Konfiguration verwenden
      • (IntelliJ Ultimate: Datei im Viewer anschauen, oberhalb des Codes Hinweis “Open Run/Debug Configurations” anklicken
  • Breakpoints setzen
  • Container starten
  • Debugger in IDE starten
  • Rest-Calls durchführen (z. B. mit rest-api.http in IntelliJ)
  • Programmlauf stoppt an Breakpoints
View Me   Edit Me