Skip to main content
Skip table of contents

Ausgehende Webservices

Prüfung der Kompatibilität

Ob ein Webservice eingebunden werden kann oder nicht, hängt von äußeren Bedingungen ab, auf die CURSOR Software AG keinen Einfluss hat. Unter anderem müssen folgende Bedingungen erfüllt sein:

  • Die sogenannte WSDL-Datei muss zur Verfügung stehen. In der Regel gibt der Anbieter eine URL bekannt, über die CURSOR-CRM die WSDL-Datei abrufen kann.

  • Die innere Struktur der WSDL-Datei muss dem Standard WS-I Basic Profile 1.1 entsprechen und zur Parameterbeschreibung die Art document/literal nutzen. Ist die Datei nicht WS-I compliant kann CURSOR-CRM den Web Service nicht ansprechen. 

    • Die Aussage des Web Service-Anbieters oder eine oberflächliche Sichtprüfung der WSDL-Datei genügen nicht. Das frei verfügbare Programm SoapUI kann die Einhaltung des WS-I Basic Profile-Standards überpüfen und einen Prüfbericht erzeugen. Hier wird nur formal geprüft, ob die WSDL gültig ist. Unstimmigkeiten bei den Aufruf- und Rückgabeparametern können weiterhin auftreten.

  • Werden Imports von Schema-Dateien innerhalb einer WSDL mit relativen Pfaden definiert, so kann es zu Problemen bei der Ausführung und dem Erstellen von Web Services führen. Hier ist eine manuelle Prüfung nötig, ob der Web Service mit dieser WSDL angelegt werden kann oder ob der eigentliche Service/Methode von dem Import-Anweisungen betroffen ist. Es könnte sein, dass der Service nicht vom Import abhängt. Generell ist der Import mit relativen Angaben ein Hindernis.

  • CURSOR-CRM unterstützt Basic Authentication und ab Version 12.2 WS-Security-Anmeldung unter Nutzung des Username-Token.

  • Der Applikationsserver oder Rich Client muss auf den Web Service zugreifen können. Dies geschieht in der Regel über die Protokolle http oder https. Dies kann an allgemeinen Beschränkungen des Internetzugriffs scheitern. Ggf. ist es notwendig, client- oder serverseitig relevante SSL-Zertifikate zu hinterlegen.

Die obig genannten Punkte sollten im Vorfeld geprüft werden, bevor die eigentliche Implementierung stattfindet.

Die Umgebung für den Aufruf des Webservices

Client oder Server

Der Aufruf des Webservices erfolgt entweder

  • im Client oder

  • im Applikationsserver, was der Standard ist.

Gesteuert wird dies über die Benutzereinstellungen oder die Systemeinstellungen durch die Einstellung

  • Integration/Web Services direkt in der Anwendung aufrufen

Wenn in den Benutzereinstellungen oder den Systemeinstellungen die Einstellung gesetzt ist, dann erfolgen die Aufrufe von Webservices im Client.

Proxy

Da der Aufruf eines Services über das Internet geht, ist es notwendig, den Proxy zu definieren, wenn ein solcher verwendet werden muss, um die Verbindung zum Internet aufzubauen. Je nachdem wo der Aufruf erfolgt - im Client oder im Server - ist die Definition des Proxys an einer anderen Stelle vorzunehmen.

Proxy bei Aufruf aus dem Client

  • Benutzereinstellungen/Netzwerk Einstellungen

Proxy bei Aufruf aus dem Server

  • Systemeinstellungen/Netzwerk Einstellungen Applikationsserver


Webservices in der Administrationskonsole

Der Eintrag Web Services in der Adminkonsole bietet Optionen zur Einrichtung, Wartung, Test, Ex- und Import eines Web Services. Die verfügbaren Optionen werden in den folgenden Kapiteln beschrieben.

Abbildung: Webservices in der Administrationskonsole

Anlegen eines neuen Webservices

Durch einen Klick auf den Schalter 

Neu startet der Einrichtungswizard.

Abbildung: Auswahl der WSDL-Datei

  • Die Schreibweise der Service-Id wird auf Gültigkeit überprüft. Sie muss mit einem Großbuchstaben beginnen und darf als weitere Zeichen nur Buchstaben, Zahlen und Unterstriche enthalten und muss zudem eindeutig sein.

  • Die angegebene Adresse der WSDL-Datei muss zum Zeitpunkt der Neuanlage zugreifbar sein. Kann z. B. eine Internet-Adresse nicht aufgelöst werden, kann der Dialog nicht fortsetzt werden.

Sind beide Angaben gemacht, muss der Benutzer die Überprüfung durch einen Klick auf die Schaltfläche Verfügbarkeit testen starten. Hierbei anhand der oben angegebenen Kriterien entschieden, ob der Wizard fortgeführt werden kann. Ist dies der Fall, wird die Weiter-Schaltfläche des Wizard freigeschaltet.

Tipp

Bei der Erstellung kann entweder auf eine lokale Kopie oder auf eine Original-URL der WSDL verwiesen werden. Im ersten Fall wird die WSDL als Kopie in der Datenbank abgelegt und für alle weiteren Operation genutzt. Bei der Angabe der Original-URL wird diese bei späteren Aufrufen neu eingelesen. Wird der erste Ansatz genutzt und der Inhalt der WSDL ändert sich, so muss der Web Service erneut eingerichtet werden.

Der zweite Ansatz birgt den Vorteil, dass eventuelle Änderungen am Web Service sofort berücksichtigt werden. Innerhalb der Adminkonsole kann man diese Eigenschaft des Web Service hinter dem Feld 'Webservice-Adresse' einsehen, wobei 'DB' für eine lokale Kopie in der Datenbank steht, 'REMOTE' für die Angabe einer URL.

Abbildung: Auswahl der Funktion


Im nächsten Schritt kann der Webservice näher definiert werden. Dazu ist der Service auszuwählen, die damit verbundenen Verbindungstypen (Ports) und die gewünschte Funktion. Die Auswahlfelder werden automatisch gemäß den verfügbaren Optionen aktualisiert (siehe Abbildung: Auswahl der Funktion)

