Consuming RESTful Web Services

The article is a step by step guide for beginners to learn how to build a RESTful web service consumer (or client) in Ensemble. The provider can be any RESTful service, but the example is based on the service we made during the previous sessions.

It is more than obvious that many client development environment has programming libraries or containers to build a RESTful client. For example in the earlier sessions we used Java Script to access services. Ensemble as a container also offers client functionality. Let us have a quick list what Ensemble offers. Integrating an external resource is the task of Outbound Adapters. Since RESTful services are using HTTP(S) as a transport layer, there is no separate Adapter from HTTP. Therefore technically service clients are using HTTP Outbound Adapter. Any Business Operation which uses the HTTP Outbound Adapter can be a consumer of a RESTful service. What does the difference make between a HTTP and a RESTful operation then? Indeed nothing. Except that the expected response is different. Usually a RESTful service client expects JSON string returned.

During the session we are going to build a Business Operation class as well as a small production to test it.  Since Ensemble uses messages to define data structure communicating between components, we are also going to define a request and a response message pair.

Before you read

In order to be able to complete the session successfully it is better to:

  • Learn basic concept of Ensemble
  • Learn basics of HTTP
  • Learn basics of RESTful Web Services
  • Complete the exercise in “Creating RESTful  Web Service in Ensemble”
  • Create a new Ensemble enabled namespace for the consumer production

Building project with Ensemble Studio

The following section explains how to create the project when you are using Ensemble Studio.

Create a new Studio project (optional)

To organize the components we need to have a Studio Project. To create a new project launch the Ensemble Studio.

Use the File menu and call the New Project menu point. Right after this call the Save Project As menu point.

Create new messages

Use the New class wizard to create the message classes. Please select the Message on the wizard selection page. Make one as a request and an other one as response.

Create new Business Operation

Use the New class wizard to build the operation. Select the Production, Business Operation wizard. Select the EnsLib.HTTP.OutboundAdapter from the drop down list, and add the message map for the created request and response message.

Building project with Atelier

The following section explains how to create the project when you are using Atelier.

Create a new Atelier project

To create a new project launch Atelier, and in the File menu call the New à Project menu point. Please remember, that Atelier requires a project to work on.

Please select the server connection you created prior and the namespace you want to work in.

Create new messages

Create two message classes (a request and a response) using the New Class File wizard of Atelier. Select the General >> Empty Class template. For the request set the Extends list to Ens.Request. For the response set to Ens.Response.

Create new Business Operation

Invoke the New Class  File wizard in order to create the  operation. Select the Ensemble >> Business Operation template. Select EnsLib.HTTP.OutboundAdapter from the adapter drop down list. Add one Operation method with the new request type and response type we just created.

Deploy project using Ensemble Management Portal

Once the project has been finished, it is time to create a deployment configuration using the Ensemble Management Portal. You should log-on to your namespace. The first step is to create a Production. The Production is the container running your service.

When you first time launch the Production configuration page, you ought to start the “New” wizard. It pops up a form. Please select “Generic production”.

Enable Testing for the production on the Production Settings page.

Add the Business Operation to the production (deployment configuration). Fill in the server name and port number of your RESTful service provider. Also enter the URL of the service, but please do not forget, that here only the root path is required without leading slash (/). The complete service URL is going to be calculated run-time on sending a request.

Implementation

The implementation order of Ensemble dictates that the data structures sent to/ received from Business Operations must be defined prior developing the operation. A data structure is defined as a class. There are two structures to be defined. Request message defines the structure of data sent to the operation. Response message defines the structure received from the operation.

For now the very basic service of “Hello world” is used. No input data to the service is required. Therefore the request is going to be empty. Almost. There is one consideration however. We are going to build a business operation receiving JSON string from the foreign system. Unfortunately JSON does not have concept for automatic structure recognition (unlike XML or HL7 v 2.*) therefore there must be some interaction between the operation’s logic and the actual message context to identify response message structure expected. There might be dozens of options but to keep the sample program simple, the request message holds a field “accept” which is the name of an existing response message class.

