Skip to main content
Previous sectionNext section

Creating an Ensemble Web Client

This chapter describes how to create an Ensemble web client. At a high level, your Ensemble web client receives Ensemble requests from elsewhere within the production, converts them to SOAP requests, and sends them to the appropriate web service. Similarly, it receives SOAP responses, converts them into Ensemble responses, and sends them back within the production. This chapter discusses the following topics:

Tip:

Ensemble also provides specialized business service classes that use SOAP, and one of those might be suitable for your needs. If so, no programming would be needed. See “Connectivity Options” in Introducing Ensemble.

Overview

An Ensemble web client consists of the following parts:

  • A proxy client class that defines a proxy method for each method defined by the web service. Each proxy method uses the same signature used by the corresponding web service method and invokes that method when requested.

  • A business operation that uses the Ensemble SOAP outbound adapter to invoke the proxy client.

  • Supporting classes as needed to define XML types and Ensemble messages.

The following figure shows how the business operation, adapter, and proxy client class work together. Supporting classes are not shown here.

images/esoap_outbound.png

In the preceding figure, all items within dashed lines can be generated by the SOAP client wizard in Studio. You can then edit this code as needed.

For a more detailed look at these parts, see “Ensemble Support for Web Clients,” earlier in this book.

Basic Steps

This section outlines the basic steps to create an Ensemble web client.

To create an Ensemble web client, do the following within Studio:

  1. Use the SOAP wizard to generate the business operation class, proxy client class, and supporting classes. This tool is described in “Using the SOAP Wizard” in this chapter.

  2. Check whether you need to adjust the types of the inputs and outputs of the methods. In particular, if any of the methods of the web service have inputs or outputs that could exceed 32 KB in length, and if you have not enabled support for long strings in Ensemble, you should change the types of those inputs or outputs to an appropriate stream class.

Using the SOAP Wizard

To use the SOAP wizard to generate an Ensemble web client, do the following:

  1. In Studio, make sure that you are in the appropriate Ensemble namespace.

  2. Click Tools —> Add-ins —> SOAP Wizard.

  3. On the first screen, enter the entire URL of the WSDL document for the web service you want to work with.

  4. Click Next.

  5. Select the check box to the left of Create Business Operation in Package. This option instructs the wizard to define a business operation class that invokes the proxy client, as well as message classes for use with that business operation.

  6. For Create Business Operation in Package, optionally change the subpackage name from BusOp to another name.

  7. For Optional Package Name, type a package name for the proxy client and related classes. The default package name is the service name. Also see the “Generated Classes and XMLKEEPCLASS section.”

  8. For Class Type, choose a general type for the proxy client class: persistent or serial (the default).

  9. Click Next. The wizard generates and compiles the classes and displays a list of these classes.

  10. Click Finish.

Generated Classes and XMLKEEPCLASS

The SOAP wizard generates a set of classes; the details of these classes are discussed later in this chapter.

You specify the package in which the tool should create the proxy client class and the supporting classes. If this package is the same as an existing package, by default the tool will overwrite any existing classes that have the same name. To prevent the wizard from overwriting a class definition, add the XMLKEEPCLASS parameter to that class and set this parameter equal to 1.

Using the Process() Method

Instead of using the wizard, you can use the Process() method of the %SOAP.WSDL.Reader class. To use this method:

  1. Create an instance of %SOAP.WSDL.Reader.

  2. Optionally set properties to control the behavior of your instance.

    Property Purpose
    CompileFlags Specifies the flags to use when compiling the generated classes. The initial expression is "dk"; use $System.OBJ.ShowFlags() to get information on the available flags.
    MakePersistent If this property is 1, the proxy client is a persistent object; otherwise, it is a registered object. The initial expression is 0.
    MakeSerial If this property is 1 and if MakePersistent is 1, the proxy client is a serial class. The initial expression is 0.
    OutputTypeAttribute Controls how the WSDL reader sets the OUTPUTTYPEATTRIBUTE parameter in the proxy client that it generates; which controls the use of the xsi:type attribute in the SOAP messages. See Creating Web Services and Web Clients in Caché in the Caché documentation set.
    MakeBusinessOperation Specifies whether to generate an Ensemble business operation and related request and response objects. The ADAPTER setting for this business operation is EnsLib.SOAP.OutboundAdapter. This option works only if you are working within an Ensemble-enabled namespace.

    For other properties, see the class documentation for %SOAP.WSDL.Reader.

  3. Invoke the Process() method, providing the following arguments:

    • The first argument 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.

    • The optional second argument is the name of the package in which the reader should place the generated classes. If you do not specify a package, Caché uses the service name as the package name.