Durch Drücken des Schalters Fertig werden die Einstellungen des Webservices in der Übersicht angezeigt. Eventuelle Änderungen können hier vorgenommen werden, bevor der Webservice durch Speichern im System abgelegt wird.

Abbildung: Übersicht

Editierbares WSDL-Adressfeld innerhalb der Adminkonsole

Innerhalb der Adminkonsole konnte bis Version 11.2 nach einer Neuanlage bislang nur das eigentliche Skript des Aufrufes geändert werden. Zuvor angegebene Eigenschaften wie z. B. die Adresse der WSDL konnten nicht geändert werden. Änderte sich der Ort der WSDL, war man bislang gezwungen den Service zu exportieren, die Adresse zu ändern und anschließend zu importieren. Nun kann die Änderung direkt in der Adminkonsole vorgenommen werden.

Diese Funktionalität steht nur zur Verfügung, falls der Web Service-Type den Wert REMOTE hat.

Testen eines Webservices

Um einen erstellten Webservice zu testen, kann der Schalter 

Test verwendet werden.

Durch einen Klick auf

Test wird der Webservice ausgeführt und im Anschluss das Ergebnis in einem Dialog angezeigt.

Wichtig hierbei ist, dass dabei Binding-Parameter bei einem Test nicht ausgewertet werden, da wir uns währenddessen im Kontext eines Datensatzes befinden.

Die Binding-Paramter beziehen sich auf Werte, die aus der Maske kommen (Maskenfelder oder Maskenskipt-Variablen). Siehe unten bei "Aufrufskripte" und im nachfolgenden Text.

Ein Beispiel vorab:
binding.parameter.get("CITY") 
bezieht sich auf folgende Maskenskriptzeile (die Maskenskript-Variable s_city enthält hier einen Ortsnamen):
parameterMap.put("CITY", s_city), 
Danach folgt im Maskenskript der Webservice-Aufruf :
Object results = callWebService("Bedirect_search", null, parameterMap);

GROOVY
def zipCode0 = binding.parameter.get("...")	//dies ist nicht möglich
def zipCode0 = 12345				//dies ist möglich
 
def result = proxy.GetWeatherByZipCode(zipCode0)

Parametergenerierung

Bei der Erstellung eines Webservice-Scriptes müssen die Methoden- und Parameter-Namen so angegeben werden, wie sie in der WSDL definiert wurden. Bei der Neuanlage eines Web Services wird, soweit wie möglich, ein Skriptgerüst generiert, um eine Hilfestellung bei der Einrichtung zu geben.

GROOVY
def accountNumber0 = binding.parameter.get("...") // <string>
def login1 = binding.parameter.get("...") // <string>
def mandator2 = binding.parameter.get("...") // <string>
def tid3 = binding.parameter.get("...") // <string>
def password4 = binding.parameter.get("...") // <string>
def bankCode5 = binding.parameter.get("...") // <string>
 
def result = proxy.accountCheck(accountNumber0, login1, mandator2, tid3, password4, bankCode5)

Alle Parameter des Methodenaufrufes werden in der Reihenfolge angegeben, wie sie in der Signatur definiert wurden. Zudem wird bei primitiven Typen ein Platzhalter eingesetzt, der indiziert um welchen Typ es sich konkret handelt (z. B. String, Float, etc.). Stellt der Parameter einen komplexen Typ dar, wird zusätzlich der Aufruf zur Objekterzeugung generiert.

GROOVY
def getWeatherByZipCode0 = proxy.create("net.webservicex.GetWeatherByZipCode") // Objekterzeugung
getWeatherByZipCode0.zipCode = binding.parameter.get("...") // <string>
def result = proxy.GetWeatherByZipCode(getWeatherByZipCode0)

 

Hinweis zur Überprüfung und Auflistung der Parameter

Um die Erstellung eines Skriptes zu vereinfachen werden die aus der WSDL generierten Java-Dateien in einem temporären Verzeichnis abgelegt sobald der Webservice mit aktivierter Benutzer- oder Systemoption In Anwendung ausführen gestartet wurde. Sie können als Hilfe für Datentypen und -Strukturen genutzt werden. Im Vorspann dieser Dateien werden auch die dazugehörigen Abschnitte aus der WSDL angegeben.

Temporäres Verzeichnis: C:\Dokumente und Einstellungen\<user>\CARMEN\<server>\tmp\jaxb\

Aufrufskripte

Um einen Webservice zu konfigurieren bzw. den Aufruf vorzubereiten, kann in der Admin-Konsole ein Skript geschrieben werden. Das Skript wird in der Skriptsprache Groovy verfasst, dessen Syntax sich stark an Java anlehnt.

Dabei werden der Vor- und Abspann (z. B. der Import, das Instantiieren der Variablen bzw. die Aufbereitung des Ergebnisses) des Skriptes automatisch eingefügt. Dabei wird auch das Proxy-Objekt initialisiert, über das die Konfiguration und der Aufruf realisiert wird.

Verfügbare Befehle des Proxy-Objektes

setBasicAuthentication>(String username, String password)

Setzt die Anmeldedaten der HTTP-Basic Authentication explizit. Normalerweise werden die in der Konsole angegebenen Anmeldedaten implizit gesetzt.

create(String qualifiedClassname)

Erstellt ein Objekt der angegebenen Klasse, die in der dazugehörigen WSDL beschrieben ist. Dabei ist darauf zu achten, das der voll qualifizierde Name (Package-Name + Klassenname) angegeben wird.

webserviceMethode(...)

Der eigentliche Aufruf des Webservices. Der Methodenname entspricht demjenigen, der zuvor bei der Einrichtung ausgewählt wurde. Der Rückgabewert des Aufrufes variiert je nach Service. Um eine einheitliche Verarbeitung zu gewährleisten muss der Rückgabewert der Variable binding.result zugewiesen werden.

nur clientseitig verfügbar)
addHeader(String elementNamespace, String elementName, Object headerElement)

Fügt dem SOAP-Request ein Header-Element hinzu. Dazu muss das Header-Objekt zuvor erstellt werden und zusätzlich dessen Name und Namespace angegeben werden.

CODE
def authHeader = proxy.create("https.webservice.com.Header");
authHeader.value = "Token-Wert";
proxy.addHeader("https://webservice.com", "AuthHeader", authHeader);

