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.
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.
-
Define the method within a subclass of EnsLib.SOAP.ServiceOpens in a new tab, as described in Basic Requirements.
-
Mark the method with the WebMethod keyword.
-
Ensure that all arguments and return values are XML-enabled:
-
If the method uses an object as an argument or a return value, you must ensure that the object is XML-enabled. That is, the class definitions for the types must extend %XML.AdaptorOpens in a new tab. The default settings for this class are normally suitable; if not, see Projecting Objects to XML.
-
If the method uses a data set as an argument or return value, you must ensure the data set is of type %XML.DataSetOpens in a new tab.
-
To use a collection (%ListOfObjectsOpens in a new tab or %ArrayOfObjectsOpens in a new tab) as an argument or a return value, you must ensure that the ELEMENTTYPE parameter of the collection is set and refers to an XML-enabled class.
-
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:
-
Create a request message and set its properties with information from the inbound SOAP message.
-
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).
-
Check the status returned from the previous step and react appropriately.
-
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:
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:
-
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.
-
Enable the business service.
-
Set the Pool Size setting to 0.
For other settings, see Configuring Productions.
-
Run the production.