The response class is going to receive the answer of the RESTful service. In our example it was a very simple JSON string. Thus the response message is very simple too. Unfortunately neither %DynamicObject-s nor “dynamic dispatch properties” are persistent. As a consequence those can not be a message instance. Message instance must be persistent. In order to keep the class flexible enough, a property value array is created where the key is the property name. For sure there must be some more creative way to transform a JSON string to a persistent message class than it is implemented here. But to keep the whole structure and program logic simple no creativity is involved. Please note, that the property assignment for the response class is done by the constructor (%OnNew).

The Business Operation implements the program logic for HTTP communication, message construction and deconstruction. All lines are free of error handling. No input validation is done either. We do not want a production grade software. We want to understand the basic logic which might be decorated by validation/ error handling on your own.

The HTTP Outbound Adapter has configuration setting URL which holds the path part of the service URL. As you know RESTful services are using the URL path as part of the data exchange. This means that the adapter URL setting is used as the root path of the actual location concatenated by the variable part. The variable part is derived from the request. In my situation the complete URL is http://localhost:57774/csp/eh2/restful/echo, where csp/eh2/restful is the root path and echo is the variable part. The root path will be set at the adapter settings, and the operation logic will concatenate the echo run time.

Request Message Class

The following definition is an example for the request message.

Class h2.consumerestfulservice.Request Extends Ens.Request 
{
 
Property accept As %Dictionary.CacheClassname;

}

Response Message Class

It is the simplest implementation for a response message structure.

Class h2.consumerestfulservice.Response Extends Ens.Response
{

Property valueArray As array Of %String;

/// This callback method is invoked by the <METHOD>%New</METHOD> method to
/// provide notification that a new instance of an object is being created.
///
/// <P>If this method returns an error then the object will not be created.
/// <p>It is passed the arguments provided in the %New call.
/// When customizing this method, override the arguments with whatever variables and types you expect to receive from %New().
/// For example, if you're going to call %New, passing 2 arguments, %OnNew's signature could be:
/// <p>Method %OnNew(dob as %Date = "", name as %Name = "") as %Status
/// If instead of returning a %Status code this returns an oref and this oref is a subclass of the current
/// class then this oref will be the one returned to the caller of %New method.
Method %OnNew(obj) As %Status [ Private, ServerOnly = 1 ]
{
  if $isObject(obj) {
  set iterator = obj.%GetIterator()
  while iterator.%GetNext(.propertyName, .propertyValue) {
    do ..valueArray.SetAt(propertyValue, propertyName)
    }
  }
  Quit $$$OK
}

Business Operation Class

The skeleton of an operation class. No error handling, no input validation just the bare code. The real job is done in four steps.

  1. Extract data from the request message: pRequest.accept
  2. Initiate communication to the remote server: ..Adapter.GetURL()
  3. Transform the response string to dynamic object: {}.%FromJSON()
  4. Transform the dynamic object to message: $classmethod(responseType,"%New",dynamicObject)
Class h2.consumerestfulservice.Operation Extends Ens.BusinessOperation
{

Parameter ADAPTER = "EnsLib.HTTP.OutboundAdapter";

Property Adapter As EnsLib.HTTP.OutboundAdapter;

Parameter INVOCATION = "Queue";

Method ProcessRequest(pRequest As h2.consumerestfulservice.Request, Output pResponse As h2.consumerestfulservice.Response) As %Status
{
  set st = $$$OK
  set responseType = pRequest.accept
  set st = ..Adapter.GetURL(..Adapter.URL_"/echo", .callResponse)
  #dim callResponse as %Net.HttpResponse
  set dynamicObject = {}.%FromJSON(callResponse.Data)
  set pResponse = $classmethod(responseType,"%New",dynamicObject)
  Quit st
}

XData MessageMap
{
<MapItems>
  <MapItem MessageType="h2.consumerestfulservice.Request">
    <Method>ProcessRequest</Method>
  </MapItem>
</MapItems>
}

}

Testing

The standard Ensemble Test utility is used for testing purpose. It is accessible from the Management Portal menu. Before you start testing, please double check if the Testing is enabled for the whole production. When you run the test, select Business Operation as a target, select your operation from the drop down list and push the button. On the pop up form enter name of your response class into the accept field and push the button (again). If you made everything right you are going to get a response almost instantly. And then happy tracing…

Stay tuned, I’ll be back soon with further reading on Ensemble RESTful web services. The next is “RESTful way of data transfer”.

 

  • + 2
  • 0
  • 1580
  • 0