Die Werte "elementNamespace" und "elementName" müssen der WSDL entnommen werden (siehe <soap:header>-Definition).

Vor dem eigentlichen Aufruf kann auf Werte der Maske oder eigens gesetzte Werte (die z. B. aus dem Maskenskript stammen) zugegriffen werden. Dazu wird ein Binding-Objekt bereitgestellt.

Verfügbare Felder des Binding-Objektes

binding.classLoader

Interne Variable.

binding.parameter oder parameter

Zugriff auf die gesetzten Parameter. Normalerweise eine HashMap <String, Object>, die die Werte des AttributeContainers und/oder Werte der benutzerdefinierten HashMap enthält.

binding.parameter.list oder parameter.list

Zugriff auf die evtl. gesetzte Liste von AttributContainern. Zum Beispiel ein Ergebnis einer Suche.

binding.result oder result

Das Objekt, dem das Ergebnis zugewiesen werden muss, um eine spätere Verarbeitung zu gewährleisten.

Beispiele

Innerhalb des Aufrufskriptes können, wie zuvor erwähnt, alle Groovy-Anweisungen genutzt werden.

GROOVY
// Auslesen eines Maskenwertes, wenn der Web Service aus einem Maskenskript aufgerufen wurde
def parameter = binding.parameter.get("Fieldname.Entity")
def parameter = getLookupKey(binding.parameter.get("Lookupfield.Entity"))
GROOVY
// Auslesen spezieller Werte, wenn beim Aufruf des Web Services eigene Daten übergeben wurden.
def parameter = binding.parameter.get("myValueKey")

Hilfsmethoden

In dem Aufrufskript werden Methoden angeboten, um spezielle Datenfelder der Maske einfacher auslesen zu können bzw. erweiterte Funktionalitäten bereitzustellen.

Methode

Beschreibung

timestampToXMLGregorianDate(Timestamp time)

Konvertiert ein Datumsfeld der Maske in das passende Datumsformat eines Web Services

getLookupKey(LookupVO vo)

Liest den Schlüssel eines Nachschlagefeldes.

getLookupDescription(LookupVO vo)

Liest die Beschreibung eines Nachschlagefeldes.

getLookupPk(LookupVO vo)

Liest den Pk eines Nachschlagefeldes.

debug(String message) und error(String message)

Gibt Informationen werden im Log-Verzeichnis des Clients in einer seperaten Datei aus. Berücksichtigt das log-Level des internen Loggers.

In Textform:

GROOVY
// Konfigurationsskript
// ####################
 
enableLoginViaCurrentUser(true) // Anmeldung am CURSOR Web Service mit dem aktuellen User

// Aufrufskript
// ############
 
// Zugriff auf Maskenfeld (Typ: Text)
def param01 = binding.parameter.get("FreeDate1.Activity")
 
// Zugriff auf Maskenfeld (Typ: Datum)
def param02 = timestampToXMLGregorianDate(binding.parameter.get("FreeDate1.Activity"));
 
// Zugriff auf Maskenfeld (Typ: Lookup-Schlüssel)
def param03 = getLookupKey(binding.parameter.get("Priority.Activity"));
 
// Zugriff auf Maskenfeld (Typ: Lookup-PK)
def param04 = getLookupPk(binding.parameter.get("Priority.Activity"));
 
// Zugriff auf Maskenfeld (Typ: Lookup-Beschreibung)
def param05 = getLookupDescription(binding.parameter.get("Priority.Activity"));
 
// Informationen loggen
error("Aufruf des Web Service mit Parameterwert [" + param05 + "]")
 
// Aufruf des Services
def result = proxy.webserviceMethode(param01, param02, ...)

Die Variablenbezeichnung "w" darf nicht benutzt werden, da sie intern genutzt wird.

Tipp

In den beiden Skripteditoren 'Konfigurations-Skript' und 'Aufruf-Skript' steht die Autovervollständigung von Methoden und Konstanten zur Verfügung. Das Nachschlagen nach Methoden und Konstanten erfolgt per Tastenkombination STRG+LEERTASTE.

Konfigurationsskript

In der Konfiguration eines Web Services gibt es die Möglichkeit, unabhängig des eigentlichen Aufruf-Skriptes eine Konfiguration anzugeben. In dem Feld 'Konfigurations-Skript' können analog zum Aufruf-Skript verschiedene Aufrufe angegeben werden. Um einen Web Service einzurichten bzw. weitere Aktionen (z. B. WSDL anzeigen) aufzurufen, müssen z. B. die globalen Proxy-Einstellungen in der Anwendung hinterlegt sein.

Methode

Ab

Bis

Beschreibung

setBasicAuthentication(String user, String password)

12.2


Setzt die Anmeldedaten bei Nutzung der HTTP-BASIC-Authentication.

enableLoginViaCurrentUser(boolean value)

10.1


Werden CURSOR-eigene Web Services aufgerufen kann dieser Aufruf genutzt werden, der eine Anmeldung mit dem aktuellen Benutzer konfiguriert.

setUsernameToken(String user, String password[, boolean isHashedPassword])

12.2


Setzt das WS-Security Username-Token.

setProxySettings(String host, String port)

10.2

18.2

Setzt die Host- und Portangabe des Proxys. Wird durch die Systemeinstellung überschrieben.

setProxySettings(String host, String port, String user, String pw)

10.2

18.2

Setzt die Host- und Portangabe des Proxys und zusätzlich den Benutzer und das Password. Wird durch die Systemeinstellung überschrieben.

forceWrappedOperation(boolean value)

11.1


Versucht den Methodenaufruf im Stil wrapped durchzuführen, sodass der Aufrufparameter als Ganzes übergeben werden kann.

enableExtendedLogging()

12.2


Aktiviert das erweiterte Logging der SOAP-request- und -response-Messages. Dies ist nützlich um die generierten und empfangenen Daten einzusehen (z. B. bei einer SSL-Verschlüsselung).

  • Bei Ausführung im Rich Client: Diese Ausgaben werden auf der Konsole ausgegeben und nicht in die Web Service-Log-Datei geschrieben.

  • Bei Ausführung im Server: Diese Ausgaben werden auf der Konsole bzw im Server-Log ausgegeben und nicht in die Web Service-Log-Datei geschrieben.

