Previous section   Next section

Defining Business Operations

This chapter describes how to define business operation classes. It contains the following sections:
Tip:
Ensemble provides specialized business operation classes that use specific outbound adapters, and one of those might be suitable for your needs. If so, no programming would be needed. For a partial list, see “Connectivity Options” in Introducing Ensemble.

Introduction

A business operation is responsible for sending requests from Ensemble to an external application or system. The following figure shows how it works:
images/egdv_business_operation.png
Note that this figure shows only the input flow of data, not the optional response.
A business operation is responsible for the following activities:
  • Waiting for requests from business services or business processes.
  • Dispatching, via a message map, the request to a specific method within the business operation. Each method within a business operation class represents a specific action within an external application.
  • Transforming the request object into a form usable by the associated outbound adapter and asking the outbound adapter to send a request to the external application.
  • Returning, if requested, a response object to the caller.
Each business operation contains a message map that specifies which external operation to perform, depending on the type of request message that it received. The message map contains one or more entries, each of which corresponds to one invocation of the associated outbound adapter.

Key Principles

First, be sure to read the chapter “Programming in Ensemble.”
By convention, a business operation is an extremely specific operation that contains very little logic and does what is requested of it without calling further operations or branching in any way. When the design of the production demands logic, this is contained in a business process.
Many productions provide a large set of extremely simple business operations. In these cases, business processes contain the logic that determines when each operation should be called.
Also see “Key Principles” in the chapter “Defining Business Services.”

Defining a Business Operation Class

To create a business operation class, define a class as follows:
  • Your business operation class must extend Ens.BusinessOperation (or a subclass).
  • In your class, the ADAPTER parameter should usually equal the name of the adapter class for this business service to use.
    Or you can define a business operation with no associated outbound adapter class. In this case, the business operation itself must contain the logic needed to communicate with an external application.
  • In your class, the INVOCATION parameter must 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 available again in 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 must 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, these methods will refer to properties and methods of the Adapter property of your business operation. For details, see “Defining Message Handler Methods.”
  • Your class can add or remove settings. See “Adding and Removing Settings,” earlier in this book.
  • Your class can implement any or all of the startup and teardown methods. See “Overriding Start and Stop Behavior,” later in this book.
    Ensemble is an integration platform potentially communicating with many other heterogeneous devices; therefore, it does not make property values dependent on server platform, time zone, time formatting, or other localization issues that may apply. Rather, InterSystems recommends you handle such cases in your production implementation. If your production requires different initial settings for property values, set the value in the OnInit() method of the business operation. See “Overriding Start and Stop Behavior,” later in this book.
  • Your class can contain methods to accomplish work internal to itself.
