Skip to main content
Skip table of contents

Outgoing web services

Compatibility check

Whether or not a web service can be utilized depends on external conditions that CURSOR Software AG has no influence over. The following are some of the conditions that must be met:

  • The so-called WSDL file must be available. The provider usually announces a URL via which CURSOR-CRM can access the WSDL file.

  • The internal structure of the WSDL file must comply with the standard WS-I Basic Profile 1.1 and use the type document/literal for its parameter description. If the file is not WS-I compliant, then CURSOR-CRM will not be able to contact th web service.

    • A mere statement of the web service provider or a superficial visual check of the WSDL file will not suffice. The free program SoapUI can verify compliance with the WS-I Basic Profile standard and generate an audit report. The only formal check here is whether the WSDL is valid. There may still be discrepancies in the invocation or return parameters.

  • Where imports are defined by schema files within a WSDL with relative paths, then problems can arise during the execution or the provision of web services. A manual verification will be required if the web service can be created with this WSDL and whether the actual service/method is affected by the import instructions. It may very well be that the service does not depend on the import. Generally speaking, an import with relative information is a hindrance.

  • CURSOR-CRM supports Basic Authentication and as of version 12.2 also WS Security login using the user name token.

  • The application server or Rich Client must be able to access the web service. That usually occurs via the protocols http or https. This may fail due to general limitations of internet access. It may be necessary to add relevant SSL certificates on client or server side.

The points mentioned above should be checked before any actual implementation is done.

The environment for the web service invocation

Client or server

A web service is called either

  • in the client or

  • in the application server, which is standard.

The call is controlled via the user preferences or the system preferences

  • Invoking integration/web services directly in the application

If the configuration is done in the user or system preferences, the web service invocations will be done in the client.

Proxy

A proxy must be defined if one is needed to establish an internet connection, since the invocation is done via the internet. Depending on where the invocation originates - in the client or the server - the definition of the proxy must be done elsewhere.

Proxy for invocations in the client

  • User settings/network settings

Proxy for invocations in the server

  • System settings/network settings application server


Web services in the administration console

The menu item Web Services in the admin console offers options for the setup, maintenance, testing, and the import/export of a web service. The available options are described in the following chapters.

Figure: Web services in the administration console

Creating a new web service

Click on the

New button to start the setup wizard.

Figure: Selecting the WSDL file

  • The notation of the service ID is checked for validity. It must begin with a capital letter, can only contain letters, numbers and underscores and must be unique.

  • The address of the WSDL file must be accessible at the time of creation. The dialog will not continue if e.g. the internet address cannot be resolved.

When both bits of information are available, then the user must start the verification by clicking Test availability. This check will decide based on the criteria above, whether the wizard can continue. If that is the case, the button Continue is activated.

Hint

During the creation, the system can refer to a local copy or to an original URL of the WSDL. In case of the former, a copy of the WSDL will be saved in the database and used for all further operations. If the original URL is stated, then it will be imported again for each new invocation. If the first approach is used and the content of the WSDL changes, then the web service must be set up again.

The second approach has the advantage that any changes to the web service will be taken into consideration right away. This web service property can be viewed in the admin console behind the field 'Web service address', whereby 'DB' stands for a local copy in the database and 'REMOTE' stands for the provision of a URL.

Figure: Selecting the function


The web service can be defined in more detail in the next step. Select the service, the related connection types (ports) and the relevant function. The selection fields will be updated automatically in line with the available options (see figure: Selecting the function)

Clicking Finished will show the web service settings in the overview. Necessary changes can be made here before the web service is added to the system by clicking Save.

Figure: Overview

Editable WSDL address field in the admin console

Up to version 11.2, only the actual script of the invocation was editable in the admin console after a new creation. Any previously entered properties, e.g. the address of the WSDL could not be edited. The service had to be exported to change the address and then imported again if the WSDL location had changed. This change can now be done directly in the admin console.

This function is only available if the web service type has the value REMOTE.

Testing a web service

Click the button

Test to try out a newly created web service.

Clicking Test will execute the web service and the result will be shown in a dialog afterwards.

Important here is that binding parameters will not be evaluated in a test, because we will be doing the test in the context of a dataset.