Ergebnistypen

Im Folgenden einige Bespiele für Ergebnistypen aus einer WSDL und wie auf das Ergebnis per Maskenskript zugegriffen wird. Listen und Arrays werden in HashMaps umgewandelt, was bedeutet, es kann auf das erste Element mit get(0) zugegriffen werden, auf das zweite mit get(1) und so weiter. Gibt der Webservice lediglich einen einfachen Datentyp zurück wird dieser ebenfalls in eine HashMap verpackt und zwar unter dem Schlüssel result. Er kann also in der Folge mit result.get("result") ausgelesen werden.

Beispiel 1

In diesem WSDL-Ausschnitt wird ein Ergebnistyp GetWeatherByPlaceNameResponse definiert. Er enthält einen komplexen Typ WeatherForecasts der wiederrum eine Reihe von einfachen Werten, sowie ein Array von WeatherData-Elementen enthält.

XML
<s:element name="GetWeatherByPlaceNameResponse">
		<s:complexType>
			<s:sequence>
				<s:element minOccurs="1" maxOccurs="1" name="GetWeatherByPlaceNameResult" type="tns:WeatherForecasts" />
			</s:sequence>
	</s:complexType>
</s:element>
<s:complexType name="WeatherForecasts">
	<s:sequence>
		<s:element minOccurs="1" maxOccurs="1" name="Latitude" type="s:float" />
		<s:element minOccurs="1" maxOccurs="1" name="Longitude" type="s:float" />
		<s:element minOccurs="1" maxOccurs="1" name="AllocationFactor" type="s:float" />
		<s:element minOccurs="0" maxOccurs="1" name="FipsCode" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="PlaceName" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="StateCode" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="Status" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="Details" type="tns:ArrayOfWeatherData" />
	</s:sequence>
</s:complexType>
<s:complexType name="ArrayOfWeatherData">
	<s:sequence>
		<s:element minOccurs="0" maxOccurs="unbounded" name="WeatherData" type="tns:WeatherData" />
	</s:sequence>
</s:complexType>
<s:complexType name="WeatherData">
	<s:sequence>
		<s:element minOccurs="0" maxOccurs="1" name="Day" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="WeatherImage" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="MaxTemperatureF" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="MinTemperatureF" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="MaxTemperatureC" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="MinTemperatureC" type="s:string" />
	</s:sequence>
</s:complexType>

Das Ergebnis würde demzufolge beispielsweise folgende Struktur haben: 

JS
"details":[ 
	"weatherData":[
		0:["weatherImage":"http://forecast.weather.gov/images/wtf/nfg.jpg", "maxTemperatureF":"56", "minTemperatureF":"43", "day":"Wednesday, November 19, 2008", "maxTemperatureC":"13", "minTemperatureC":"6"],
		1:["weatherImage":"http://forecast.weather.gov/images/wtf/ra90.jpg", "maxTemperatureF":"52", "minTemperatureF":"47", "day":"Thursday, November 20, 2008", "maxTemperatureC":"11", "minTemperatureC":"8"],
		2:["weatherImage":"http://forecast.weather.gov/images/wtf/ra50.jpg", "maxTemperatureF":"52", "minTemperatureF":"42", "day":"Friday, November 21, 2008", "maxTemperatureC":"11", "minTemperatureC":"6"]
	]
], 
"status":null, "fipsCode":"53", "allocationFactor":0.001192, "stateCode":"WA", "placeName":"SEATTLE", "longitude":122.33046, "latitude":47.611435

Um auf latitude zuzugreifen, muss result.get("latitude") aufgerufen werden, um den Wert 47.611435 zu bekommen. result.get("details").get("weatherData").get(0).get("maxTemperatureF") würde 56 zurückgeben.

Beispiel 2

Diese WSDL-Datei definiert einen Rückgabetyp GetSupplierByCityResponse der ein boolean GetSupplierByCityResult und eine Liste SupplierDataLists enthält.

XML
<s:element name="GetSupplierByCityResponse">
	<s:complexType>
		<s:sequence>
			<s:element minOccurs="1" maxOccurs="1" name="GetSupplierByCityResult" type="s:boolean" />
			<s:element minOccurs="1" maxOccurs="1" name="SupplierDataLists" type="tns:SupplierDataList" />
		</s:sequence>
	</s:complexType>
</s:element>
 
<s:complexType name="SupplierDataList">
	<s:sequence>
		<s:element minOccurs="0" maxOccurs="1" name="SupplierDatas" type="tns:ArrayOfSupplierData" />
		<s:element minOccurs="1" maxOccurs="1" name="TotalRecords" type="s:int" />
	</s:sequence>
</s:complexType>
 
<s:complexType name="ArrayOfSupplierData">
	<s:sequence>
		<s:element minOccurs="0" maxOccurs="unbounded" name="SupplierData" type="tns:SupplierData" />
	</s:sequence>
</s:complexType>
 
<s:complexType name="SupplierData">
	<s:sequence>
		<s:element minOccurs="0" maxOccurs="1" name="SupplierNumber" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="CompanyName" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="Address1" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="Address2" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="City" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="State" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="Zip" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="ZipPlus4" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="Telephone" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="Description" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="IsSupplierParticipating" type="s:string" />
	</s:sequence>
</s:complexType>

Diese Struktur würde ein Aufruf ergeben: 

CODE
0=true, 
1={ 
	supplierDatas={
		supplierData={
			0={zipPlus4=10119, zip=NY, isSupplierParticipating=04, description=(212)760-1242, state=null, address1=250 W 34TH ST, address2=, companyName=KMART CORP, supplierNumber=0127051883, telephone=0002, city=NEW YORK},
			1={zipPlus4=10010, zip=NY, isSupplierParticipating=05, description=(212)982-7850, state=null, address1=6 E 23RD ST, address2=, companyName=PEARLE VISION INC, supplierNumber=0132600348, telephone=4401, city=NEW YORK},
			2={zipPlus4=10019, zip=NY, isSupplierParticipating=05, description=(212)245-0686, state=null, address1=732 9TH AVE, address2=, companyName=WESTWAY VISION INC, supplierNumber=0133130001, telephone=7317, city=NEW YORK}
		}
	}
}

