Создание CORBA-сервера
Усложним задачу, добавив в проект новый сервер для CORBA-соединения. Его создание как две капли воды похоже на изготовление обычного сервера, о чем мы только что говорили. Вся разница состоит лишь в том, что на начальном этапе вместо мастера Remote Data Module мы запускаем мастер New?Multitier?CORBA Data Module. Компоненты доступа к данным и их связывание точно такое же. Модуль формы сервера сохраните как CORBAMain.pas, имя формы (свойство Caption) установите как MsgForm, ее заголовок (свойство Caption) — «Client Messages», а сам проект должен быть сохранен как CORBA_RDM_ Server.dpr. Точно так же в форму нужно положить компонент TProgressBar. Не забудьте включить опцию проекта Build with runtime packages.
Теперь о различиях. Они проявятся, как только вы запустите мастер CORBA Data Module. Поле Class Name вам уже знакомо, в него следует ввести имя CORBA_RDM. Зато ранее мы не сталкивались с полями Instancing и Threading Model. Если вы хотите, чтобы для каждого клиентского вызова создавался новый экземпляр удаленного модуля данных, следует установить в поле Instancing опцию Instance-per-client. Если установить опцию Shared Instance, один экземпляр модуля будет обслуживать запросы от разных клиентов (то, что нужно нам). В поле Threading Model нужно указывать, должен ли модуль обслуживать несколько вызовов одновременно (Multithreaded) или по одному вызову за раз (Single-threaded), что мы с вами и сделаем.
Сохраним исходный текст в файле с именем CORBA_RDM_Impl.pas и откомпилируем проект. В отличие от обычного удаленного модуля данных, аналогичный модуль на основе CORBA не требует регистрации. Если же вы хотите автоматически запускать подобный CORBA-сервер, то следует обратиться к документации по Inprise VisiBroker к разделу, посвященному OAD.
Исходные тексты CORBA-сервера приведены в листинге 1.
Листинг 1
CORBA-сервер
Файл CORBA_RDM_Impl.dfm object CORBA_RDM: TCORBA_RDM OldCreateOrder = False Left = 65 Top = 197 Height = 480 Width = 696 object DataSetProvider1: TDataSetProvider DataSet = IBQuery1 Constraints = True AfterGetRecords = DataSetProvider1AfterGetRecords Left = 45 Top = 20 end object IBDatabase1: TIBDatabase Connected = True DatabaseName = ? D:BorlandInterbaseexamplesdatabase Employee.gdb? Params.Strings = ( ?user_name=SYSDBA? ?password=masterkey?) LoginPrompt = False DefaultTransaction = IBTransaction1 IdleTimer = 0 SQLDialect = 1 TraceFlags = [] Left = 45 Top = 105 end object IBTransaction1: TIBTransaction Active = True DefaultDatabase = IBDatabase1 Left = 165 Top = 110 end object IBQuery1: TIBQuery Database = IBDatabase1 Transaction = IBTransaction1 Active = True CachedUpdates = False SQL.Strings = ( ?select CUST_NO, SALES_REP, ORDER_DATE, PAID, QTY_ORDERED, TOTAL_? + ?VALUE from SALES?) Left = 45 Top = 200 object IBQuery1CUST_NO: TIntegerField FieldName = ?CUST_NO? Required = True end object IBQuery1SALES_REP: TSmallintField FieldName = ?SALES_REP? end object IBQuery1ORDER_DATE: TDateTimeField FieldName = ?ORDER_DATE? Required = True end object IBQuery1PAID: TIBStringField FieldName = ?PAID? Size = 1 end object IBQuery1QTY_ORDERED: TIntegerField FieldName = ?QTY_ORDERED? Required = True end end end Файл CORBA_RDM_Impl.pas unit CORBA_RDM_Impl; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComObj, VCLCom, StdVcl, DataBkr, CorbaRdm, CorbaObj, CORBA_Server_TLB, Db, IBCustomDataSet, IBQuery, IBDatabase Provider, CORBAMain; type TCORBA_RDM = class(TCorbaDataModule, ICORBA_RDM) DataSetProvider1: TDataSetProvider; IBDatabase1: TIBDatabase; IBTransaction1: TIBTransaction; IBQuery1: TIBQuery; IBQuery1CUST_NO: TIntegerField; IBQuery1SALES_REP: TSmallintField; IBQuery1ORDER_DATE: TDateTimeField; IBQuery1PAID: TIBStringField; IBQuery1QTY_ORDERED: TIntegerField; procedure DataSetProvider1AfterGetRecords(Sender: TObject; var OwnerData: OleVariant); private { Private declarations } public { Public declarations } protected { Protected declarations } end; var CORBA_RDM: TCORBA_RDM; implementation {$R *.DFM} uses CorbInit, CorbaVcl; procedure TCORBA_RDM .DataSetProvider1AfterGetRecords(Sender: TObject; var OwnerData: OleVariant); begin with MsgForm.ProgressBar1 do begin If Position < Max then StepIt else Position := 0; end; end; initialization TCorbaVclComponentFactory .Create(?CORBA_RDMFactory?, ?CORBA_RDM?, ?IDL:CORBA_Server /CORBA_RDMFactory:1.0?, ICORBA_RDM, TCORBA_RDM, iSingleInstance, tmSingleThread); end.
Создание клиента
Наконец мы добрались до кульминационного момента — создания программы-клиента (исходные тексты приведены в листинге 2).
Создадим новый проект и, как обычно, включим опцию проекта Build with runtime packages. Проект сохраним под именем Client.dpr, а главное окно программы будет носить имя ClientForm. Модуль окна сохраняется в файле ClientFormUnit.pas.
Интерфейс пользователя сделать несложно: поместим в главную форму компонент TCoolBar и установим его свойство AutoSize в значение True. Внутрь TCoolBar поместим компоненты TDBNavigator (для перемещения по данным) и TComboBox (для переключения между различными типами соединений). В раскрывающемся списке отредактируем свойство Items, определяющее пункты выбора. Таких пунктов должно быть три: DCOMConnection, SocketConnection и CorbaConnection.
В соответствии с традицией все компоненты, заведующие работой с данными, следует вынести в отдельный модуль. Поэтому командой New...?New? Data Module создадим подобный модуль данных и сохраним его под именем ClientDM, его свойство Name установим как dm. Внутрь полученного модуля кладутся следующие компоненты: TClientDataSet, TDataSource, TsocketConnection, TDCOMConnection и TCorbaConnection. Настройка первого из них очень проста. Его свойство ProviderName должно указывать на компонент DataSetProvider1. Еще важно, чтобы свойству Active было присвоено False, т. е. клиент должен быть отключен от сервера. Компонент TDataSource своим свойством DataSet будет указывать на TClientDataSet.
Теперь поработаем с компонентами соединения. TDCOMConnection будет носить имя DCOMGate, а его свойство ComputerName однозначно определяет имя компьютера, где запущен сервер MIDAS-приложения. Так же подстраиваем свойство ServerName. Delphi сам предложит для него правильное значение. Свойство Connected устанавливается в отключенное положение (должно быть False). Аналогично производится настройка TSocketConnection, только его имя будет SocketGate, а вместо свойства ComputerName настраивается Host.
С компонентом TCorbaConnection возни чуть больше. Для его корректного функционирования нужно присвоить свойству RepositaryId правильное значение, ссылающееся на удаленный модуль CORBA. Его можно найти в исходных текстах удаленного модуля данных CORBA_RDM. Разыщите строчку с вызовом TCorbaVclComponentFactory.Create(). Его третий параметр и будет правильным значением для RepositaryId.
Остается подстроить свойство DataSource компонентов TDBNavigator и TDBGrig так, чтобы оно указывало на dm.DataSource1, и откомпилировать проект.
Исходные тексты программы-клиента вы найдете в листинге 2.Листинг 2
Программа-клиент
Файл ClientFormUnit.dfm object ClientForm: TClientForm Left = 143 Top = 192 Width = 632 Height = 381 Caption = ?Universal MIDAS Client? Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -13 Font.Name = ?MS Sans Serif? Font.Style = [] OldCreateOrder = False OnShow = FormShow PixelsPerInch = 120 TextHeight = 16 object CoolBar1: TCoolBar Left = 0 Top = 0 Width = 624 Height = 29 AutoSize = True Bands = < item Control = DBNavigator1 ImageIndex = -1 Width = 273 end item Break = False Control = ComboBox1 ImageIndex = -1 MinHeight = 24 Width = 345 end> object ComboBox1: TComboBox Left = 284 Top = 0 Width = 332 Height = 24 Style = csDropDownList ItemHeight = 16 TabOrder = 0 OnChange = ComboBox1Change Items.Strings = ( ?DCOMConnection? ?SocketConnection? ?CorbaConnection?) end object DBNavigator1: TDBNavigator Left = 9 Top = 0 Width = 260 Height = 25 DataSource = dm.DataSource1 TabOrder = 1 end end object DBGrid1: TDBGrid Left = 0 Top = 29 Width = 624 Height = 320 Align = alClient DataSource = dm.DataSource1 TabOrder = 1 TitleFont.Charset = DEFAULT_CHARSET TitleFont.Color = clWindowText TitleFont.Height = -13 TitleFont.Name = ?MS Sans Serif? TitleFont.Style = [] end end Файл ClientDM.dfm object dm: Tdm OldCreateOrder = False Left = 58 Top = 179 Height = 480 Width = 696 object DCOMGate: TDCOMConnection ServerGUID = ?{CEFB8363-867D-11D3-9531-008048DEAFF9}? ServerName = ?RDM_Server.RDM? ComputerName = ?Dimos? Left = 55 Top = 10 end object SocketGate: TSocketConnection ServerGUID = ?{CEFB8363-867D-11D3-9531-008048DEAFF9}? ServerName = ?RDM_Server.RDM? Host = ?Dimos? Left = 145 Top = 10 end object CorbaGate: TCorbaConnection RepositoryId = ?CORBA_Server/CORBA_RDM? Left = 230 Top = 10 end object DataSource1: TDataSource DataSet = ClientDataSet1 Left = 55 Top = 150 end object ClientDataSet1: TClientDataSet Aggregates = <> Params = <> ProviderName = ?DataSetProvider1? Left = 55 Top = 85 end end Файл ClientFormUnit.pas unit ClientFormUnit; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, DBCtrls, StdCtrls, ToolWin, ComCtrls, Grids, DBGrids, ClientDM, DBClient; type TClientForm = class(TForm) CoolBar1: TCoolBar; ComboBox1: TComboBox; DBNavigator1: TDBNavigator; DBGrid1: TDBGrid; procedure ComboBox1Change(Sender: TObject); procedure FormShow(Sender: TObject); private { Private declarations } public { Public declarations } procedure Reconnect; end; var ClientForm: TClientForm; LastConnection: Integer; Connections: array[0..2] of ^TCustomRemoteServer; implementation {$R *.DFM} procedure TClientForm .ComboBox1Change(Sender: TObject); begin if LastConnection <> ComboBox1 .ItemIndex then Reconnect; end; procedure TClientForm.Reconnect; begin // Отключиться от удаленного сервера Connections[LastConnection].Connected := False; LastConnection := ComboBox1.ItemIndex; // Подключиться к удаленному серверу dm.ClientDataSet1.Close; dm.ClientDataSet1.RemoteServer := Connections [LastConnection]^; dm.ClientDataSet1.Open; Connections[LastConnection].Connected := True; dm.ClientDataSet1.Refresh; // Показать тип соединения ComboBox1.ItemIndex := LastConnection; end; procedure TClientForm.FormShow(Sender : TObject); begin // Заполнить массив указателей на компоненты соединения Connections[0] := @dm.DCOMGate; Connections[1] := @dm.SocketGate; Connections[2] := @dm.CorbaGate; // Установить индекс соединения на DCOM LastConnection := 0; ComboBox1.ItemIndex := LastConnection; Reconnect; end; end.
Как запустить MIDAS-приложение
Для обеспечения работы систем, выполненных по технологии MIDAS, могут потребоваться дополнительные утилиты. Так, чтобы стало действовать соединение на основе CORBA, следует активизировать программу Smart Agent из пакета VisiBroker. Соединение через сокеты установится после запуска SCKTSRVR.EXE каталога BIN пакета Delphi. Дополнительных действий не требует лишь соединение по протоколу DCOM.
Запустив наш пример, попробуйте переключиться с одного соединения на другое. Каждый раз при выборке удаленных данных вы увидите, как увеличивается значение индикатора прогресса (рис. 1).
Рис. 1 |
* * *
Напоследок маленькое напоминание. Не забывайте о том, что MIDAS — высокотехнологичный информационный продукт и подпадает под особую лицензионную политику. Свяжитесь с вашим поставщиком Delphi 5, чтобы узнать об этом поподробнее.