|
Здравствуйте, подскажите пожалуйста где можно достать материалы по курсу Кросс-платформенные и многозвенные технологии, о которых говориться, к примеру, в Лекции 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 - идентификатор узла, на котором запущен сервис имен. Порт может быть любым свободным, но должен согласовываться при запуске сервиса имен, клиента и сервера.