Создание серверов на основе POA

Для знакомства с работой компиляторов IDL2JAVA и IDL2CPP из комплектов VisiBroker for Java 4.0 и VisiBroker for C++ 4.0. создается тестовое описание на языке IDL и помещается в файл Test.idl:

interface Test

{

string operation(in char x);

};

Сначала запускается IDL-компилятор для Java командой

idl2java Test.idl

и просматриваются те файлы, которые получились в результате ее выполнения.

Первый файл — заглушка (stub) для соединения клиента с объектом — хранится в файле _TestStub.java. Имя заглушек создается по схеме _<имя интерфейса>.java. Сам интерфейс объекта Test описан в файле Test.java.

Скелет объекта, от которого следует реализовать сервант, именуется по схеме <имя интерфейса>POA.java (для интерфейса Test это будет TestPOA.java). Если скелет создается с использованием tie-механизма, то вместо обычного единственного класса скелета будут получены целых два: tie и operation. Первый именуется по схеме <имя интерфейса>POATie.java, а второй — <имя интерфейса>Operation.java. Компиляция IDL-описания приводит к появлению файлов TestPOATie.java и TestOperations.java.

В случае с POA, как и с основным объектным адаптером BOA, для интерфейса Test будут созданы Helper- и Holder-классы в файлах TestHelper.java и TestHolder.java. Holder-класс служит «оберткой» создаваемого объекта для передачи его через ORB.

Что касается Helper-класса, то его назначение заключается в предоставлении программисту полезных методов-утилит, как, например, методов bind для связывания с объектом: ссылка на объект вызывается методом bind(). Это справедливо как для объектного адаптера BOA, так и для переносимого POA. Поэтому можно считать, что написание программы-клиента для объектов, зарегистрированных с помощью POA, ничем не отличается от аналогичных действий, которые рассматривались в предыдущей работе. Тем не менее одно отличие в этих методах для разных объектных адаптеров есть: появился вариант, позволяющий найти объект, зарегистрированный в конкретном адаптере POA, для чего методу bind() в качестве одного из параметров передается полное имя POA.

Теперь возможно обратиться к ситуации с Си++ и запустить следующую команду:

idl2cpp test.idl

В результате появятся файлы test_c.cc, test_c.hh, test_s.cc и test_s.hh. Файлы с суффиксом _s хранят описания классов серверной части приложения CORBA, а с суффиксом _c — клиентской. Расширения .cc и .hh легко меняются опциями -src_suffix и -hdr_suffix компилятора IDL2CPP.

Типичный случай использования POA рассмотрен на примере языка Java.

Обычно работа сервера на POA состоит из нескольких шагов:

· получение ссылки на корневой адаптер POA;

· определение политик для нового POA;

· создание нового POA, порождаемого корневым POA;

· создание серванта и его активация;

· активация POA вызовом его менеджера.

Ззапустившись, типичный сервер CORBA считывает системные свойства и передает их методу инициализации брокера объектных запросов:

import org.omg.PortableServer.*;

public class POA_Server

{

public static void main(String[] args)

{

new POA_Server();

try

{

org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,System.getProperties());

}

}

Затем сервер получает ссылку на корневой объектный адаптер «RootPOA». Это производится посредством вызова специального метода resolve_initial_references(), часто используемого для инициализации различных служб CORBA. Поскольку возвращаемая ссылка имеет тип Object, ее нужно привести к типу POA с помощью метода narrow(), который находится в Helper-классе объекта POA:

POA poaRoot = POAHelper.narrow(orb.resolve_initial_references(«RootPOA»));

Теперь следует создать массив ссылок на объекты политик для нового POA и создать нужные экземпляры объектов. К примеру, необходимо создать дочерний POA, который будет хранить долгоживущие объекты, поэтому вызывается метод create_lifespan_policy(). Надо обратить внимание на тот факт, что этот метод вызывается для корневого объектного адаптера:

String new_POA_name = ”TestInterface_POA”;

org.omg.CORBA.Policy[] TestInterfacePolicies = {

poaRoot.create_lifespan_policy(LifespanPolicyValue.PERSISTENT)

};

Собственно создание POA заключается в вызове метода create_POA() корневого адаптера «RootPOA», которому передается имя создаваемого адаптера, ссылка на менеджер POA и массив объектов политик:

POA interface = poaRoot.create_POA(new_POA_name,poaRoot.the_POAManager(),TestInterfacePolicies);

Остается создать экземпляр серванта TestInterfaceImpl и передать ссылку на него методу активации серванта вместе с идентификатором объекта:

interface.activate_object_with_id(new_POA_name.getBytes(), new TestInterfaceImpl());

Когда готов POA с активным сервантом, следует активировать сам POA, вызвав метод activate() менеджера объектных адаптеров POA:

poaRoot.the_POAManager().activate();

Дело в том, что новый POA игнорирует запросы, адресуемые объекту, т.е. как бы выключен. Активизацией объектного адаптера «открывается кран» для запросов, и они начинают «течь» через POA к соответствующим сервантам.

Заключительный штрих в инициализации сервера — переход в цикл ожидания запросов, что делается вызовом run() брокера объектных запросов:

orb.run();

}

catch(Exception ex)

{

ex.printStackTrace();

}

}

}

Это самый простой вариант сервера. Если создавать POA с сервантами по умолчанию или с менеджером сервантов, исходный текст будет отличаться. Вариантов построения серверов на POA — множество, все зависит от предполагаемой архитектуры создаваемых серверов. Большее о РОА можно узнать в «The Portable Object Adapter» версии 2.3 спецификации CORBA.

Наши рекомендации