Skip to content

Tutorial 04 05 Add Dispatcher Classes

Steve Ives edited this page May 20, 2020 · 23 revisions

Harmony Core Logo

Tutorial 4: Add Dispatcher Classes

For each traditional Synergy routine, you must add a dispatcher, which is a class that inherits from the RoutineStub class which is defined in the Traditional Bridge library code, and which has helper methods for serializing and deserializing, exception handling, and logging (see RoutineDispatcher.dbl for more information).

Each method dispatcher class does these things:

  • De-serializes any in or inout parameters from a JSON-RPC request message into suitable variables, and prepares variables for any out parameters and function return values.
  • Calls the underlying subroutine or function, passing the parameter variables.
  • Serializes any inout parameters, out parameters or function return values into a JSON-RPC response message.

This is what the generic code for each dispatcher class looks like:

;;*****************************************************************************
;;
;; Title:       <ROUTINE>Dispatcher.dbl
;;
;; Description: Dispatcher class for calls to <ROUTINE>
;;
;;*****************************************************************************

import Harmony.TraditionalBridge
import Json
import System
import System.Collections

.ifdef DBLV11
import System.Text.Json
.define JSON_ELEMENT @JsonElement
.else
.define JSON_ELEMENT @JsonValue
.endc

namespace TraditionalBridge.Dispatchers

    ;;; <summary>
    ;;; Dispatcher for <ROUTINE>
    ;;; </summary>
    public class <ROUTINE>Dispatcher extends RoutineStub

        ;;; <summary>
        ;;; Dispatch to <ROUTINE>
        ;;; </summary>
        ;;; <param name="name">Name of routine to call.</param>
        ;;; <param name="callFrame">Current JSON-RPC request.</param>
        ;;; <param name="serializer">Outbound data serializer.</param>
        ;;; <param name="dispatcher">Inbound routine dispatcher.</param>
        protected override method DispatchInternal, void
            required in name,       string
            required in callFrame,  JSON_ELEMENT
            required in serializer, @DispatchSerializer
            required in dispatcher, @RoutineDispatcher

            ;;Declare data for any parameters and/or return value
            record
                arguments,          JSON_ELEMENT
            endrecord
        proc
            ;;------------------------------------------------------------
            ;;Process inbound arguments

            arguments = callFrame.GetProperty("params")

            ;TODO: Add code for to de-serialize inbound parameters here

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

            ;TODO: Call the underlying routine here

            ;;------------------------------------------------------------
            ;;Process any outbound return value and/or parameters

            ;TODO: Serialize any outbound return value and/or parameters here

        endmethod

    endclass

endnamespace

We recommend organizing all dispatcher classes in a project folder and namespace path.

  1. In Solution Explorer, right-click on the TraditionalBridge, select Add > Folder, and name the folder Dispatchers.

Add GetEnvironmentDispatcher

Your next task is to create a dispatcher class for each of the three routines being exposed. First, you will create a dispatcher for the GetEnvironment function.

  1. Right-click on the Dispatchers folder, select Add > Class, and name the new file GetEnvironmentDispatcher.dbl.

  2. Replace the current code in the file with the sample scaffolding code shown above.

  3. Replace all instances of the token <ROUTINE> with the word GetEnvironment.

    TIP: The Visual Studio shortcut key for "Find and Replace" is Ctrl+H.

The routine being called has no parameters, but it is a function that returns an alpha value. This means we need to do the following:

  • Declare an appropriate 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.
  1. In the data division of the DispatchInternal method, add a new string variable named returnValue to the existing record, like this:

    ;;Declare data for any parameters and/or return value
    record
        arguments,          JSON_ELEMENT
        returnValue,        string
    endrecord
    
  2. As we have no inbound parameters, remove the TODO comment Add code for to de-serialize inbound parameters here.

  3. Locate the TODO comment Call the underlying routine here and replace it with a call to the synergy function:

    returnValue = %GetEnvironment
    
  4. Locate the TODO comment Serialize any outbound return value and/or parameters here and replace it with the following code:

    ;;Argument 0 is the return value
    serializer.ArgumentData(0, returnValue,FieldDataType.AlphaField,returnValue.Length,0,true)
    

    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 argument number, 0 representing the return value of a 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.
  5. Save the file.

Your dispatcher should now look like this:

;;*****************************************************************************
;;
;; Title:       GetEnvironmentDispatcher.dbl
;;
;; Description: Dispatcher class for calls to GetEnvironment
;;
;;*****************************************************************************

import Harmony.TraditionalBridge
import Json
import System
import System.Collections

.ifdef DBLV11
import System.Text.Json
.define JSON_ELEMENT @JsonElement
.else
.define JSON_ELEMENT @JsonValue
.endc