The binding parameters refer to values originating from the mask (mask field or mask script variables). See below under "Call scripts" and in the subsequent text.

An example first:
binding.parameter.get("CITY")
refers to the following mask script line (the mask script variable s_city contains the name of a city here):
parameterMap.put("CITY", s_city),
This is followed by the Web service call in the mask script:
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)

Generating parameters

When creating a web service script, the method names and parameter names must be entered exactly as they were defined in the WSDL. A script framework will be provided for the new creation of a web service to offer help with the configuration.

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)

All parameters of the method invocation are stated in the order in which they are defined in the signature. Furthermore, a placeholder is inserted for primitive types, which indicates the exact type (e.g. string, float, etc.). If the parameter represents a complex type, then the invocation for creating an object will be additionally generated.

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

Remark on the verification and listing of the parameters

The Java files generated from the WSDL will be saved in a temporary directory as soon as the web service is initiated with the user or system option Execute in application active to simplify script creation. These can then be used to help with data types and structures. The relevant sections in the WSDL are stated in the prefix of these files.

Temporary directory: C:\Documents and settings\<user>\CARMEN\<server>\tmp\jaxb\

Invocation scripts

A script for the configuration of a web service or its invocation can be written in the admin console. The script is written in the script language Groovy with a syntax that is very similar to Java.

The prefix and postfix (e.g. the import, the instantiation of the variables or the processing of the result) are automatically inserted in the script. The proxy object via which the configuration and the invocation will be implemented, will also be initialized.

Available commands of the proxy object

setBasicAuthentication>(String username, String password)

Explicitly sets the login information for the HTTP basic authentication. The login information provided in the console would usually be implicitly set.

create(String qualifiedClassname)

Creates an object of the specified class, which is described in the associated WSDL. The fully qualified name (package name + class name) must be stated.

webserviceMethod(...)

The actual invocation of the web service. The method name matches the name selected during setup. The return value of the call varies depending on the service. The return value of the variable binding.result must be assigned to guarantee unified processing.

only available on the client side)
addHeader(String elementNamespace, String elementName, Object headerElement)

Adds a header element to the SOAP request. The header object must be created first and its name and namespace must also be stated.

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

The values "elementNamespace" and "elementName" must come from the WSDL (see <soap:header> definition).

Values from the mask or custom values (e.g. originating from the mask script) can be used before the actual invocation. A binding object is provided for that purpose.

Available fields of the binding object

binding.classLoader

Internal variable.

binding.parameter or parameter

Access to the set parameters. Usually a HashMap <String, Object>, which contains the values of the AttributeContainers and/or values of the user-defined HashMap.

binding.parameter.list or parameter.list

Access to any set list of AttributeContainers. For example the result of a search.

binding.result or result

The object to which the result must be assigned to allow later processing.

Examples

As mentioned above, all groovy instructions can be used in the invocation script.

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")

Assist methods

Methods for easier export of special data fields in the mask or to provide advanced functionalities are offered in the invocation script.

Method

Description

timestampToXMLGregorianDate(Timestamp time)

Converts a date field in the mask to the correct date format of a web service

getLookupKey(LookupVO vo)

Gets key value of lookup field.

getLookupDescription(LookupVO vo)

Gets description of lookup field.

getLookupPk(LookupVO vo)

Gets primary key of lookup field.

debug(String message) and error(String message)

Outputs information from the log directory of the client in a separate file. Includes the log level of the internal logger.

In text form:

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

The variable name "w" must not be used, because it is used internally.

Hint

Auto complete for methods and constants is provided in the two script editors 'configuration script' and 'invocation script'. The method and constants lookup is done via the shortcut CTRL+SPACE BAR.

Configuration script

The configuration of a web service includes the option to enter a configuration independent of the actual invocation script. Like in the invocation script, various invocations can be entered in the field 'Configuration script'. The global proxy settings and other information must be saved in the application to set up a web service or to invoke other actions (e.g. show WSDL).

Method

From

Until

Description

setBasicAuthentication(String user, String password)

12.2


Sets the login information when using HTTP BASIC Authentication.

enableLoginViaCurrentUser(boolean value)

10.1