Mit result.get(0) kann GetSupplierByCityResult erfragt werden, in diesem Fall also true. get(1).get("supplierDatas").get("supplierData").get(1).get("description")" liefert (212)982-7850.

Fehler-Codes

Wenn ein Fehler während der Bearbeitung auftritt, kann dieser nach folgenden Typen unterschieden werden:

CONFIG

Fehler beim Laden der Web Service Configuration, z.B. falsche ID

SCRIPT

Ungültiges WebService Skript

FAULT

Eine SOAP Fault Nachricht, d.h. der WebService meldet eine Ausnahme

AUTH

Die Authentifizierung funktioniert nicht bzw. ist fehlerhaft konfiguriert

SSL

Die SSL-Konfiguration ist fehlerhaft

REMOTE

Es konnte keine Verbindung zum WebService aufgebaut werden

NONE

Ein nicht näher spezifizierter Fehler

Die genaue Fehlerursache wird ins Client- bzw. Server-Log geschrieben.

Aufruf-Beispiele

Beispiel 1

Als erstes Beispiel soll ein einfachter Service-Aufruf installiert werden, der zu einer Bankleitzahl die Bank ermittelt. Die WSDL dafür lautet:

http://www.thomas-bayer.com/axis2/services/BLZService?wsdl

Für den ersten Versuch soll der Service über den Button Test aufgerufen werden. Dabei ist wie folgt vorzugehen:

  • Start der Admin-Konsole - Menüpunkt Sonstige Bereiche/Webservices

  • Neuen Webservice Aufruf anlegen über den Button Neu

  • Als ID beliebigen eindeutigen Namen eingeben, der mit einem Großbuchstaben beginnt. zB GetBank

  • URL der WSDL Datei angeben

  • Button Verfügbarkeit testen drücken. Wenn der Webservice erreichbar ist, wird der Button Weiter aktiv. Bei Problemen die Schreibweise der URL durch Eingabe im Browser testen. Dann müsste die WSDL Definition ausgegeben werden. Ansonsten prüfen, ob der Proxy in den Benutzereinstellungen korrekt gesetzt ist.

  • Button Weiter drücken

  • Servicename BLZService, Portname BLZServiceSOAP12port_http, Methodenname getBank wählen

  • Button Fertig anklicken. Die Daten werden in das Hauptformular übernommen und es wird ein Aufruf-Script generiert.

  • Wenn ein Proxy zum Zugriff auf das Internet verwendet wird, dann muss dieser auch im Konfigurations-Skript definiert werden: setProxySettings("proxy", "8080").

  • Das generierte Aufruf-Script ist zum einen falsch und zum anderen funktionert der Aufruf von binding.parameter.get() beim Drücken des Test-Buttons nicht. Es wird deshalb geändert, so dass der Parameter als Konstante mitgegeben wird:def result = proxy.getBank("50010517")

  • Den Aufruf des Web-Services durch Drücken des Buttons Speichern speichern

  • Den Button Test drücken. Als Ergebnis sollte jetzt {bezeichnung=ING-DiBa, ort=Frankfurt am Main, plz=60628, bic=INGDDEFFXXX} - die zur BLZ 50010517 passende Bank ausgegeben werden

Beispiel 2

Nach oben beschriebenem Vorgehen wird ein WebService RiskCode angelegt, dessen Methode GetLloydsRiskCodeDetailByRiskCode aufgerufen werden soll. Sollten Benutzername und Passwort erforderlich sein, können diese in der Maske eingegeben oder im Skript mit setBasicAuthentication(String username, String password) nachgetragen werden.

Abbildung: Konfiguration des Webservice RiskCode

Das passende Skript könnte beispielsweise so aussehen:

GROOVY
def RiskCode = "3"
def result = proxy.GetLloydsRiskCodeDetailByRiskCode(RiskCode)

Dabei ist vorgeschrieben, dass das Ergebnis in einer Variable result gespeichert wird, da diese intern später weiterverwendet wird.

Das Objekt proxy wird zur Verfügung gestellt und die gewünschte Methoden müssen darauf aufgerufen werden. Dieses Objekt wird intern durch ergänzen des Codes durch folgende Zeile bereitgestellt:

GROOVY
def proxy = new GroovyWSClient("http://www.webservicex.net:85/LloydsRiskCodeService.asmx?wsdl", binding.classloader)

Die hier gewählte Methode GetLloydsRiskCodeDetailByRiskCode erwartet einen String-Parameter RiskCode, der hier auf 3 gesetzt wird. Das vom Methodenaufruf zurückgegebene Ergebnis wird in diesem Fall in result geschrieben. binding ist wie proxy ein bereitgestelltes Objekt. In binding.result muss das Ergebnis geschrieben werden, das später verwendet werden soll. Die Vereinheitlichung des Ergebnisses wird intern durch folgenden Aufruf erreicht:

GROOVY
WebServiceHelper w = new WebServiceHelper()
binding.result = w.flattenResult(result)

Damit sieht das tatsächlich ausgeführte Skript folgendermaßen aus:

GROOVY
def proxy = new GroovyWSClient("http://www.webservicex.net:85/LloydsRiskCodeService.asmx?wsdl", binding.classloader)
def RiskCode = "3"
 
result = proxy.GetLloydsRiskCodeDetailByRiskCode(RiskCode)
 
WebServiceHelper w = new WebServiceHelper()
binding.result = w.flattenResult(result)

Wie im folgenden WSDL-Ausschnitt dieses Webservices zu sehen, wird der komplexe Typ GetLloydsRiskCodeDetailByRiskCodeResponse zurück gegeben, der in diesem Fall in result steht. Dieser komplexe Typ enthält den weiteren komplexen Typ ArrayOfRiskCode, auf den mit result.get("riskCode") zugegriffen werden kann. Dieses ArrayOfRiskCode-Objekt wiederrum ist ein Array dessen RiskCode-Elemente mit get(0) ... get(x) erhalten werden können. Diese RiskCode-Elemente schließlich enthalten String-Objekte mit Werten. Diese String-Objekte werden mit get("IhrName") ausgelesen.

