Skip to content

Tutorial 04 05 Add Dispatcher Classes

Matt Linder edited this page Jun 30, 2023 · 22 revisions

Harmony Core Logo

Tutorial 4: Adding Dispatcher Classes for Routines

For each traditional Synergy routine exposed by Traditional Bridge, there must be a dispatcher, which is a class that

  • deserializes in and inout parameters from JSON-RPC request messages into suitable variables and prepares variables for out parameters and function return values.
  • calls the underlying traditional Synergy subroutine or function, passing parameter variables.
  • serializes inout parameters, out parameters, and the function return value into a JSON-RPC response message.

Each dispatcher class must inherit from the RoutineStub class, which is defined in Traditional Bridge library code and has helper methods for serializing/deserializing, exception handling, and logging (see RoutineDispatcher.dbl). We recommend organizing all dispatcher classes in a project folder and a namespace path.

If you create a Traditional Bridge environment from scratch, you will need to create routine dispatcher classes for your methods. But with xfServerPlus migration, code generation creates these classes, as we'll see in the steps that follow.

Add Dispatcher Classes

With xfServerPlus migration, dispatcher classes are generated from definitions in a Synergy method catalog (SMC). In Adding Traditional Synergy Routines, we selected an interface from our sample SMC, so now the code generation feature of the Harmony Core GUI tool will generate dispatcher classes from methods in the selected interface.

  1. Open a Windows command prompt and navigate to the directory with the .sln file for your Harmony Core solution. Then enter the following command to open the Harmony Core GUI tool:

    harmonycore gui
    
  2. When the "Loading Solution" message disappears, select Codegen > Regen from the menu to generate code for the solution. Then, when the "Finished" message appears at the top of the Regen window, click OK.

  3. In Visual Studio Solution Explorer, right-click the Dispatchers folder in the TraditionalBridge project (TraditionalBridge\Source\Dispatchers) and select Add > Existing Item from the context menu.

  4. In the Add Existing Item window, navigate to the Dispatchers folder (Which is under TraditionalBridge\Source), select the BridgeMethodsMethodDispatchers.dbl file, and click Add. (You'll also see a BridgeMethodsDispatcher.dbl file in this folder. We'll add that file in the next section of this tutorial: Adding the Main Dispatcher Class.)

Examine the Generated Routine Dispatchers

  1. Now open BridgeMethodsMethodDispatchers.dbl in the Visual Studio editor. Notice that this file has one dispatcher class for each method in the BridgeMethods interface—i.e., it has a dispatcher for each of our traditional Synergy routines in the Methods folder.

GetEnvironment_Dispatcher

Scroll down to the GetEnvironment_Dispatcher class. This is a good place to start our examination of dispatchers because the underlying GetEnvironmentroutine has no parameters. GetEnvironment is a function that simply returns an alpha value, which means this dispatcher class must

  • declare a variable to store the return value from the function.
  • call the function and assign the return value to the variable.
  • serialize the return value into the JSON-RPC response to the caller.

Notice that the data division of the DispatchInternal method has a new string variable named returnValue:

returnValue,        string

This method also includes a call to the Synergy function:

returnValue = %GetEnvironment

And there is code to serialize the outbound return value:


;;Function return value
serializer.ArgumentData(0,%atrim(returnValue),FieldDataType.StringField,,0,false)

This code essentially adds the return value to the JSON-RPC response that will be returned to the caller. The parameters for ArgumentData are the following:

  • The argument number, 0, representing the return value of the function
  • The actual value to be returned
  • The data type of the argument, using the ENUM FieldDataType
  • The length of the data being returned
  • The number of decimal places (for implied decimal fields)
  • A Boolean value indicating whether the value contains any binary data

GetLogicalName_Dispatcher

In this case, the routine being called has one inbound parameter and is a function that returns an alpha value. This means this dispatcher class must

  • declare variables for the logical name (to pass to the function) and for the function's return value.
  • call the function, passing the parameter variable and assigning the return value to the return value variable.
  • serialize the return value into the JSON-RPC response to the caller.

Notice that in the data division of the DispatchInternal method, there is a string variable (arg1) for the logical name and a string variable named returnValue:

;;Argument 1 (REQUIRED IN aLogicalName string)
arg1,               string
returnValue,         STRING

The method also has code to extract the value of the inbound parameter from the received JSON-RPC message and store the value in arg1:

;;Argument 1 (REQUIRED IN aLogicalName string)

arg1 = dispatcher.GetText(arguments[1])

There is also code to call to the Synergy function:

returnValue = %GetLogicalName(arg1)

And there is code to serialize any outbound return value and/or parameters:

;;Function return value
serializer.ArgumentData(0,%atrim(returnValue),FieldDataType.StringField,,0,false)

AddTwoNumbers_Dispatcher

The traditional Synergy AddTwoNumbers routine has three parameters, all defined as numeric. There are two in parameters and one out parameter. This means this dispatcher class must

  • declare variables for the three parameter values.
  • extract the values of the inbound parameters from the received JSON-RPC message.
  • call the subroutine.
  • serialize the out parameter into the JSON-RPC response to the caller.

In the data division of the DispatchInternal method, there are three decimal variables (arg1, arg2 and arg3):

record
    requestId,          int
    arguments,          JSON_ELEMENT
    argumentDefinition, @ArgumentDataDefinition

    ;;Argument 1 (REQUIRED IN number1 d28.10)
    arg1,               d28.10
    ;;Argument 2 (REQUIRED IN number2 d28.2)
    arg2,               d28.2
    ;;Argument 3 (REQUIRED OUT result d28.10)
    arg3,               d28.10
endrecord

The method has code to extract the values of the inbound parameters from the received JSON-RPC message and store the values in the arg1 and arg2 variables:

;;------------------------------------------------------------
;;Prepare variables for arguments

arguments = callFrame.GetProperty("params")

;;Argument 1 (REQUIRED IN number1 d28.10)

arg1 = dispatcher.GetImplied(arguments[1])

;;Argument 2 (REQUIRED IN number2 d28.2)

arg2 = dispatcher.GetImplied(arguments[2])

;;Argument 3 (REQUIRED OUT result d28.10)

Also notice that the arguments variable is used to represent the arguments that are passed to the routine and is populated by the code arguments = callFrame.GetProperty("params"). You can use one of several helper methods that are provided by the RoutineDispatcher class (represented here by the dispatcher variable) to access the data associated with each parameter. (TODO: Document all the helper methods and provide example code here.)

There is also code to call to the underlying subroutine:

;;------------------------------------------------------------
;; Call the underlying routine

xcall AddTwoNumbers(arg1,arg2,arg3)

And there is code to serialize the outbound return value:

;;--------------------------------------------------------------------------------
;;Argument 3 (REQUIRED OUT result d28.10)
        
serializer.ArgumentData(3,arg3,FieldDataType.ImpliedDecimalField,28,10,false)

Next topic: Adding the Main Dispatcher Class


Clone this wiki locally