Skip to main content

Creating SOAP Web Services

This chapter describes the basics of how to create a web service in Caché. It includes the following topics:

See the first appendix for a table that summarizes the URLs related to your web service.

Overview of Caché Web Services

To create a web service in Caché, you create a class that extends %SOAP.WebServiceOpens in a new tab, which provides all the functionality required to make one or more methods callable via the SOAP protocol. In addition, this class automates the management of SOAP-related bookkeeping, such as maintaining a WSDL document that describes a service.

This class is derived from the %CSP.PageOpens in a new tab class. Because of this, every web service class can respond to HTTP requests. Thus, the %SOAP.WebServiceOpens in a new tab class implements methods that respond to HTTP events to do the following:

  • Publish the WSDL document for the web service as an XML document.

  • Publish a human-readable catalog page (using HTML) describing the web service and its methods. The descriptions on this page show the comments included in the class definition.

Basic Requirements

To create and publish a web service in Caché, create and compile a Caché class that meets the following basic requirements:

  • The class must extend %SOAP.WebServiceOpens in a new tab.

  • The class must define the SERVICENAME parameter. Caché does not compile the class unless it defines this parameter.

  • This class should define methods or class queries that are marked with the WebMethod keyword.

    Important:

    In most cases, web methods should be instance methods. Within a web method, it is often necessary to set properties of and invoke methods of the web service instance (as described in later chapters) to fine-tune the behavior of the method. Because a class method cannot do these tasks, a class method is usually not suitable as a web method.

  • For any web methods, make sure that each value in the method signature has an XML projection. For example, suppose that your method had the following signature:

    Method MyWebMethod(myarg as ClassA) as ClassB [ WebMethod ]
    

    In this case, both ClassA and ClassB must have an XML representation. In most cases, this means that their superclass lists must include %XML.AdaptorOpens in a new tab; see Projecting Objects to XML. Caché SOAP support provides special handling for collections and streams, as noted after this list.

    The web method can specify the ByRef and Output keywords in the same way that ordinary methods do. (For information on these keywords, see the chapter “Methods” in Using Caché Objects.)

  • Consider the values that are likely to be carried within these arguments and return values. XML does not permit nonprinting characters, specifically characters below ASCII 32 (except for carriage returns, line feeds, and tabs, which are permitted in XML).

    If you need to include any disallowed nonprinting character, specify the type as %BinaryOpens in a new tab, %xsd.base64BinaryOpens in a new tab (which is equivalent), or a subclass. This value is automatically converted to base–64 encoding on export to XML (or automatically converted from base–64 encoding on import).

  • Do not rely on the method signature to specify the default value for an argument. If you do, the default value is ignored and a null string is used instead. For example, consider the following method:

    Method TestDefaults(val As %String = "Default String") As %String [ WebMethod ]
    

    When you invoke this method as a web method, if you do not supply an argument, a null string is used, and the value "Default String" is ignored.

    Instead, at the start of the method implementation, test for a value and use the desired default if applicable. One technique is as follows:

     if arg="" {
       set arg="Default String"
     }

    You can indicate the default value in the method signature as usual, but this is purely for informational purposes and does not affect the SOAP messages.

  • For any required arguments in a web method, specify the REQUIRED property parameter within the method signature. For example:

    Method MyWebMethod(myarg as ClassA(REQUIRED=1)) as ClassB [ WebMethod ]
    

By default, any inherited methods are treated as ordinary methods, even if a superclass marks them as web methods (but see “Subclassing an Existing Caché Web Services,” later in this chapter).

Input and Output Objects That Do Not Need %XML.Adaptor

In most cases, when you use an object as input or output to a web method, that object must extend %XML.AdaptorOpens in a new tab. The exceptions are as follows:

  • If the object is %ListOfDataTypesOpens in a new tab, %ListOfObjectsOpens in a new tab, %ArrayOfDataTypesOpens in a new tab, %ArrayOfObjectsOpens in a new tab, or a subclass, the Caché SOAP support implicitly treats the object as if it included %XML.AdaptorOpens in a new tab. You do not need to subclass these classes. However:

    • You must specify ELEMENTTYPE within the method signature, as follows:

      Method MyMethod() As %ListOfObjects(ELEMENTTYPE="MyApp.MyXMLType") [WebMethod]
      {
         //method implementation
      }
      

      Or, in the case of an input argument:

      Method MyMethod(input As %ListOfObjects(ELEMENTTYPE="MyApp.MyXMLType")) [WebMethod]
      {
         //method implementation
      }
      
    • If the class that you name in ELEMENTTYPE is an object class, it must inherit from %XML.AdaptorOpens in a new tab.

  • If the object is one of the stream classes, the Caché SOAP support implicitly treats the object as if it included %XML.AdaptorOpens in a new tab. You do not need to subclass the stream class.

    If it is a character stream, the Caché SOAP tools assume that the type is string. If it is a binary stream, the tools treat it as base-64–encoded data. Thus it is not necessary to supply type information.