The following example shows the general structure that you need:
Class MyProduction.NewOperation Extends Ens.BusinessOperation 
{
Parameter ADAPTER = "MyProduction.MyOutboundAdapter";

Parameter INVOCATION = "Queue";

Method SampleCall(pRequest As Ens.Request, Output pResponse As Ens.Response) As %Status
{
  Quit $$$ERROR($$$NotImplemented)
}

XData MessageMap
{
<MapItems>
  <MapItem MessageType="Ens.Request">
    <Method>SampleCall</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.
For examples of business operation classes, see the adapter guides.

Defining a Message Map

A message map is an XML document, contained within an XData MessageMap block in the business operation host class. For example:
Class MyProduction.Operation Extends Ens.BusinessOperation
{

XData MessageMap
{
<MapItems>
  <MapItem MessageType="MyProduction.MyRequest">
    <Method>MethodA</Method>
  </MapItem>
  <MapItem MessageType="Ens.StringRequest">
    <Method>MethodB</Method>
  </MapItem>
</MapItems>
}

}
The operation of the message map is straightforward. When the business operation receives an incoming request, it searches, starting at the top of the message map, through each MapItem until it finds the first one whose MessageType attribute matches the type of the incoming message. It then invokes the operation method associated with this MapItem.
Some things to keep in mind about message maps:
  • The message map is searched from top to bottom; once a match is found, no more searching is performed.
  • If the incoming request object is a subclass of a given MessageType then it is considered a match. If you want to filter out subclasses, be sure to place them above any super classes within the message map.
  • If the incoming request does not match any of the MapItem entries, then the OnMessage method is called.

Defining Message Handler Methods

When you create a business operation class, typically the biggest task is writing message handlers for use with this adapter, that is, methods that receive Ensemble messages and then invoke methods of the adapter in order to communicate with targets outside the production.
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 some or all of the following:
  1. Optionally set properties of the business operation class (at any appropriate time). See “Business Operation Properties.”
  2. Examine the input object.
  3. Create an instance of the response class.
  4. Call the applicable method or methods of the adapter. These methods are available via the Adapter property of your business operation. For example:
        Set tSc=..Adapter.SendMail(email,.pf)
    
    
    This method is discussed after these steps.
    Or, to send messages to a target within the production, see “Sending Messages to a Target within the Production.”
  5. Examine the response.
  6. Use information in the response to create an Ensemble response message (an instance of Ens.Response or a subclass), which the method returns as output.
    For information on defining message classes, see the chapter “Defining Ensemble Messages.”
  7. Make sure that you set the output argument (
    pOutput
    ). Typically you set this equal to the response message. This step is required.
  8. Return an appropriate status. This step is required.

Business Operation Properties

Within an operation method, the following properties of the business operation class are available:
Property Description
%ConfigName The configuration name for this business operation.
%SessionId The session ID of the current message being processed.
Adapter The associated outbound adapter for this business operation.
DeferResponse To defer the response from this business operation for later delivery, set the DeferResponse property to the integer value 1 (true) and obtain a deferred response delivery token before exiting the business operation.
FailureTimeout The length of time (in seconds) during which to continue retry attempts. After this number of seconds has elapsed, give up and return an error code. See Retry and RetryInterval.
Retry Set this property to the integer value 1 (true) if you want to retry the current message. Typically, the retry feature is used when the external application is not responding and you wish to retry without generating an error. See RetryInterval and FailureTimeout.
RetryInterval How frequently (in seconds) to retry access to the output system if this message is marked for retry. See Retry and FailureTimeout.
SuspendMessage Set this property to the integer value 1 (true) if you want the business operation to mark its current in-progress message as having Suspended status. See the section “Suspending Messages.”

Sending Requests to Targets within the Production

Although a business operation is primarily responsible for delivering a request to the specific external application, it can also send messages to other business operations or to business processes, as needed. To send messages to a target within the production, call SendRequestSync(), SendRequestAsync(), or SendDeferredResponse().
For information on these methods, see “Sending Request Messages” in the chapter “Defining Business Services.”
Ens.BusinessOperation defines an additional method that you can use: DeferResponse().

The DeferResponse() Method

This method returns a %Status value indicating success or failure. It provides one by-reference argument, token, which returns the deferred response delivery token required for a later call to SendDeferredResponse(). For example:
   Set sc=..DeferResponse(.token)
   // Send the token out somewhere...
   Quit $$$O
For an overview of deferred sending, see “Using Deferred Sending” in the chapter “Programming in Ensemble.”

Suspending Messages

If you want the business operation to mark its current in-progress message as having Suspended status, set the business operation property SuspendMessage to the integer value 1 (true). Typically a business operation will do this for messages that have been rejected by the external system for some reason.
Ensemble places a Suspended message on a special queue so that a system administrator can diagnose the problem, fix the problem, and then resend the message. The system administrator can perform a simple resend (to the original target) or can send it to a new destination. For information, see Monitoring Ensemble.
The following sample method is from a business operation that sends a document to an external system. The method sets the SuspendMessage property to 1 if an error returns from the call to Validate() the document that is about to be sent:
Method validateAndIndex(pDoc As MyX12.Document) As %Status
{
  If ""=..Validation||'$method($this,"OnValidate",pDoc,..Validation,.tSC) {
    Set tSC=##class(MyX12.Validator).Validate(pDoc,..Validation)
  }
  Set:'$D(tSC) tSC=$$$OK
  If $$$ISERR(tSC) {
    Set ..SuspendMessage=1
    Do ..SendAlert(##class(Ens.AlertRequest).%New($LB(
        ..%ConfigName,"Suspended document "_pDoc.%Id()_
        " because it failed validation using spec '"
        _..Validation_"' with error "_
        $$$StatusDisplayString(tSC))))
    Quit tSC
  }
  If ""'=..SearchTableClass {
    TRY {
      Set tSCStore=$classmethod(..SearchTableClass,"IndexDoc",pDoc)
      If $$$ISERR(tSCStore)
        $$$LOGWARNING("Failed to create SearchTable entries")
    }
    CATCH errobj {
      $$$LOGWARNING("Failed to invoke SearchTable class")
     }
  }
  Quit $$$OK
}
Previous section   Next section