This invocation, which configures a login with the current user can be used when CURSOR-specific web services are invoked.

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

12.2


Sets the WS security username token.

setProxySettings(String host, String port)

10.2

18.2

Sets the host and port input for the proxy. Is overwritten by the system setting.

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

10.2

18.2

Sets the host and proxy input, as well as the user and password. Is overwritten by the system setting.

forceWrappedOperation(boolean value)

11.1


Forces a wrapped call of the method so the call parameters can be passed as a whole.

enableExtendedLogging()

12.2


Activates extended logging of the SOAP request/response messages. This is helpful for viewing the generated and received data (e.g. in case of SSL encryption).

  • For execution in the Rich Client: The information is output on the console and will not be written to the web service log file.

  • For server execution: The information is output on the console or in the server log and will not be written to the web service log file.

Result types

The following are examples for result types from a WSDL and how the result can be accessed via mask script. Lists and arrays are converted to HashMaps, which means that get(0) can be used to access the first element and get(1) to access the second, etc. Should the web service return only a simple data type, then this will also be packed into a HashMap under the key result. It can then be read via result.get("result").

Example 1

The result type GetWeatherByPlaceNameResponse is defined in this WSDL section. It contains a complex type WeatherForecasts, which in turn contains a number of simple values and an array of WeatherData elements.

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>

The result would therefore have the following structure:

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

To access latitude , result.get("latitude") must be called to get the value 47.611435. result.get("details").get("weatherData").get(0).get("maxTemperatureF") would return 56.

Example 2

This WSDL file defines the return type GetSupplierByCityResponse, which contains a Boolean GetSupplierByCityResult and a list SupplierDataLists.

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>

An invocation would return the following structure:

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}
		}
	}
}

result.get(0) can be used to query GetSupplierByCityResult, in this case true. get(1).get("supplierDatas").get("supplierData").get(1).get("description")" returns (212)982-7850.

Error codes

Errors occurring during processing are differentiated as follows:

CONFIG

Error while loading the web service configuration, e.g. wrong ID

SCRIPT

Invalid web service script

FAULT

A SOAP Fault message, i.e. the web service reports an exception

AUTH

Authentication isn't working, i.e. is incorrectly configured

SSL

The SSL configuration is incorrect

REMOTE

Unable to connect to the web service

NONE

An unspecified error

The exact cause of the error is written to the client or server log.

Invocation examples

Example 1

In our first example, we want to install a simple service invocation, which finds the bank connected to a sort code. The relevant WSDL is:

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

First, we will try to invoke the service via the button Test. Proceed as follows:

  • Start the admin console - menu item Miscellaneous/Web services

  • Click New to create a new web service invocation

  • Add a unique name starting with an uppercase letter, e.g. GetBank

  • Add the URL of the WSDL file

  • Click Test availability. The button 'Continue' will be activated if the web service is available. Test the notation of the URL by entering it into the browser if you have problems here. The result should be the output of the WSDL definition. If not, then check whether the proxy in the user preferences is set correctly.

  • Click Continue

  • Select the service name BLZService, the port name BLZServiceSOAP12port_http and the method name getBank

  • Click Done. The data is applied to the main template and an invocation script is generated.

  • Should a proxy be used for internet access, then the proxy will also have to be defined in the configuration script: setProxySettings("proxy", "8080").

  • The generated invocation script is incorrect and the invocation of binding.parameter.get() doesn't work via the Test button. We will now change it, so that the parameter is given with it as a constant: def result = proxy.getBank("50010517")

  • Click Save to save the web service invocation

  • Click Test. The result should now be {name=ING-DiBa, city=Frankfurt am Main, zip=60628, bic=INGDDEFFXXX} - i.e. the bank connected to the sort code 50010517

Example 2

Using the procedure described above, the web service RiskCode is created, whose method GetLloydsRiskCodeDetailByRiskCode is to be invoked. Should a user name and password be required, then these can be input into the mask or added later in the script via setBasicAuthentication(String username, String password).

Figure: Configuring the web service RiskCode

The correct script could look something like this:

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

The script specifies that the result must be saved to the variable result, as it will be used internally again at a later stage.