Using Result Sets as Input or Output

You can use result sets as input or output, but your approach depends on the intended web clients.

Simple Example

This section shows an example web service, as well as an example of a request message that it can recognize and the corresponding response message.

First, the web service is as follows:

/// MyApp.StockService
Class MyApp.StockService Extends %SOAP.WebService 
{

/// Name of the WebService.
Parameter SERVICENAME = "StockService";

/// TODO: change this to actual SOAP namespace.
/// SOAP Namespace for the WebService
Parameter NAMESPACE = "http://tempuri.org";

/// Namespaces of referenced classes will be used in the WSDL.
Parameter USECLASSNAMESPACES = 1;

/// This method returns tomorrow's price for the requested stock
Method Forecast(StockName As %String) As %Integer [WebMethod]
{
    // apply patented, nonlinear, heuristic to find new price
    Set price = $Random(1000)
    Quit price
}
}

When you invoke this method from a web client, the client sends a SOAP message to the web service. This SOAP message might look like the following (with line breaks and spaces added here for readability):

<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope 
xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' 
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' 
xmlns:s='http://www.w3.org/2001/XMLSchema'>
  <SOAP-ENV:Body>
    <Forecast xmlns="http://tempuri.org">
     <StockName xsi:type="s:string">GZP</StockName>
    </Forecast>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Note that the message body (the <SOAP-ENV:Body> element) includes an element named <Forecast>, which is the name of the method that the client is invoking. The <Forecast> includes one element, <StockName>, whose name is based on the argument name of the web method that we are invoking. This element contains the actual value of this argument.

The web service performs the requested action and then sends a SOAP message in reply. The response message might look like the following:

<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope 
xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' 
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' 
xmlns:s='http://www.w3.org/2001/XMLSchema'>
  <SOAP-ENV:Body>
    <ForecastResponse xmlns="http://www.myapp.org">
      <ForecastResult>799</ForecastResult>
    </ForecastResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

These examples do not include the HTTP headers that precede the SOAP message itself.

Creating a Web Service

You can create web services in any of the following ways:

Using the Web Service Wizard

The Web Service Wizard generates a simple stub.

  1. Click File > New.

    This displays the New dialog box.

  2. Click the General tab.

  3. Click New Web Service and then click OK.

    This displays a wizard.

  4. Enter values for the package name, class name, and web service name. These are required.

  5. Optionally edit the namespace URI (or change this initial value later). This is the XML namespace, not the Caché namespace.

  6. Optionally type a list of method names, on separate lines.

  7. Click OK.

Now, you have a new web service class that contains stubs for the web methods. For example:

/// MyApp.StockService
Class MyApp.StockService Extends %SOAP.WebService 
{

/// Name of the WebService.
Parameter SERVICENAME = "StockService";

/// TODO: change this to actual SOAP namespace.
/// SOAP Namespace for the WebService
Parameter NAMESPACE = "http://tempuri.org";

/// Namespaces of referenced classes will be used in the WSDL.
Parameter USECLASSNAMESPACES = 1;

/// TODO: add arguments and implementation.
/// Forecast
Method Forecast() As %String [ WebMethod ]
{
   ;Quit "Forecast"
}

}

Using the SOAP Wizard with an Existing WSDL

