Creating SOAP and REST Services and Web Clients with Ensemble Version 2015.1 11 February 2015 InterSystems Corporation 1 Memorial Drive Cambridge MA 02142 www.intersystems.com
Creating SOAP and REST Services and Web Clients with Ensemble Ensemble Version 2015.1 11 February 2015 Copyright 2015 InterSystems Corporation All rights reserved.,,,, Caché WEBLINK, and Distributed Cache Protocol are registered trademarks of InterSystems Corporation.,, InterSystems Jalapeño Technology, Enterprise Cache Protocol, ECP, and InterSystems Zen are trademarks of InterSystems Corporation. All other brand or product names used herein are trademarks or registered trademarks of their respective companies or organizations. This document contains trade secret and confidential information which is the property of InterSystems Corporation, One Memorial Drive, Cambridge, MA 02142, or its affiliates, and is furnished for the sole purpose of the operation and maintenance of the products of InterSystems Corporation. No part of this publication is to be used for any other purpose, and this publication is not to be reproduced, copied, disclosed, transmitted, stored in a retrieval system or translated into any human or computer language, in any form, by any means, in whole or in part, without the express prior written consent of InterSystems Corporation. The copying, use and disposition of this document and the software programs described herein is prohibited except to the limited extent set forth in the standard software license agreement(s) of InterSystems Corporation covering such programs and related documentation. InterSystems Corporation makes no representations and warranties concerning such software programs other than those set forth in such standard software license agreement(s). In addition, the liability of InterSystems Corporation for any losses or damages relating to or arising out of the use of such software programs is limited in the manner set forth in such standard software license agreement(s). THE FOREGOING IS A GENERAL SUMMARY OF THE RESTRICTIONS AND LIMITATIONS IMPOSED BY INTERSYSTEMS CORPORATION ON THE USE OF, AND LIABILITY ARISING FROM, ITS COMPUTER SOFTWARE. FOR COMPLETE INFORMATION REFERENCE SHOULD BE MADE TO THE STANDARD SOFTWARE LICENSE AGREEMENT(S) OF INTERSYSTEMS CORPORATION, COPIES OF WHICH WILL BE MADE AVAILABLE UPON REQUEST. InterSystems Corporation disclaims responsibility for errors which may appear in this document, and it reserves the right, in its sole discretion and without notice, to make substitutions and modifications in the products and practices described in this document. For Support questions about any InterSystems products, contact: InterSystems Worldwide Customer Support Tel: +1 617 621-0700 Fax: +1 617 374-9391 Email: support@intersystems.com
Table of Contents About This Book... 1 1 About SOAP and Web Services... 3 1.1 Ensemble Support for Web Services... 3 1.2 Ensemble Support for Web Clients... 4 1.2.1 The SOAP Wizard... 5 1.2.2 The Proxy Client... 6 1.2.3 The Business Operation of an Ensemble Web Client... 6 2 Creating an Ensemble Web Service... 9 2.1 Overall Behavior... 9 2.2 Basic Requirements... 10 2.3 Defining Web Methods for Use in Ensemble... 11 2.3.1 Basic Steps of an Ensemble Web Method... 11 2.3.2 Returning Faults to the Caller... 12 2.3.3 Example... 12 2.4 Viewing the WSDL... 13 2.5 Web Service Example... 14 2.6 Enabling SOAP Sessions... 15 2.7 Additional Options... 15 2.8 Adding and Configuring the Web Service... 15 3 Creating an Ensemble Web Client... 17 3.1 Overview... 17 3.2 Basic Steps... 18 3.2.1 Using the SOAP Wizard... 19 3.3 Generated Classes for an Ensemble Web Client... 20 3.4 Creating a Business Operation Class Manually... 22 3.4.1 Basic Requirements of the Class... 22 3.4.2 Basic Requirements of the Methods... 22 3.4.3 Ways to Execute the Proxy Methods... 23 3.4.4 Reference Information... 24 3.5 Adding and Configuring the Web Client... 25 3.5.1 Specifying Basics... 25 3.5.2 Specifying Credentials... 25 3.5.3 Specifying an SSL Configuration... 26 3.5.4 Specifying a Proxy Server... 26 4 Developing REST Services and Operations... 27 4.1 Developing a REST Service... 28 4.1.1 Defining the URL Using URLMap and EnsServicePrefix... 29 4.1.2 Specifying the Data Format... 31 4.1.3 Using a CSP Session with REST... 31 4.1.4 Authentication in REST... 31 4.1.5 Walkthrough the REST Samples in ENSDEMO... 31 4.2 Developing a REST Operation... 34 5 Using HTTP, REST, and SOAP Pass-through Services and Operations... 37 5.1 Configuring Pass-through Business Services... 38 5.2 Configuring Pass-through Business Operations... 38 Creating SOAP and REST Services and Web Clients with Ensemble iii
5.3 Using SAML Validation in Pass-through Services... 39 5.4 Pass-through Service and Operation Walkthrough... 40 5.4.1 Using REST Pass-through Services and Operations... 40 5.4.2 Using SOAP Pass-through Services and Operations... 43 Appendix A: Configuring Ensemble for SOAP and REST Services... 45 Appendix B: Using the SOAP Inbound Adapter... 49 B.1 Notes... 49 B.2 Development Tasks... 49 B.3 Configuration Tasks... 50 Appendix C: Older Ensemble Web Service Variation... 51 C.1 Overview... 51 C.2 Implementing the OnProcessInput() Method... 51 C.2.1 Using the phint Argument... 52 Reference for Settings... 53 Settings for the SOAP Inbound Adapter... 54 Settings for the SOAP Outbound Adapter... 56 Index... 59 iv Creating SOAP and REST Services and Web Clients with Ensemble
About This Book This book describes how an Ensemble programmer can create the following: SOAP web services SOAP operations (clients to external SOAP web services) REST services REST operations (clients to external REST services) Pass-through HTTP, REST, and SOAP services and operations. You should be familiar with the web protocol, HTTP, REST, or SOAP, that you are using. This book contains the following sections: About SOAP and Web Services Creating an Ensemble Web Service Creating an Ensemble Web Client Developing REST Services and Operations Using HTTP, REST, and SOAP Pass-through Services and Operations Configuring Ensemble for SOAP and REST Services Using the SOAP Inbound Adapter Older Ensemble Web Service Variation Reference for Settings For a detailed outline, see the table of contents. For more information, try the following sources: Ensemble Best Practices describes best practices for organizing and developing Ensemble productions. Developing Ensemble Productions explains how to perform the development tasks related to creating an Ensemble production. Configuring Ensemble Productions describes how to configure the settings for Ensemble productions, business hosts, and adapters. It provides details on settings not discussed in this book. Creating Web Services and Web Clients in Caché describes the specific standards followed by InterSystems product support for SOAP and web services. Projecting Objects to XML describes how to project Caché objects to XML and how to control that projection. (If you want to use an object as an argument for a web method, the class must be XML-enabled.) For general information, see the InterSystems Documentation Guide. Creating SOAP and REST Services and Web Clients with Ensemble 1
1 About SOAP and Web Services Ensemble provides support for SOAP 1.1 and 1.2 (Simple Object Access Protocol). This support is easy to use, efficient, and fully compatible with the SOAP specification. This support is built into Ensemble and is available on every platform supported by Ensemble. Using Ensemble SOAP support, you can do the following: Add a web service to an Ensemble production to provide a SOAP-enabled front end to the production. Client applications can invoke this Ensemble web service by using the SOAP protocol. Such methods can be discovered and invoked by other SOAP-aware applications. Ensemble runs SOAP methods directly within the database; the execution is highly efficient. Add a web client to an Ensemble production. You can use a tool to generate a business operation and the proxy client classes, given the existing WSDL document of the web service you want to use. The Ensemble web client invokes the external web service via the Ensemble SOAP outbound adapter and a generated proxy client class. This chapter discusses the following topics: Ensemble support for web services Ensemble support for web clients See the Creating Web Services and Web Clients in Caché book in the Caché documentation set for information on the specific standards followed by InterSystems product support for SOAP and web services, including WSDL limitations. 1.1 Ensemble Support for Web Services You can provide a SOAP-enabled front end for your Ensemble production. To do so, you create an Ensemble web service, which is both a web service and an Ensemble business service. Internally, your web methods generally receive SOAP request messages, use them to create and send Ensemble request messages as needed within the production, receive the Ensemble response messages, and use them to create SOAP response messages. Creating SOAP and REST Services and Web Clients with Ensemble 3
About SOAP and Web Services To enable you to create an Ensemble web service, Ensemble provides the base Ensemble web service class (EnsLib.SOAP.Service), as well as supporting classes in the %SOAP and %XML packages. Ensemble provides powerful, built-in support for web services. The base Ensemble web service class does the following for you: Validates incoming SOAP messages. Unpacks SOAP messages, converts data to Ensemble representation, and invokes the corresponding method, which sends an Ensemble request message to a destination inside the production. Runs the method. Receives an Ensemble response message and then creates and returns a response message (a SOAP message) to the caller. 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 an Ensemble 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. The Ensemble web service class also provides the full functionality of any Ensemble business service. Note: To create an Ensemble web service, you do not use an Ensemble adapter. 1.2 Ensemble Support for Web Clients You can invoke an external web service from within an Ensemble production. To do so, you create an Ensemble web client. 4 Creating SOAP and REST Services and Web Clients with Ensemble
Ensemble Support for Web Clients At a high level, your Ensemble web client receives Ensemble requests, converts them to SOAP requests and sends them to the appropriate web service. Similarly, it receives SOAP responses and converts them into Ensemble responses. The Ensemble web client consists of the following parts, all of which you can generate in Studio by using the SOAP wizard: A proxy client class that defines a proxy method for each method defined by the web service. The purpose of the proxy client is to specify the location of the web service and to contain the proxy methods. 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 methods. Supporting classes as needed to define XML types and Ensemble messages. 1.2.1 The SOAP Wizard In order to understand these parts, it is useful to consider how they are generated. First, when you use the SOAP wizard, you provide the URL for the WSDL of the web service of interest. The wizard reads the WSDL and then generates a set of classes. Creating SOAP and REST Services and Web Clients with Ensemble 5
About SOAP and Web Services 1.2.2 The Proxy Client The generated classes include the proxy client class that defines a proxy method for each method of the web service. Each proxy method sends a SOAP request to the web service and receives the corresponding SOAP response. As shown in the figure, the generated classes also include classes that define any XML types needed as input or output for the methods. 1.2.3 The Business Operation of an Ensemble Web Client The wizard cab also generate a business operation class that invokes the proxy client, as well as classes that define message types as needed. The following figure shows how these classes work: 6 Creating SOAP and REST Services and Web Clients with Ensemble
Ensemble Support for Web Clients The classes and methods shown within dashed lines are all generated by the SOAP wizard. The business operation uses the SOAP outbound adapter, which provides useful runtime settings and the generic method InvokeMethod(). To invoke a proxy method in the proxy client class, the business operation class calls InvokeMethod(), passing to it the name of the method to run, as well as any arguments. In turn, InvokeMethod() calls the method of the proxy client class. Creating SOAP and REST Services and Web Clients with Ensemble 7
2 Creating an Ensemble Web Service This chapter describes how to create an Ensemble web service, which is a web service in an Ensemble production. When you do this, you are providing a SOAP-enabled interface to the production. This chapter discusses the following: Overall behavior of an Ensemble web service Basic requirements How to define web methods How to view the generated WSDL for your web service A simple web service example How to enable SOAP sessions A summary of ways you can fine-tune the web methods How to add and configure the web service For settings not listed in this book, see Settings in All Productions in Managing Ensemble Productions. For an alternative approach, see the appendix Using the SOAP Inbound Adapter. 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. 2.1 Overall Behavior An Ensemble web service is based on EnsLib.SOAP.Service or a subclass. This class extends both Ens.BusinessService (so that it is an Ensemble business service) and %SOAP.WebService (so that it can act as a web service as well). An Ensemble 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 an Ensemble business service, it is an integral part of the Ensemble production to which you add it. Monitoring, error logging, runtime parameters, and all the rest of the Ensemble machinery are available as usual. Note: An Ensemble web service is not available unless the production is running (and the business service is enabled). Creating SOAP and REST Services and Web Clients with Ensemble 9
Creating an Ensemble Web Service Communication with the outside world is done via SOAP request and response messages. Ensemble request and response messages are used within the production. 2.2 Basic Requirements To create a web service in an Ensemble 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 Ensemble Messages in Developing Ensemble Productions. The following list describes the basic requirements of the business service class: Your class should extend EnsLib.SOAP.Service. This class extends both Ens.BusinessService (so that it is an Ensemble business service) and %SOAP.WebService (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 SERVICENAME NAMESPACE TYPENAMESPACE RESPONSENAMESPACE Description Name of the web service.this name must start with a letter and must contain only alphanumeric characters. The default service name is "MyEnsembleRequestWebService" 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. 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. 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 the Defining Web Methods section. For other options and general information, see Defining a Business Service Class in Developing Ensemble Productions. 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"; 10 Creating SOAP and REST Services and Web Clients with Ensemble
Defining Web Methods for Use in Ensemble 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. 2.3 Defining Web Methods for Use in Ensemble This section describes the basic requirements for an Ensemble web method. Define the method within a subclass of EnsLib.SOAP.Service, 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.Adaptor. 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.DataSet, which is an XML-enabled subclass of the standard %ResultSet. To use a collection (%ListOfObjects or %ArrayOfObjects) 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. 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 in the chapter Creating Web Services in Creating Web Services and Web Clients in Caché. 2.3.1 Basic Steps of an Ensemble Web Method Within an Ensemble web service, a web method should generally do the following: 1. Create an Ensemble 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 in Developing Ensemble Productions Each of these methods returns a status (specifically, an instance of %Status). 3. Check the status returned from the previous step and react appropriately. 4. Then: Creating SOAP and REST Services and Web Clients with Ensemble 11
Creating an Ensemble Web Service In the case of success, look at the Ensemble 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. 2.3.2 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: Cache 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 - </error> </detail> </SOAP-ENV:Fault> </SOAP-ENV:Body> logged as '13 Jul 2007' number 4 @' set x=100/0'</text> The ReturnMethodStatusFault() and ReturnStatusFault() methods return a SOAP fault to the caller and then generate an exception which will create an Ensemble 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. 2.3.3 Example The following shows a simple example: Method GetCustomerInfo(ID As %Numeric) As ESOAP.SOAPResponse [WebMethod] //create Ensemble request message with given ID 12 Creating SOAP and REST Services and Web Clients with Ensemble
Viewing the WSDL set request=##class(esoap.customerrequest).%new() set request.customerid=id //send Ensemble request message set sc=..sendrequestsync("getcustomerinfobo",request,.response) if $$$ISERR(sc) do..returnmethodstatusfault(sc) //use info from Ensemble 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 2.4 Viewing the WSDL Ensemble automatically creates and publishes a WSDL document that describes your Ensemble web service. Whenever you modify and recompile the web service, Ensemble automatically updates the WSDL correspondingly. To view the WSDL for the web service, use the following URL: base/app-name/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 CSP 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 Ensemble namespace that contains the CSP application. ) For example: http://localhost:57772/csp/samples/myapp.stockservice.cls?wsdl The browser displays the WSDL document as an XML document. The following shows an example: Creating SOAP and REST Services and Web Clients with Ensemble 13
Creating an Ensemble Web Service 2.5 Web Service Example The following simple example shows an Ensemble 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 Ensemble request message with given ID set request=##class(esoap.customerrequest).%new() set request.customerid=id //send Ensemble request message set sc=..sendrequestsync("getcustomerinfobo",request,.response) if $$$ISERR(sc) do..returnmethodstatusfault(sc) //use info from Ensemble 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 an Ensemble response message and uses it to create a SOAP response message. The SOAP response class has the same properties as the corresponding Ensemble response class. Unlike the Ensemble response, however, the SOAP response class is XML-enabled and non-persistent. 14 Creating SOAP and REST Services and Web Clients with Ensemble
Enabling SOAP Sessions 2.6 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 an Ensemble 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.Service and set SOAPSESSION to 1 in the subclass. Base your Ensemble web service on this subclass. For more information on SOAP sessions, see Creating Web Services and Web Clients in Caché in the Caché documentation. 2.7 Additional Options Because your Ensemble web service extends %SOAP.WebService, 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 in Caché in the Caché documentation set. 2.8 Adding and Configuring the Web Service To add your Ensemble web service (a business service) to an Ensemble production, use the Management Portal to do the following: 1. Add an instance of your custom class to the Ensemble production. Important: Ensure that the configuration name is the same as the full class name, including package. This is a requirement for running an Ensemble web service. 2. Enable the business service. 3. Set the Pool Size setting to 0. For other settings, see Configuring Ensemble Productions. Creating SOAP and REST Services and Web Clients with Ensemble 15
Creating an Ensemble Web Service 4. Run the production. 16 Creating SOAP and REST Services and Web Clients with Ensemble
3 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: An overview of the parts of an Ensemble web client The basic steps to create an Ensemble web client Information on the generated classes Details on how to create your own business operation class manually How to add and configure the web client 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. 3.1 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. Creating SOAP and REST Services and Web Clients with Ensemble 17
Creating an Ensemble Web Client 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. 3.2 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. 18 Creating SOAP and REST Services and Web Clients with Ensemble
Basic Steps 3.2.1 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. 3.2.1.1 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. 3.2.1.2 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 CompileFlags MakePersistent MakeSerial OutputTypeAttribute Purpose 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. If this property is 1, the proxy client is a persistent object; otherwise, it is a registered object. The initial expression is 0. If this property is 1 and if MakePersistent is 1, the proxy client is a serial class. The initial expression is 0. 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. Creating SOAP and REST Services and Web Clients with Ensemble 19
Creating an Ensemble Web Client Property MakeBusinessOperation Purpose 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. 3.3 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> 20 Creating SOAP and REST Services and Web Clients with Ensemble
Generated Classes for an Ensemble Web Client 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) 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; The response class is as follows: Class MyClient.BusOp.AddResponse Extends Ens.Response Property AddResult As MyClient.ComplexNumber; 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"); 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 SOAP and REST Services and Web Clients with Ensemble 21
Creating an Ensemble Web Client 3.4 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 business operation class Basic requirements of the methods Specific techniques, with examples, for calling the proxy methods Reference information for the adapter property and methods used here 3.4.1 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> You will also need to define the Ensemble message classes that the business operation uses. 3.4.2 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.) 22 Creating SOAP and REST Services and Web Clients with Ensemble
Creating a Business Operation Class Manually 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. 3.4.3 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; And Class GetStock.BusOp.GetQuoteRequest Extends Ens.Request Parameter RESPONSECLASSNAME = "GetStock.BusOp.GetQuoteResponse"; Property StockName As %String; 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 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: Creating SOAP and REST Services and Web Clients with Ensemble 23
Creating an Ensemble Web Client 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 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 In this case, you can provide any number of arguments. 3.4.4 Reference Information This section provides reference information for the adapter property and methods mentioned in the previous section. %Client property %SOAP.WebClient 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 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 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. 24 Creating SOAP and REST Services and Web Clients with Ensemble
Adding and Configuring the Web Client Invoke() method Method Invoke(pWebMethod As %SOAP.ProxyDescriptor) As %Status Calls the given method and returns the status. 3.5 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: Basic settings Settings related to credentials The setting that controls use of SSL Settings that control the use of a proxy server For settings not listed in this book, see Settings in All Productions in Managing Ensemble Productions. 3.5.1 Specifying Basics The following settings specify the basic information for the Ensemble web client: Web Service URL Web Service Client Class Response Timeout 3.5.2 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. Creating SOAP and REST Services and Web Clients with Ensemble 25
Creating an Ensemble Web Client Use the technique that is appropriate for the web service you are using. 3.5.3 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. 3.5.4 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. 26 Creating SOAP and REST Services and Web Clients with Ensemble
4 Developing REST Services and Operations Ensemble provides the capabilities to implement a REST service that can be invoked from a REST call and to implement a REST operation that is a client that can call an external REST service. REST, which is named from Representational State Transfer, has the following attributes: REST is an architectural style rather than a clearly defined format. Although REST is frequently implemented using HTTP for transporting messages and JSON for passing data, you can also pass data as XML or plain text. REST makes use of existing web standards such as HTTP, URL, XML, and JSON. REST is resource oriented. Typically a resource is identified by a URL and uses operations based explicitly on HTTP methods, such as GET, POST, PUT, and DELETE. REST typically has a small overhead. Although it can use XML to describe data, it typically uses JSON which is a light-weight data wrapper. JSON identifies data with tags but the tags are not specified in a formal schema definition and do not have explicit data types. To implement a REST service, you must extend the abstract class EnsLib.REST.Service, which itself extends the %CSP.REST, EnsLib.HTTP.Service, and Ens.Util.JSON classes. See Creating REST Services in SOAP and REST for Developers for information on creating REST services in Caché. To implement a REST operation to call an external REST service, you must extend the abstract class EnsLib.REST.Operation, which itself extends Ens.BusinessOperation and Ens.Util.JSON. The Demo.REST.MathService in ENSDEMO implements a very simple math service that simply adds two numbers. It is available in Studio. If you want to run it, you need to compile it in Studio and then add it to a production. The Demo.Rest.Production production in ENSDEMO has an example of both a REST service and a REST operation. To make the production self-contained and not dependent on an external REST service, the production s operation calls the production s own REST service rather than an external REST service. The sample was implemented in this way for convenience and not because this is an expected usage. Typically, you would add a REST service to a production because an external application is to access Ensemble data through a REST service. And you would a REST operation when your production needs to call an external REST service. This chapter contains: Developing a REST Service Developing a REST Operation Creating SOAP and REST Services and Web Clients with Ensemble 27
Developing REST Services and Operations 4.1 Developing a REST Service To develop a REST service you extend the class EnsLib.REST.Service. Ensemble REST services typically use Ensemble s CSP port, but they can also use a special port dedicated to providing the service. The special port is specified in the service configuration. Implementing a REST service is an extension of implementing an HTTP service. See Using the HTTP Inbound Adapter for details. Note: In most cases, we recommend that you use Ensemble s CSP port and not a special port. Using Ensemble s CSP port allows you to use a full-featured web server to provide robustness and security. To configure your REST service to use only the CSP port, you should: Leave the Port field blank. Check the Enable Standard Requests checkbox. Set the Pool Size to 0. If you do want to use the special port, set the port number and set a positive pool size. The EnsLib.REST.Service class, which is a subclass of %CSP.REST allows you to implement REST services. It provides the ability to: Define URL maps that specify the method that is executed for a REST URL and HTTP method. Specify whether each REST call is executed under its own CSP session or shares a single session with other REST calls. Optionally, override error handling methods. To implement a REST service, you extend the EnslLib.REST.Service class. Your extension of the class provides the URLMap, can optionally set the USESession parameter, and provides methods to perform the REST operations. You can have multiple services in a production that are share the same subclass of EnslLib.REST.Service. Ensemble uses the configuration name of the service to distinguish between them. These services can either share the same web application or have separate web appications. You define the CSP web application and specify its security for on the Management Portal s [System] > [Security Management] > [Web Application] page, which you can access by clicking System Administration, Security, Applications, and Web Applications. When you define the CSP web application, you specify the first part of the URL for the REST call as the name of the web application. Although EnsLib.REST.Service is a subclass of %CSP.REST, they have the following differences: In %CSP.REST, the methods that implement a REST service must be class methods. In EnsLib.REST.Service, they can be either class or instance methods. You can define more than one subclass of %CSP.REST in a namespace, but each subclass that you define must have its own CSP web application. But a single web application can handle multiple business services with the class EnsLib.REST.Service, Ensemble uses the configuration name to distinguish between them. EnsLib.REST.Service has the EnsServicePrefix parameter that helps define the URL to call the service and has features to remove the application name and configuration name from the URL. %CSP.REST does not have this feature. The following sections describe: Defining the URL Using URLMap and EnsServicePrefix Specifying the Data Format Using a CSP Session with REST 28 Creating SOAP and REST Services and Web Clients with Ensemble
Developing a REST Service Authentication in REST Walkthrough the REST Samples in ENSDEMO 4.1.1 Defining the URL Using URLMap and EnsServicePrefix The complete REST URL consists of the following pieces: Server name and port of the Ensemble CSP port. In this chapter, the server name and port http://localhost:57772 is used in the examples. Name of the web application as defined on the [System] > [Security Management] > [Web Application] page. Configuration name of the REST business service. The string defined by the EnsServicePrefix parameter. If you are calling the service through the CSP port and are using URLMap, this string must start with a (vertical bar) which tells Ensemble to remove the web application name, configuration name, and prefix before processing it with URLMap. The remainder or the REST URL is defined by the Route Url element. If a segment of the Url element is preceded by a : (colon), it represents a parameter. The REST URL call can have any value in that segment. It is passed to the method as a parameter, In order to call a REST service using the CSP port, you must first define a web application to handle the class of the service. For example, to call the Demo.REST.MathService or the Demo.REST.DirectoryService in ENSDEMO, you could define a web application named /RestServices in the ENSDEMO namespace. You must allow access to the ENSDEMO database and the SAMPLES database. See Configuring Ensemble for SOAP and REST Services for a walkthrough of configuring Ensemble and defining a web application. The XDATA URLMap defines Routes, where each Route specifies a class method to be called for the specified URL and HTTP operation. Typically REST uses the GET, POST, PUT, or DELETE operations, but you can specify any HTTP operation. The URL can optionally include parameters that are specified as part of the REST URL and passed to the specified method as parameters. The Route definition has three parts: Url specifies the format of the last part of the REST URL to call the REST service. Method specifies the HTTP operation for the REST call: typically these are GET, POST, PUT, or DELETE, but any HTTP operation can be used. You should choose the REST operation that is appropriate for the function being performed by the service, but the %CSP.REST class does not perform any special handling of the different operations. Call specifies the method to call to perform the REST service. By default, this method is defined in the class that subclasses EnsLib.REST.Service, but you can explicitly specify a class method in any Caché class. You can define multiple Route definition in a single REST service. For example, consider the following UrlMap. This is not the UrlMap that is defined in Demo.REST.MathService provided in ENSDEMO, but is an enhanced version of that service. XData UrlMap <Routes> <Route Url="/sum/:number1/:number2" Method="GET" Call="Sum"/> <Route Url="/product/:number1/:number2" Method="GET" Call="Product"/> <Route Url="/difference/:number1/:number2" Method="GET" Call="Difference"/> <Route Url="/quotient/:number1/:number2" Method="GET" Call="Quotient"/> </Routes> Parameter EnsServicePrefix = " math" The complete REST URL consists for the sum route is: Creating SOAP and REST Services and Web Clients with Ensemble 29
Developing REST Services and Operations Server name and port of the Ensemble CSP port: http://localhost:57772 Name of the web application: /RestServices EnsServerPrefix: directory: math The string defined by the Route Url element, which is /sum followed by two numbers The following URL is sent to the CSP port with the HTTP GET command: http://localhost:57772/restservices/math/sum/7/5 Ensemble calls the Sum method of the service and includes the two numbers as parameters to the call. The method has the following prototype: ClassMethod Sum( pinput As %Library.AbstractStream, Output poutput As %Stream.Object, pnumber1 As %Integer, pnumber2 As %Integer ) As %Status If a URLMap defines multiple Routes, Ensemble must be able to distinguish them based on one or more of the following: URL segment text (excluding parameters indicated by :) Number of segments HTTP operation In the MathService, each Route is unique because of the text value of the first segment. In the ENSDEMO DirectoryService, the Route URLs consist completely of parameters. They are differentiated by either the number of segments in the URL or the HTTP command: XData UrlMap <Routes> <Route Url="/:personType" Method="PUT" Call="createPerson"/> <Route Url="/:personType/:keyfield/:keyval/:getfield" Method="GET" Call="retrievePerson"/> <Route Url="/:personType/:keyfield/:keyval" Method="GET" Call="retrievePerson"/> <Route Url="/:personType/:keyfield/:keyval" Method="POST" Call="updatePerson"/> <Route Url="/:personType/:keyfield/:keyval" Method="DELETE" Call="deletePerson"/> </Routes Parameter EnsServicePrefix = " directory" You can define a different method for each HTTP operation for a single URL. Note: The :parameter-name syntax for defining parameters in the URL is implemented using regular expressions. Each segment specified as :parameter-name is converted to a matching group in the regular expression. In most cases this format provides enough flexibility to specify the REST URL, but advanced users can use the regular expression format directly in the route definition. The URL must match the regular expression and each matching group, which is specified by a pair of parentheses, defines a parameter to be passed to the method. The :parameter-name syntax is translated to a ([^/]+) within the regular expression. This syntax matches any character except the / (slash). So the sum sample, which is Url="/sum/:number1/:number2", is equivalent to: Url="/sum/([^/]+)/([^/]+)" where there are two matching groups that specify two parameters. If you wanted a component of the URL to have the values: Direction_Up or Direction_Down, you could define the route map as follows: <Route Url="/controlVehicle/Direction_(Up Down)" Method="POST" Call="Move" /> With this definition, the parameter would have either the value Up or Down since that is the value of the matching group. 30 Creating SOAP and REST Services and Web Clients with Ensemble
Developing a REST Service 4.1.2 Specifying the Data Format You can define your REST service to handle data in different formats, such as JSON, XML, text, or CSV. A REST call can specify the form that it expects data it is sending by specifying a ContentType element in the HTTP request and can request the return data format by specifying an Accept element in the HTTP request. See Creating REST Services in SOAP and REST for Developers for an example. 4.1.3 Using a CSP Session with REST The UseSession parameter controls whether Ensemble uses a new CSP session for each REST service call or preserves a CSP session across multiple REST service calls. One of the goals of REST is to be stateless, that is no knowledge is stored on the server from one REST call to the next. Having a CSP session preserved across REST calls breaks the stateless paradigm, but there are two reasons why you might want to preserve a CSP session: Minimize license usage if each REST call creates a new CSP session it requires a separate license. Ensemble frees the license after a brief timeout period. If you are making rare and infrequent REST calls, this is usually not a problem, but if you are making many REST calls in a brief time period, you can exceed the number of licenses available on your system. If you use the same CSP session for multiple REST calls, the session only consumes one license. Preserve data across REST calls in some cases, preserving data across REST calls may be necessary to efficiently meet your business requirements. To enable using a single CSP session over multiple REST calls, set the UseSession parameter to 1 in your subclass of EnsLib.REST.Service. For example: Class REST.MyServices Extends EnsLib.REST.Service Parameter UseSession As Integer = 1 4.1.4 Authentication in REST If your REST service is accessing confidential data, you should use authentication. You can use either of the two following forms of authentication: HTTP authentication headers this is the recommended form of authentication for REST services. CSP session authentication where the username and password are specified in the URL following a question mark. 4.1.5 Walkthrough the REST Samples in ENSDEMO The Demo.REST.DirectoryService implements a REST service that provides access to a Caché database provided in the SAMPLES namespace. In order to call a REST service using the CSP port, you must first define a web application to handle the class of the service. For example, to call the Demo.REST.MathService or the Demo.REST.DirectoryService in ENSDEMO, you could define a web application named /RestServices in the ENSDEMO namespace. You must allow access to the ENSDEMO database and the SAMPLES database. See Configuring Ensemble for SOAP and REST Services for a walkthrough of configuring Ensemble and defining a web application. If you are running Demo.Rest.Production, then you can enter following REST call in a web browser. This sends an HTTP GET request that queries for the people in the database whose name begins with j : http://localhost:57772/restservices/demo.rest.directoryservice/directory/person/name/j* The browser sends this URL as an HTTP Get command. The URLMap sends this request to the retrieveperson method with the following parameters: Creating SOAP and REST Services and Web Clients with Ensemble 31
Developing REST Services and Operations retrieveperson("person","name","j*") This method builds an SQL query statement that requests the information from the SAMPLES database and executes the query. It then calls the ObjectToJSONStream() method and returns the following JSON to the REST caller: [, ] "Age":38, "Company":"InterTron Holdings Inc.", "DOB":"1975-06-05", "FavoriteColors":, "Home": "City":"Islip", "State":"WY", "Street":"1199 Maple Place", "Zip":38998, "ID":179, "Name":"Jung,Jules G.", "Office": "City":"Youngstown", "State":"OH", "Street":"803 Madison Place", "Zip":70937, "SSN":"584-94-9346", "Spouse":"Underman,Diane Z." "Age":24, "Company":"MacroNet Associates", "DOB":"1989-06-05", "FavoriteColors":["Black","Purple" ], "Home": "City":"Jackson", "State":"VT", "Street":"9371 Elm Drive", "Zip":93057, "ID":186, "Name":"Jung,Sam B.", "Office": "City":"Gansevoort", "State":"SD", "Street":"6284 First Place", "Zip":84332, "SSN":"173-48-2772", "Spouse":"Fripp,Hannah D." Although you can create an HTTP GET command by just entering a URL in a browser, it is harder to generate an HTTP POST, PUT, or DELETE. You can use a utility such as curl to generate these HTTP commands or you can use the DirectoryPage and DirectoryOperation provided in the ENSDEMO REST sample. Since the DirectoryOperation calls the REST service from the Ensemble DirectoryService, it is not an ideal example showing how to call an external REST service, but it is a very useful tool to demonstrate calling the DirectoryService REST services. To use the DirectoryPage and Directory Operation, in Studio select the ENSDEMO namespace and open the class Demo.REST.DirectoryPage. Select View Web Page and Studio displays the following web page in your default browser: 32 Creating SOAP and REST Services and Web Clients with Ensemble
Developing a REST Service If you enter j* as the Key Value and click Retrieve, the web page and DirectoryOperation sends the same HTTP GET command that you entered in the browser. The web page displays the URL sent to the DirectoryService and the JSON returned by it. The page displays a table with two columns from the returned data. If you click on one of the rows, the page displays all of the properties and values for that person. You can then alter some of the values and click Update, which generates an HTTP POST command. If you click Delete, it deletes the record with the specified ID value with an HTTP DELETE command. Finally if you update the SSN field with a unique value and click Create, it creates a new record with an HTTP PUT command. The DirectoryPage web page displays the JSON value returned by DirectoryService but does not display any JSON values sent to the service. One way to view these values is to use a TCP trace utility. Simply modify the DirectoryOperation configuration page to specify another port, such as 9989 and then use the TCP trace utility to transfer the message from port 9989 to 9988. Remember, if you use this page to update the data, you are changing the data in the Caché SAMPLES database. It is also possible to not use URLMap and implement the lower-level OnProcessInput() method. The following shows to process the call in this method: Class Demo.REST.DirectoryService Extends EnsLib.REST.Service Parameter ADAPTER = "EnsLib.HTTP.InboundAdapter"; /// The EnsServicePrefix parameter identifies the URL prefix that this component handles Parameter EnsServicePrefix = "/directory"; Method OnProcessInput( pinput As %Library.AbstractStream, Output poutput As %Stream.Object) As %Status /// Contains the HTTP command /// Output to return to REST call /// Get the HTTP operation: GET, POST, PUT, or DELETE Set tcmd=$zconvert(pinput.attributes("httprequest"),"u") /// Get the URL Set turl=$zconvert(pinput.attributes("url"),"i","url") /// Get the 2nd part of the URL which contains the service, /// Test that it matches EnsServicePrefix, "/directory" Set tservice="/"_$zconvert($piece(turl,"/",2),"l") Quit:..#EnsServicePrefix'=tService /// Get the 3rd part of the URL either person or employee Set ttype=$zconvert($piece(turl,"/",3),"l") /// Get the 4th part of the URL in this case name Set tkeyin=$piece(turl,"/",4), tkey=$zconvert(tkeyin,"l") Creating SOAP and REST Services and Web Clients with Ensemble 33
Developing REST Services and Operations /// Get the 5th part of the URL, the value to query for Set tkeyval=$replace($zconvert($piece(turl,"/",5),"i","url"),"'","''") 4.2 Developing a REST Operation To develop a REST operation, you extend the class EnsLib.REST.Operation. The REST operation uses Ensemble s outbound HTTP adapter, which is described in Using the HTTP Outbound Adapter. Using the HTTP Outbound Adapter, you specify the server, port, and address of the external web service in the HTTP adapter configuration. For example, to define a REST operation that calls a weather service, you could configure the operation as follows: In your extension of EnsLib.REST.Operation, you specify the remaining parts of the URL by appending the value to the adapter URL property. Then you call one of the following adapter methods depending on what HTTP operation you want to use: GetURL() uses the HTTP GET operation. PostURL() uses the HTTP POST operation. PutURL() uses the HTTP PUT operation. DeleteURL() uses the HTTP DELETE operation. SendFormDataArray() allows you to specify the HTTP operation as a parameter. For example, the following extension of EnsLib.REST.Operation calls the weather REST service and provides a city name as a parameter: Class Test.REST.WeatherOperation Extends EnsLib.REST.Operation Parameter INVOCATION = "Queue"; Method getweather( prequest As Test.REST.WeatherRequest, Output presponse As Test.REST.WeatherResponse) As %Status try // Prepare and log the call 34 Creating SOAP and REST Services and Web Clients with Ensemble
Developing a REST Operation // Append the city to the URL configured for adapter Set turl=..adapter.url_"?q="_prequest.city_"&units=imperial" // Execute the call Set tsc=..adapter.geturl(turl,.thttpresponse) // Return the response If $$$ISERR(tSC)&&$IsObject(tHttpResponse)&&$IsObject(tHttpResponse.Data)&&tHttpResponse.Data.Size Set tsc=$$$error($$$enserrgeneral,$$$statusdisplaystring(tsc)_":"_thttpresponse.data.read()) Quit:$$$ISERR(tSC) If $IsObject(tHttpResponse) // Instantiate the response object set presponse = ##class(test.rest.weatherresponse).%new() // Convert JSON into a Proxy Cache Object set tsc =..JSONStreamToObject(tHttpResponse.Data,.tProxy) if (tsc) // Set response properties from the Proxy Object set presponse.temperature = tproxy.main.temp_"f" set presponse.humidity = tproxy.main.humidity_"%" set presponse.maxtemp = tproxy.main."temp_max"_"f" set presponse.mintemp = tproxy.main."temp_min"_"f" set presponse.pressure = tproxy.main.pressure_" mbar" set presponse.windspeed = tproxy.wind.speed_" MPH" set presponse.winddirection = tproxy.wind.deg_" degrees" // Convert from POSIX time set presponse.sunrise = $ZT($PIECE($ZDTH(tProxy.sys.sunrise, -2),",",2),3) set presponse.sunset = $ZT($PIECE($ZDTH(tProxy.sys.sunset, -2),",",2),3) catch Set tsc=$$$systemerror Quit tsc XData MessageMap <MapItems> <MapItem MessageType="Test.REST.WeatherRequest"> <Method>getWeather</Method> </MapItem> </MapItems> The message sent to the operation specifies the city: Class Test.REST.WeatherRequest Extends (%Persistent, Ens.Util.MessageBodyMethods) Property City As %String; This operation calls the JSONStreamToObject() method and returns a Caché object that makes the elements of the JSON accessible. The message returned by this sample returns the following properties taken from the JSON stream: Class Test.REST.WeatherResponse Extends (%Persistent, Ens.Util.MessageBodyMethods) Property Temperature As %String; Property MinTemp As %String; Property MaxTemp As %String; Property Pressure As %String; Property Humidity As %String; Property WindSpeed As %String; Property WindDirection As %String; Property Sunrise As %String; Property Sunset As %String; If you don t have a business process running you can run and test this and other operations in [Ensemble > Production Configuration] by selecting your operation, navigating to Actions in the Production Settings menu and clicking Test. Creating SOAP and REST Services and Web Clients with Ensemble 35
5 Using HTTP, REST, and SOAP Pass-through Services and Operations Ensemble s pass-through services and operations enable you to receive an HTTP, REST, or SOAP request and pass it through to an external service. In this case, you are not using Ensemble to provide or consume a service but are using Ensemble to route a service request. This capability allows you to develop productions that can: Provide a log or audit trail for HTTP, REST, and SOAP calls. The calls pass through Ensemble as messages. Consequently, you can use any of Ensemble s capabilities to preserve or track the messages. Transform the messages when passing them between the client and provider. The following services and operations provide the pass-through capabilities: EnsLib.HTTP.GenericService and EnsLib.HTTP.GenericOperation the service accepts an HTTP call and the operation passes it to a service provider. EnsLib.REST.GenericService and EnsLib.REST.GenericOperation the service accepts a REST call and the operation passes it to a service provider. EnsLib.SOAP.GenericService and EnsLib.SOAP.GenericOperation the service accepts a SOAP call and the operation passes it to a service provider. EnsLib.REST.SAMLGenericService subclass of EnsLib.REST.GenericService that validates the SAML data in the HTTP Authorization header. EnsLib.SOAP.SAMLGenericService subclass of EnsLib.SOAP.GenericService that validates the SAML data in the SOAP header. In the simplest case, a pass-through service sends the message directly to a pass-through operation. But it is possible to send the message to a router or any custom business process or operation. In a similar manner, a pass-through operation can receive a message from any custom business service or process. We recommend that pass-through services use the CSP port to accept requests, but you can configure them to accept requests on a special port. This chapter contains: Configuring Pass-through Business Services Configuring Pass-through Business Operations Using SAML Validation in Pass-through Services Pass-through Service and Operation Walkthrough Creating SOAP and REST Services and Web Clients with Ensemble 37
Using HTTP, REST, and SOAP Pass-through Services and Operations 5.1 Configuring Pass-through Business Services To add a pass-through business service, click the + sign for adding a new service in the Production Configuration page, then: 1. Select the class based on the protocol used and whether SAML security is being used. Choose a class from the following: EnsLib.HTTP.GenericService EnsLib.REST.GenericService EnsLib.REST.SAMLGenericService EnsLib.SOAP.GenericService EnsLib.SOAP.SAMLGenericService 2. Decide if the pass-through service is to be called through the CSP port or a special port, or both. In most cases, you should configure your service to be called through the CSP port If your pass-through service is to be called on the CSP port: Leave the Port field blank. Check the Enable Standard Requests checkbox in the Connection Settings field on the Settings tab. On the Additional Settings section, set the Pool Size to 0. This suppresses the pass-through service from listening on the special port. If you omit this step and leave the Port field blank, Ensemble displays an error message. If your pass-through service is to be called from a special port: Specify a port number. Uncheck the Enable Standard Requests checkbox in the Connection Settings field on the Settings tab. 3. Set the Target to point to the pass-through operation. To optimize performance for pass-through services that use the CSP port, you can configure the pass-through business service to keep the connection open between calls. You can do this by checking the Keep Standard Request Partition checkbox. See Using SAML Validation in Pass-through Services for information on using SAML validation on SOAP and REST pass-through services. The AdapterURL field is only present on the SOAP pass-through services. For SOAP Services invoked through the SOAP Inbound Adapter on a custom local port, this setting allows a custom URL to be used. 5.2 Configuring Pass-through Business Operations The HTTP Server setting specifies the endpoint for the external server. The URL setting controls how the URL from the pass-through service is modified. In a pass-through operation, you can specify the URL to use to call the external server in the following ways: Explicitly specify the URL in the URL setting. 38 Creating SOAP and REST Services and Web Clients with Ensemble
Using SAML Validation in Pass-through Services Use the URL that was used to call the pass-through service, optionally removing the part of the URL used to specify the standard CSP port. You control how to specify the URL in a pass-through operation by setting the URL property as follows: If you specify a URL path in this property, the pass-through operation uses the URL as specified. If the URL from the pass-through service specifies parameter values, the operation appends the parameter values from the pass-through service to the URL specified in this property. To use the URL specified in calling the pass-through service, set the URL property to: empty string: Use the URL from the GenericMessage, which is typically the URL passed into the generic service. Typically, you use this if the pass-through service is called from a special port and the URL does not contain the web application name and the service component name. (vertical bar): Remove the web application name and configuration name from the URL value in the GenericMessage and use the remainder as the URL. Typically, you use this when the GenericService is called using the standard CSP port. The web application name and the configuration name of the business service are needed to route the call to the GenericService but are not needed by the external server. If any text follows the vertical bar, this text is inserted at the beginning of the URL in place of the web application name and configuration name. If the web application name and configuration name are not present, then this text is inserted at the beginning of the URL. ^ (circumflex): Remove the web application name from the URL value in the GenericMessage and use the remainder as the URL. Typically, this is only used if the GenericService is called using the standard CSP port and the pass-through operation component has a name that is identical to the first part of the URL expected by the external server. The HTTP, REST, and SOAP pass-through operations additional settings specify other details about the operation. Two fields that are only present for SOAP pass-through operations are the SOAPPrefix and VDoccFormat fields. For most passthrough SOAP operations the message sent to the operation has both a SOAP envelope and XML stream as well as the XML object. These two fields instruct the operation on how to generate the SOAP envelope if it is missing and how to convert the XML object to an XML stream if that is missing. 5.3 Using SAML Validation in Pass-through Services Pass-through services validates the SAML token but does not check it to see if it provides access to the resources on the external server. The external server must check if the SAML token permits the requested access. The Validation field controls the level of SAML token validation done by the pass-through business service. The following flags specify the kind of validation that is done: t Must contain an Authorization header SAML token with key 'access_token=' a Token must contain an Assertion. r Requires Assertions to contain NotBefore/NotOnOrAfter time conditions v Verifies Assertion signatures using a Trusted X.509 certificate and, if present, NotBefore/NotOnOrAfter conditions. o Validates other signed nodes such as TimeStamp. By default, validation has a value of 1, which is equivalent to specifying tarvo. If you specify a value of 0, the pass-through service performs no validation. Creating SOAP and REST Services and Web Clients with Ensemble 39
Using HTTP, REST, and SOAP Pass-through Services and Operations When checking the NotBefore and NotOnOrAfter time conditions, the default clock skew allowance is 90 seconds. To change the skew allowance, set the global ^Ens.Config("SAML","ClockSkew"). To set the default clock skew for all components to 180 seconds, enter the following command: Set ^Ens.Config("SAML","ClockSkew")=180 To change the skew allowance for a specific component to 180 seconds, enter the following command: Set ^Ens.Config("SAML","ClockSkew",component-name)=180 5.4 Pass-through Service and Operation Walkthrough This walkthrough demonstrates how to use pass-through services and operations. Note: This walkthrough makes use of some free services provided by the openweathermap.org server and the www.webservicex.net server. Neither of these servers is associated with InterSystems Corporation and these servers may not always be available. If they are not available, you can substitute any other REST or SOAP server available to you. The openweathermap.org server supplies free weather data. If you intend to use it in an application, you should get a application ID. Although the service is free, product support is available for the weather server at a fee. See http://openweathermap.com/ for more information about this server. The www.webservicex.net server is provided by Cloud Computing Technologies Ltd. For more information on the server, contact them at Info@WebserviceX.NET. This section contains: Using REST Pass-through Services and Operations Using SOAP Pass-through Services and Operations 5.4.1 Using REST Pass-through Services and Operations This section adds a REST pass-through service and a REST pass-through operation. The service listens on the CSP port and sends the HTTP REST message to the pass-through operation. The pass-through operation sends the HTTP REST message to an external server, api.openweathermap.org, that returns current weather information. Select or create a namespace and production. In order to use the CSP port, you must define a web application in the namespace and a role. See Configuring Ensemble for SOAP and REST Services for step-by-step instructions to create a namespace, role, and web application. For this walkthrough, name the web application /RESTpassthrough and set the web application Dispatch Class to EnsLib.REST.GenericService. 1. On the production configuration page, click the plus sign for adding new operations. a. Specify the operation class: EnsLib.REST.GenericOperation b. Name the operation, such as WeatherRESTPassthroughOp. c. Don't enable it yet. d. Click OK. 2. Select the Pass-through operation that you created and select the Settings tab. a. Enter the HTTP Server: api.openweathermap.org b. Set the URL field to: c. Leave the other fields at their default values. 40 Creating SOAP and REST Services and Web Clients with Ensemble
Pass-through Service and Operation Walkthrough d. Check the Enabled checkbox. e. Click Apply. 3. Click the plus sign for adding new services. a. Specify the service class: EnsLib.REST.GenericService b. Name the service, such as WeatherRESTPassthroughServ. c. Don't enable it yet. d. Click OK. 4. Select the Pass-through service that you created and select the Settings tab. a. Ensure that the Port number is blank. b. In the TargetConfigName field, choose the pass-through operation that you added in the previous step. c. In Connection Settings, check the Enable Standard Requests checkbox. d. In Additional Settings, set Pool Size to 0. This suppresses the pass-through service from listening on the special port. If do not set the pool size to 0, you must specify a port number. e. Check the Enabled checkbox. f. Click Apply. 5. Start the production. 6. Enter the URL for the pass-through service using the CSP port. The URL consist of the following parts: http://localhost:nnnnnn/ where nnnnnn is the default CSP port. web-application-name/ passthrough-service-name/ URL required by the external service, such as data/2.5/weather?q=london,uk. For example, enter the following URL in a web browser: http://localhost:57772/restpassthrough/weatherrestpassthroughserv/data/2.5/weather?q=boston,ma If all is working, the call returns a JSON message with the current weather in London. For example, it can return the following JSON message: "coord":"lon":-0.13,"lat":51.51, "sys":"message":0.0441,"country":"gb","sunrise":1399609017,"sunset":1399664214, "weather":["id":802,"main":"clouds","description":"scattered clouds","icon":"03n"], "base":"cmc stations", "main":"temp":285.32,"pressure":1008,"temp_min":284.15,"temp_max":286.48,"humidity":91, "wind":"speed":5.14,"gust":6.17,"deg":284, "rain":"3h":0, "clouds":"all":32, "dt":1399600508, "id":2643743, "name":"london", "cod":200 5.4.1.1 Pass-through Background Information Notice how the URL is transformed between your call to the pass-through service and the call to the external server. The URL sent to the pass-through service is: Creating SOAP and REST Services and Web Clients with Ensemble 41
Using HTTP, REST, and SOAP Pass-through Services and Operations http://localhost:57772/restpassthrough/weatherrestpassthroughserv/data/2.5/weather?q=boston,ma and the URL sent to the external server is: http://api.openweathermap.org/data/2.5/weather?q=london,uk The last parts of the URL starting with data are identical. The HTTP Server field sets the server in the outgoing call. The in the URL field instructs the operation to strip the web application name and configuration name from the incoming URL and then include the remainder in the outgoind URL. Note: The EnsLib.REST.GenericService class does not provide any additional functionality over the EnsLib.HTTP.GenericService class. Although you could use the EnsLib.HTTP.GenericService class to pass-through a REST call, you should use the appropriate subclass. 5.4.1.2 Pass-through Troubleshootiing There are a few troubleshooting steps you can take if you don't get the expected results. 1. Enter the openweathermap URL directly in the web browser without using Ensemble. Enter the following URL in the web browser: http://api.openweathermap.org/data/2.5/weather?q=london,uk This ensures that the weather server is working correctly. 2. Examine the Ensemble message tracing for the production. A successful message trace looks like the following: The trace may help you identify where the error is. 3. Run a TCP trace utility. Specify a local port to listen on, the server api.openweathermap.org, and port 80. In the passthrough operation settings, set the following properties: HTTP Server: localhost HTTP Port: port that TCP trace is listening on Then click Apply and enter the pass-through service URL in a web browser: http://localhost:57772/restpassthrough/weatherrestpassthroughserv/data/2.5/weather?q=boston,ma 42 Creating SOAP and REST Services and Web Clients with Ensemble
Pass-through Service and Operation Walkthrough The TCP trace should show the HTTP request being sent out by the pass-through operation and the server's response. 5.4.2 Using SOAP Pass-through Services and Operations This section adds a SOAP pass-through service and a SOAP pass-through operation. The service listens on the CSP port and sends the SOAP message to the pass-through operation. The pass-through operation sends the SOAP message to an external server, www.webservicex.net, which among other services provides a currency conversion service that returns the exchange rate for two specified currencies. In order to call the SOAP passthrough services, you need to use a SOAP toolkiit, such as SOAPUI. For information on the SOAPUI toolkit, see http://www.soapui.org/. Select or create a namespace and production. In order to use the CSP port, you must define a web application in the namespace and a role. See Configuring Ensemble for SOAP and REST Services for step-by-step instructions to create a namespace, role, and web application. For this walkthrough, name the web application /SOAPpassthrough and set the web application Dispatch Class to EnsLib.SOAP.GenericService. 5.4.2.1 Calling the External Server from the SOAP Toolkit Before creating the pass-through services and operations, use a SOAP toolkit to create a project and call the external server directly. Using your SOAP toolkit, do the following: Create a new project. Specify the following as the location of the WSDL file: http://www.webservicex.net/currencyconvertor.asmx?wsdl Select the request generated for the project. If your toolkit generates a SOAP 1.1 and 1.2 requests, use the SOAP version 1.2 request. The toolkit displays the SOAP message that is sent to the server. For example, SOAPUI displays: <soap:envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:web="http://www.webservicex.net/"> <soap:header/> <soap:body> <web:conversionrate> <web:fromcurrency>?</web:fromcurrency> <web:tocurrency>?</web:tocurrency> </web:conversionrate> </soap:body> </soap:envelope> Replace the two question marks with the abbreviations for the currencies. For example, to convert Euros to US Dollars, replace the first question mark with EUR and the second question mark with USD. Execute the request. Using SOAPUI, you execute the request by clicking the green arrow. The SOAP toolkit displays the response SOAP message, such as: <soap:envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xsd="http://www.w3.org/2001/xmlschema"> <soap:body> <ConversionRateResponse xmlns="http://www.webservicex.net/"> <ConversionRateResult>1.3603</ConversionRateResult> </ConversionRateResponse> </soap:body> </soap:envelope> 5.4.2.2 Adding the SOAP Passthrough Service and Operation This section adds a SOAP passthrough operation and a SOAP passthrough service that use the CSP port. 1. Go to the Production Configuration page and click the plus sign for adding new operations. a. Specify the operation class: EnsLib.SOAP.GenericOperation Creating SOAP and REST Services and Web Clients with Ensemble 43
Using HTTP, REST, and SOAP Pass-through Services and Operations b. Name the operation, such as ConvertCurrencySOAPCSPOp. c. Don't enable it yet. d. Click OK. 2. Select the Passthrough operation that you created and select the Settings tab. a. Enter the HTTP Server: www.webservicex.net b. In the URL field, enter (vertical bar). This instructs the operation to remove the extra parts of the incoming URL that are needed by the web application but are not expected by the external service c. Check the Enabled checkbox. d. Click Apply. 3. Click the plus sign for adding new services. a. Specify the operation class: EnsLib.SOAP.GenericService b. Name the operation, such as ConvertCurrencySOAPCSPServ. c. Don't enable it yet. d. Click OK. 4. Select the Passthrough service that you created and select the Settings tab. a. Check the Enabled checkbox. b. Ensure that the Port field is blank. c. Set the TargetConfigName to the passthrough operation that you created in the previous step. d. In Connection Settings, check the Enable Standard Requests checkbox. e. In Additional Settings, set Pool Size to 0. This suppresses the passthrough service from listening on the special port. f. Click Apply. 5. In your SOAP toolkit, change the URL that uses the special port to the following: http://localhost: nnnnn/currencyconverter/convertcurrencysoappassthroughserv/currencyconvertor.asmx Where nnnnn is the CSP port number for the Ensemble instance Then execute the request. The SOAP toolkit should return the same XML message that it previously returned. 44 Creating SOAP and REST Services and Web Clients with Ensemble
A Configuring Ensemble for SOAP and REST Services This appendix briefly discusses how to configure your system so that you can use HTTP, SOAP, and REST services through the Ensemble CSP port. This information is intended to help you set up a development or test system for these services. Complete information about these topics is provided in the Caché documentation. See Configuring Caché in the Caché System Administration Guide for more details. To set up an Ensemble development or test system for HTTP, SOAP, or REST services, follow these steps: 1. If you have installed Ensemble in a locked down installation, Studio access is disabled. Open the Management Portal and enable Studio access: a. Start the Management Portal from the Ensemble cube. You will have to use your Windows login username rather than _system to access the portal. Enter the password that you specified during installation. b. Select System Administration, Security, and Services to get to the Services portal page. c. The %Services_Bindings service is disabled by default. Select the service name and check the Service Enabled checkbox and save the setting. 2. Configure the Web Gateway Management: a. Select System Administration, Configuration, and CSP Gateway Management. b. Login to the CSP gateway. By default, use the CSPSystem account with the password you specified during Ensemble installation. c. Select Server Access. d. Unless you have customized the CSP gateway, select LOCAL and Edit Server and click the Submit button. e. Change the Minimum Server Connections from its default value of 3 to 1 and then click the Save Configuration button. f. Select Back to Management Portal to return to the Ensemble portal. 3. If you are not using an existing Ensemble namespace, create a new namespace: a. Select System Administration, Configuration, System Configuration, and Namespaces to get to the Namespaces portal page. b. Click the Create New Namespace button, specify a name for the namespace, such as SERVICESNS. c. Click the Create New Database button for the globals database. Creating SOAP and REST Services and Web Clients with Ensemble 45
Configuring Ensemble for SOAP and REST Services d. In the Database Wizard, enter a name for the globals database, such as SERVICES_GDB. The wizard uses the name to create a directory for the database. e. Click the Next button twice to get to the Database Resource form. Select the Create a new resource radio button. The wizard displays a Create New Resource form. Accept the suggested name, such as %DB_SERVICES_GDB and ensure that Public Permissions Read and Write checkboxes are not checked. Click the Save button on the Database Resource form and the Finish button on the Database Wizard form. f. Repeat steps c through e for the routines database. g. Click the Save button to complete creating the namespace. h. Click Close to close the log. 4. Create an empty role and assign it to the unknown user: a. Select System Administration, Security, and Roles to display the Roles portal page. b. Click the Create New Role button and name the role, for example, Services_Role, and click the Save button. c. Select the Members tab, select the Unknown User, click the right arrow, and click the Assign button. 5. Define a web application that will handle calls to the Ensemble CSP port. The web application name defines the root of the URL that will call the service. A single web application can support multiple business services but they must all have a class that is the same or a subclass of the web application dispatch class. a. Select System Administration, Security, Applications, and Web Applications to display the Web Applications portal page. Click the Create New Web Application button. b. Name the web application, such as /weatherapp or /math/sum. You must start the name with a / (slash) character. c. Set the Namespace to the namespace that the production is running in, such as SERVICESNS. Leave the Namespace Default Application unchecked. d. You can check the Application, CSP/ZEN, and Inbound Web Services checkboxes. e. Leave the Resource Required and Group By ID fields empty. f. Check the Unauthenticated checkbox on the Allowed Authentication Methods line. g. Set the Dispatch Class to the component class, such as EnsLib.REST.GenericService or EnsLib.SOAP.GenericService. h. Click Save. i. Select the Matching Roles tab. j. In the Select a Matching Role: field, select the role that you created in the previous step. k. In the Select target roles to add to the selected matching role field, select the role or roles associated with the namespace globals and routines. The globals and routines may be in the same database or in separate databases. If your service, accesses another Caché database, you should also select its role. For example, if you are defining a web application for the Demo.REST.DirectoryService class in ENSDEMO, you must also select the %DB_SAMPLES role. You can select multiple roles while holding the Ctrl key. Note: The globals database also may have a secondary database and a corresponding role, such as %DB_GDBSECONDARY. This secondary database is used to store passwords. You don t need access to this database for pass-through services and operations, but if you create a custom web service that uses password access, you should also add the secondary database role to the target database. l. After the roles are highlighted, click the right-arrow key to move them to the Selected text box. m. Then click the Assign button. 46 Creating SOAP and REST Services and Web Clients with Ensemble
Configuring Ensemble for SOAP and REST Services This completes the system configuration. Creating SOAP and REST Services and Web Clients with Ensemble 47
B Using the SOAP Inbound Adapter This appendix briefly discusses the class EnsLib.SOAP.InboundAdapter, which you can use as an alternative to EnsLib.SOAP.Service (which is described in Creating an Ensemble Web Service. ) The standard way to create an Ensemble web service is to create a subclass of EnsLib.SOAP.Service and set up a web server to be your production web server. In this way, your system will be able to utilize all the SOAP and security features provided by a commercial web server and the Ensemble SOAP framework. Using the EnsLib.SOAP.InboundAdapter is easier to configure and lighter weight but doing so bypasses the above mentioned formal web support machinery. Also, the adapter does not expose the WSDL and test page the way the standard Ensemble SOAP framework does. B.1 Notes The SOAP inbound adapter (EnsLib.SOAP.InboundAdapter) does not require web server software. Instead it spawns a TCP listener job using the Ensemble super server. This lets you run your service in a foreground window, which is useful for debugging. (To do this, you must be running the service locally. Also make sure the PoolSize setting is 1 and the JobPerConnection setting is false.) It also supports SSL. The EnsLib.SOAP.InboundAdapter listens for HTTP input on a given port. When the adapter receives input, the following occurs: 1. It extracts the HTTP SOAPaction header. 2. It creates a stream (%Library.GlobalBinaryStream) that contains the body of the input. 3. It calls the web method that corresponds to the given SOAPaction. This adapter provides an advantage in that it supports persistent connections for successive SOAP calls. Also, if you use it with JobPerConnection=0, it can retain expensively instantiated resources such as XPath parsers even across successive connections that encompass individual SOAP service calls. B.2 Development Tasks To use the Ensemble SOAP inbound adapter, write and compile a new business service class in Studio. The following list describes the basic requirements: Your class should extend EnsLib.SOAP.Service. This class extends both Ens.BusinessService (so that it is an Ensemble business service) and %SOAP.WebService (so that it can act as a web service as well). Creating SOAP and REST Services and Web Clients with Ensemble 49
Using the SOAP Inbound Adapter Your class should provide values for SERVICENAME and other parameters, as described in Basic Requirements. The class should define web methods, as described in Defining Web Methods for Use in Ensemble. Optionally, to disable support for calls via the adapter in your service, add this to your class: Parameter ADAPTER=""; B.3 Configuration Tasks Use the Management Portal to do the following: 1. Add an instance of your custom class to the Ensemble production. Important: Ensure that the configuration name is the same as the full class name, including package. This is a requirement for running an Ensemble web service. 2. Enable the business service. 3. Set the PoolSize setting to 1 so that the adapter can use its TCP listener. 4. Set the StayConnected setting to 0. Otherwise, clients may hang for their timeout period while waiting for the server to drop the connection. 5. Specify other settings as needed; see Settings for the SOAP Inbound Adapter in Reference for Settings. 6. Run the production. 50 Creating SOAP and REST Services and Web Clients with Ensemble
C Older Ensemble Web Service Variation In previous releases, an Ensemble web method could not directly call SendRequestSync(), SendRequestAsync(), or SendDeferredResponse(). An alternative approach was needed. This appendix provides the details, for the benefit of anyone who is maintaining code that uses this alternative approach. C.1 Overview In previous releases, an Ensemble web method could not directly call SendRequestSync(), SendRequestAsync(), or SendDeferredResponse(). Instead, there were two requirements for an Ensemble web service, in addition to the requirements discussed earlier in this book: Each web method had to invoke the ProcessInput() method as appropriate, passing to it the appropriate request Ensemble message and receiving an Ensemble response message. The web service class had to define the OnProcessInput() callback method. In this method, you would call SendRequestSync(), SendRequestAsync(), or SendDeferredResponse(). The following figure shows the overall flow of request messages in this scenario: C.2 Implementing the OnProcessInput() Method The OnProcessInput() method has the following signature: Creating SOAP and REST Services and Web Clients with Ensemble 51
Older Ensemble Web Service Variation Method OnProcessInput(pInput As %RegisteredObject, ByRef poutput As %RegisteredObject, ByRef phint As %String) As %Status Here: 1. pinput is the Ensemble request message that you are sending. 2. poutput is the Ensemble response message that is sent in return. 3. phint is an optional string that you can use to decide how to handle the Ensemble request; see the subsection Using the phint Argument. The following shows an example: Method OnProcessInput(pInput As %RegisteredObject, ByRef poutput As %RegisteredObject) As %Status set sc=..sendrequestsync("lookup",pinput,.poutput) Quit sc C.2.1 Using the phint Argument If a web service defined multiple methods, and you wanted to send them to different destinations within the production, you used the optional hint argument of the ProcessInput() and OnProcessInput() methods, as follows: 1. When you invoke ProcessInput(), you used a value for the hint argument to indicate which web method is making this call. For example: Method GetCustomerInfo(ID As %Numeric) As ESOAP.SOAPResponse [ WebMethod ] //create Ensemble request message with given ID set request=##class(esoap.customerrequest).%new() set request.customerid=id... //send Ensemble request message //ProcessInput() calls OnProcessInput(), which actually //sends the message set sc=..processinput(request,.response,"getcustomerinfo") quit soapresponse 2. Within OnProcessInput(), you used the hint argument to determine the flow. For example: Method OnProcessInputAlt(pInput As %RegisteredObject, ByRef poutput As %RegisteredObject, phint As %String) As %Status if phint="getcustomerinfo" set sc=..sendrequestsync("getcustomerinfobo",pinput,.poutput) elseif phint="getstoreinfo" set sc=..sendrequestsync("getstoreinfobo",pinput,.poutput) Quit sc 52 Creating SOAP and REST Services and Web Clients with Ensemble
Reference for Settings This section provides the following reference information: Settings for the SOAP Inbound Adapter Settings for the SOAP Outbound Adapter Also see Settings in All Productions in Managing Ensemble Productions. Creating SOAP and REST Services and Web Clients with Ensemble 53
Reference for Settings Settings for the SOAP Inbound Adapter Provides reference information for settings of the SOAP inbound adapter, EnsLib.SOAP.InboundAdapter. Also see Creating an Ensemble Web Service, which does not require this adapter. Summary The inbound SOAP adapter has the following settings: Group Basic Settings Additional Settings Settings Call Interval, Port Enable Standard Requests, Adapter URL, Job Per Connection, Allowed IP Addresses, OS Accept Connection Queue Size, Stay Connected, Read Timeout, SSL Configuration, Local Interface The remaining settings are common to all business services. For information, see Settings for All Business Services in Configuring Ensemble Productions. Adapter URL A specific URL for the service to accept requests on. For SOAP services invoked through the SOAP inbound adapter on a custom local port, this setting allows a custom URL to be used instead of the standard csp/namespace/classname style of URL. Allowed IP Addresses Specifies a comma-separated list of remote IP addresses from which to accept connections. The adapter accepts IP addresses in dotted decimal form. An optional :port designation is supported, so either of the following address formats is acceptable: 192.168.1.22 or 192.168.1.22:3298. Note: IP address filtering is a means to control access on private networks, rather than for publicly accessible systems. InterSystems does not recommend relying on IP address filtering as a sole security mechanism, as it is possible for attackers to spoof IP addresses. If a port number is specified, connections from other ports will be refused. If the string starts with an exclamation point (!) character, the inbound adapter initiates the connection rather than waiting for an incoming connection request. The inbound adapter initiates the connection to the specified address and then waits for a message. In this case, only one address may be given, and if a port is specified, it supersedes the value of the Port setting; otherwise, the Port setting is used. Call Interval Specifies the number of seconds that the adapter will listen for incoming data from its configured source, before checking for a shutdown signal from the Ensemble framework. If the adapter finds input, it acquires the data and passes it to the business service. The business service processes the data, and then the adapter immediately begins waiting for new input. This cycle continues whenever the production is running and the business service is enabled and scheduled to be active. The default is 5 seconds. The minimum is 0.1 seconds. 54 Creating SOAP and REST Services and Web Clients with Ensemble
Settings for the SOAP Inbound Adapter Enable Standard Requests If this setting is true, the adapter can also receive SOAP requests in the usual way (bypassing the TCP connection). The default is false. Job Per Connection If this setting is true, the adapter spawns a new job to handle each incoming TCP connection and allows simultaneous handling of multiple connections. When false, it does not spawn a new job for each connection. The default is true. Local Interface Specifies the network interface through which the connection should go. Select a value from the list or type a value. An empty value means use any interface. OS Accept Connection Queue Size Specifies the number of incoming connections should the operating system should hold open. Set to 0 if only one connection at a time is expected. Set to a large number if many clients will connecting rapidly. Port Identifies the TCP port on the local machine where the adapter is listening for SOAP requests. Avoid specifying a port number that is in the range used by the operating system for ephemeral outbound connections. See Inbound Ports May Conflict with Operating System Ephemeral Ports in the Ensemble Release Notes for more information. Read Timeout Specifies the number of seconds to wait for each successive incoming TCP read operation, following receipt of initial data from the remote TCP port. The default is 5 seconds. The range is 0 600 seconds (a maximum of 10 minutes). SSL Config The name of an existing SSL/TLS configuration to use to authenticate this connection. This should be a server configuration. To create and manage SSL/TLS configurations, use the Management Portal. See the chapter Using SSL/TLS with Caché in the Caché Security Administration Guide. The first field on the Edit SSL/TLS Configuration form is Configuration Name. Use this string as the value for the SSLConfig setting. If your SSL configuration requires a private key password, include that in the SSL Config setting. To do so, add a vertical bar character after the configuration name, followed by the password. For example: MySSLItem mypassword. Stay Connected Specifies whether to keep the connection open between requests. If this setting is 0, the adapter will disconnect immediately after every event. If this setting is -1, the adapter auto-connects on startup and then stays connected. This setting can also be positive (which specifies the idle time, in seconds), but such a value is not useful for this adapter, which works by polling. If the idle time is longer than the polling interval (that is, the CallInterval) the adapter stays connected all the time. If the idle time is shorter than the polling interval, the adapter disconnects and reconnects at every polling interval. Creating SOAP and REST Services and Web Clients with Ensemble 55
Reference for Settings Settings for the SOAP Outbound Adapter Provides reference information for settings of the SOAP outbound adapter, EnsLib.SOAP.OutboundAdapter. Summary The outbound SOAP adapter has the following settings: Group Basic Settings Connection Settings Proxy Settings Additional Settings Settings Web Service URL, Web Service Client Class, SOAP Credentials, Credentials SSL Configuration, SSL Check Server Identity Proxy Server, Proxy Port, Proxy HTTPS, ProxyHttpTunnel, ProxyHttpSSLConnect ResponseTimeout, HttpVersion, ConnectTimeout The remaining settings are common to all business operations. For information, see Settings for All Business Operations in Configuring Ensemble Productions. ConnectTimeout Specifies the number of seconds to wait for the connection to the server to open. The default value is 5. If the connection is not opened in this time period, the adapter retries repeatedly, up to the number of times given by Failure Timeout divided by Retry Interval. Credentials Specify the ID of the Ensemble credentials that contain the username and password to be used in the HTTP header. For information on creating Ensemble credentials, see Configuring Ensemble Productions. HttpVersion Specifies the HTTP version that the adapter should report in the HTTP request it sends to the server. ProxyHTTPS Specifies whether the proxy (if any) uses HTTPS to communicate with the real HTTP/HTTPS server. ProxyHttpTunnel Specifies whether the adapter use the HTTP CONNECT command to establish a tunnel through the proxy to the target HTTP server. ProxyPort Specifies the proxy server port on which to send HTTP requests, if using a proxy server. The default value is 80. ProxyServer Specifies the proxy server through which to send HTTP requests, if any. ProxyHttpSSLConnect Specifies whether the adapter should use a proxy SSL connection to the proxy. Note that the use of SSL to the eventual endpoint is determined by the protocol part of web service's location URL. 56 Creating SOAP and REST Services and Web Clients with Ensemble
Settings for the SOAP Outbound Adapter ResponseTimeout Specifies the timeout for getting a response from the remote web server (the timeout for opening the connection to the server is set by ConnectTimeout). The default value is 30. SOAPCredentials Specify the ID of the Ensemble credentials that contain the username and password to be used in the WS-Security header of the SOAP request. For more information on WS-Security support, see Securing Caché Web Services in the Caché documentation set. SSLCheckServerIdentity Specifies that when making an SSL connection, the adapter should check that the server identity in the certificate matches the name of the system being connecting to. This defaults to specifying that the check should be made. Uncheck this for test and development systems where the name specified in the SSL certificate does not match the DNS name. SSLConfig The name of an existing SSL/TLS configuration to use to authenticate this connection. Choose a client SSL/TLS configuration, because the web client initiates the communication. To create and manage SSL/TLS configurations, use the Management Portal. See the chapter Using SSL/TLS with Caché in the Caché Security Administration Guide. The first field on the Edit SSL/TLS Configuration form is Configuration Name. Use this string as the value for the SSLConfig setting. If your SSL configuration requires a private key password, include that in the SSL Config setting. To do so, add a vertical bar character after the configuration name, followed by the password. For example: MySSLItem mypassword. Note: You must also ensure the web service is at a URL that uses https://. The web service location is determined by the WebServiceURL setting; if this is not specified, the Ensemble web client assumes the web service is at the URL specified by the LOCATION parameter in proxy client class. WebServiceClientClass Specifies the full name (including package) of the proxy client class, specifically the class that actually sends and receives SOAP messages to the web service. WebServiceURL Specifies the URL where the web service is located. If this setting is not given, the adapter uses the default location (the LOCATION parameter) declared in the proxy client class; see the WebServiceClientClass setting. Note that SSL will only work if this URL uses https:// Creating SOAP and REST Services and Web Clients with Ensemble 57
Index A AdapterURL, 54 AllowedIPAddresses, 54 C CallInterval, 54 ConnectTimeout, 56 E EnableStandardRequests, 55 J JobPerConnection, 55 L LocalInterface, 55 O OSAcceptConnectionQueueSize, 55 R ReadTimeout, 55 S SSL Check Server Identity, 57 SSLConfig, 55 StayConnected, 55 Creating SOAP and REST Services and Web Clients with Ensemble 59