-
Notifications
You must be signed in to change notification settings - Fork 14
Tutorial 04 05 Add Dispatcher Classes

For each traditional Synergy routine, there must be a dispatcher, which is a class that inherits from the RoutineStub class defined in the Traditional Bridge library code. A dispatcher class has helper methods for serializing and deserializing, exception handling, and logging (see RoutineDispatcher.dbl for more information). Each method dispatcher class:
- deserializes
inandinoutparameters from JSON-RPC request messages into suitable variables and prepares variables foroutparameters and function return values. - calls the underlying subroutine or function, passing parameter variables.
- serializes
inoutparameters,outparameters, and the function return value into a JSON-RPC response message.
If you were creating a Traditional Bridge environment from scratch, you would write these classes. But with xfServerPlus migration, code generation generates them for you, as we'll see in the steps that follow. Note that we recommend organizing all dispatcher classes in a project folder and a namespace path.
This is what generic code for a dispatcher class looks like for a method with two in parameters and one out parameter. In this code, there are some placeholders: "" represents the data type for a parameter (e.g., d28.10), "<routine_name>" represents the name of the traditional Synergy routine that the dispatcher is for, and "<interface_name>" represents the name of the (SMC) interface that includes definitions for the Synergy routine:
import Json
import Harmony.TraditionalBridge
import System.Collections
import TraditionalBridge.Models
.ifdef DBLV11
import System.Text.Json
.define JSON_ELEMENT @JsonElement
.else
.define JSON_ELEMENT @JsonValue
.endc
namespace TraditionalBridge.Dispatchers.<interface_name>
;;-------------------------------------------------------------------------
;;; <summary>
;;; Dispatcher for method BridgeMethods.AddTwoNumbers
;;; </summary>
public class <routine_name>_Dispatcher extends RoutineStub
public method <routine_name>_Dispatcher
proc
;;Initialize the meta data for any data objects that are used by parameters to the method
endmethod
protected override method DispatchInternal, void
required in name, string
required in callFrame, JSON_ELEMENT
required in serializer, @DispatchSerializer
required in dispatcher, @RoutineDispatcher
record
requestId, int
arguments, JSON_ELEMENT
argumentDefinition, @ArgumentDataDefinition
;;Argument 1 (REQUIRED IN number1 <type>)
arg1, d28.10
;;Argument 2 (REQUIRED IN number2 <type>)
arg2, d28.2
;;Argument 3 (REQUIRED OUT result <type>)
arg3, d28.10
endrecord
proc
;;------------------------------------------------------------
;;Prepare variables for arguments
arguments = callFrame.GetProperty("params")
;;Argument 1 (REQUIRED IN number1 <type>)
arg1 = dispatcher.GetImplied(arguments[1])
;;Argument 2 (REQUIRED IN number2 <type>)
arg2 = dispatcher.GetImplied(arguments[2])
;;Argument 3 (REQUIRED OUT result <type>)
;;------------------------------------------------------------
;; Call the underlying routine
xcall <routine_name>(arg1,arg2,arg3)
;;--------------------------------------------------------------------------------
;;Argument 3 (REQUIRED OUT result d28.10)
serializer.ArgumentData(3,arg3,FieldDataType.ImpliedDecimalField,28,10,false)
endmethod
endclass
endnamespace
As you can see in the code sample above, the arguments variable is used to represent the arguments that were 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.
As mentioned above, with xfServerPlus migration, code generation generates dispatcher classes from definitions in an SMC. We've selected an interface from our sample SMC (in Add Traditional Bridge Project), so now we'll invoke code generation:
-
Open a Windows command prompt and navigate to the directory with the
.slnfile for your Harmony Core solution. Then enter the following command to open the Harmony Core GUI tool:harmonycore gui -
When the "Loading Solution" message disappears, select
Codegen > Regenfrom the menu to generate code for the solution (including code based on theBridgeMethodsinterface you added in Add Traditional Synergy routines). -
In Visual Studio Solution Explorer, right-click the Dispatchers folder in the TraditionalBridge project (
TraditionalBridge > Source > Dispatchers) and selectAdd > Existing Itemfrom the context menu. -
In the Add Existing Item window, navigate to the Dispatchers folder, select the
BridgeMethodsMethodDispatchers.dblfile, and clickAdd. -
In Visual Studio open the
BridgeMethodsMethodDispatchers.dblfile. This file has one class for each traditional Synergy method in the Methods folder (TraditionalBridge > Source > Methods).
Let's take a look at GetEnvironment_Dispatcher (which you'll need to scroll down to). This is a good place to start because the GetEnvironmentroutine has no parameters. It is a function that simply returns an alpha value, which means the 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 outbound return values:
;;--------------------------------------------------------------------------------
;;Argument 3 (REQUIRED OUT result d28.10)
serializer.ArgumentData(3,arg3,FieldDataType.ImpliedDecimalField,28,10,false)
This code essentially adds the return value to the JSON-RPC response that will be returned to the caller. The parameters to the ArgumentData method 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 value being returned, using the ENUM FieldDataType. Possible values are
- AlphaField
- DecimalField
- ImpliedDecimal
- ImpliedDecimalField
- IntegerField
- DataObjectField
- DataObjectCollectionField
- EnumField
- HandleField
- BinaryHandleField
- StringField
- AlphaArrayField
- DecimalArrayField
- ImpliedDecimalArrayField
- IntegerArrayField
- StringArrayField
- 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
In this case, the routine being called has one inbound parameter and is a function that returns an alpha value. This means the 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 an alpha variable named logicalName and a string variable named returnValue:
logicalName, a256
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 logicalName:
logicalName = dispatcher.GetText(arguments[1])
There is code to call to the Synergy function:
returnValue = %GetLogicalName(logicalName)
And there is code to serialize any outbound return value and/or parameters:
serializer.ArgumentData(0, returnValue,FieldDataType.AlphaField,returnValue.Length,0,true)
The AddTwoNumbers routine has three parameters, all defined as numeric, and there are two in parameters and one out parameter. This means the dispatcher class needs to
- declare variables for the three parameter values.
- call the subroutine.
- serialize the
outparameter 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 also 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:
```
;;Argument 1 (REQUIRED IN number1 d28.10)
arg1 = dispatcher.GetImplied(arguments[1])
;;Argument 2 (REQUIRED IN number2 d28.2)
arg2 = dispatcher.GetImplied(arguments[2])
```
There is code to call to the underlying subroutine:
```
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: Add Main Dispatcher Class
-
Tutorial 2: Building a Service from Scratch
- Creating a Basic Solution
- Enabling OData Support
- Configuring Self Hosting
- Entity Collection Endpoints
- API Documentation
- Single Entity Endpoints
- OData Query Support
- Alternate Key Endpoints
- Expanding Relations
- Postman Tests
- Supporting CRUD Operations
- Adding a Primary Key Factory
- Adding Create Endpoints
- Adding Upsert Endpoints
- Adding Patch Endpoints
- Adding Delete Endpoints
-
Harmony Core CLI Tool
-
OData Aware Tools
-
Advanced Topics
- CLI Tool Customization
- Adapters
- API Versioning
- Authentication
- Authorization
- Collection Counts
- Customization File
- Custom Field Types
- Custom File Specs
- Custom Properties
- Customizing Generated Code
- Deploying to Linux
- Dynamic Call Protocol
- Environment Variables
- Field Security
- File I/O
- Improving AppSettings Processing
- Logging
- Optimistic Concurrency
- Multi-Tenancy
- Publishing in IIS
- Repeatable Unit Tests
- Stored Procedure Routing
- Suppressing OData Metadata
- Traditional Bridge
- Unit Testing
- EF Core Optimization
- Updating a Harmony Core Solution
- Updating to 3.1.90
- Creating a new Release
-
Background Information