Skip to main content

Using the HTTP Outbound Adapter

This chapter describes the overall behavior of the Ensemble HTTP outbound adapter (EnsLib.HTTP.OutboundAdapterOpens in a new tab) and describes how to use this adapter in your productions. It discusses the following topics:

Tip:

Ensemble also provides specialized business service classes that use this adapter, and one of those might be suitable for your needs. If so, no programming would be needed. See “Connectivity Options” in Introducing Ensemble.

Overall Behavior

Within a production, an outbound adapter is associated with a business operation that you create and configure. The business operation receives a message from within the production, looks up the message type, and executes the appropriate method. This method usually executes methods of the associated adapter.

EnsLib.HTTP.OutboundAdapterOpens in a new tab is the Ensemble adapter for sending HTTP requests outside Ensemble and receiving HTTP responses. This adapter provides settings to control items such as the following:

  • Server and port to which the adapter will send HTTP requests

  • URL path for the resource to request, at the given server and port

  • An optional SSL configuration to use for the connection to the server

  • Optional information to specify a proxy server through which the adapter can route requests

The adapter provides methods for sending HTTP POST, GET, and PUT actions:

  • The main methods are PostFormData() and GetFormData(). Each accepts an output argument for the response object, a comma-separated list of form variable names, and a variable number of form variable arguments, one for each of the names in the comma-separated list. If you want to set multiple values for a form variable, you may use the same name multiple times in the list. Of course, you can also use these methods with no form variables to request flat scalar content such as a regular web page.

  • For situations with a complicated set of form variables, use the methods PostFormDataArray() and GetFormDataArray(). These methods accept a multidimensional array instead of a variable argument list. This can help keep things organized, because multiple values for a given form variable can be given as subnodes in the array, rather than by using multiple entries in the list of names. You can also index the array by form variable name rather than by position.

  • The low-level worker method SendFormDataArray() is available for situations when you need to use a PUT or some other unusual HTTP request, or where you need to customize aspects of your HTTP request other than form variables or cookies.

The HTTP requests are in the default character encoding of the local Ensemble server. To specify a different character encoding, create and send custom HTTP requests, as described in “Creating Custom HTTP Requests.”

Creating a Business Operation to Use the Adapter

To create a business operation to use the EnsLib.HTTP.OutboundAdapterOpens in a new tab, you create a new business operation class. 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 operation class:

  • Your business operation class should extend Ens.BusinessOperationOpens in a new tab.

  • In your class, the ADAPTER parameter should equal EnsLib.HTTP.OutboundAdapterOpens in a new tab.

  • 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 is 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 a message map that includes at least one entry. A message map is an XData block entry that has the following structure:

    XData MessageMap
    {
    <MapItems>
      <MapItem MessageType="messageclass">
        <Method>methodname</Method>
      </MapItem>
      ...
    </MapItems>
    }
    
    
  • Your class should define all the methods named in the message map. These methods are known as message handlers. Each message handler should have the following signature:

    Method Sample(pReq As RequestClass, Output pResp As ResponseClass) As %Status
    

    Here Sample is the name of the method, RequestClass is the name of an Ensemble request message class, and ResponseClass is the name of an Ensemble response message class. In general, the method code will refer to properties and methods of the Adapter property of your business operation.

    For information on defining message classes, see “Defining Ensemble Messages” in Developing Ensemble Productions.

    For information on defining the message handler methods, see “Creating Message Handler Methods,” later in this chapter.

  • For other options and general information, see “Defining a Business Operation Class” in Developing Ensemble Productions.

The following example shows the general structure that you need:

Class EHTTP.NewOperation1 Extends Ens.BusinessOperation
{
Parameter ADAPTER = "EnsLib.HTTP.OutboundAdapter";

Parameter INVOCATION = "Queue";

Method Sample(pReq As RequestClass, Output pResp As ResponseClass) As %Status
{
  Quit $$$ERROR($$$NotImplemented)
}

XData MessageMap
{
<MapItems>
  <MapItem MessageType="RequestClass">
    <Method>Sample</Method>
  </MapItem>
</MapItems>
}
}
Note:

Studio provides a wizard that you can use to create a business operation stub similar to the preceding. To access this wizard, click File —> New and then click the Production tab. Then click Business Operation and click OK.

Creating Message Handler Methods

When you create a business operation class for use with EnsLib.HTTP.OutboundAdapterOpens in a new tab, typically your biggest task is writing message handlers for use with this adapter, that is, methods that receive Ensemble messages and then perform various HTTP operations.