In obigem Maskenskript-Beispiel wird also zunächst das GetLloydsRiskCodeDetailByRiskCodeResponse-Objekt ausgegeben, anschließend das erste RiskCode-Element aus dem Array genommen und sein Wert firstYearOfAccount ausgegeben, sowie sein Wert riskCodeDescription in das Maskenfeld Freitext 1 geschrieben.

XML
<s:element name="GetLloydsRiskCodeDetailByRiskCode">
	<s:complexType>
		<s:sequence>
			<s:element minOccurs="0" maxOccurs="1" name="RiskCode" type="s:string" />
		</s:sequence>
	</s:complexType>
</s:element>
 
<s:element name="GetLloydsRiskCodeDetailByRiskCodeResponse">
	<s:complexType>
		<s:sequence>
			<s:element minOccurs="0" maxOccurs="1" name="GetLloydsRiskCodeDetailByRiskCodeResult" type="tns:ArrayOfRiskCode" />
		</s:sequence>
	</s:complexType>
</s:element>
 
<s:complexType name="ArrayOfRiskCode">
	<s:sequence>
		<s:element minOccurs="0" maxOccurs="unbounded" name="RiskCode" nillable="true" type="tns:RiskCode" />
	</s:sequence>
</s:complexType>
 
<s:complexType name="RiskCode">
	<s:sequence>
		<s:element minOccurs="0" maxOccurs="1" name="LloydsRiskCode" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="RiskType" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="MarketCode" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="NewTerrorismCode" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="LastYearOfAccount" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="FirstYearOfAccount" type="s:string" />
		<s:element minOccurs="0" maxOccurs="1" name="RiskCodeDescription" type="s:string" />
	</s:sequence>
</s:complexType>

Beispiel 3

Ein weiterer Webservice "WeatherForecast" wird mit folgender Konfiguration eingerichtet:

"GetWeatherByPlaceName" erwartet einen String, der den Namen einer Stadt enthält. In diesem Beispiel soll diese Stadt aus dem Textfeld "Freitext 1" der Aktivität ausgelesen werden. Dazu ist folgender Skript-Code nötig:

GROOVY
def PlaceName = binding.parameter.get("FreeText1.Activity")
def result = proxy.GetWeatherByPlaceName(PlaceName)

In "binding.parameter" sind alle Felder der Maske enthalten, aus der der Webservice aufgerufen wurde. Mit "get("derNameDesFeldes")" kann damit der Inhalt des gewünschten Feldes erfragt werden. Hier wird dieser Inhalt in "PlaceName" gespeichert und an die Methode "GetWeatherByPlaceName" übergeben.

Mit diesem Maskenskript würde der soeben erstellte Webservice aufgerufen:

GROOVY
IWebServiceResult result = callWebService("WeatherForecast");
alert(result);

Beispiel - Suchen im CURSOR-CRM

Die WSDL-Datei des JBoss kann unter folgender URL gefunden werden

http://localhost:18080/CARMEN-ejb/WebServiceController?wsdl

Oder die Datei kann auch im Dateisystem geladen werden

..\JBoss\server\default\data\wsdl\CARMEN.ear\CARMEN-ejb.jar\WebServiceController.wsdl

Für dieses Beispiel wird die Funktion search aufgerufen und dafür die XML-Struktur einer Suche übergeben.

Die eigentliche Suche bzw. eine Vorlage kann aus der Anwendung exportiert werden.

Die Suche wird mit den Rechten des für den Webservice angegebenen Benutzers ausgeführt. Das Kürzel ist in Großbuchstaben anzugeben, als Passwort benötigt man den Hashwert aus der Datenbank.

Im Groovy-Skript ist die XML-Suche als Parameter zu übergeben.

GROOVY
def xmlSearch = """<CreateComplexSearch> <ExtendedSearch PK="" PlainKey="Search" Description="Search" UserPrivateSearch="false" QuickSearch="false" UseCost="true" IgnoreCase="true" SubmaskOnly="false" SystemSearch="false" CursorStandard="false" UseDistinct="false" TopCount="-1"> <Query> <SubQuery operator="de.cursor.jevi.common.search.Operator\$AndOperator" relationName="" entityName="Customer" subQueryInSearchResult="true" useExists="false" useOuterJoin="false" optionalQuery="false" breakQuery="false" hint=""> <Condition searchResultField="true" listKey="false" searchField="false" deleteable="false" readOnly="false" defaultSearchValue="false"> <AttributeName>MatchCode.Customer</AttributeName> <Function functionClassName="de.cursor.jevi.common.search.function.NoConditionFunction" numberOfParameters="0"> <FunctionProperty functionPropertyName="TableName" functionPropertyDataType="java.lang.String" functionPropertyValue="" /> </Function> </Condition> <Condition searchResultField="false" listKey="false" searchField="false" deleteable="false" readOnly="false" defaultSearchValue="false"> <AttributeName>Active.Customer</AttributeName> <Function functionClassName="de.cursor.jevi.common.search.function.EqualFunction" numberOfParameters="1"> <Parameter parameterClassName="java.lang.Boolean" parameterValue="true" /> </Function> </Condition> </SubQuery> </Query> </ExtendedSearch> </CreateComplexSearch>"""

Das $-Zeichen ist ein geschütztes Zeichen in der Groovy-Scriptsprache. Dieses muss mit \$ ersetzt werden. Ein Parameter über mehrere Zeilen mit 3 Anführungszeichen angegeben werden.

Zum Aufruf muss auf dem Proxy die Methode search aufgerufen werden. Das Ergebnis wird der definierten Variable result zugewiesen.

GROOVY
def result = proxy.search(xmlSearch)

Welchen Parameter die Methode benötigt und von welchem Typ der Rückgabewert ist, kann aus der WSDL-Datei ausgelesen werden.

XML
  ...
<message name="search">
	<part name="xmlSearch" type="xsd:string"></part>
</message>
<message name="searchResponse">
	<part name="result" type="xsd:string"></part>
</message>

Zum Aufruf des Webservices kann folgendes Maskenskript verwendet werden:

GROOVY
String result = callWebService("Search").get("result");

In unserem Beispiel hat das Ergebnis folgende Struktur und Inhalt:

XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<Entries testRun="false">
	<Entry entity="Customer" createIfNotFound="false">
		<Field name="MatchCode.Customer" value="CURSOR GIESSEN" />
	</Entry>
	<Entry entity="Customer" createIfNotFound="false">
		<Field name="MatchCode.Customer" value="CURSOR ENTWICKLUNG" />
	</Entry>
</Entries>

Der Aufbau der XML-Import-Struktur wird im Kapitel XML Import-Schnittstelle genauer erläutert.

Import und Export eines Webservices

Über die Schalter Importieren und Exportieren kann eine Webservice-Konfiguration als externe Datei geladen bzw. gespeichert werden.

Export

Nach dem Öffnen einer Konfiguration zeigt die Exportfunktion den Inhalt der abzuspeichernden Datei an und ermöglicht das Auswählen eines Speicherortes (siehe Abbildung: Export).

Abbildung: Export

Import

Die Importfunktion öffnet einen Dialog zur Dateiauswahl. Nach Auswahl der Datei wird die geladene Konfiguration in der Übersicht angezeigt und kann bearbeitet bzw. gespeichert werden.

Feldmapping

Es besteht die Möglichkeit, dass ein Web Service mit verschiedenen Entitäten genutzt werden kann. Um dies zu ermöglichen, müssen die Felder im Web Service-Skript auf die gleiche Weise referenziert werden. Da jedoch die einzelnen Entitäten verschiedene Feldnamen haben, muss ein gemeinsamer Zugriff auf die jeweiligen Felder realisiert werden. Dieser Vorgang kann durch das 'Feldmapping' umgesetzt werden.

Definition des Mappings

In der Aktionsleiste der Web Service-Adminkonsole befindet sich der Punkt Mapping, der einen weiteren Editor öffnet.

In diesem Editor kann für verschiedene Felder eine gemeinsamer Variablenname angegeben werden. Über die Schaltfläche   Neue Entiät   werden alle Enitäten festgelegt, die diesen Web Service nutzen sollen. Im Anschluss wird das Synonym, also der gemeinsame Variablenname, für alle Entitäten festgelegt, indem die Schaltfläche   Neues Synonym   gedrückt wird. Nach der Benennung des Synonyms kann der jeweilige Feldname in der Spalte der Entität über eine Auswahlbox festgelegt werden. Angelegte Synonyme können wieder entfernt werden. Durch einen Klick auf   Synonym entfernen   wird die momentan markierte Zeile gelöscht. In gleicher Weise wird die momentan markierte Spalte durch einen Klick auf  Entität entfernen gelöscht. Die erste Spalte mit den Synonymen kann nicht gelöscht werden. Sind keine Zeilen vorhanden wird beim Klick auf   Entität entfernen   die Spalte, die momentan als sortierende Spalte ausgewählt ist, gelöscht. Durch einen Klick auf  Abbrechen, das Drücken von ESC oder das Klicken des Schließen-Knopfes am rechten oberen Dialogrand wird das ausgewählte Mapping verworfen. OK setzt das Mapping. Gespeichert ist es jedoch erst nach dem speichern des Webservice-Dialogs. Es muss für jede Entität für jedes Synonym ein Attribut ausgewählt werden, passiert dies nicht kann der Dialog nicht mit OK bestätigt werden.

Nutzung im Web Service-Script

Anstelle des Zugriffes über binding.parameter.get("FreeText14.Activty") kann nun über binding.parameter.get("accountNumber") auf den Feldwert der Aktivitäten- bzw. der Ansprechpartnermaske zugegriffen werden.

Das folgende Beispiel zeigt die Nutzung des selben Skriptes für mehrere Entitäten.

GROOVY
def login1 = <string>
def mandator2 = <string>
def password4 = <string>
def tid3 = <string>
 
// accountNumber = "FreeText14.Activity" oder "Freenumber4.ContactPerson"
def accountNumber0 = binding.parameter.get("accountNumber")
// bankCode = "FreeText15.Activity" oder "Freenumber5.ContactPerson"
def bankCode5 = binding.parameter.get("bankCode")
 
def result = proxy.accountCheck(accountNumber0, login1, mandator2, tid3, password4, bankCode5)

Webservices im Maskenscripting

Das Maskenskripting bietet die Möglichkeit einen Webservice aufzurufen und dessen Rückgabe zu verarbeiten. Dazu muss im Maskenskript die Methode callWebService("webservice-id", [List<AttributeContainer>, HashMap<String, Object>]*) aufgerufen werden.

Aufrufparameter

"webservice-id"

Die Service-ID des Webservices

List<AttributeContainer>

Optional: Eine Liste von AttributeContainern, z. B. aus einer Suche.

HashMap<String, Object>

Optional: Eine HashMap, die eigene Werte übergibt bzw. Werte des Standard-AttributeContainers überschreibt.

Im Fehlerfall ist das Ergebnis nicht vom Typ IWebServiceResult, sondern vom Typ WebServiceExceptionType. Die genaue Aufstellung der verschieden Fehler-Arten finden Sie im Kapitel Fehler-Codes.

Webservices durch einen Externen Aufruf

Einrichtung des Externen Aufrufes

Bei dem Erstellen eines Externen Aufrufes ist als ID die WebserviceID anzugeben. Sie entspricht der ID der Webservice-Neuanlage. Zusätzlich muss der Aufruftyp Webservice angegeben werden. Es erfolgt lediglich ein asynchroner Aufruf, dessen Rückgabewert nicht ausgewertet wird.

In dem Parameterfeld des Externen Aufrufes wird der benötigte Parameter WEBSERVICEID eingetragen. Der Wert dieser Variable bestimmt sich aus der Service-ID des in der Adminkonsole eingerichteten Web-Services.

Das folgende Beispiel zeigt einen Beispielaufruf eines BLZ-Services:

WEBSERVICEID = weatherPlace

Die eigentliche Konfiguration des Webservices wird durch das Groovy-Skript in der Admin-Konsole bestimmt, dem der AttributeContainer zur Verfügung steht.

Sobald eine Aktivität geöffnet ist, wird der zuvor eingerichtete Externe Aufruf angeboten.

FAQ

Fehlermeldungen und mögliche Fehlerursache

Fehlermeldung