The object proxy is provided and the desired methods must be invoked in it. This object is made available internally by adding the following line to the code:

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

The method GetLloydsRiskCodeDetailByRiskCode selected here expects the string parameter RiskCode, which in this case will be set to 3. In this case, the result returned by the method call is written to result. binding is a provided object like proxy. The result to be used later must be written to binding.result. A result consolidation is done internally via the following invocation:

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

The script actually invoked will therefore look like this:

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)

As you can see in the WSDL section of the web services below, the complex type GetLloydsRiskCodeDetailByRiskCodeResponse is returned, which in this case is in result. This complex type contains another complex type ArrayOfRiskCode, which can be accessed via result.get("riskCode"). This ArrayOfRiskCode is an array, whose RiskCode elements can be called via get(0) ... get(x). And finally, these RiskCode elements contain string objects with values. These string objects are read via get("IhrName").

In the above mask script example, the GetLloydsRiskCodeDetailByRiskCodeResponse object is returned first, then the first RiskCode is taken from the array and its value firstYearOfAccount output. The value riskCodeDescription is written to the mask field Freitext 1.

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>

Example 3

Another web service "WeatherForecast" is set up using the following configuration:

"GetWeatherByPlaceName" expects a string containing the name of a city. In this example, the city in the text field "Freetext 1" of the activity should be used. The following script code is needed:

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

All mask fields from which the web service was invoked are contained in "binding.parameter". The content of the relevant field can be requested via "get("theNameOfTheField")". This content is saved in "PlaceName" and forwarded to the method "GetWeatherByPlaceName".

The web service that was just created would be called with this mask script:

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

Example - Searches in CURSOR-CRM

The JBoss WSDL can be found via the following URL

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

Alternatively, the file can be loaded in the file system

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

For this example, we will invoke the function search and forward the XML structure of a search.

The actual search or a search template can be exported from the application.

The search is conducted based on the rights of the user of the web service. The token must be provided in uppercase letters and the hash value from the database will be needed as password.