Each message handler method should have the following signature:

Method Sample(pReq As RequestClass, Output pResp As ResponseClass) As %Status

Here Sample is the name of the method, RequestClass is the name of an Ensemble request message class, and ResponseClass is the name of an Ensemble response message class.

In general, the method should do the following:

  1. Examine the inbound request message.

  2. Using the information from the inbound request, call a method of the Adapter property of your business operation. For example, call the Get method, which sends the HTTP GET command:

     set status=..Adapter.Get(.pHttpResponse,"Name",pRequest.Name)
    

    This example sends a GET request, passing in a parameter called Name, which has the value of pRequest.Name.

    The available methods are discussed in the next section. Each of them returns a status (specifically an instance of %StatusOpens in a new tab).

    These methods also return an HTTP response as output. In the preceding example, the response is placed into pHttpResponse. The response is an instance of %Net.HttpResponseOpens in a new tab; for information on using this object, see the chapter “Using the HTTP Response.”

  3. Examine the HTTP response.

  4. Use information in the HTTP response to create an Ensemble response message (an instance of Ens.ResponseOpens in a new tab or a subclass), which the method returns as output.

    For basic information on defining message classes, see “Defining Ensemble Messages” in Developing Ensemble Productions.

  5. Make sure that you set the output argument (pOutput). Typically you set this equal to the response message. This step is required.

  6. Return an appropriate status. This step is required.

The following shows an example:

Method PostMessage(pRequest As EHTTP.Request.OutboundPost,
Output pResponse As EHTTP.Response.OutboundPost) As %Status
{
  Set $ZT="Trap",tSC=$$$OK
  do {

    set input=pRequest.MessageStream
    set tResponse = ##class(%Net.HttpResponse).%New()
    set tsc = ..Adapter.Post(.tResponse,,input)

    set pResponse = ##class(EHTTP.Response.OutboundPost).%New()
    set len = tResponse.Data.SizeGet()
     While (tResponse.Data.AtEnd = 0) {
      do pResponse.MessageStream.Write(tResponse.Data.Read())
     }
    Quit
  } while (0)
Exit
  Quit tSC
Trap
  Set $ZT="",tSC=$$$EnsSystemError
  Goto Exit
}

Calling HTTP Commands

This section describes how to use the EnsLib.HTTP.OutboundAdapterOpens in a new tab to send HTTP commands (GET, POST, PUT, or DELETE). Within an HTTP command, you can send either form data or a request body. This section discusses the following topics:

Sending Form Data

To send HTTP form data, use any of the following methods: Post, PostFormDataArray(), Get, GetFormDataArray(), or SendFormDataArray(). Each of these methods returns (as output) an HTTP response, an instance of %Net.HttpResponseOpens in a new tab. For information on using this object, see the chapter “Using the HTTP Response.”

The details differ from method to method, but a partial example follows:

 set tFormVar="USER,ROLE,PERIOD"

 set tUserID=pRequest.UserID
 set tRole=pRequest.UserRole
 set tED=pRequest.EffectiveDate

 set tSC=..Adapter.Get(.tResponse,tFormVar,tUserID,tRole,tED)

Note that this example assumes that the Ensemble request message has the properties UserID, UserRole, and EffectiveDate.

Sending a Request Body

A request body can be either a stream or a string, depending on your needs. For information on creating as stream and writing to it, see the Caché documentation; for example, the chapter “Defining and Using Stream Properties” in Using Caché Objects.

Then use any of the following methods: Post(), PostFormDataArray(), Get(), or GetFormDataArray(). In this case, you will pass the request body as an argument, and you will leave the form data argument empty. Each of these methods returns (as output) an HTTP response, an instance of %Net.HttpResponseOpens in a new tab. For information on using this object, see the chapter “Using the HTTP Response.”

The details differ from method to method, but a partial example follows:

   set tsc = ..Adapter.Post(.tResponse,,pRequest.MessageStream)

Note that this example assumes that the Ensemble request message has a property MessageStream.

Stream Attributes as HTTP Headers

If you create a stream and send that as the request body, you can force the HTTP outbound adapter to include some or all of the stream attributes as HTTP headers. To do so, set the SkipBodyAttrs property equal to a list of attributes that should not be used as HTTP headers. The default value is "*" which means that the stream attributes are ignored by default (and not used as headers). Note that this property is not available as a runtime setting.

For information on stream attributes, see the class reference for %Library.AbstractStreamOpens in a new tab.

Reference Information for HTTP Methods

This section provides reference information on the methods you can use to invoke HTTP commands.