Generated Classes for an Ensemble Web Client

This section provides information about the classes that the SOAP wizard generates.

Consider a web service named MyService that has the following details:

  • It is hosted at http://localhost:57772/csp/gsop/MyApp.AddService.CLS

  • The target XML namespace for the web service is http://www.myapp.org

  • It defines a web method named AddService, which accepts two complex numbers as arguments and returns the result.

Suppose that you use the SOAP wizard to generate a Ensemble web client for this web service. If you specify the package for the client classes as MyClient, the SOAP wizard will generate the following classes and add them all to your current project:

  • It generates the MyClient.BusOp.MyServiceSoap class, which defines the business operation.

    Class MyClient.BusOp.MyServiceSoap Extends Ens.BusinessOperation
    {
    
    Parameter ADAPTER = "EnsLib.SOAP.OutboundAdapter";
    
    Method Add(pRequest As MyClient.BusOp.AddRequest,
    Output pResponse As MyClient.BusOp.AddResponse) As %Library.Status
    {
       Set ..Adapter.WebServiceClientClass = "MyClient.MyServiceSoap"
       Set tSC = ..Adapter.InvokeMethod("Add",.AddResult,
    pRequest.a,pRequest.b) Quit:$$$ISERR(tSC) tSC
    
       Set tSC = pRequest.NewResponse(.pResponse) Quit:$$$ISERR(tSC) tSC
       Set pResponse.AddResult=AddResult
       Quit $$$OK
    }
    
    XData MessageMap
    {
    <MapItems>
        <MapItem MessageType="MyClient.BusOp.AddRequest">
            <Method>Add</Method>
        </MapItem>
    </MapItems>
    }
    
    }
    Copy code to clipboard
  • It generates the MyClient.AddServiceSOAP class, the proxy client class:

    Class MyClient.AddServiceSoap Extends %SOAP.WebClient
    {
    
    /// This is the URL used to access the web service.
    Parameter LOCATION = "http://localhost:57772/csp/gsop/MyApp.AddService.cls";
    
    /// This is the namespace used by the Service
    Parameter NAMESPACE = "http://www.myapp.org";
    
    /// Use xsi:type attribute for literal types.
    Parameter OUTPUTTYPEATTRIBUTE = 1;
    
    /// This is the name of the Service
    Parameter SERVICENAME = "AddService";
    
    Method Add(a As MyClient.ComplexNumber, b As MyClient.ComplexNumber)
       As MyClient.ComplexNumber [ Final, 
       SoapBindingStyle = document, SoapBodyUse = literal, WebMethod ]
    {
     Quit ..WebMethod("Add").Invoke($this,
          "http://www.myapp.org/MyApp.AddService.Add",.a,.b)
    }
    
    }
    Copy code to clipboard
  • It generates the request and response message classes needed by the business operation. The request class is as follows:

    Class MyClient.BusOp.AddRequest Extends Ens.Request
    {
    
    Parameter RESPONSECLASSNAME = "MyClient.BusOp.AddResponse";
    
    Property a As MyClient.ComplexNumber;
    
    Property b As MyClient.ComplexNumber;
    
    }
    Copy code to clipboard

    The response class is as follows:

    Class MyClient.BusOp.AddResponse Extends Ens.Response
    {
    
    Property AddResult As MyClient.ComplexNumber;
    
    }
    Copy code to clipboard
  • Finally, it generates the MyClient.ComplexNumber class, which defines a complex number and which is used by the other classes.

    /// Created from: http://localhost:57772/csp/gsop/MyApp.AddService.CLS?WSDL=1
    Class MyClient.ComplexNumber Extends (%RegisteredObject, %XML.Adaptor)
    {
    Parameter XMLNAME = "ComplexNumber";
    
    Parameter XMLSEQUENCE = 1;
    
    Property Real As %xsd.double(XMLNAME = "Real") [ SqlFieldName = _Real ];
    
    Property Imaginary As %xsd.double(XMLNAME = "Imaginary");
    
    }
    Copy code to clipboard

