# XTA-Client Ein Client zum Senden und Empfangen von XTA Nachrichten. Der Client verwendet *XTA 2 Version 3.1* mit [XTA-Modul-Webservice-Version](https://www.xoev.de/osci-xta/standard-xta-2/xta-versionsuebersicht-23036) `2.1.1`. Er wird als Maven-Artefakt `xta-client-lib` bereitgestellt und kann in Java-Anwendungen eingebunden werden. 1. [Konfiguration](#Konfiguration) 1. [Filterung von Nachrichten vor der Abholung](#Filterung-von-Nachrichten-vor-der-Abholung) 2. [Senden einer Nachricht](#Senden-einer-Nachricht) 1. [Validierung der Xdomea-ZIP-Datei](#Validierung-der-Xdomea-ZIP-Datei) 3. [Empfangen von Nachrichten](#Empfangen-von-Nachrichten) 4. [Referenzen](#Referenzen) ## Konfiguration Der XTA-Client wird mit einer `XtaClientConfig` konfiguriert: - XTA-Service-Port-URLs: `management`, `send` und `msgBox ` - Client-Zertifikat der Autor-Kennung (für `sendMessage`) und der Leser-Kennungen (für `fetchMessages`) - Leser-Client-Kennungen für `fetchMessages`. - ... siehe [XtaClientConfig](src/main/java/de/ozgcloud/xta/client/config/XtaClientConfig.java) **Beispielcode:** ```java var config = XtaClientConfig.builder() .managementServiceUrl("https://my-xta-server.de/MB_XTA-WS/XTA210managementPort.svc") .sendServiceUrl("https://my-xta-server.de/MB_XTA-WS/XTA210sendPort.svc") .msgBoxServiceUrl("https://my-xta-server.de/MB_XTA-WS/XTA210msgBoxPort.svc") .clientCertKeystore(XtaClientConfig.KeyStore.builder() .content(Files.toByteArray(new File("/path/to/client-cert.p12"))) .type("PKCS12") .password("keystore-password") .bulid()) .clientIdentifiers(List.of( XtaIdentifier.builder() .category("Generischer Antragsempfänger") .value("gae:test-environment@ozg-cloud.de") .build(), XtaIdentifier.builder() .category("Generischer Antragsempfänger") .value("gae:dev-environment@ozg-cloud.de") .build() )) .build(); var client = XtaClient.from(config); ``` <small>Hinweis: Sollte die Root-CA des XTA-Servers nicht für das Ziel-System konfiguriert sein, muss zudem ein entsprechender `XtaClientConfig::trustStore` konfiguriert werden.</small> ### Filterung von Nachrichten vor der Abholung Um Nachrichten vor dem Abholen basierend auf `XtaMessageMetadata` zu filtern, sollte das optionale `Predicate<XtaMessageMetadata>` für `XtaClientConfig::isMessageSupported` konfiguriert werden. Zum Beispiel kann auf diese Weise verhindert werden, dass nicht unterstützte Nachrichten, die unausweichlich zu einem Verarbeitungsfehler führen, vollständig heruntergeladen werden müssen. ## Senden einer Nachricht Zum Senden einer Nachricht konfiguriert die Nutzer*in einen neuen XTA-Client mit einem Client-Zertifikat, welches sie für das Senden mit einer Autor-Kennung autorisiert. Die Nutzer*in erstellt die zu sendende Nachricht mit entsprechender Autor- und Leser-Kennung. Anschließend übergibt sie die Nachricht an den XTA-Server mit einem Aufruf von `XtaClient::sendMessage`. Wenn der zurückgegebene Transport-Report den Status `OPEN` meldet, steht die Nachricht dem Leser zur Abholung bereit. ```mermaid %% Senden einer Nachricht sequenceDiagram participant A as Nutzer*in participant B as XTA-Client participant C as XTA-Server Note left of A: (1) XTA-Client erzeugen activate A Note left of A: (2) Nachricht erzeugen Note left of A: (3) Nachricht senden A->>B: sendMessage activate B B->>C: checkAccountActive activate C C-->>B: deactivate C B->>C: lookupService activate C C-->>B: deactivate C B->>C: createMessageID activate C C-->>B: deactivate C B->>C: sendMessage activate C C-->>B: deactivate C B->>C: getTransportReport activate C C-->>B: deactivate C B-->>A: deactivate B Note left of A: (4) Nachrichtenstatus prüfen deactivate A ``` <small>* Der XTA-Server wird oft als Nachrichtenbroker oder Nachrichtenvermittler bezeichnet.</small> **Beispielcode:** ```java // (1) XTA-Client erzeugen var client = XtaClient.from(config); // (2) Nachricht erzeugen var zipFileName = "d5be7468-e620-4126-a40e-61a7f9b46345_Geschaeftsgang.Geschaeftsgang.0201.zip"; var zipFileContentDataHandler = new DataHandler(new FileDataSource("/path/to/" + zipFileName)); var xdomeaXtaFile = XtaFile.builder() .name(zipFileName) .content(zipFileContentDataHandler) .contentType("application/zip") .build(); var message = XtaMessage.builder() .metaData(XtaMessageMetaData.builder() .service("urn:xoev-de:xdomea:schema:2.4.0/xdomea240Antrag.wsdl") .businessScenarioCode("XDOMEAGAD_DATA") .businessScenarioListUri("urn:de:dataport:codeliste:business.scenario") .businessScenarioListVersionId("1.0") .messageTypeCode("Geschaeftsgang.Geschaeftsgang.0201") .messageTypePayloadSchema("urn:xoev-de:xdomea:schema:2.4.0") .authorIdentifier(XtaIdentifier.builder() .category("Generischer Antragsdienst") .value("gad:010200100000") .build()) .readerIdentifier(XtaIdentifier.builder() .category("Generischer Antragsempfänger") .value("gae:test-environment@ozg-cloud.de") .build()) .build()) .messageFile(xdomeaXtaFile) .attachmentFiles(emptyList()) .build(); // (3) Nachricht senden var transportReport = client.sendMessage(message); // (4) Nachrichtenstatus prüfen assert transportReport.status() == XtaMessageStatus.OPEN; ``` Da eine Xdomea-Nachricht die Leser- und Autor-Kennung bereits enthält, ist es möglich aus der Xdomea-ZIP-Datei die Metadaten der XTA-Nachricht abzuleiten: ```java // ... // (2) Nachricht erzeugen // ... var message = XdomeaXtaMessageCreator.createInstance().createMessage(xdomeaXtaFile); // (3) Nachricht senden var transportReport = client.sendMessage(message); // ... ``` Hierbei wird die Xta-Autor-Kennung aus dem *Xdomea-Absender-Kennung/Behoerdenschluessel* gelesen und die Xta-Leser-Kennung aus dem *Xdomea-Empfaenger-Kennung/Behoerdenschluessel*. ### Validierung der Xdomea-ZIP-Datei Wenn eine `XtaMessage` für eine Xdomea-ZIP-Datei mit `XdomeaXtaMessageCreator::createMessage` erstellt wird, wird zudem geprüft, ob die Nachricht die ["Transportfestlegungen Generischer Antragsdienst"](doku/Transportfestlegungen%20Generischer%20Antragsdienst.pdf) einhält. Für eine erfolgreiche Validierung muss eine Xdomea-ZIP-Datei folgende Bedingungen erfüllen: - Der ZIP-Dateiname ist `<ProzessID>_<Nachrichtentyp>.zip` (z.B. `00000000-0000-0000-0000-_Geschaeftsgang.Geschaeftsgang.0201.zip`) - Die ProzessID in der Xdomea-Nachricht entspricht der ProzessID im Dateinamen - Die Xdomea-Nachricht `<ProzessID>_<Nachrichtentyp>.xml` in der ZIP-Datei ist schema-konform. - Der Xdomea-Nachrichten-Typ ist zulässig: - `Geschaeftsgang.Geschaeftsgang.0201` mit Xdomea 2.4.0 - `Abgabe.Abgabe.0401` mit Xdomea 3.0.0 - `Abgabe.ImportBestaetigen.0402` mit Xdomea 3.0.0 - Alle Dateien, die die Xdomea-Nachricht referenziert, sind in der ZIP-Datei enthalten. - Eine Absender-Kennung ist vorhanden mit dem Präfix `gad` - Eine Empfänger-Kennung ist vorhanden mit dem Präfix `gae` <small>Hinweis: Die Xdomea-Nachricht sollte mit UTF-8 kodiert sein.</small> ## Empfangen von Nachrichten Zum Empfangen von Nachrichten konfiguriert die Nutzer*in einen neuen XTA-Client mit den gewünschten Leser-Kennungen. Zudem konfiguriert sie das Client-Zertifikat, welches sie zum Lesen mit den Leser-Kennungen autorisiert. Beim Aufruf von `fetchMessages` werden alle Nachrichten für die Leser-Kennungen abgeholt und verarbeitet. Die Nachrichten-Verarbeitung erfolgt durch die übergebene `processMessage`-Funktion. Nachdem alle Nachrichten verarbeitet sind, werden die Transport-Reports zurückgegeben. Eine erfolgreich abgeholte/geschlossene Nachricht hat den Status `RED`, `YELLOW` oder `GREEN`. Hierbei signalisiert `RED` einen kritischen Fehler, `YELLOW` einen Warnhinweis und `GREEN` eine fehlerfreie Verarbeitung. ```mermaid %% Empfangen von Nachrichten sequenceDiagram participant A as Nutzer*in participant B as XTA-Client participant C as XTA-Server Note left of A: (1) XTA-Client erzeugen activate A Note left of A: (2) Nachrichten abholen A->>B: fetchMessages activate B loop Für jede Leser-Kennung B->>C: checkAccountActive activate C C-->>B: deactivate C B->>C: getStatusList activate C C-->>B: deactivate C loop Für jede ungelesene Nachricht B->>C: getMessage activate C Note left of B: Nachricht abholen C-->>B: deactivate C B->>A: processMessage Note left of A: (3) Nachricht verarbeiten A-->>B: B->>C: close activate C Note left of B: Nachricht schließen C-->>B: deactivate C B->>C: getTransportReport activate C C-->>B: deactivate C end end B-->>A: deactivate B Note left of A: (4) Nachrichtenstatus prüfen deactivate A ``` <small>* Sollte `processMessage` bei der Verarbeitung eine *RuntimeException* werfen, wird `Nachricht schließen` übersprungen.</small> <small>Hinweis: Nicht geschlossene Nachrichten mit Status `OPEN` werden beim nächsten Aufruf von `fetchMessages` erneut bearbeitet.</small> **Beispielcode:** ```java // (1) XTA-Client erzeugen var client = XtaClient.from(config); // (2) Nachrichten abholen var transportReports = client.fetchMessages(xtaMessage -> { // (3) Nachricht verarbeiten }); // (4) Nachrichtenstatus prüfen for (var transportReport : transportReports) { assert transportReport.status() == XtaMessageStatus.GREEN; } ``` ## Referenzen - Dieser XTA-Client basiert auf dem [XTA-Client-Beispielcode für XTA 2 Version 3 vom 21.07.2021](https://www.xoev.de/sixcms/media.php/13/XTA_Client_Version_3_20210721.zip) auffindbar unter [Hilfsmittel](https://www.xoev.de/xta/hilfsmittel). - Die [XTA 2 Version 3.1 Spezifikation](https://www.xoev.de/sixcms/media.php/13/XTA_2_Version_3.1_Spezifikation_30112021.pdf) ist auffindbar unter [XTA 2 Version 3.1](https://www.xoev.de/xta/v3).