Post()
Method Post(Output pHttpResponse As %Net.HttpResponse,
            pFormVarNames As %String = "",
            pData...) As %Status

Sends the HTTP POST command to the configured destination (see “Specifying the Destination”), sending either form data or a request body.

The HTTP response is returned as output in the first argument. This is an instance of %Net.HttpResponseOpens in a new tab; for information on using this object, see the chapter “Using the HTTP Response.”

With this method, do one of the following:

  • To send form data to the named form variables, specify the pFormVarNames argument and pData arguments as needed. pFormVarNames is a comma-separated list of form variable names to use. For each name in the list, a pData argument should be supplied.

    To pass multiple values for a given form variable, include the variable name multiple times in the pFormVarNames list.

    Any extra pData arguments you supply will be assigned to the last form variable in the list.

  • To send a request body instead of form variables, leave pFormVarNames empty and pass the body text as the pData argument.

A data value passed for body text may be of either string or stream type. Data values passed for form variables must be of string type.

PostFormDataArray()
Method PostFormDataArray(Output pHttpResponse As %Net.HttpResponse,
                         pFormVarNames As %String = "",
                         ByRef pData) As %Status

Sends the HTTP POST command to the configured destination (see “Specifying the Destination”), sending form data to the named form variables.

pFormVarNames is a comma-separated list of form variable names to use. For each name in the list, a pData argument should be supplied.

The pData argument is an array. The top node of the array is not used. Each subnode is subscripted by the index of the corresponding form variable in the pFormVarNames list. The value at a given subscript should be specified as follows:

  • For a form variable (varname) with a single value, the value at pData(“varname”) should be the form data value to send. There should be no subnodes.

  • For a form variable (varname) with multiple values, the value pData(“varname”) should be the count of the values. Each of the values for this form variable should appear in a subnode, subscripted by its position in the node.

PostURL()
method PostURL(pURL As %String, 
              Output pHttpResponse As %Net.HttpResponse, 
              pFormVarNames As %String = "", 
              pData...) as %Status

Sends the HTTP POST command to the specified URL (pURL), sending form data to the named form variables. See the remarks for PostFormDataArray().

Get()
Method Get(Output pHttpResponse As %Net.HttpResponse,
           pFormVarNames As %String = "",
           pData...) As %Status

Sends the HTTP GET command to the configured destination (see “Specifying the Destination”), sending either form data or a request body. See the remarks for Post().

GetFormDataArray()
Method GetFormDataArray(Output pHttpResponse As %Net.HttpResponse,
                        pFormVarNames As %String = "",
                        ByRef pData) As %Status

Sends the HTTP GET command to the configured destination (see “Specifying the Destination”), sending form data to the named form variables. See the remarks for PostFormDataArray().

GetURL()
method GetURL(pURL As %String, 
              Output pHttpResponse As %Net.HttpResponse, 
              pFormVarNames As %String = "", 
              pData...) as %Status

Sends the HTTP GET command to the specified URL (pURL), sending form data to the named form variables. See the remarks for PostFormDataArray().

Put()
Method Get(Output pHttpResponse As %Net.HttpResponse,
           pFormVarNames As %String = "",
           pData...) As %Status

Sends the HTTP PUT command to the configured destination (see “Specifying the Destination”), sending either form data or a request body. See the remarks for Post().

PutFormDataArray()
Method PutFormDataArray(Output pHttpResponse As %Net.HttpResponse,
                        pFormVarNames As %String = "",
                        ByRef pData) As %Status

Sends the HTTP PUT command to the configured destination (see “Specifying the Destination”), sending form data to the named form variables. See the remarks for PostFormDataArray().

PutURL()
method PutURL(pURL As %String, 
              Output pHttpResponse As %Net.HttpResponse, 
              pFormVarNames As %String = "", 
              pData...) as %Status

Sends the HTTP PUT command to the specified URL (pURL), sending form data to the named form variables. See the remarks for PostFormDataArray().

Delete()
method Delete(Output pHttpResponse As %Net.HttpResponse, 
              pFormVarNames As %String = "", 
              pData...) as %Status

Sends the HTTP DELETE command to the configured destination (see “Specifying the Destination”), sending either form data or a request body. See the remarks for Post().

DeleteFormDataArray()
method DeleteFormDataArray(Output pHttpResponse As %Net.HttpResponse, 
                           pFormVarNames As %String = "", 
                           ByRef pData) as %Status

Sends the HTTP DELETE command to the configured destination (see “Specifying the Destination”), sending form data to the named form variables. See the remarks for PostFormDataArray().