In some cases, the WSDL has been designed already and it is necessary to create a web service that matches the WSDL; this is known as “WSDL-first development.” In Caché, there are three steps to this development:

  1. Use the SOAP Wizard to read the WSDL and to generate the web service and all supporting classes.

    This wizard can also generate web client classes (which is more common).

    For information on using this wizard, see “Using the SOAP Wizard,” later in this book. Follow the steps described in that section and also select the Create Web Service option within the wizard.

    Or use the %SOAP.WSDL.ReaderOpens in a new tab class as described in “Using the %SOAP.WSDL.Reader Class.”

  2. Examine the generated classes to see if you need to change any %StringOpens in a new tab values in the method signatures.

    When the 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.

    See “Adjusting the Generated Classes for Long Strings,” later in this book.

  3. Edit the methods in the generated web service so that they perform the desired actions.

    Each method is initially a stub like the following example:

    Method Add(a As Test.ns2.ComplexNumber, b As Test.ns2.ComplexNumber) As Test.ns2.ComplexNumber 
    [ Final, SoapAction = "http://www.mynamespace.org/GSOAP.AddComplexWS.Add", 
    SoapBindingStyle = document, SoapBodyUse = literal, WebMethod ]
    {
     // Web Service Method Implementation Goes Here.
    }

    The wizard includes compiler keywords such as Final and SoapBindingStyle. You should not change the values of these keywords.

If the WSDL includes WS-Policy elements, the wizard also generates a configuration class for the web service. The default configuration class name is the web service name, with Config appended to it. For information on WS-Policy, see Securing Caché Web Services.

Subclassing an Existing Caché Web Service

You can create a web service by creating a subclass of an existing Caché web service class and then adding the SOAPMETHODINHERITANCE parameter to your class as follows:

PARAMETER SOAPMETHODINHERITANCE = 1;

The default for this parameter is 0. If this parameter is 0, your class does not inherit the web methods as web methods. That is, the methods are available as ordinary methods but cannot be accessed as web methods within the web service defined by the subclass.

If you set this parameter to 1, then your class can use web methods defined in any superclasses that are web services.

Specifying Parameters of the Web Service

Make sure that your web service class uses appropriate values for the following parameters.

Note:

If you use the SOAP wizard to generate a web service from an existing WSDL, do not modify any of these parameters.

SERVICENAME

Name of the web service. This name must start with a letter and must contain only alphanumeric characters.

Caché does not compile the class unless the class defines this parameter.

NAMESPACE

URI that defines the target namespace for your web service, so that your service, and its contents, do not conflict with another service. This is initially set to "http://tempuri.org" which is a temporary URI often used by SOAP developers during development.

If you do not specify this parameter, the target namespace is "http://tempuri.org".

For a Caché web service, there is no way to put request messages in different namespaces. A Caché web client, however, does not have this limitation; see “Namespaces for the Messages,” later in this book.

RESPONSENAMESPACE

URI that defines the namespace for the response messages. By default, this is equal to the namespace given by the NAMESPACE parameter.

For a Caché web service, there is no way to put response messages in different namespaces. A Caché web client, however, does not have this limitation; see “Namespaces for the Messages,” later in this book.

TYPENAMESPACE

Namespace for the schema for the types defined by the web service. If you do not specify this parameter, the schema is in the target namespace of the web service (that is, either NAMESPACE or the default, which is "http://tempuri.org").

For a Caché web service, there is no way to put the request message types in different namespaces. A Caché web client does not have this limitation; see “Namespaces for Types,” later in this book.

RESPONSETYPENAMESPACE

URI that defines the namespace for types used by the response messages. By default, this is equal to the namespace given by the TYPENAMESPACE parameter.

This parameter is used only if SoapBindingStyle equals "document" (the default).

For either a Caché web service or a Caché web client, the types for the response messages must all be in the same namespace.

SOAPVERSION

Specifies the SOAP version or versions advertised in the WSDL of the web service. Use one of the following values:

  • "" — Use this value for SOAP 1.1 or 1.2.

  • "1.1" — Use this value for SOAP 1.1. This is the default.

  • "1.2" — Use this value for SOAP 1.2.

When the web service receives a SOAP request, the SoapVersion property of the web service is updated to equal the SOAP version of that request.

See also “Restricting the SOAP Versions Handled by a Web Service,” later in this book.

For details on how these values affect the WSDL, see the appendix “Details of the Generated WSDLs.”

About the Catalog and Test Pages

When you compile a web service class, the class compiler creates a convenient catalog page that you can use to examine the web service. This catalog page provides a link to a simple test page.

To see these CSP pages:

  1. In Studio, display the web service class.

  2. Click View > Web Page.

The catalog page is immediately displayed. Its URL is constructed as follows:

base/csp/app/web_serv.cls

Here base is the base URL for your web server (including port if necessary), /csp/app is the name of the web application in which the web service resides, and web_serv is the class name of the web service. (Typically, /csp/app is /csp/namespace.) For example:

http://localhost:57772/csp/samples/MyApp.StockService.cls

Access to These Pages

