Опубликован: 18.03.2010 | Доступ: свободный | Студентов: 840 / 85 | Оценка: 4.48 / 4.33 | Длительность: 12:01:00
Лекция 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 - идентификатор узла, на котором запущен сервис имен. Порт может быть любым свободным, но должен согласовываться при запуске сервиса имен, клиента и сервера.

Антон Зубеков
Антон Зубеков

Здравствуйте, подскажите пожалуйста где можно достать материалы по курсу Кросс-платформенные и многозвенные технологии, о которых говориться, к примеру, в Лекции 2. Пример "Служба мгновенных сообщений"