When you compile these classes, the compiler also generates a class for each method defined in the web service. These classes are not automatically added to your project and their internal details are subject to change. These classes extend %SOAP.ProxyDescriptor, which you should never subclass yourself.

Creating a Business Operation Class Manually

Rather than using the business operation class that the SOAP wizard generates, you can create your own class. This section describes how to do so. It discusses the following:

Basic Requirements of the Class

The following list describes the basic requirements of the business operation class:

  • Your business operation class should extend Ens.BusinessOperation.

  • In your class, the ADAPTER parameter should equal EnsLib.SOAP.OutboundAdapter.

  • In your class, the INVOCATION parameter should specify the invocation style you want to use, which must be one of the following.

    • Queue means the message is created within one background job and placed on a queue, at which time the original job is released. Later, when the message is processed, a different background job will be allocated for the task. This is the most common setting.

    • InProc means the message will be formulated, sent, and delivered in the same job in which it was created. The job will not be released to the sender’s pool until the message is delivered to the target. This is only suitable for special cases.

  • Your class should define one method for each method of the proxy client, as described in the following section.

  • Your class should define a message map that includes one entry for each method. A message map is an XData block entry that has the following structure:

    XData MessageMap
    {
    <MapItems>
      <MapItem MessageType="messageclass">
        <Method>methodname</Method>
      </MapItem>
      ...
    </MapItems>
    }
    
    Copy code to clipboard

You will also need to define the Ensemble message classes that the business operation uses.

Basic Requirements of the Methods

Within your business operation class, your methods should invoke the proxy methods. Here the general requirements are as follows:

  1. The method should have the same signature as the proxy method that it is invoking.

  2. The method should be marked with the WebMethod keyword.

  3. The method should set the SoapBindingStyle and SoapBodyUse keywords as expected by the proxy client. (That is, use the same values as in the signature of the corresponding proxy method.)

  4. The method should set the WebServiceClientClass property of the adapter. When this property is set, a proxy client instance is created and placed in the %Client property of the adapter.

  5. The method should call the corresponding proxy method, using one of the techniques in the next section.

  6. The method should check the status.

  7. Then:

    • In the case of success, create a new response message (via the NewResponse() method of the request) and set its properties as appropriate.

    • In the case of failure, quit with the error.

Ways to Execute the Proxy Methods

Within your business operation, your methods should execute the proxy methods of the proxy client class. You can do this in multiple ways, which are best shown via an example. This section uses an example web service that has a web method named GetStock that accepts a stock symbol (a string) and returns a number. Suppose that you have used the SOAP wizard to generate a proxy client (GetStock.StockServiceSoap), which contains a method called GetStock.

Also suppose that you have created message classes as follows:

Class GetStock.BusOp.GetQuoteRequest Extends Ens.Request
{

Parameter RESPONSECLASSNAME = "GetStock.BusOp.GetQuoteResponse";

Property StockName As %String;

}
Copy code to clipboard

And

Class GetStock.BusOp.GetQuoteResponse Extends Ens.Response 
{

Property StockValue As %Numeric;

}
Copy code to clipboard

