# 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).