Skip to main content

Creating a Web Service in a Production

This topic describes how to create an production web service, which is a web service in a production. When you do this, you are providing a SOAP-enabled interface to the production.

For settings not discussed here, see Settings in All Productions.

For an alternative approach, see Using the SOAP Inbound Adapter.

Tip:

InterSystems IRIS® 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.

Overall Behavior

A production web service is based on EnsLib.SOAP.ServiceOpens in a new tab or a subclass. This class extends both Ens.BusinessServiceOpens in a new tab (so that it is a business service) and %SOAP.WebServiceOpens in a new tab (so that it can act as a web service as well). A production web service behaves as follows:

  • Because it is a web service, it has a WSDL document (generated automatically) that describes the web methods available in it. The service can receive any SOAP message that conforms to the WSDL and sends SOAP responses in return.

  • Because it is a business service, it is an integral part of the production to which you add it. Monitoring, error logging, runtime parameters, and all the rest of the production machinery are available as usual.

    Note:

    A production web service is not available unless the production is running (and the business service is enabled).

Communication with the outside world is done via SOAP request and response messages. InterSystems IRIS Interoperability request and response messages are used within the production.

Basic Requirements

To create a web service in a production, you create a new business service class as described here. Later, add it to your production and configure it.

You must also create appropriate message classes, if none yet exist. See Defining Messages.

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

  • Your class should extend EnsLib.SOAP.ServiceOpens in a new tab. This class extends both Ens.BusinessServiceOpens in a new tab (so that it is a business service) and %SOAP.WebServiceOpens in a new tab (so that it can act as a web service as well).

  • The class should define the ADAPTER parameter as null (""). For example:

    Parameter ADAPTER = "";

    Or, equivalently:

    Parameter ADAPTER;
  • The class should specify values for other parameters:

    Parameter Description
    SERVICENAME Name of the web service. This name must start with a letter and must contain only alphanumeric characters. The default service name is "MyProductionRequestWebService"
    NAMESPACE URI that defines the target XML 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 used by SOAP developers during development.
    TYPENAMESPACE XML namespace for the schema in the types defined by the web service. If you do not specify this parameter, the schema is in the namespace given by NAMESPACE instead.
    RESPONSENAMESPACE URI that defines the XML namespace for the response messages. By default, this is equal to the namespace given by the NAMESPACE parameter.
  • The class should define web methods, as described in Defining Web Methods.

  • For other options and general information, see Defining a Business Service Class.

The following example shows in general what the class might look like:

Class Hospital.MyService Extends EnsLib.SOAP.Service
{

///For this business service, ADAPTER should be "" so that we use the normal SOAP processing
Parameter ADAPTER = "";

Parameter SERVICENAME = "MyService";

Parameter NAMESPACE = "http://www.myhospital.org";

Parameter USECLASSNAMESPACES = 1;

Method GetAuthorization(patientID As %Integer, RequestedOperation As %String, 
LikelyOutcome As %String) As %Status [ WebMethod ]
{
    set request = ##class(Hospital.OperateRequest).%New()
    set request.PatientID = patientID
    set request.RequestedOperation = RequestedOperation
    set request.LikelyOutcome = LikelyOutcome
    set tSC=..SendRequestSync("Hospital.PermissionToOperateProcess",request,.response)
    // Create the SOAP response, set its properties, and return it.
}

}

Defining Web Methods for Use in InterSystems IRIS

This section describes the basic requirements for an InterSystems IRIS web method.

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 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 additional notes, see Basic Requirements.

Basic Steps of an InterSystems IRIS Interoperability Web Method

