RemObjects SDK Client Sample (Delphi)

The RemObjects SDK Client sample demonstrates how to use Hydra to share RemObjects SDK connection details (channel, message) between host and plugin. In this sample, we will show how to use a service from both host and plugin.

Please note that you will need the RO SDK for Delphi and the Hydra RO SDK integration package installed in order to build and run this application.

Configuring the Server

In this sample we will use the server from the Mega Demo sample that is shipped with RemObjects SDK, so the first thing you need to do is to compile the [Mega Demo sample](MegaDemo Sample (Delphi) "wikilink").

The client is configured to use the HTTP channel, so before you can use the client, you need to activate the HTTP server as shown in the screenshot.

Examine the Client

The client is a regular RemObjects SDK VCL client application, @@@that access to a service exposed by the server@@@. If you need more information on how to create an RO SDK client, please refer to the RemObjects SDK docs.

Unlike common Hydra host applications, our sample contains the THYROModuleManager component, which provides two additional properties:

  • ROChannel
  • ROMessage

These properties allow you to connect your channel and message components to the module manager, so these components will be transferred to the plugin.

Let's examine the client code:

procedure THostForm.btnLoadPluginClick(Sender: TObject);
const
  PLUGIN_NAME = 'ROPlugin.dll';
begin
  fVisualPlugin := nil;
  with ROModuleManager do begin
    if FindModule(PLUGIN_NAME) = nil then
      LoadModule(PLUGIN_NAME);
    CreateVisualPlugin('MegaDemoClientForm', fVisualPlugin);
    fVisualPlugin.ShowParented(pnlHost);
  end;
end;

procedure THostForm.btnCallSumLocallyClick(Sender: TObject);
var
  A, B: Integer;
begin
  A := Random(10) + 1;
  B := Random(10) + 1;
  ShowMessage(IntToStr(A) + ' + ' + IntToStr(B) + ' = ' +
    IntToStr((RemoteService as IMegaDemoService).Sum(a, b)));
end;
  • btnLoadPluginClick method - Using module manager we are loading the plugin module, creating a visual plugin and showing it in the panel. As you can see, there is no difference between a regular module manager and the RO module manager.
  • btnCallSumLocallyClick method - This method calls the Sum method from a remote server.

MegaDemoPackage.bpl

Please note that in addition to the standard packages, both host and plugin use the MegaDemoPackage.bpl package.

We are using the shared package to avoid possible issues with multiple types initialization. If the "_Intf" files is placed in a package that is loaded by the host, it will be initialized only once.

Examine the Plugin

The plugin consists of two parts: a module control and a visual plugin. Let's describe each part:

Module Controller

The module controller is an entry point for the plugin module; it supplies the host with information about stored plugins and provides a method that allows the host to instantiate and work with plugins.

The module controller is a singleton, so we can use it to initialize data that can be used by all plugins in the module.

Our module controller has a TRORemoteService component. To be able to process calls to a remote service, this component requires channel and message, so let's take a look at how to initialize them:

procedure TROPluginController.HYModuleControllerSetHost(
  const Sender: IHYHostAware; const aHost: IHYHost);
begin
  if aHost = nil then
    exit;
  with (aHost as IHYRemObjectsHost) do begin
    svcNewService.Channel := ROChannel;
    svcNewService.Message := ROMessage;
  end;
end;

We are using the OnSetHost event of the THYModuleController component, so we can initialize a remote service when the host is set.

To initialize our remote service, we are casting the aHost parameter to the IHYRemObjectsHost interface, and now we can access the host channel and message components.

Please note that you should always check if the aHost parameter is nil, as the host will clear its reference on module unload.

We can do this initialization on the plugin using the same OnSetHost event, but if there is more than one plugin that requires access to the host components, we will need to initialize every plugin, and with module controller we can do this only once.

Visual Plugin

Our plugin is a regular Hydra Visual plugin If you need more information on how to create a VCL plugin, please refer to this article.

The most important thing here is how we call the remote service:

uses
  mcROPluginController, MegaDemoLibrary_Intf;

procedure TMegaDemoClientForm.btnSumClick(Sender: TObject);
var res : integer;
begin
  res := (ROPluginController.svcNewService as IMegaDemoService).Sum(edtA.Value, edtB.Value);
  ShowMessage('The result is '+IntToStr(res));
end;

As you can see, we are accessing the svcNewService, which is a TRORemoteService component located in our module controller. After casting it to the service interface, we can call service methods just like in regular RemObjects SDK clients.

Putting It All Together

Now that we've examined all major parts of the sample, we can build both plugin and host. And after we launch the sample, we should get the following results:

Calling a service from the host:

Calling a service from the plugin:

Concepts Covered