namespace TraditionalBridge.Dispatchers

    ;;; <summary>
    ;;; Dispatcher for GetEnvironment
    ;;; </summary>
    public class GetEnvironmentDispatcher extends RoutineStub

        ;;; <summary>
        ;;; Dispatch to GetEnvironment
        ;;; </summary>
        ;;; <param name="name">Name of routine to call.</param>
        ;;; <param name="callFrame">Current JSON-RPC request.</param>
        ;;; <param name="serializer">Outbound data serializer.</param>
        ;;; <param name="dispatcher">Inbound routine dispatcher.</param>
        protected override method DispatchInternal, void
            required in name,       string
            required in callFrame,  JSON_ELEMENT
            required in serializer, @DispatchSerializer
            required in dispatcher, @RoutineDispatcher

            ;;Declare data for any parameters and/or return value
            record
                arguments,          JSON_ELEMENT
                returnValue,        string
            endrecord
        proc
            ;;------------------------------------------------------------
            ;;Process inbound arguments

            arguments = callFrame.GetProperty("params")

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

            returnValue = %GetEnvironment

            ;;------------------------------------------------------------
            ;;Process any outbound return value and/or parameters

            ;;Argument 0 is the return value
            serializer.ArgumentData(0, returnValue,FieldDataType.AlphaField,returnValue.Length,0,true)

        endmethod

    endclass

endnamespace

The dispatcher for the GetEnvironment function is now complete.

GetLogicalNameDispatcher

Your next task is to develop a dispatcher for the GetLogicalName function.

  1. Right-click on the Dispatchers folder, select Add > Class, and name the new file GetLogicalNameDispatcher.dbl.

  2. Replace the current code in the file with the sample scaffolding code shown above.

  3. Replace all instances of the token <ROUTINE> with the word GetLogicalName.

TIP: The Visual Studio shortcut key for "Find and Replace" is Ctrl+H.

The routine being called has one inbound parameter and is a function that returns an alpha value. This means we need to do the following:

  • Declare appropriate variables to store the logical name to pass to the function and the return value from the function.
  • Call the function, passing the parameter variable, and assign the return value to the return value variable.
  • Serialize the return value into the JSON-RPC response to the caller.
  1. In the data division of the DispatchInternal method, add an alpha variable named logicalName and a string variable named returnValue to the existing record, like this:
;;Declare data for any parameters and/or return value
record
    arguments,          JSON_ELEMENT
    logicalName,        a256
    returnValue,        string
endrecord

Next you need extract the value of the inbound parameter from the received JSON-RPC message and store the value in the new logicalName field that you just created.

  1. Locate and remove the TODO comment Add code for to de-serialize inbound parameters here, and replace it with this code:

    ;;Argument 1 is the inbound logical name
    logicalName = dispatcher.GetText(arguments[1])
    
  2. Now locate the TODO comment Call the underlying routine here and replace it with a call to the synergy function:

    returnValue = %GetLogicalName(logicalName)
    
  3. Finally, locate the TODO comment Serialize any outbound return value and/or parameters here and replace it with the following code:

    ;;Argument 0 is the return value
    serializer.ArgumentData(0, returnValue,FieldDataType.AlphaField,returnValue.Length,0,true)
    
  4. Save the file.

Your dispatcher should now look like this:

;;*****************************************************************************
;;
;; Title:       GetLogicalNameDispatcher.dbl
;;
;; Description: Dispatcher class for calls to GetLogicalName
;;
;;*****************************************************************************

import Harmony.TraditionalBridge
import Json
import System
import System.Collections

.ifdef DBLV11
import System.Text.Json
.define JSON_ELEMENT @JsonElement
.else
.define JSON_ELEMENT @JsonValue
.endc

namespace TraditionalBridge.Dispatchers

    ;;; <summary>
    ;;; Dispatcher for GetLogicalName
    ;;; </summary>
    public class GetLogicalNameDispatcher extends RoutineStub

        ;;; <summary>
        ;;; Dispatch to GetLogicalName
        ;;; </summary>
        ;;; <param name="name">Name of routine to call.</param>
        ;;; <param name="callFrame">Current JSON-RPC request.</param>
        ;;; <param name="serializer">Outbound data serializer.</param>
        ;;; <param name="dispatcher">Inbound routine dispatcher.</param>
        protected override method DispatchInternal, void
            required in name,       string
            required in callFrame,  JSON_ELEMENT
            required in serializer, @DispatchSerializer
            required in dispatcher, @RoutineDispatcher

            ;;Declare data for any parameters and/or return value
            record
                arguments,          JSON_ELEMENT
                logicalName,        a256
                returnValue,        string
            endrecord
        proc
            ;;------------------------------------------------------------
            ;;Process inbound arguments

            arguments = callFrame.GetProperty("params")

            ;;Argument 1 is the inbound logical name
            logicalName = dispatcher.GetText(arguments[1])

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

            returnValue = %GetLogicalName(logicalName)

            ;;------------------------------------------------------------
            ;;Process any outbound return value and/or parameters

            ;;Argument 0 is the return value
            serializer.ArgumentData(0, returnValue,FieldDataType.AlphaField,returnValue.Length,0,true)

        endmethod

    endclass