These CSP pages are part of a Caché web application, as noted in the previous chapter. If there is no web application for the namespace you are using, you cannot access these pages. Also, by default, these pages are inaccessible. To enable access to them, open the Terminal, go to the %SYS namespace, and enter the following commands:

set ^SYS("Security","CSP","AllowClass",webapplicationname,"%SOAP.WebServiceInfo")=1
set ^SYS("Security","CSP","AllowClass",webapplicationname,"%SOAP.WebServiceInvoke")=1

Where webapplicationname is the web application name with a trailing slash, for example, "/csp/mynamespace/". This access is enabled by default for the /csp/samples web application.

Also, you can use these pages only if you are logged in as a user who has USE permission for the %Development resource.

Notes on These Pages

The catalog page displays the class name, namespace, and service name, as well as the comments for the class and web methods. The Service Description link displays the WSDL; for information, see the section “Viewing the WSDL,” later in this chapter. The page then lists the web methods, with links (if you have the suitable permissions). The link for a given method displays a test page where you can test that method in a limited fashion.

Notes about this test page:

  • It does not enable you to see the SOAP request.

  • It does not test the full SOAP pathway. This means, for example, it does not write to the SOAP log that is discussed later in this chapter.

  • It accepts only simple, literal inputs, so you cannot use it to call methods whose arguments are objects, collections, or datasets.

This book does not discuss this page further. To test your web service more fully, generate and use a web client as described later in this book.

Viewing the WSDL

When you use %SOAP.WebServiceOpens in a new tab to define a web service, the system creates and publishes a WSDL document that describes this web service. Whenever you modify and recompile the web service, the system automatically updates the WSDL correspondingly. This section discusses the following:

Also see “WSDL Support in Caché” in the first chapter.

Important:

By definition, a web service and its web clients are required to comply to a common interface, regardless of their respective implementations (and regardless of any underlying changes in technology). A WSDL is a standards-compliant description of this interface. It is important to note the following:

  • In practice, a single SOAP interface can often be correctly described by multiple, slightly different WSDL documents.

    Accordingly, the WSDL generated by Caché may have a slightly different form depending on the version of Caché. It is beyond the scope of this documentation to describe any such differences. InterSystems can commit only to the interoperability of web services and their respective clients, as required in the W3C specifications.

  • The W3C specifications do not require that either a web service or a web client be able to generate a WSDL to describe the interface with which it complies.

    The system generates the WSDL document and serves it at a specific URL, for convenience. However, if the containing web application requires password authentication or requires an SSL connection, you may find it impractical to access the WSDL in this way. In such cases, you should download the WSDL to a file and use the file instead. Also, as noted previously, the generated WSDL does not contain any information about SOAP headers added at runtime. If you need a WSDL document to contain information about SOAP headers added at runtime, you should download the WSDL to a file, modify the file as appropriate, and then use that file.

Viewing the WSDL

To view the WSDL for the web service, use the following URL:

base/csp/app/web_serv.cls?WSDL

Here base is the base URL for your web server (including port if necessary), /csp/app is the name of the web application in which the web service resides, and web_serv is the class name of the web service. (Typically, /csp/app is /csp/namespace.)

Note:

Any percent characters (%) in your class name are replaced by underscore characters (_) in this URL.

For example:

http://localhost:57772/csp/samples/MyApp.StockService.cls?WSDL

The browser displays the WSDL document, for example:

generated description: wsdl

Important:

Not all browsers display the schema correctly. You might need to view the page source to see the actual schema. For example, in Firefox, right-click and then select View Source.

Generating the WSDL

You can also generate the WSDL as a static document. The %SOAP.WebServiceOpens in a new tab class provides a method you can use for this:

FileWSDL()
ClassMethod FileWSDL(fileName As %String, includeInternalMethods As %Boolean = 1) As %Status 

Where fileName is the name of the file, and includeInternalMethods specifies whether the generated WSDL includes any web methods that are marked as Internal.

Suppressing Internal Web Methods from the WSDL

If the web service has web methods that are marked as Internal, by default the WSDL includes these web methods. You can prevent these methods from being included in the WSDL. To do so, do either of the following:

  • Use the FileWSDL() method of the web service to generate the WSDL; see the previous section. This method provides an argument that controls whether the WSDL includes internal web methods.

  • Specify the SOAPINTERNALWSDL class parameter as 0 in the web service class. (The default for this class parameter is 1.)

FeedbackOpens in a new tab