Within a production web service, a web method should generally do the following:

  1. Create a request message and set its properties with information from the inbound SOAP message.

  2. Call a suitable method of the business service to send the request to a destination within the production. Specifically, call SendRequestSync(), SendRequestAsync(), or (less common) SendDeferredResponse(). For details, see Sending Request Messages.

    Each of these methods returns a status (specifically, an instance of %StatusOpens in a new tab).

  3. Check the status returned from the previous step and react appropriately.

  4. Then:

    • In the case of success, look at the response message that is returned by reference and use it to create the return value of the web method. As noted previously, the return value must be XML-enabled so that it can be packaged as a SOAP response.

    • In the case of failure, call the ReturnMethodStatusFault() or ReturnStatusFault() method of the web service so that a SOAP fault can be returned and an Ens.Alert can be generated; see the next section for details.

Returning Faults to the Caller

By default, if an error occurs when a web method runs, the web service returns a SOAP message to the caller, but this message does not indicate where precisely the fault occurred. An example follows:

  <SOAP-ENV:Body>
   <SOAP-ENV:Fault>
    <faultcode>SOAP-ENV:Server</faultcode>
    <faultstring>Server Application Error</faultstring>
   <detail>
      <error xmlns='http://www.myapp.org' >
        <text>ERROR #5002: ObjectScript error: <INVALID OREF>
            zGetCustomerInfo+10^ESOAP.WebService.1</text>
      </error>
   </detail>
   </SOAP-ENV:Fault>
  </SOAP-ENV:Body>

Your web methods should check for an error and use ReturnMethodStatusFault() or ReturnStatusFault(). In case of error, the message will be more informative, as follows:

  <SOAP-ENV:Body>
   <SOAP-ENV:Fault>
    <faultcode>SOAP-ENV:Method</faultcode>
    <faultstring>Server Application Error</faultstring>
    <faultactor>ESOAP.WebService</faultactor>
    <detail>
      <error xmlns='http://www.myapp.org' >
       <text>ERROR <Ens>ErrException:
             <DIVIDE>zGetCustomerRequest+8^ESOAP.MyOperation.1 -
             logged as '13 Jul 2007' number 4 @'    set x=100/0'</text>
     </error>
   </detail>
   </SOAP-ENV:Fault>
  </SOAP-ENV:Body>

The ReturnMethodStatusFault() and ReturnStatusFault() methods return a SOAP fault to the caller and then generate an exception which will create an alert (depending on settings). These methods have the following signatures:

ClassMethod ReturnStatusFault(pCode As %String,
                              pStatus As %Status)

ClassMethod ReturnMethodStatusFault(pStatus As %Status)

Here:

  • pCode is a string that represents the error code to use in the <faultcode> element of the SOAP fault. The ReturnMethodStatusFault() method uses the generic error code SOAP-ENV:Method

  • pStatus is the status to use in the returned SOAP fault. This is used to create the details of the SOAP fault.

Also notice that these methods set the <faultactor> element of the SOAP fault.

Example

The following shows a simple example:

Method GetCustomerInfo(ID As %Numeric) As ESOAP.SOAPResponse [WebMethod]
{
    //create request message with given ID
    set request=##class(ESOAP.CustomerRequest).%New()
    set request.CustomerID=ID

    //send request message 
    set sc= ..SendRequestSync("GetCustomerInfoBO",request,.response)
    if $$$ISERR(sc) do ..ReturnMethodStatusFault(sc)

    //use info from InterSystems IRIS response to create SOAP response
    set soapresponse=##class(ESOAP.SOAPResponse).%New()
    set soapresponse.CustomerID=response.CustomerID
    set soapresponse.Name=response.Name
    set soapresponse.Street=response.Street
    set soapresponse.City=response.City
    set soapresponse.State=response.State
    set soapresponse.Zip=response.Zip

    quit soapresponse
}

Viewing the WSDL

In InterSystems IRIS, a web service runs within an InterSystems IRIS web application. In turn, the web application is served by your choice of web server (the same web server that serves the Management Portal).

InterSystems IRIS automatically creates and publishes a WSDL document that describes your web service. Whenever you modify and recompile the web service, InterSystems IRIS automatically updates the WSDL correspondingly.

The URL has the following form, using the <baseURL> for your instance:

https:<baseURL>/csp/app/web_serv.cls?WSDL