DeleteURL()
method DeleteURL(pURL As %String, 
              Output pHttpResponse As %Net.HttpResponse, 
              pFormVarNames As %String = "", 
              pData...) as %Status

Sends the HTTP DELETE command to the specified URL (pURL), sending form data to the named form variables. See the remarks for PostFormDataArray().

SendFormDataArray()
Method SendFormDataArray(Output pHttpResponse As %Net.HttpResponse,
                        pOp As %String,
                        pHttpRequestIn As %Net.HttpRequest,
                        pFormVarNames As %String = "",
                        ByRef pData) As %Status

Sends the HTTP request to the configured destination (see “Specifying the Destination”), sending form data to the named form variables.

The pOp argument specifies the HTTP action to take. This should be one of the following: "POST" "GET" "PUT"

pFormVarNames is a comma-separated list of form variable names to use. For each name in the list, a pData argument should be supplied.

The pData argument is an array; see the remarks for the GetFormDataArray() method.

For special needs, create an instance of %Net.HTTPRequest or a subclass, specify its properties, and use this as the pHttpRequestIn argument. If you do this, the HTTP request is initialized with the properties of your instance. This method gives you more control than the other methods of the outbound adapter. For example, it enables you to add your own HTTP headers to the request.

Handling the HTTP Response

When you use any of the methods described in the previous subsection, you receive, as output, an HTTP response. This object is an instance of %Net.HttpResponseOpens in a new tab. The chapter “Using the HTTP Response” describes how to use this object.

Managing Cookies

A cookie is a text string in a response header that a server can ask a client to save and return as a header value in subsequent HTTP requests. Some servers use cookies to maintain open sessions,

The EnsLib.HTTP.OutboundAdapterOpens in a new tab provides the following properties and methods to manage cookies. Your custom methods can use these.

UseCookies property

Specifies whether to save cookies received in HTTP responses while this adapter is instantiated, and insert them in each subsequent HTTP request. If UseCookies is true, then any job associated with an instance of that adapter will maintain a collection of cookies and send the appropriate selection of them with each new request that it sends. If UseCookies is false (0), cookies will not be sent. This convention allows each of these jobs to maintain its own persistent session with any web server that requires it.

The default is false. This property is also available as a runtime setting.

%Cookies property

Contains an array of cookies. Indexed by Domain/Server; each element is $LB(name, domain, path, value, expires, secure). This property is Caché multidimensional array.

DeleteCookie() method
Method DeleteCookie(pName As %String,
                pPath As %String,
                pDomain As %String) As %Status

Deletes a particular cookie.

DeleteCookies() method
Method DeleteCookies(pDomain As %String = "",
                pPath As %String = "") As %Status

Deletes all cookies from the specified domain and/or path.

Note:

Remember that cookies are specific to an HTTP server. When you insert a cookie, you are using a connection to a specific server, and the cookie is not available on other servers.

Creating Custom HTTP Requests

If you use the more common methods of the HTTP outbound adapter (such as Get), the adapter automatically creates and sends an HTTP request, which can include either form data or a request body. In special cases, you may want to create a custom HTTP request so that you can specify details such as proxy authorization or a different character encoding.

To send the custom request, use the SendFormDataArray() method of the HTTP outbound adapter as described in “Calling HTTP Commands” in the previous chapter. Then see the chapter “Sending HTTP Requests and Reading HTTP Responses” of Using the Caché Internet Utilities.

Using the HTTP Response

After you use the outbound adapter to send an HTTP request, you receive a response object (%Net.HttpResponseOpens in a new tab). Specifically, the main methods of the HTTP.OutboundAdapter enable you to send an HTTP request. All these methods give you access to the HTTP response that is sent in return:

  • If you use the PostFormData(), PostFormDataArray(), GetFormData() or GetFormDataArray method, the HTTP response is returned as output in the first argument of the method call. This argument is an instance of %Net.HttpResponseOpens in a new tab.

  • If you use the SendFormDataArray() method, the HttpResponse property of the request is updated. This property is an instance of %Net.HttpResponseOpens in a new tab.

For details on these methods, see “Calling HTTP Commands” in the chapter “Using the HTTP Outbound Adapter.”

For more information on using the HTTP response, see “Sending HTTP Requests and Reading HTTP Responses” in Using the Caché Internet Utilities.

Examples

This section provides a couple of examples.

Example with Post

The following example uses the HTTP outbound adapter and posts an XML message to the configured destination. First, the business operation class is as follows:

Class EHTTP.PostService Extends Ens.BusinessOperation
{

Parameter ADAPTER = "EnsLib.HTTP.OutboundAdapter";

Parameter INVOCATION = "Queue";

Method PostMessage(pRequest As EHTTP.Request.OutboundPost,
Output pResponse As EHTTP.Response.OutboundPost) As %Status
{
  Set $ZT="Trap",tSC=$$$OK
  do {

    set tResponse = ##class(%Net.HttpResponse).%New()
    set tsc = ..Adapter.Post(.tResponse,,pRequest.MessageStream)
    set stream = ""

    set pResponse = ##class(EHTTP.Response.OutboundPost).%New()
    set len = tResponse.Data.SizeGet()
     While (tResponse.Data.AtEnd = 0) {
      do pResponse.MessageStream.Write(tResponse.Data.Read())
     }
    Quit
  } while (0)
Exit
  Quit tSC
Trap
  Set $ZT="",tSC=$$$EnsSystemError
  Goto Exit
}

XData MessageMap
{
<MapItems>
  <MapItem MessageType="EHTTP.Request.OutboundPost">
    <Method>PostMessage</Method>
  </MapItem>
</MapItems>
}

}

The request message class is as follows:

Class EHTTP.Request.OutboundPost Extends Ens.Request
{

/// MessageStream contains the complete SOAP Message to post
Property MessageStream As %GlobalCharacterStream(CONTENT = "MIXED");

}

The response message class is as follows:

Class EHTTP.Response.OutboundPost Extends Ens.Response
{

/// MessageStream contains the Response to the SOAP Message post
Property MessageStream As %GlobalCharacterStream(CONTENT = "MIXED");

}

Example with Get

The following example uses the Get() method.

Method GetKPI(pRequest As EHTTP.Request.GetKPI,
ByRef pResponse As EHTTP.Response.GetKPI) As %Status
{
   set $ZT="ErrTrap",tSC=$$$OK
   do {
      set pResponse=##class(EHTTP.Response.GetKPI).%New()

      set tFormVar="KPINAME,PHYSICIAN,ROLE,PERIOD"

      set tRole=pRequest.UserRole
      set tUserID=pRequest.UserID
      set tED=pRequest.EffectiveDate
      set tYear=$p(tED,"-",1)
      set tMonth=$p(tED,"-",2)
      set tPeriod=tYear_tMonth

      if tRole="MFA" set tUserID="MEDICAL FACULTY ASSOCIATES"

      set tSC=..Adapter.Get
        (.tResponse,tFormVar,pRequest.KPI,tUserID,tRole,tPeriod)

      if '$IsObject(tResponse) Quit
      ;
      ;now parse the XML stream
      ;
      set reader=##class(%XML.Reader).%New()
      do tResponse.Data.Rewind()
      set ^drltrace("xml")=tResponse.Data.Read(32000)
      do tResponse.Data.Rewind()
      set tSC=reader.OpenStream(tResponse.Data)
      if $$$ISERR(tSC) {
         $$$LOGWARNING("Unable to open the XML Stream returned from IDX")
         $$$TRACE("XML request probably failed")
         do tResponse.Data.Rewind()
         set traceline=tResponse.Data.Read(1000)
         $$$TRACE(traceline)
         set tSC=$$$OK
         quit
      }
      ;
      ;Associate a class name with the XML element Name
      do reader.Correlate("KPIResult","EHTTP.IDX.KPIResult")

      if reader.Next(.tResults,.tSC)
      {

         set pResponse.KPIValues=tResults.KPIValues

      }
      if tSC=0 {
         $$$TRACE("Error reading values from IDX")
      }
   } while (0)
Exit
   Quit tSC
ErrTrap
   set $ZT="",tSC=$$$EnsSystemError
   goto Exit
}

This example retrieves an XML file from the target server, parses it, retrieving specific data.

Adding and Configuring the Business Operation

To add your business operation 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.

  2. Configure the adapter to communicate with a specific external data source. Specifically:

  3. Enable the business operation.

  4. Run the production.

Specifying the Destination Server and URL Path

Use the following runtime settings to specify the destination to which you will send HTTP requests:

Example

For example, suppose that the URL to which you are posting is http://122.67.980.43/HTTPReceive.aspx

In this case, you would use the following settings:

Setting Value
HTTPServer 122.67.980.43
URL HTTPReceive.aspx

Specifying a Proxy Server

Use the following runtime settings to route the HTTP request via a proxy server, if needed:

FeedbackOpens in a new tab