The XML search must be forwarded as a parameter in the groovy script.

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>"""

The $ character is a protected character of the groovy script language. It must be replaced with \$. A parameter across several lines must be specified with 3 quotation marks.

The method search must be invoked on the proxy. The result will be assigned to the defined variable result.

GROOVY
def result = proxy.search(xmlSearch)

The WSDL file provides information about which parameter the method needs and what the type of the return value is.

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

The following mask script can be used for invoking the mask script:

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

In our example, the result has the following structure and content:

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>

The appearance of the XML import structure is discussed in more detail in chapter XML interface.

Import and Export of a web service

A web service configuration can be loaded or saved as an external file via the buttons Import and Export.

Export

When a configuration is opened, the export function displays the content of the file to be saved and allows the selection of a storage location (see Figure: Export).

Figure: Export

Import

The import function opens a file selection dialog. After the file is selected, the overview displays the loaded configuration, which can then be edited or saved.

Field mapping

A web service can optionally be used with various entities. The fields in the web service script must be referenced identically to allow that. However, a common access to the relevant fields must be implemented, because individual entities will have different field names. This is done via 'field mapping'.

Definition of mapping

The taskbar of the web service admin console contains the item Mapping, which opens another editor.

A common variable name can be provided in this editor for various fields. All entities that are to use this web service are specified via the button New entity. As a next step, a synonym, i.e. the common variable name, is defined for all entities by clicking the button New synonym. Once the synonym is specified, you can then specify the actual field name in the entity column via a selection box. New synonyms can also be removed. Clicking Remove synonym will delete the currently selected row. The currently selected column can be deleted the same way by clicking Remove entity. The first column containing the synonyms cannot be deleted. Should a column not contain any rows then clicking Remove entity will delete the column currently selected for sorting. Clicking Cancel, ESC or the 'Close' button at the top right edge of the dialog will discard the selected mapping. OK applies the mapping. However, it will only be saved after the web service dialog is saved. An attribute must be selected for each entity and synonym, as otherwise the dialog cannot be confirmed with OK.

Use in the web service script

Instead of accessing the field value of the activity or contact person mask via binding.parameter.get("FreeText14.Activty") it can now be accessed via binding.parameter.get("accountNumber").

The following example shows how the same script can be used for multiple entities.

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)

Web services in mask scripting

Mask scripting offer the opportunity to invoke a web service and process its return. The method callWebService("webservice-id", [List<AttributeContainer>, HashMap<String, Object>]*) must be invoked in the mask script.

Call parameter

"webservice-id"

The service ID of the web service

List<AttributeContainer>

Optional: A list of AttributeContainers from e.g. a search.

HashMap<String, Object>

Optional: A HashMap that forwards own values, e.g. that overwrites values of the default AttributeContainer.

Should an error occur, then the result will not be type IWebServiceResult but type WebServiceExceptionType. A complete list of error types can be found in the chapter Error codes.

Web services via external invocation

Setup of the external call

The WebserviceID must be provided as ID when creating an external call. It matches the ID of the newly created web service. The invocation type Webservice must be additionally stated. The result is an asynchronous invocation, the return value of which will not be evaluated.

The required parameter WEBSERVICEID is entered into the parameter field of the external invocation. The value of this variable is gleaned from the service ID of the web service configured in the admin console.

The following example shows the invocation of a sort code service:

WEBSERVICEID = weatherPlace

The actual web service configuration is determined by the groovy script in the admin console, which can access the AttributeContainer.

The previously configured invocation is offered for execution when an activity is opened.

FAQ

Error messages and possible causes

Exception

Cause

Troubleshooting

The Element "HTML" does not contain a namespace.

The remote station delivers a message as its result, which is composed in an invalid XHTML - most likely a proxy message.

Check the validity of the proxy settings.

The application server crashes when the button 'Test' is activated, resulting in the exception: ERROR [de.cursor.jevi.server.web.WebServiceController] : de.cursor.exception.WebServiceException : java.net.ConnectException: connection refused: connect

No access to the web service. The proxy was likely not defined.

Check the proxy settings in the system preferences. Does the configuration setting contain the invocation setProxySettings()?

Response to the activation of the 'Test' button: null - org.jboss.remoting.serialization.ClassLoaderUtility.loadClass(ClassLoaderUtility.java:103)

No access to the web service. The proxy was likely not defined.

Check the proxy settings in the system preferences. Does the configuration setting contain the invocation setProxySettings()?

Response to the activation of the 'Test' button: java.net.ConnectException: Connection refused: connect

No access to the web service. The proxy was likely not defined.

Check the proxy settings in the system preferences. Does the configuration setting contain the invocation setProxySettings()?

Response to the activation of the 'Test' button: 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.

No access to the web service. The proxy was likely not defined.

Check the proxy settings in the system preferences. Does the configuration setting contain the invocation 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.

A required library did not load. An entry is missing in the file Wrapper.conf if the application server is set up as service.

Add the line wrapper.java.additional.<#>=-Djava.endorsed.dirs=<JBoss path>\lib\endorsed and restart the service.

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

The generated parameter classes could not be loaded.

Please check the log output to see if it contains an error message from the compiler. The temporary user directory seems inaccessible.

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

The WSDL definition is not WS-I compliant (RPC/encoded, Document/encoded instead of RPC/literal or Document/literal).

The WSDL must be replaced with a version compliant with the WS-I web service standard.

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

The definition of this element has the attribute notNillable="true".

  • Change the schema within WSDL and remove the attribute. Make sure that the attribute is assigned a value.

or

  • Create an object of type JAXBElement in the invocation script and assign a value to this object.

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.

or

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

or

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

The invocation of the web server method uses the style "unwrapped", i.e. the parameters are expected individually.

  • Rewrite the invocation to forward the parameters individually.

Example: def result = proxy.getMyValue(parameter01) becomes def result = proxy.getMyValue(parameter01.member01, parameter01.member02).

  • (From 11.1) Set the invocation forceWrappedOperation(boolean value) in the configuration script.

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

The login data may be incorrect.

Correct the input.

<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>

The login data may be incorrect.

Correct the input.

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)

The web service is invoked via https and the certification body of the certificate is unknown to Java.

Add the certificate including a valid certification chain (chain of trust) to the Java runtime keystore of the client or to the server keystore.

JavaScript errors detected

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

If this problem persists, please contact our support.