To execute the proxy method GetStock, your business operation class can do any of the following:

  • Call the InvokeMethod() method of the adapter and specify the name of the proxy method to run, as well as any number of arguments. In this case, there is only one argument (which we specify as pRequest.StockName). For example:

    Method GetQuote1(pRequest As GetStock.BusOp.GetQuoteRequest,
    Output pResponse As GetStock.BusOp.GetQuoteResponse) As %Status
    {
     set ..Adapter.WebServiceClientClass = "GetStock.StockServiceSoap"
    
     set status = ..Adapter.InvokeMethod("GetQuote",.answer,pRequest.StockName)
     if $$$ISERR(status) quit status
    
     set pResponse=##class(GetStock.BusOp.GetQuoteResponse).%New()
     set pResponse.GetQuoteResult=answer
     quit $$$OK
    }
    
    Copy code to clipboard

    When you use the SOAP wizard to generate the business operation, it uses this method.

  • Access the %Client property of the adapter, which gives you an instance of the proxy client class, and execute the proxy method of that property. The %Client property is set when you set the WebServiceClientClass property. In this case, %Client has a method named GetQuote, which accepts a string stock symbol. For example:

    Method GetQuote2(pRequest As GetStock.BusOp.GetQuoteRequest,
    Output pResponse As GetStock.BusOp.GetQuoteResponse) As %Status
    {
     set ..Adapter.WebServiceClientClass = "GetStock.StockServiceSoap"
    
     set client=..Adapter.%Client
     set answer=client.GetQuote("GRPQ")
    
     set pResponse=##class(GetStock.BusOp.GetQuoteResponse).%New()
     set pResponse.GetQuoteResult=answer
     quit $$$OK
    }
    Copy code to clipboard

    Note that with this technique, you do not have access to the retry logic of Ensemble.

  • Create a proxy method object by calling the WebMethod() method of the adapter. Set properties of this object as appropriate (one property per named argument). In this case, WebMethod() returns an object with one property: StockName. After setting properties as needed, call the Invoke() method of that object. For example:

    Method GetQuote3(pRequest As GetStock.BusOp.GetQuoteRequest,
    Output pResponse As GetStock.BusOp.GetQuoteResponse) As %Status
    {
     set ..Adapter.WebServiceClientClass = "GetStock.StockServiceSoap"
    
    
     set proxymethod=..Adapter.WebMethod("GetQuote")
     set proxymethod.StockName=pRequest.StockName
    
    
     set status=..Adapter.Invoke(proxymethod)
     if $$$ISERR(status) quit status
    
    
     set pResponse=##class(GetStock.BusOp.GetQuoteResponse).%New()
     set pResponse.GetQuoteResult=proxymethod.%Result
     quit $$$OK
    }
    
    Copy code to clipboard

    In this case, you can provide any number of arguments.

Reference Information

This section provides reference information for the adapter property and methods mentioned in the previous section.

%Client property
%SOAP.WebClient 
Copy code to clipboard

The associated instance of the proxy client (an instance of %SOAP.WebClient). This property is set when you set the WebServiceClientClass property of the adapter.

InvokeMethod() method
Method InvokeMethod(pMethodName As %String,
       Output pResult As %RegisteredObject,
       pArgs...) As %Status
Copy code to clipboard

Calls the specified method of the proxy client class, passing all the arguments and returns the status. The output is returned by reference as the second argument.

WebMethod() method
Method WebMethod(pMethodName As %String) As %SOAP.ProxyDescriptor
Copy code to clipboard

Returns an object that corresponds to the specified method. This object has one property corresponding to each method argument; you should set this properties before using the Invoke() method. For details on %SOAP.ProxyDescriptor, see the class reference.

Invoke() method
Method Invoke(pWebMethod As %SOAP.ProxyDescriptor) As %Status
Copy code to clipboard

Calls the given method and returns the status.

Adding and Configuring the Web Client

To add your Ensemble web client to an Ensemble production, use the Management Portal to do the following:

  1. Add an instance of your custom business operation class to the Ensemble production, specifically the business operation class generated by the SOAP wizard.

  2. Enable the business operation.

  3. Specify appropriate values for the runtime settings of the associated adapter, as discussed below.

  4. Run the production.

The following subsections describes the runtime settings for your Ensemble web client, which fall into several general groups:

For settings not listed in this book, see “Settings in All Productions” in Managing Ensemble Productions.

Specifying Basics

The following settings specify the basic information for the Ensemble web client:

Specifying Credentials

The web service that you are accessing might require a username and password. In general, the Ensemble SOAP client can log into a web service in either of the following ways:

  • You can use WS-Security user authentication. In this case, you include a WS-Security header in the SOAP request; this header includes the username and password. The proxy client automatically does this if you specify a value for the SOAP Credentials setting.

    Caution:

    Ensure that you are using SSL between the web client and the web service. The WS-Security header is sent in clear text, so this technique is not secure unless SSL is used.

  • You can use basic HTTP user authentication, which is less secure than WS-Security but is sometimes required. In this case, you include the username and password in the HTTP header of the SOAP request. The proxy client automatically does this if you specify a value for the Credentials setting.

Use the technique that is appropriate for the web service you are using.

Specifying an SSL Configuration

If the web server supports it, you can connect with SSL. To do so, specify a value for the SSL Configuration setting.

Note:

You must also ensure the web service is at a URL that uses https://. The web service location is determined by the Web Service URL setting; if this is not specified, the Ensemble web client assumes the web service is at the URL specified by the LOCATION parameter in the proxy client class.

Specifying a Proxy Server

You can communicate with the web service via a proxy server. To set this up, use Proxy Server and other settings in the Proxy Settings group.