Creating Web Clients
A web client is software that accesses a web service. A web client provides a set of proxy methods, each of which corresponds to a method of the web service. A proxy method uses the same signature as the web service method to which it corresponds, and it invokes the web service method when asked to do so. This chapter describes how to create and use web clients in Caché:
For information on logging SOAP calls to your Caché web clients, see “Caché SOAP Log,” later in this book.
For a Caché web service, the automatically generated WSDL might not include information about the SOAP header elements:
-
If you add SOAP headers manually by setting the HeadersOut property, be sure to follow the instructions in “Specifying Supported Header Elements,” in the chapter “Adding and Using Custom Header Elements.” If you do, the WSDL contains all the applicable information. Otherwise, it does not, and you must save the WSDL to a file and edit it manually as needed.
-
If you add WS-Security header elements by setting the SecurityOut property (as described in Securing Caché Web Services), the WSDL does not include all needed information. (This is because the WSDL is generated at compile time and the headers are added later, at runtime.) In this case, save the WSDL to a file and edit it manually as needed.
For many reasons, it is simpler and easier to add WS-Security elements by using WS-Policy, as described in the same book. With WS-Policy, the generated WSDL includes all needed information.
-
In other cases, the generated WSDL includes all needed information.
Note that the W3C specifications do not require a web service to provide a generated WSDL.
Overview of the SOAP Wizard
To create a Caché web client, you can use the SOAP Wizard in Studio or the corresponding class method provided by Caché. In either case, the input is a WSDL document. The tools generate a web client class and all needed supporting classes.
You can use the tool with nearly any WSDL document; see “WSDL Support in Caché” in the first chapter.
You can provide either the URL or the file path for the WSDL.
If the WSDL indicates support for both SOAP 1.1 and SOAP 1.2, then the SOAP Wizard generates two sets of classes, if needed.
Using the SOAP Wizard
Studio provides the SOAP Wizard, which enables you to generate a client for a given web service, given the WSDL of that service.
When using templates such as the SOAP Wizard, Studio will use a proxy server, if it is enabled. For information on specifying the proxy server and port, see “Using a Proxy Server” in Using Caché Internet Utilities.
To use the SOAP wizard:
-
Examine the WSDL and check for the following items:
-
Do the <message> elements contain multiple parts?
-
Do the types used by the response messages belong to multiple namespaces?
In either case, if the answer is yes, then you will need to select the option Use unwrapped message format for document style web methods, which is described in a later step.
-
-
Click Tools > Add-ins > SOAP Wizard.
-
On the first screen:
-
Click either URL or FILE, depending on the location of the WSDL.
-
Enter the location of the WSDL. Type either the entire URL or the complete path and filename for the WSDL.
-
If the WSDL is at a location that uses SSL (that is, if the URL starts with https), then select a suitable SSL configuration from the SSL Configuration dropdown list. For information on creating and managing SSL/TLS configurations, see the chapter “Using SSL/TLS with Caché” in the Caché Security Administration Guide.
Important:This wizard specifies an SSL configuration to use when accessing the WSDL. This field is not used in any other way.
-
If the WSDL is at a location that uses SSL, the wizard will (by default) checks whether the certificate server name matches the DNS name used to connect to the server. If these names do not match, the connection is not permitted. This default behavior prevents “man in the middle” attacks and is described in RFC 2818Opens in a new tab, section 3.1; also see RFC 2595Opens in a new tab, section 2.4.
To disable this check, clear the check box When making an SSL connection check that the server identity in the server certificate matches the name of the system being connected to.
-
-
Click Next.
The wizard then attempts to access the WSDL and display it so that you can verify that you have chosen the correct one.
If the wizard cannot access the WSDL, it displays a screen that displays the error and provides options that you can use to provide a username and password. (Many WSDLs are at URLs that are protected by a username and password, and this is a common reason for failing to access the WSDL.) In this scenario, first do one of the following:
-
To provide a Caché username and password, select CACHÉ user name and password
-
To provide a username and password for HTTP Basic authentication, select HTTP authentication user name and password
Then enter values in the Username and Username fields and press Try Again. Note that the wizard does not save your entries for these items.
-
-
On the screen that displays the WSDL, specify options as follows:
-
Create Client for Web Service — Select this if you want the wizard to generate web client classes.
-
Create Web Service — Select this if you want the wizard to generate web service classes.
-
Compile generated classes — Select this if you want the wizard to compile the classes after generating them.
-
Compile flags — Specify flags to control how the compiler behaves. To get information about the compiler flags, execute the following command:
Do $System.OBJ.ShowFlags()
-
Class Type — Choose a type to use for the generated type classes:
-
Persistent — The type classes should inherit from %PersistentOpens in a new tab. Any collections should be defined as lists.
-
Persistent using one-many relationships — The type classes should inherit from %PersistentOpens in a new tab and any collection properties should be defined as one-to-many relationships.
-
Persistent using indexed one-many relationships — The same as the preceding item except that Caché also defines an index for the relationship.
-
Persistent using parent-child for relationships — The type classes should inherit from %PersistentOpens in a new tab and any collection properties should be defined as parent-child relationships.
-
Serial — The type classes should inherit from %SerialObjectOpens in a new tab.
-
Registered — The type classes should inherit from %RegisteredObjectOpens in a new tab.
-
-
Add %OnDelete method to classes in order to cascade deletes — This option is displayed if you choose any persistent class type. If you select this option, when the wizard generates class definitions, it includes an implementation of the %OnDelete() callback method. The generated %OnDelete() method deletes all persistent objects that are referenced by the class.
Note:Do not use this option if you select Persistent using parent-child for relationships.
If you modify the generated classes, be sure to modify the %OnDelete() callback method as needed.
-
Proxy Class Package — Type a package name for the web client. This is also used as the base package for any generated type classes. The default package name is the service name.
If this package is the same as an existing package, by default the tool overwrites any existing classes that have the same name.
-
-
If you have an Ensemble installation, optionally provide values for the following additional fields:
-
Create Business Operation — Select this to generate an Ensemble business operation and related request and response message classes.
-
Business Operation Package — Specify the package for the business operation class.
-
Request Package — Specify the package for the request message class.
-
Response Package — Specify the package for the response message class.
For information on Ensemble, see the Ensemble documentation.
-
-
Click Next. The wizard then displays a screen like the following:
-
Specify the following options:
-
Add NAMESPACE class parameter, which affects how generated type classes are assigned to namespaces:
-
If the WSDL explicitly indicates the namespace to which a given type belongs, Add NAMESPACE Class Parameter is selected and grayed out. In this case, the generated type class will include the NAMESPACE class parameter set equal to that namespace.
-
If the WSDL does not indicate the namespace for a given type, you can select or clear Add NAMESPACE Class Parameter.
If you select this option, the generated type class will include the NAMESPACE class parameter set equal to the namespace of the web service.
If you clear this option, the generated type class will not include the NAMESPACE class parameter.
-
-
Use unwrapped message format for document style web methods, which affects the signature of the methods in the generated web client. See the appendix “Details of the Generated Classes” and see “Using Caché Web Client Classes,” later in this chapter.
Important:If the WSDL that you are using contains <message> elements with multiple parts, be sure to select this option. If you do not, the wizard fails and displays a message like the following:
ERROR #6425: Element 'wsdl:binding:operation:msg:input' - message 'AddSoapOut' Message Style must be used for document style message with 2 or more parts.
Similarly, if the types used by the response messages are in different namespaces than each other, be sure to select this option.
This option affects only methods that have SoapBindingStyle equal to "document".
-
Do not create array properties, which controls whether the wizard generates array properties. If you select this option, the wizard does not generate array properties but instead generates another form. See “Creation of Array Properties” in the appendix “Details of the Generated Classes.”
-
Generate XMLNIL property parameter for nillable elements, which controls whether the wizard specifies the XMLNIL property parameter for applicable properties in the generated classes.
This option applies to each property that corresponds to an XML element that is specified with nillable="true". If you select this option, the wizard adds XMLNIL=1 to the property definition. Otherwise, it does not add this parameter.
For details on this property parameter, see “Handling Empty Strings and Null Values” in Projecting Objects to XML.
-
Generate XMLNILNOOBJECT property parameter for nillable elements, which controls whether the wizard specifies the XMLNILNOOBJECT property parameter for applicable properties in the generated classes.
This option applies to each property that corresponds to an XML element that is specified with nillable="true". If you select this option, the wizard adds XMLNILNOOBJECT=1 to the property definition. Otherwise, it does not add this parameter. For details on this parameter, see “Handling Empty Strings and Null Values” in Projecting Objects to XML.
-
Set XMLSEQUENCE parameter to 0, which controls how the wizard sets the XMLSEQUENCE class parameter in the generated classes.
By default, the wizard sets this parameter to 1 in the generated classes, which ensures that the classes respect the order of elements as given in the schema in the WSDL; this value is useful when the schema has multiple elements of the same name within a given parent. For details, see “Handling a Document with Multiple Tags with the Same Name” in Projecting Objects to XML.
-
Generate XMLIGNORENULL parameter set to 1, which controls whether the wizard specifies the XMLIGNORENULL class parameter in the generated classes. If you select this option, the wizard adds XMLIGNORENULL=1 to the class definitions, including the generated web client (or web service). Otherwise, it does not add this parameter.
For details on this class parameter, see “Handling Empty Strings and Null Values” in Projecting Objects to XML.
-
Use Streams for Binary, which controls how the wizard handles any element of type xsd:base64Binary. If you select this option, the corresponding property is of type %Stream.GlobalBinaryOpens in a new tab. If this option is clear, the property is of type %xsd.base64BinaryOpens in a new tab instead.
Note that the wizard ignores any attributes of type xsd:base64Binary.
-
Specify SECURITYIN class parameter, which controls the class parameter SECURITYIN in the generated client class. If you are using Web-Services security, use REQUIRE or ALLOW, depending on whether you want the client to require the elements or simply validate them. Otherwise, IGNORE or IGNOREALL is generally suitable. For details, see “Validating WS-Security Headers” in Securing Caché Web Services.
Important:The SECURITYIN parameter is ignored if there is a security policy in an associated (and compiled) configuration class. See Securing Caché Web Services.
-
-
Optionally edit the package names. The wizard uses the following rules for package names:
-
The packages specified in Web Client Package or Web Service Package contain the main generated web client or web service class. These values are initialized by your entry in the previous page of the wizard.
-
If the wizard generates a policy class as well (because the WSDL contains WS-Policy information), that class is in the same package by default. To specify a different package, specify a value for Configuration Sub-Package.
By default, the class name is the web client or service name, with Config appended to it. If you specify a value for Configuration Sub-Package, then this generated class has the same name as the web client or service (but is in the given subpackage instead).
For information on WS-Policy, see Securing Caché Web Services.
-
For any supporting classes that are generated, the wizard detects all the namespaces used in the WSDL. By default, it organizes the generated classes into packages, with one package for each namespace.
Optionally edit these package names.
Not all namespaces necessarily correspond to generated classes. For example, the WSDL used in this example uses the namespaces http://schemas.xmlsoap.org/wsdl, http://schemas.xmlsoap.org/wsdl/mime, and http://schemas.xmlsoap.org/wsdl/soap. No generated classes are in these namespaces in this case, and the corresponding packages are not generated.
-
-
Click Next. The wizard generates and compiles the classes and displays a list of these classes.
-
Click Finish.
If you use a WSDL URL and there are problems with the wizard, save the WSDL as a file and try again, using that file as input.
If the WSDL contains references to externally defined entities, the wizard attempts to resolve those; for this task, the timeout period is 10 seconds.
For properties of these classes, if the corresponding element in the schema has a name that starts with an underscore (_), the name of the property starts with a percent sign (%).
Generating the Client Classes Programmatically
You can instead generate the client classes programmatically by using the %SOAP.WSDL.ReaderOpens in a new tab class.
The resulting generated classes and their organization may not be the same as if you used the SOAP wizard, which provides greater control over the packages for the generated classes.
To generate the client classes programmatically:
-
Create an instance of %SOAP.WSDL.ReaderOpens in a new tab.
-
Optionally set properties to control the behavior of your instance. For details, see the class documentation for %SOAP.WSDL.ReaderOpens in a new tab.
Note that if the WSDL is at a location that uses SSL, %SOAP.WSDL.ReaderOpens in a new tab (by default) checks whether the certificate server name matches the DNS name used to connect to the server. If these names do not match, the connection is not permitted. This default behavior prevents “man in the middle” attacks and is described in RFC 2818Opens in a new tab, section 3.1; also see RFC 2595Opens in a new tab, section 2.4.
To disable this check, set the SSLCheckServerIdentity property of the instance equal to 0.
-
If you need the ability to control the HTTP request in a way that is not directly supported by %SOAP.WSDL.ReaderOpens in a new tab, do this:
-
Create an instance of %Net.HttpRequestOpens in a new tab and set its properties as needed.
-
For your instance of %SOAP.WSDL.ReaderOpens in a new tab, set the HttpRequest property equal to the instance of %Net.HttpRequestOpens in a new tab that you just created.
For example, you might do this if the server requires authentication. See “Providing Login Credentials” in the chapter “Sending HTTP Requests” in Using Caché Internet Utilities.
-
-
Invoke the Process() method of your instance:
method Process(pLocationURL As %String, pPackage As %String = "") as %Status
-
pLocationURL must be the URL of the WSDL of the web service or the name of the WSDL file (including its complete path). Depending on the configuration of the web service, it may be necessary to append a string that provides a suitable username and password; see the examples.
-
pPackage is the name of the package in which to place the generated classes. If you do not specify a package, Caché uses the service name as the package name.
Note:If this package is the same as an existing package, by default the tool overwrites any existing classes that have the same name. To prevent the tool from overwriting a class definition, add the following to that class definition:
Parameter XMLKEEPCLASS = 1;
-
The following shows an example Terminal session:
set r=##class(%SOAP.WSDL.Reader).%New()
GSOAP>set url="http://localhost:57772/csp/gsop/GSOP.AddComplexWS.CLS?WSDL=1"
GSOAP>d r.Process(url)
Compilation started on 11/09/2009 12:53:52 with qualifiers 'dk'
Compiling class AddComplex.ns2.ComplexNumber
Compiling routine AddComplex.ns2.ComplexNumber.1
Compilation finished successfully in 0.170s.
Compilation started on 11/09/2009 12:53:52 with qualifiers 'dk'
Compiling class AddComplex.AddComplexSoap
Compiling routine AddComplex.AddComplexSoap.1
Compiling class AddComplex.AddComplexSoap.Add
Compiling routine AddComplex.AddComplexSoap.Add.1
Compilation finished successfully in 0.363s.
The WSDL URL is part of a web application, which might be protected by password authentication. For details on using the WSDL in this case, to generate Caché web clients or third-party web clients, see “Using a Password-Protected WSDL URL,” later in this book.
In all cases, it is also possible to retrieve the WSDL from a browser after supplying the required username and password, save it as a file, and use the file instead.
Modifying the Generated Client Classes
After you generate a Caché web client class, you do not usually edit the class. Instead you write code that creates an instance of the web client and that provides provide client-side error handling. This section documents the notable exceptions where you do modify the generated client class.
Also see the section “Additional Notes on Web Methods in the Generated Class” and the chapter “Fine-Tuning a Caché Web Client.”
Do not create a subclass of the generated web client class. The compiler will not generate the supporting classes that it would need in order to run properly, and your subclass would not be usable.
Adjusting the Generated Classes for Long Strings
In some cases, you might need to edit the generated client class to accommodate long strings or long binary values.
When the SOAP Wizard reads a WSDL, it assumes that any string-type input or output can be represented in Caché as %StringOpens in a new tab, which is not always true. Some strings might exceed the Caché 32 KB limit for strings, and there is no information in the WSDL to inform the SOAP Wizard of this.
Similarly, it assumes that any input or output with XML type base64Binary can be represented in Caché as %xsd.base64BinaryOpens in a new tab), which is not always true, due to the same long string limitation. There is no information in the WSDL to inform the SOAP Wizard that this input or output could exceed the long string limit.
In either case, if you have enabled long string operations in Caché, your web client works.
If you have not enabled long string operations in Caché, however, when your web client encounters a string or a binary value that is too long, it throws one of the following errors:
-
A <MAXSTRING> error
-
A datatype validation error:
ERROR #6232: Datatype validation failed for tag your_method_name ...
(This error, of course, can also be caused by a datatype mismatch.)
The problem, however, is easy to correct. If you expect long values for these inputs and outputs, adjust the method signature in your generated web client class (specifically the class that inherits from %SOAP.WebClientOpens in a new tab) to use an appropriate stream class:
-
Use %GlobalCharacterStreamOpens in a new tab instead of %StringOpens in a new tab.
-
Use %GlobalBinaryStreamOpens in a new tab instead of %xsd.base64BinaryOpens in a new tab.
For example, consider a web service (MyGiantStringService) that has one method (WriteIt), which takes no arguments and returns a very long string, greater than 32 KB. If you use the SOAP Wizard to generate the web client class, the web client class originally looks something like this:
Class GetGiantString.MyServiceSoap Extends %SOAP.WebClient
{
Method WriteIt() As %String
[Final,SoapBindingStyle=document,SoapBodyUse=literal,WebMethod]
{
Quit ..WebMethod("WriteIt").Invoke(##this,"http://tempuri.org/MyApp.MyGiantStringService.WriteIt")
}
}
In this case, there is only one adjustment to make. Change the return type of WriteIt as follows:
Method WriteIt() As %GlobalCharacterStream
[Final,SoapBindingStyle=document,SoapBodyUse=literal,WebMethod]
{
Quit ..WebMethod("WriteIt").Invoke(##this,"http://tempuri.org/MyApp.MyGiantStringService.WriteIt")
}
When you compile this class, the system automatically regenerates the associated classes as needed.
You may also need to adjust property types within any generated type classes. For example, suppose the web service uses an element called <Container>, which includes an element <ContainerPart> of type string. When you generate the Caché web client classes, the system creates a Container class with a ContainerPart property of type %StringOpens in a new tab. If the web service sends a string longer than 32 KB in the <ContainerPart> element, and if you have not enabled long string operations, your web client throws an error. To avoid this error, change the type of the ContainerPart property to %GlobalCharacterStreamOpens in a new tab.
Other Adjustments
If the WSDL does not specify the location of the web service, the SOAP Wizard does not specify the LOCATION parameter of the web client. This is a rare scenario. In this scenario, edit the web client class to include the LOCATION parameter. For example:
Parameter LOCATION = "http://localhost:57772/csp/gsop/GSOP.AddComplexWS.cls";
Or specify the Location property of your web client instance as shown later in this chapter.
You might need to adjust other parameters of the web client class to make other changes. See the chapter “Fine-Tuning a Caché Web Client” for details.
Using the Generated Web Client Classes
As noted in the previous section, after you generate a Caché web client class, you do not usually edit the generated class. Instead you write code that creates an instance of that web client and that provides provide client-side error handling. In this code, do the following:
-
Create an instance of the web client class.
-
Set its properties. Here you can control items such as the following:
-
Endpoint of the web client (the URL of the web service it uses). To control this, set the Location property, which overrides the LOCATION parameter of the web client class.
-
Settings that designate a proxy server.
-
Settings that control HTTP Basic authentication.
See the next section in this chapter as well as the chapter “Fine-Tuning a Caché Web Client.”
-
-
Invoke the methods of the web client as needed.
-
Perform client-side error handling. See the chapter “SOAP Fault Handling.”
-
Optionally examine the HTTP response received by the web client, as described later in this chapter.
The following shows a simple example, from a session in the Terminal:
GSOAP>set client=##class(Proxies.CustomerLookupServiceSoap).%New()
GSOAP>set resp=client.GetCustomerInfo("137")
GSOAP>w resp
11@Proxies.CustomerResponse
GSOAP>w resp.Name
Smith,Maria
Example 1: Using the Client That Uses Wrapped Messages
In this example, we create a wrapper class for a web client that uses wrapped messages. To use the example GSOAPClient.AddComplex.AddComplexSoap shown previously, we could create a class like the following:
Class GSOAPClient.AddComplex.UseClient Extends %RegisteredObject
{
ClassMethod Add(arg1 As ComplexNumber, arg2 As ComplexNumber) As ComplexNumber
{
Set client=##class(AddComplexSoap).%New()
//uncomment the following to enable tracing
//set client.Location="http://localhost:8080/csp/gsop/GSOP.AddComplexWS.cls"
Set ans=client.Add(arg1,arg2)
Quit ans
}
}
The client application would invoke this method in order to execute the web method.
Example 2: Using the Client That Uses Unwrapped Messages
In this example, we create a wrapper class for a web client that uses unwrapped messages. To use the example GSOAPClient.AddComplex.AddComplexSoap shown previously, we could create a class like the following:
Class GSOAPClient.AddComplexUnwrapped.UseClient Extends %RegisteredObject
{
ClassMethod Add(arg1 As GSOAPClient.AddComplexUnwrapped.s0.ComplexNumber,
arg2 As GSOAPClient.AddComplexUnwrapped.s0.ComplexNumber)
As GSOAPClient.AddComplexUnwrapped.s0.ComplexNumber
{
//create the Add message
Set addmessage=##class(GSOAPClient.AddComplexUnwrapped.s0.Add).%New()
Set addmessage.a = arg1
Set addmessage.b = arg2
Set client=##class(AddComplexSoap).%New()
//send the Add message to client and get response
Set addresponse=client.Add(addmessage)
//get the result from the response message
Set ans=addresponse.AddResult
Quit ans
}
}
The method has the signature that would typically be expected; that is, it accepts two complex numbers and returns a complex number. The method creates the message that the web client expects. The elements of this message are the two complex numbers.
As you can see, when the web client uses unwrapped messages, it is necessary to write slightly more code to convert arguments in a user-friendly form into the message used by the web client.
Adjusting Properties of a Web Client Instance
When you use an instance of your web client classes, you can specify properties of that instance to control its behavior. This section discusses the properties that are most commonly set, as well as their default values.
Changing the Endpoint for the Web Client
The SOAP Wizard automatically sets the endpoint for the web client by setting the LOCATION parameter of the web client. By default, it sets this parameter equal to the URL of the web service with which it communicates.
To override this, set the Location property of your web client instance. If Location is null, then the LOCATION parameter is used.
A common usage is to set the Location property to use a different port, in order to enable tracing. For example, suppose that in the generated web client class, the endpoint is defined as follows:
Parameter LOCATION = "http://localhost:57772/csp/gsop/GSOP.AddComplexWS.cls";
When you use this client, you can include the following line:
Set client.Location="http://localhost:8080/csp/gsop/GSOP.AddComplexWS.cls"
If the WSDL does not specify the location of the web service, the SOAP Wizard does not specify the LOCATION parameter of the web client. This is a rare scenario. In this scenario, either edit the web client class to include the LOCATION parameter or specify the Location property of your web client instance as shown here.
Configuring the Client to Use SSL
If the endpoint for a web client has HTTPS protocol, the web client must be configured to use SSL. Specifically:
-
If you have not already done so, use the Management Portal to create an SSL/TLS configuration that contains the details of the needed SSL connection. For information, see the chapter “Using SSL/TLS with Caché” in the Caché Security Administration Guide.
-
Set the SSLConfiguration property of the web client equal to that SSL/TLS configuration name.
Note that if the client is connecting via a proxy server, you must also set the HttpProxySSLConnect property equal to 1 in the web client. For information on configuring a Caché web client to use a proxy server, see the chapter “Fine-Tuning the Web Client.”
Specifying the SOAP Version
The SOAP Wizard automatically specifies the SOAP version to use in request messages, based on the SOAP version in the WSDL of the web service. Specifically it sets the SOAPVERSION parameter.
To override this, set the SoapVersion property of your web client instance. Use one of the following values:
-
"" — The client sends SOAP 1.1 messages.
-
"1.1" — The client sends SOAP 1.1 messages.
-
"1.2" — The client sends SOAP 1.2 messages.
If SoapVersion is null, then the SOAPVERSION parameter is used.
Other Adjustments
You might need to set other properties of the web client instance to make other changes. See the chapter “Fine-Tuning a Caché Web Client” for details.
Using the HTTP Response
By default, when you invoke a web client method, you do so via HTTP. The HTTP response is then available as the HttpResponse property of the web client instance. This property is an instance of %Net.HttpResponseOpens in a new tab, which in turn has properties like the following:
-
Headers contains the headers of the HTTP response.
-
Data is a Caché multidimensional array that contains any data in the HTTP response.
-
StatusCode, StatusLine, and ReasonPhrase provide status information.
For details, see the book Using Caché Internet Utilities. Or see the class documentation for %Net.HttpResponseOpens in a new tab.