endnamespace

Your dispatcher for the GetLogicalName routine is now complete.

AddTwoNumbersDispatcher

Your final task is to create a dispatcher class for the AddTwoNumbers function.

  1. Right-click on the Dispatchers folder, select Add > Class, and name the new file AddTwoNumbersDispatcher.dbl.

  2. Replace the current code in the file with the sample scaffolding code shown above.

  3. Replace all instances of the token <ROUTINE> with the word AddTwoNumbers.

TIP: The Visual Studio shortcut key for "Find and Replace" is Ctrl+H.

The routine being called is a subroutine with three parameters, all defined as numeric. There are two in parameters, and one out parameter. This means we need to do the following:

  • Declare appropriate variables represent the three parameter values.
  • Call the subroutine, passing the appropriate parameters.
  • Serialize the out parameter into the JSON-RPC response to the caller.
  1. In the data division of the DispatchInternal method, add three new decimal variables named arg1, arg2 and arg3 to the existing record, like this:
;;Declare data for any parameters and/or return value
record
    arguments,          JSON_ELEMENT
    arg1,               decimal
    arg2,               decimal
    arg3,               decimal
endrecord

Now extract the value of the inbound parameters from the received JSON-RPC message and store the value in the new arg1 and arg2 variables.

  1. Locate and remove the TODO comment Add code for to de-serialize inbound parameters here, and replace it with this code:

    ;;Arguments 1 and 2 are passed in to the underlying routine
    arg1 = dispatcher.GetImplied(arguments[1])
    arg2 = dispatcher.GetImplied(arguments[2])
    
  2. Locate the TODO comment Call the underlying routine here and replace it with a call to the underlying subroutine:

    xcall AddTwoNumbers(arg1,arg2,arg3)
    
  3. Finally, locate the TODO comment Serialize any outbound return value and/or parameters here and replace it with the following code:

    ;;Argument 3 is the returned value
    serializer.ArgumentData(3,arg3,FieldDataType.ImpliedDecimal,28,10,false)
    
  4. Save the file.

Your dispatcher should now look like this:

;;*****************************************************************************
;;
;; Title:       GetEnvironmentDispatcher.dbl
;;
;; Description: Dispatcher class for calls to GetEnvironment
;;
;;*****************************************************************************

import Harmony.TraditionalBridge
import Json
import System
import System.Collections

.ifdef DBLV11
import System.Text.Json
.define JSON_ELEMENT @JsonElement
.else
.define JSON_ELEMENT @JsonValue
.endc

namespace TraditionalBridge.Dispatchers

    ;;; <summary>
    ;;; Dispatcher for GetEnvironment
    ;;; </summary>
    public class GetEnvironmentDispatcher extends RoutineStub

        ;;; <summary>
        ;;; Dispatch to GetEnvironment
        ;;; </summary>
        ;;; <param name="name">Name of routine to call.</param>
        ;;; <param name="callFrame">Current JSON-RPC request.</param>
        ;;; <param name="serializer">Outbound data serializer.</param>
        ;;; <param name="dispatcher">Inbound routine dispatcher.</param>
        protected override method DispatchInternal, void
            required in name,       string
            required in callFrame,  JSON_ELEMENT
            required in serializer, @DispatchSerializer
            required in dispatcher, @RoutineDispatcher

            ;;Declare data for any parameters and/or return value
            record
                arguments,          JSON_ELEMENT
                returnValue,        string
            endrecord
        proc
            ;;------------------------------------------------------------
            ;;Process inbound arguments

            arguments = callFrame.GetProperty("params")

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

            returnValue = %GetEnvironment

            ;;------------------------------------------------------------
            ;;Process any outbound return value and/or parameters

            ;;Argument 0 is the return value
            serializer.ArgumentData(0, returnValue,FieldDataType.AlphaField,returnValue.Length,0,true)

        endmethod

    endclass

endnamespace

The dispatcher for the AddTwoNumbers function is now complete.


Next topic: Add Main Dispatcher Class


Clone this wiki locally