Ursache

Problembehebung

The Element "HTML" does not contain a namespace.

Die Gegenstelle liefert als Ergebnis eine Meldung, die in ungültigem XHTML verfasst ist - meist eine Meldung des Proxys.

Prüfen Sie die Proxyeinstellungen auf ihre Gültigkeit.

Absturz des Applikationsserver beim Drücken des Test-Buttons mit der Exception: ERROR [de.cursor.jevi.server.web.WebServiceController] : de.cursor.exception.WebServiceException : java.net.ConnectException: connection refused: connect

Kein Zugriff auf den Webservice. Wahrscheinlich wurde der Proxy nicht definiert.

Prüfen Sie die Proxyeinstellungen in den Systemeinstellungen. Enthält das Konfigurations-Skript den Aufruf setProxySettings()?

Antwort beim Drücken des Test-Buttons: null - org.jboss.remoting.serialization.ClassLoaderUtility.loadClass(ClassLoaderUtility.java:103)

Kein Zugriff auf den Webservice. Wahrscheinlich wurde der Proxy nicht definiert.

Prüfen Sie die Proxyeinstellungen in den Systemeinstellungen. Enthält das Konfigurations-Skript den Aufruf setProxySettings()?

Antwort beim Drücken des Test-Buttons: java.net.ConnectException: Connection refused: connect

Kein Zugriff auf den Webservice. Wahrscheinlich wurde der Proxy nicht definiert.

Prüfen Sie die Proxyeinstellungen in den Benutzereinstellungen. Enthält das Konfigurations-Skript den Aufruf setProxySettings()?

Antwort beim Drücken des Test-Buttons: javax.script.ScriptException: groovyx.net.ws.exceptions.InvokeException: org.apache.cxf.binding.soap.SoapFault: Error writing to XMLStreamWriter.

groovyx.net.ws.exceptions.InvokeException: org.apache.cxf.binding.soap.SoapFault: Error writing to XMLStreamWriter.

Kein Zugriff auf den Webservice. Wahrscheinlich wurde der Proxy nicht definiert.

Prüfen Sie die Proxyeinstellungen in den Benutzereinstellungen. Enthält das Konfigurations-Skript den Aufruf setProxySettings()?

  • java.lang.UnsupportedOperationException: setProperty must be overridden by all subclasses of SOAPMessage

  • java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: com.ctc.wstx.io.WstxInputLocation

  • org.apache.cxf.binding.soap.SoapFault: Error reading XMLStreamReader. javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,1] Message: Premature end of file.

Eine benötigte Bibliothek wurde nicht geladen. Falls der Applikationsserver als Dienst eingerichtet ist, fehlt ein Eintrag in der Datei Wrapper.conf.

Fügen Sie die Zeile wrapper.java.additional.<#>=-Djava.endorsed.dirs=<JBoss-Pfad>\lib\endorsed hinzu und starten Sie den Dienst neu.

Unable to create JAXBContext for generated packages: "net.java.dev.jaxb.array" doesnt contain ObjectFactory.class or jaxb.index

Die generierten Parameter-Klassen können nicht geladen werden.

Bitte prüfen Sie die Log-Ausgaben, ob sie eine Fehlermeldung des Compilers enthalten. Das temporäre Benutzer-Verzeichnis scheint nicht zugänglich zu sein.

org.apache.cxf.interceptor.Fault: Found element {xxx}getxxxReturn but could not find matching RPC/Literal part

Die Definition der WSDL ist nicht WS-I compliant (RPC/encoded, Document/encoded anstelle von RPC/literal oder Document/literal).

Die WSDL muss gegen eine nach dem WS-I Web Service-Standard gültige Version ersetzt werden.

Cannot cast object 'abc' with class 'java.lang.String' to class 'javax.xml.bind.JAXBElement'

Die Definition dieses Elementes hat das Attribute notNillable="true".

  • Ändern Sie das Schema innerhalb der WSDL und entfernen Sie das Attribut. Stellen Sie sicher, dass dieses Attribut einen Wert zugewiesen bekommt.

oder

  • Erstellen Sie im Aufruf-Skript ein Objekt des Types JAXBElement und weisen Sie diesem Objekt den Wert zu.

org.apache.cxf.interceptor.Fault: Marshalling Error: Instance of "com.example.Class01" is substituting "com.example.Class02", but "com.example.Class01" is bound to an anonymous type.

oder

Interceptor for {com.example}Class01 has thrown exception, unwinding now java.lang.IllegalArgumentException: Part {com.example}Class01 should be of type com.example.Class02 , not com.example.Class01

oder

Part {urn:com.example}request should be of type com.example.Class01Request, not com.example.Class01

Der Aufruf der Web Service-Methode nutzt den Stil "unwrapped", d. h. die Parameter werden einzeln erwartet.

  • Schreiben Sie den Aufruf um, indem Sie die Parameter einzeln übergeben.

Bsp: Aus def result = proxy.getMyValue(parameter01) wird def result = proxy.getMyValue(parameter01.member01, parameter01.member02).

  • (Ab 11.1) Setzen Sie den Aufruf forceWrappedOperation(boolean value) im Konfigurationsskript.

javax.script.ScriptException: groovyx.net.ws.exceptions.InvokeException: java.lang.RuntimeException: Can't find input stream in message

groovyx.net.ws.exceptions.InvokeException: java.lang.RuntimeException: Can't find input stream in message

Die Anmeldedaten können falsch sein.

Korrigieren Sie die Anmeldedaten.

<body><h1>HTTP Status 401 - </h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u></u></p><p><b>description</b> <u>This request requires HTTP authentication ().</u></p><HR size="1" noshade="noshade"><h3>JBoss Web/3.0.0-CR2</h3></body>

Die Anmeldedaten können falsch sein.

Korrigieren Sie die Anmeldedaten.

java.lang.RuntimeException: java.lang.reflect.InvocationTargetException: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)

Der Web Service wird über https aufgerufen und die Zertifizierungsstelle des Zertifikates ist Java nicht bekannt.

Hinterlegen Sie das Zertifikat inkl. gültiger Verifizierungskette (Chain of Trust) im Keystore der Java Runtime des Clients bzw. im Keystore des Servers.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.