Here /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, where namespace is the namespace that contains the web application and the production. )

For example:

https://devsys/csp/mysamples/MyApp.StockService.cls?WSDL

The browser displays the WSDL document as an XML document. The following shows an example:

file  listing showing XML WSDL definition for a sample GetCustomerInfo method

Web Service Example

The following simple example shows a production web service that can be used to look up customer information, given a customer ID.

Class ESOAP.WebService Extends EnsLib.SOAP.Service
{

Parameter ADAPTER;

Parameter NAMESPACE = "http://www.myapp.org";

Parameter SERVICENAME = "CustomerLookupService";

Method GetCustomerInfo(ID As %Numeric) As ESOAP.SOAPResponse [WebMethod]
{
    //create request message with given ID
    set request=##class(ESOAP.CustomerRequest).%New()
    set request.CustomerID=ID

    //send request message 
    set sc= ..SendRequestSync("GetCustomerInfoBO",request,.response)
    if $$$ISERR(sc) do ..ReturnMethodStatusFault(sc)

    //use info from InterSystems IRIS response to create SOAP response
    set soapresponse=##class(ESOAP.SOAPResponse).%New()
    set soapresponse.CustomerID=response.CustomerID
    set soapresponse.Name=response.Name
    set soapresponse.Street=response.Street
    set soapresponse.City=response.City
    set soapresponse.State=response.State
    set soapresponse.Zip=response.Zip

    quit soapresponse
}

}

The SOAP response class is as follows:

///
Class ESOAP.SOAPResponse Extends (%RegisteredObject, %XML.Adaptor)
{

Property CustomerID As %Numeric;
Property Name As %String;
Property Street As %String;
Property City As %String;
Property State As %String;
Property Zip As %Numeric;

}

Note the following points:

  • The example web method (GetCustomerInfo) uses SendRequestSync() to communicate with a business operation elsewhere in the production. The method receives a response message and uses it to create a SOAP response message.

  • The SOAP response class has the same properties as the corresponding production message response class. Unlike the production message response, however, the SOAP response class is XML-enabled and non-persistent.

Enabling SOAP Sessions

The SOAP specification does not include session support. However, it is often useful to maintain a session between a web client and the web service that it uses. You can do this with a production web service. If a web service uses sessions, it establishes a session ID and allows repeated calls on the service after one successfully authenticated call from a client.

Support for SOAP sessions is controlled by the SOAPSESSION class parameter. The default is 0, which means that the web service does not use sessions.

To enable SOAP sessions, create a subclass of EnsLib.SOAP.ServiceOpens in a new tab and set SOAPSESSION to 1 in the subclass. Base your production web service on this subclass.

For more information on SOAP sessions, see Creating Web Services and Web Clients.

Additional Options

Because your production web service extends %SOAP.WebServiceOpens in a new tab, you can use all the SOAP support provided by that class. This support includes options for the following customizations, among others:

  • Customizing the SOAP headers

  • Passing attachments in the SOAP messages

  • Changing the binding style of the SOAP messages from document-style (the default) to rpc-style

  • Changing the encoding style of the messages from literal (the default) to SOAP-encoded

  • Customizing the XML types used in the SOAP messages

  • Customizing the SOAPAction header used to invoke a web method

  • Controlling whether elements are qualified (controlling the elementFormDefault attribute of the web service)

  • Controlling the form of null arguments (to be an empty element rather than omitted)

  • Writing the web method to have output parameters instead of return values

For these options and others, see Creating Web Services and Web Clients.

Adding and Configuring the Web Service

To add your production web service (a business service) to a production, use the Management Portal to do the following:

  1. Add an instance of your custom class to the production.

    Important:

    Ensure that the configuration name is the same as the full class name, including package. This is a requirement for running a production web service.

  2. Enable the business service.

  3. Set the Pool Size setting to 0.

    For other settings, see Configuring Productions.

  4. Run the production.

FeedbackOpens in a new tab