Здравствуйте, подскажите пожалуйста где можно достать материалы по курсу Кросс-платформенные и многозвенные технологии, о которых говориться, к примеру, в Лекции 2. Пример "Служба мгновенных сообщений" |
Технология CORBA
Использование BOA
Одним из существенных недостатков реализации службы мгновенных сообщений в первом примере была необходимость передачи IOR сервера клиенту (например, путем копирования файла). Более удобный способ получения ссылки на объект - использование механизма bind. Этот механизм не является стандартным,то есть не предусмотрен стандартом CORBA, но предоставляется VisiBroker.
В качестве объектного адаптера в данном примере используется Basic Object Adapter (BOA).Он менее переносим (однако, более прост в использовании), чем более новый Portable Object Adapter (POA).
Отметим, что, поскольку здесь (как и в первом примере) используется BOA,при компиляции IDL-файла в качестве параметра требуется указать -boa.
В приведенном ниже листинге класса сервера изменения по сравнению с предыдущим примером выделены жирным шрифтом. Их смысл заключается в том, что теперь сервер инициализирует BOA и сообщает ему о готовности CORBA -объекта и его серванта. Теперь при создании серванта в качестве параметра ему передается имя CORBA -объекта. Это имя регистрируется конструктором родителя серванта ( Message.MessagingServiceImplBase ) для последующего использования механизмом bind.
public class Server { public static void main(String[] args) { org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null); com.inprise.vbroker.CORBA.BOA boa = ((com.inprise.vbroker.CORBA.ORB)orb).BOA_init(); Message.MessagingService messagingService =new MessagingServiceImpl("MessagingService"); boa.obj_is_ready(messagingService); System.out.println(messagingService + " is ready."); boa.impl_is_ready(); } }
Реализация серванта остается прежней. Единственное изменение: добавляется вызов родительского конструктора, которому передается имя CORBA -объекта.
public MessagingServiceImpl(String name) { super(name); System.out.println("Constructing MessagingServiceImpl"); nameToId = new HashMap(); users = new ArrayList(); }
В реализации клиента добавилась инициализация BOA. Кроме того, ссылка на сервер теперь не получается напрямую из IOR, а находится по имени MessagingService, зарегистрированному сервером. Поиск выполняется при помощи метода bind класса MessagingServiceHelper, который был автоматически сгенерирован из IDL -описания.
public class Client { public static void main(String[] args) { try { org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null); com.inprise.vbroker.CORBA.BOA boa = ((com.inprise.vbroker.CORBA.ORB)orb).BOA_init(); Message.MessagingService service = Message.MessagingServiceHelper.bind(orb, "MessagingService"); MessagingFrame mf = new MessagingFrame(service); Message.MessageReceiver receiver = new MessageReceiverImpl(mf); LoginFrame loginFrame = new LoginFrame(service, receiver, mf); loginFrame.show(); } catch (Throwable t) { t.printStackTrace(); } } }
Использование POA
В данном примере используется другой вид объектного адаптера - Portable Object Adapter (POA).В связи с этим в реализации сервера произошли следующие изменения:
- За инициализацией ORB следует получение ссылки на корневой объектный адаптер rootPOA. Корневой адаптер всегда существует, ссылку на него можно получить с помощью метода ORB resolve_initial_references.
- Далее создается массив политик, который после передается в качестве одного из параметров конструктору нового объектного адаптера myPOA. Адаптер myPOA создается внутри корневого объектного адаптера ( POA можно вкладывать друг в друга).
- После создания серванта имя будущего CORBA -объекта представляется в виде набора байт. Далее объектному адаптеру дается команда активировать CORBA- объект с заданным именем и ссылкой на сервант.
- В корневом объектном адаптере активируется менеджер объектных адаптеров.
- Для ожидания подключений в данном примере используется метод ORB run(). В предыдущих примерах использовался альтернативный способ - присоединение сервера к некоторому потоку.
import org.omg.PortableServer.*; public class Server { public static void main(String[] args) { try { org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null); POA rootPOA = POAHelper.narrow(orb.resolve initial references("RootPOA")); org.omg.CORBA.Policy[] policies = {rootPOA.create lifespan policy( LifespanPolicyValue.PERSISTENT)}; POA myPOA = rootPOA.create_POA("messaging poa", rootPOA.the_POAManager(), policies ); MessagingServiceImpl messagingServant =new MessagingServiceImpl(); byte[] messagingId = "MessagingService".getBytes(); myPOA.activate object with id(messagingId, messagingServant); rootPOA.the_POAManager().activate(); System.out.println(myPOA.servant to reference(messagingServant) + " is ready."); orb.run(); } catch (Exception e) { e.printStackTrace(); } } }
Класс серванта теперь наследуется от другого скелетона - Message.MessagingServicePOA. Здесь нет необходимости указывать имя CORBA- объекта в качестве параметра конструктора родителя.
public class MessagingServiceImpl extends Message.MessagingServicePOA { private HashMap nameToId; private ArrayList users; public MessagingServiceImpl() { System.out.println("Constructing MessagingServiceImpl"); nameToId = new HashMap(); users = new ArrayList(); } }
Изменения в клиенте аналогичны изменениям в сервере:
- После получения ссылки на корневой объектный адаптер создаются политики и адаптер callbackPOA, в котором будет размещен CORBA -объект получатель сообщений ( MessageReceiver ).
- Далее с помощью механизма bind получаем ссылку на сервер.
- Создание пользовательского интерфейса.
- Активация получателя сообщений и менеджера объектных адаптеров.
- Получение ссылки на MessageReceiver для последующей передачи серверу.
public static void main(String[] args) { try { org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null); POA rootPOA = POAHelper.narrow(orb.resolve_initial_references("RootPOA")); org.omg.CORBA.Policy[] policies = {rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT)}; POA callbackPOA = rootPOA.create_POA("MessageReceive", rootPOA.the_POAManager(), policies); byte[] messagingId = "MessagingService".getBytes(); Message.MessagingService service = Message.MessagingServiceHelper.bind(orb, "/messaging_poa", messagingId); MessagingFrame mf = new MessagingFrame(service); MessageReceiverImpl mr = new MessageReceiverImpl(mf); callbackPOA.activate_object(mr); callbackPOA.the_POAManager().activate(); Message.MessageReceiver receiver = Message.MessageReceiverHelper.narrow(callbackPOA.servant_to_reference(mr)); LoginFrame loginFrame = new LoginFrame(service, receiver, mf); loginFrame.show(); } catch (Throwable t) { t.printStackTrace(); } }
Сервер получателя сообщений теперь наследуется от другого скелетона:
static class MessageReceiverImpl extends Message.MessageReceiverPOA...
Использование сервиса имен
В данном примере рассмотрен еще один способ получения ссылки на CORBA -объект -использование сервиса имен. Этот способ более удобен, чем прямое задание IOR, и, в отличие от механизма bind, является стандартным.Основные изменения в реализации сервера состоят в следующем:
- Подключение пакета CosNaming
- Получение ссылки на сервис имен
- Создание пути размещения объекта в виде последовательности компонентов имени (в данном случае имя состоит из одного компонента, однако в более сложных случаях удобно использовать иерархическую структуру)
- Установление соответствия между полным именем объекта и ссылкой на него. Метод rebind контекста именования отличается от его метода bind тем, что при конфликте имен он будет разрешен в пользу нового сопоставления.
import org.omg.PortableServer.*; import org.omg.CosNaming.*; import org.omg.CORBA.*; public class Server { public static void main(String[] args) { try { ORB orb = ORB.init(args,null); POA rootPOA = (POA)orb.resolve_initial_references("RootPOA"); rootPOA.the_POAManager().activate(); MessagingServiceImpl messagingServant = new MessagingServiceImpl(orb); org.omg.CORBA.Object rootObj =orb.resolve_initial_references("NameService"); NamingContext root = NamingContextHelper.narrow(rootObj); NameComponent[] path ={new NameComponent("MessagingService", "")}; org.omg.CORBA.Object ref =rootPOA.servant_to_reference(messagingServant); root.rebind(path, ref); System.out.println("Ready"); orb.run(); } catch (Exception e) { e.printStackTrace(); } }
Класс серванта по сравнению с предыдущим примером остается неизменным. Изменения в клиенте аналогичны изменениям в сервере. Метод resolve контекста именования позволяет получить ссылку на CORBA -объект по его полному имени.
public static void main(String[] args) { try { ORB orb = ORB.init(args,null); org.omg.CORBA.Object rootObj = orb.resolve initial references("NameService"); NamingContext root = NamingContextHelper.narrow(rootObj); NameComponent[] path = {new NameComponent("MessagingService", "")}; org.omg.CORBA.Object msgObj = root.resolve(path); Message.MessagingService service =Message.MessagingServiceHelper.narrow(msgObj); MessagingFrame mf = new MessagingFrame(service); MessageReceiverlmpl mr = new MessageReceiverlmpl(mf); POA rootPOA = (POA)orb.resolve_initial_references("RootPOA"); rootPOA.the_POAManager().activate(); Message.MessageReceiver receiver = Message.MessageReceiverHelper.narrow( rootPOA.servant_to_reference(mr)); LoginFrame loginFrame new LoginFrame(service, mf, orb.object to string(receiver)); loginFrame.show(); } catch (Throwable t) { t.printStackTrace(); } }
При использовании сервиса имен необходимо использовать дополнительные параметры командам запуска сервера и клиента. Кроме того, необходимо запустить сам сервис имен. Это делается следующим образом:
start nameserv -J-Dvbroker.se.iiop_tp.scm.iiop_tp.listener.port=<port> NameService start vbj Server -ORBInitRef NameService=iioploc://<host>:<port>/NameService start vbj Client -ORBInitRef NameService=iioploc://<host>:<port>/NameService
Здесь host - идентификатор узла, на котором запущен сервис имен. Порт может быть любым свободным, но должен согласовываться при запуске сервиса имен, клиента и сервера.