Dieses Tag beinhaltet die eigentliche Definition eines Webservices, der über verschiedene Steuerelemente oder per Programmierung angesprochen werden kann.
Das Tag beinhaltet zwingend das Id- und die ModelType-Attribute, alle anderen Attribute sind optional.
Attribute
Id
Eine eindeutige Id, die diesen Webservice identifiziert. Da diese Id über alle Ids eindeutig sein muss, sollte sinnvoll gepräfixt werden (Projektname/Namespace/etc).
displayName
Der Anzeigename dieses Webservices. Dieser taucht bei den Webservice-Auswahlen der Steuerelemente im Designer und in Protokollen auf und sollte daher ausreichend sprechend sein. Es kann neben einem Reintext auch die Guid einer Übersetzung verwendet werden. Das Attribut ist optional, ohne diese Angabe wird in den Auswahlen die Id des Webservices angezeigt.
outboundModelType / inboundModelType
Die Typen der Models, auf welche dieser Webservice aufgerufen werden kann. Bei der reinen Verwendung des Webservices in den Menübandaktionen im Designer, sind diese beiden Typen immer gleich und der Typ des Datensatzes, auf den der Webservice aufgerufen wird. Unterschiedliche Typangaben können nur per Programmierung sinnvoll genutzt werden.
Diese beiden Attribute sind zwar theoretisch Optional, als Standardwerte wird allerdings System.Object
verwendet, was die Nutzungsmöglichkeiten stark einschränkt.
lifeCycleEventHandler
Enthält den Typen einer speziell programmierten Klasse, welche Möglichkeiten besitzt, die aus- und eingehenden Daten auf eine Weise zu manipulieren, welche über die Möglichkeiten der Konfiguration hinausgeht.
selectable
Optionale boolsche Angabe, ob dieser Webservice in den Steuerelementen, die in der Lage sind Webservices abzufragen, zur Auswahl stehen soll (Standard ist „true“).
callLog
Angabe, ob und in welchem Umfang für Aufrufe dieses Webservice ein Webservice-Aufrufprotokoll geschrieben werden soll. Mögliche Angaben sind „None“, „Medium“ und „Full“, Standardwert ist „None“ (s. Webservice-Aufrufprotokolle)
Inhalte
Das WebService-Tag kann weitere Tags beinhalten, von denen manche optional und manche erforderlich sind:
<Method>
Das Method-Tag ist erforderlich und bestimmt die HTTP-Methode, mit der auf den entfernten Webservice zugegriffen werden soll. Folgende Methoden werden unterstützt: „GET“, „POST“, „PUT“, „PATCH“, „DELETE“ und „OPTION“.
Hinweis: Obwohl das Tag selbst benötigt wird, kann der Inhalt an dieser Stelle leer sein und später über eine WebServiceModification (s. XML-Definitionen zur Änderung bereits konfigurierter Webservices) gefüllt werden, da ein gültiger Webservice am Ende zwingend eine Methode angeben muss.
<Url>
Das <URL>
-Tag ist erforderlich und bestimmt die URL, auf welche die Webservice-Anfrage abgesetzt wird. Die URL-Angabe kann Platzhalter beinhalten, welche über die Verwendung von sog. URL-Mappings befüllt werden (s. u.). Es muss für jeden Platzhalter genau ein Url-Mapping existieren.
Hinweis: Obwohl das Tag selbst benötigt wird, kann der Inhalt an dieser Stelle leer sein und später über eine WebServiceModification (s. XML-Definitionen zur Änderung bereits konfigurierter Webservices) gefüllt werden, da ein gültiger Webservice am Ende zwingend eine Url angeben muss.
<UrlMappings>
Tatsächlich ist es sogar üblich, dass die Url auf einen Webservice nicht immer dieselbe ist. Manchmal muss zum Beispiel der Host für unterschiedliche Anwender veriiert werden, häufiger eine Guid oder Id in den Pfad der Url gerechnet werden. Hierfür stehen Platzhalter in der Url und Url-Mappings zum Füllen dieser Platzhalter zur Verfügung. Die Inhalte eines Url-Mappings sind wiederum beliebige zur Verfügung stehende Typen von Mappings, in deren Zuordnungs-Tag (<To>
) der Name des jeweilligen Platzhalters steht. Es muss ein Mapping für jeden in der Url verwendeten Platzhalter existieren. Die Mappings werden auf das Quellobjekt (sourceModel
) des Webservices ausgeführt.
Beispiel:
<Url>{baseUrl}/api/web/v1/crm/data/{guid}</Url>
<UrlMappings>
<Mapping>
<From>BAGetConfigValueText('WebServicesBaseURI', 'Application', 'WebServiceConfig')</From>
<To>baseUrl</To>
</Mapping>
<Mapping>
<From>[ExternalGuid]</From>
<To>guid</To>
</Mapping>
</UrlMappings>
Erläuterungen:
Die Url beinhaltet zwei Platzhalter, {baseUrl} und {guid}. Der Wert für {baseUrl} wird per Formel aus der Anwendungskonfiguration gelesen, der für {guid} aus einem Feld namens ExternalGuid
im Quelldatensatz.
<Authentication>
Dieses Tag dient dazu, um den Webservice-Aufruf am Zielserver authentifizieren zu können. Hierfür stehen drei Authentifizierungstypen als Inhalts-Tags zur Auswahl, von denen genau eins angegeben sein muss:
<JWT serviceRef=“(JWT-WebService-Id)“ />
JWT-Authentifizierung zeichnet sich dadurch aus, dass bei Bedarf ein weiterer Webservice aufgerufen wird, um Authentifizierunsinformationen (JWT-Token) vom Zielserver abzurufen. Für den REST-Zugriff auf andere Business App Instanzen wird ein entsprechender Webservice mit der Id „BA.Login.JWT“ mit ausgeliefert, dessen Verwendung und Einrichtung unter „Allgemeine Webservices“ näher erläutert wird.
<Basic>
Eine früher gängige Methode, um sich an Webdiensten anzumelden: Die sog. Basic Authentication. Benutzername und Passwort werden hier als Berechnungsformel oder im Klartext (nicht empfohlen) in der XML-Definition hinterlegt. Die Berechnungsformel wird gegen das Quellobjekt und damit gegen den sourceModelType des Webservices kompiliert und ausgeführt, was in der Praxis bedeutet, dass das Passwort entweder in dem Quelldatensatz verfügbar sein muss oder über eine Konfigurationsformel beschafft werden kann.
<Basic>
<Username type=“text|formula“>…</Username>
<Password type=“text|formula“>…</Password >
</Basic>
<Header>
Diese Art der Authentifizierung wird verwendet, wenn ein bestimmter HTTP-Header für die Authentifizierung verwendet werden soll. Hier kann beispielsweise ein permanentes Token für Bearer-Authentication hinterlegt werden.
<Header>
<Name type=“text|formula“>…</Name>
<Value type=“text|formula“>….</Value>
</Header>
<OutboundMappings>
Dieses Tag stellt die Mapping-Sammlung für ausgehende Mappings dar. Sie dienen dazu, Werte aus dem Quellobjekt (Datensatz) in eine JSON-Struktur zu übertragen. Der erwartete Typ des Quellobjekts ist der Typ, der am <WebService>
-Tag im Attribut outboundModelType
angegeben ist. Der Zieltyp ist hier immer System.Collections.Generic.Dictionary`2[[System.String],[System.Object]]
.
Zur Definition der Inhalte, siehe Abschnitt Mappings.
<InboundMappings>
Dieses Tag stellt die Mapping-Sammlung für eingehende Mappings dar. Sie dienen dazu, Werte aus der JSON-Antwort des aufgerufenen Webservices in das Zielobjekt (Datensatz) zu übertragen. Der Typ des Quellobjekts ist hier immer Newtonsoft.Json.Linq.JToken
, der erwartete Typ des Zielobjekts der im Attribut inboundModelType
des <WebService>
-Tags angegebene Typ.
Zur Definition der Inhalte, siehe Abschnitt Mappings.
<ErrorMapping>
Das Error-Mapping ist ein besonderes Mapping, das dafür gedacht ist, einen ordentlichen Fehler, also einen Fehler, zu dem der aufgerufene Webservice Informationen in einer JSON-Fehlerstruktur geliefert hat, in eine einem Anwender verständliche Form zu überführen. Es hat eine festgelegte Zielstruktur und benutzt als Quelltypen Newtonsoft.Json.Linq.JToken
und als Zieltypen das Model BA.DataIntegration.WebServices.Models.RemoteError
.
Folgende XML-Tags können hierunter verwendet werden:
<Message>
Eine JSONPath-Angabe, um die Nachricht, die einem Benutzer angezeigt werden soll, aus einem Feld der gelieferten JSON-Struktur zu übernehmen. Dieser Wert kann im Weiteren noch verändert/angepasst werden. Die Angabe dieses Tags ist notwendig, der Inhalt kann aber über die Attributangabexsi:nil="true"
genullt werden, wenn das Message-Property des RemoteError-Models nicht direkt verwendet werden soll.
<DetailsArray>
Tag, über welches ein Mehrfachwert (String) aus der gelieferten JSON-Struktur direkt übernommen werden kann. Die Angabe dieses Tags ist optional.
<CacheStorage><Entry index="…">…</Entry></CacheStorage>
Dieses Tag erlaubt das Zwischenspeichern von beliebig vielen Werten aus der gelieferten JSON-Struktur unter festgelegten Indexen, da in JSONPath keine Berechnungen möglich sind. Auf diese Werte kann in der finalen Ausgabewertberechnung per Formel zugegriffen werden, um die Meldung an den Benutzer herzustellen. Die Nutzung dieses Tags ist optional.
<TransformOutput>
Dieses Tag erlaubt die Angabe einer Formel, um eine Meldung an den aktuellen Anwender aus den Daten des RemoteError-Models zu berechnen. Die Angabe dieses Tags ist optional; ist es nicht vorhanden, wird dem Benutzer das Ergebnis des Message-Tags angezeigt.
Beispiel:
Nehmen wir an, der aufgerufene Webservice liefert einen Status 400 (Bad Request) und folgende Daten zurück:
{
"errorcode": "CF1456",
"message": "Es fehlen Informationen zur weiteren Verarbeitung.",
"details": [
"Die Angabe von 'LastName' fehlt.",
"Die Angabe von 'FirstName' fehlt.",
"Die Angabe von 'Mode' muss entweder '1' oder '2' lauten."
]
}
Dann wäre ein Error-Mapping wie folgt vorstellbar:
<ErrorMapping>
<Message>$.message</Message>
<DetailsArray>$.details</DetailsArray>
<CacheStorage>
<Entry index="0">$.errorcode</Entry>
</CacheStorage>
<TransformOutput>'Lieber Anwender, der Aufruf ist leider fehlgeschlagen: ' + [Message] + ' (' + [CacheStorage][Index == 0].Single([Text]) + ').\nGrund: ' + [DetailsArray].BAImplode([Text], ' ')</TransformOutput>
</ErrorMapping>
Erklärung:
Als Hauptfehlermeldung wird durch die Angabe von „$.message“ das Feld „message“ aus der Antwort verwendet. Das DetailsArray
wird mit der Liste von Daten aus dem Feld details
befüllt. Da das RemoteError
-Model keinen gesonderten Wert für den Errorcode hat, wird dieser unter dem konkreten Index „0“ für die spätere Verwendung in den Zwischenspeicher abgelegt.
Der aktuelle Benutzer bekommt das Ergebnis der Formel im Tag <TransformOutput>
angezeigt. Diese Formel setzt eine Meldung aus mehreren Teilen zusammen: Sie beginnt mit einem statischen Text, hängt dort dann die Hauptmeldung des empfangenen Fehlers an, gefolgt von dem Fehlercode in Klammern, der aus dem Index „0“ des Zwischenspeichers entnommen wird. Die zweite Zeile der Fehlermeldung beginnt erneut mit einem statischen Text und allen angehängten Details (mit Leerzeichen voneinander getrennt).
<FollowUpWebService serviceRef=“…“>
Dieses Tag dient dem Aufruf eines Folge-Webservices, dessen Id im Attribut serviceRef
angegeben werden muss. Folge-Webservices werden nun dann aufgerufen, wenn der Aufruf des Haupt-Webservices erfolgreich war. Abhängig von den weiteren Angaben unterhalb dieses Tags verläuft der Aufruf dieses angegebenen Folge-Webservices unterschiedlich:
- Sind keine weiteren Tags gegeben, wird der angegebene Webservice auf das Objekt aufgerufen, auf welches auch der aktuelle Webservice aufgerufen wurde.
<SourceProperty>
Gibt eine existierende Eigenschaft des Quelltypen des Haupt-Webservices an, auf deren Inhalt der Folge-Webservice aufgerufen werden soll.- Ist der Inhalt dieser Quelleigenschaft eine Collection, so wird der Folge-Webservice auf jedes einzelne Element dieser Collection aufgerufen. Sollten die Elemente dieser Collection Objekte des Typs OrmBase sein, so werden diese jeweils bei erfolgreichem Aufruf des Folge-Webservices gespeichert, wenn Änderungen durchgeführt wurden.
- Ist der Inhalt dieser Quelleigenschaft keine Collection, so wird der Folge-Webservice einmal auf genau diesen Inhalt aufgerufen. Ist der Inhalt ein Objekt des Typs OrmBase, so wird dieses bei erfolgreichem Aufruf des Folge-Webservices gespeichert, wenn daran Änderungen durchgeführt wurden.
Die Verarbeitung von Orm-Objekten erfolgt jeweils nur, wenn der aktuelle Anwender die Berechtigung hat, dieses Orm-Objekt zu bearbeiten. Orm-Objekte werden zur Verarbeitung immer frisch aus der Datenbank geladen; es werden keine Änderungen an In-Memory-Objekten gemacht.
<FilterCollection>
Ist die unter<SourceProperty>
angegebene Eigenschaft bekanntermaßen eine Collection, so kann hier eine Formel angegeben werden, um nur bestimmte Elemente dieser Collection zu verarbeiten. In diesem Fall muss die angegebene Formel für jedes Element, das verarbeitet werden soll, den boolschen Wert „True“ zurückgeben.
Hinweis: Wird der Datensatz, welcher das Quellobjekt des aufgerufenen Haupt-Webserivce darstellt, nach erfolgter Verarbeitung gespeichert, kann es zu Konflikten mit durch einen Folge-Webservice zuvor gespeicherten abhängigen Datensätzen kommen.