Skip to content

Tutorial 04 07 Add Traditional Bridge Host

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

Harmony Core Logo

Tutorial 4: Configuring the Traditional Bridge Host Program

The traditional Synergy side of your Traditional Bridge environment is almost complete. But before we finish the process, let's look at the Traditional Bridge host program that was generated when Traditional Bridge was added to the Harmony Core solution.

The host program performs these steps:

  • Opens and configures the terminal channel environment
  • Configures and initializes logging
  • Creates an instance of the master dispatcher class
  • Sends a "READY" message on STDOUT to tell Harmony Core that the host program is running
  • Instructs the master dispatcher class to start listening for and dispatching messages
  • Closes the log file when the master dispatcher exits
  • Gracefully handles unexpected exceptions
  1. In Solution Explorer, open host.dbl (in the TraditionalBridge\Source folder). Notice that because this program manipulates classes from several namespaces, those namespaces are imported to make the classes easier to access.

    import Harmony.TraditionalBridge
    import Json
    import TraditionalBridge
    import TraditionalBridge.Dispatchers
    

Exception Handling

If any code in this environment fails, we want to trap and log the exception and exit gracefully, so most of the code is wrapped in one big TRY-CATCH statement:

try
begin
...
end
catch(ex, @Exception)
begin
...
end
endtry

Harmony Core sends JSON-RPC request messages on stdin, and it expects Traditional Bridge to respond by sending JSON-RPC response messages on stdout. In traditional Synergy, both are represented by a terminal channel. So the code opens a terminal and configures the environment:

xcall flags(1907050020)
open(ttChan=0,o,"TT:")

Although it is possible to debug both sides of a Traditional Bridge environment using Visual Studio, logging is always a valuable debugging tool, particularly in client/server environments. Traditional Bridge incorporates a comprehensive logging subsystem that is configurable to operate at six levels. (Level 2 is considered normal logging, and level 6 is full verbose logging.) So the following is in the try block:

;;Does the environment define the logging level?
getlog("HARMONY_LOG_LEVEL", tmpa, length)
if (length) then
begin
   logLevel = %integer(tmpa)
end
else
begin
   ;Levels are 1 to 6, 2 is normal logging, 6 is highest logging
   logLevel = 2
end

;;Define the log file name
logFileName = "BRIDGE_" + %string(%jbno) + ".LOG"

;;Initiate logging
Logger.Instance = new Logger(logFileName, logLevel, false)

The following is in the catch block, so if anything goes wrong, the program will deal with it gracefully.

;;If anything failed, log an error if we can
if (Logger.Instance != ^null)
begin
   Logger.Instance.Log("DISPATCHER EXITED with exception" + ex.ToString())
end

Starting the Dispatcher

The code also creates an instance of the master dispatcher class:

;;Create a new instance of the main "dispatcher" class
dispatcher = new SuperRoutineDispatcher(MethodDispatcher.GetDispatchers())
   
;;Issue the "READY" message.
;;Harmony Core looks for this and considers the connection active when it sees it
puts(ttChan, "READY" + %char(13)+ %char(10))

;;Start dispatching requests
dispatcher.Dispatch(ttChan)

As you can see, this is where the action happens. The code creates an instance of the MethodDispatcher class, lets Harmony Core know it's ready to go, and hands control over to the Dispatch method.

From this point on, Traditional Bridge library code will take care of receiving requests, dispatching to routines, and issuing responses.

Change the Way the Main Dispatcher Is Instantiated

The main dispatcher class is instantiated in a way that works for a Traditional Bridge implementation that uses multiple SMC interfaces. It passes the MethodDispatcher.GetDispatchers() method, which is available in generated code only when there are methods from multiple interfaces. In this tutorial, however, our Traditional Bridge implementation exposes methods from only one interface, so we need to change the way the main dispatcher class is instantiated:

  1. In host.dbl (which is in TraditionalBridge\Source), find the line that instantiates SuperRoutineDispatcher (the dispatcher = new SuperRoutineDispatcher... line) and change it to the following:

    dispatcher = new SuperRoutineDispatcher(new RoutineDispatcher[#] { new BridgeMethodsDispatcher() })
    
  2. Save host.dbl.

Program Termination

Finally, note that there are two scenarios that can cause the host program to terminate:

  • The master dispatcher exits
  • An exception is trapped and logged

In both cases, the log file is closed, and the application is terminated by the following code, which follows the TRY-CATCH block:

;;Close the log
if (Logger.Instance != ^null)
begin
   Logger.Instance.CloseLog()
end

stop

Launch.bat

If your Traditional Bridge host application will run on Windows (in a local or remote process), you will need to provide an environment suited to run the program. The Synergy environment on Windows is generally configured by calling %SYNERGYDE32%dbl\dblvars32.bat for a 32-bit environment or %SYNERGYDE64%dbl\dblvars64.bat for 64-bit. But you may also need to configure additional environment variables, etc., depending on the requirements of your code.

For this reason, on Windows we generally recommend having Harmony Core launch a batch file to configure the runtime environment as necessary. (This usually isn't needed on UNIX, Linux, or OpenVMS because you can generally use command shell login scripts on these platforms for any necessary configuration.)

  1. In Solution Explorer, double-click launch.bat (in the TraditionalBridge folder) to open the file in the Visual Studio editor.

    @echo off
    pushd %~dp0
    setlocal
    
    rem Set any environment required by the underlying methods
    
    rem Configure a Synergy environment
    rem call "%SYNERGYDE32%dbl\dblvars32.bat"
    call "%SYNERGYDE64%dbl\dblvars64.bat"
    
    rem Launch the host program
    dbs host.dbr
    
    rem Launch the host program for remote debugging
    rem dbr -dv -rd 4444:60 host.dbr
    
    endlocal
    popd
    

    Notice the following:

    • The script in this file defaults to calling dblvars64.bat, which should be in line with the way that you configured your build environment earlier.

    • By default, the file launches the host.dbr using the dbs runtime. But there is an alternate command that uses the dbr runtime with the -dv -rd 4444:60 command line options. Use this alternate command if you want to start the host program in remote debugging mode and then attach to it using the Visual Studio debugger.

Also note that the Harmony Core implementation for this tutorial expects to find launch.bat alongside the host program. To make this happen, the value of the Copy to Output Directory property for launch.bat should be set to Copy always. (You can check this setting by right-clicking launch.bat in Solution Explorer and selecting Properties from the context menu. Then, in the Properties dialog, you'll see the Copy to Output Directory setting.) This setting ensures that the batch file is copied to the appropriate bin folder when running in the Visual Studio development environment, and it also ensures that the file will become part of the distribution when you publish your completed application. You will see how this batch file comes into play later when you configure the Harmony Core environment.


Next topic: Adding a Helper Service Class


Clone this wiki locally