| div.main {margin-left: 20pt; margin-right: 20pt}Простое CORBA приложение - своими руками. 
 
 Технология CORBA - это стандарт написания распределенных приложений, 
предложенный консорциумом OMG (Open Management Group). Создавая CORBA-объекты, 
мы можем ,например, существенно уменьшить время решения задач, требующих 
выполнения большого объема вычислений. Это возможно благодаря размещению 
CORBA-объектов на разных машинах. Каждый удаленный объект решает определенную 
подзадачу, тем самым разгружает клиент от выполнения лишней работы. 
 Рассмотрим взаимодействие объектов в архитектуре CORBA 
 
 
 
Рис.1 Взаимодействие объектов в архитектуре CORBA
 Основу CORBA составляет объектный брокер запросов (Object Request Broker). 
ORB управляет взаимодействием объектов в распределенной сетевой среде. IIOP 
(Internet Inter-ORB Protocol) - это специальный протокол взаимодействия между 
ORB. 
 В адресном пространстве клиента функционирует специальный объект, называемый 
заглушкой (stub). Поучив запрос от клиента, он упаковывает параметры запроса в 
специальный формат и передает его серверу, а точнее скелету. 
 Скелет (skeleton) – объект, работающий в адресном пространстве сервера. 
Получив запрос от клиента, он распаковывает его и передает серверу. Также скелет 
преобразует ответы сервера и передает их клиенту (заглушке). 
 Для того, чтобы написать любое приложение CORBA используя технологию Java, 
необходимо иметь две вещи – это установленный пакет JDK1.2 и компилятор 
idltojava. JDK предоставляет набор классов для работы с 
CORBA объектами, а idltojava производит отображение языка 
IDL в Java. 
 Создание CORBA приложения на Java начинается с написания интерфейса для 
удаленного объекта, используя язык описания интерфейсов (Interface Definition 
Language, IDL). 
 Создадим файл test.idl module testApp {
    interface test
    {
       long count(in string msg);
    };
};
 Данный интерфейс описывает лишь один метод count. Причем, нам не 
важно, что делает этот метод, главное мы определяем, что он есть, определяем 
какие у него входные и выходные параметры. 
 Воспользуемся компилятором idltojava. 	idltojava Hello.idlПримечание. Данный компилятор по 
умолчанию использует препроцессор языка С++, поэтому что бы не мучится с 
сообщением об ошибке имя команды или файла указано неправильно (в 
переменной окружения CPP должен быть прописан путь к нему) отключим его 
использование, установив флаги.	idltojava –fno-cpp Hello.idl
Результат работы данной программы можно представить в виде 
схемы. 
 
 
Рис.2 Работа idltojava компилятора
 В текущей директории появилась новая папка testApp, в которой 
содержатся пять java – файлов. Каждый из них имеет свое назначение.
 
 _testImplBase.java – абстрактный класс, который представляет собой не 
что иное, как скелет сервера (skeleton) и обеспечивает функциональность сервера; 
 _testStub.java – класс, реализующий заглушку (stub) клиента. 
Обеспечивает функциональность клиента; 
 test.java – класс, содержащий описание интерфейса test на языке Java; 
 testHelper.java и testHolder.java – классы, предоставляющие 
вспомогательные функции для CORBA объектов. 
 Теперь наша задача – написать класс, реализующий интерфейс test. Такие 
классы должны называться так, чтобы в их имени было слово “Servant”, в нашем 
случае это будет testServant. class testServant extends _testImplBase
{
    public int count(String msg)
    {
	return msg.length();
    }
}
 Обратите внимание, что этот класс унаследован от _testImplBase. Как 
видно, здесь реализован метод count, который в данном примере считает количество 
букв в принятом сообщении. Теперь перейдем непосредственно к написанию серверной части приложения. 
 Первое что мы делаем, создаем ORB. Затем создаем экземпляр класса удаленного 
объекта (testServant) и регистрируем его в ORB. Дальше вызываем специальную 
службу имен (NameService) и регистрируем в ней имя удаленного объекта, чтобы 
клиент смог его найти (есть и другой способ нахождения удаленного объекта, но о 
нем чуть позже). 
 Рассмотрим подробнее эти этапы. 
  Создание и инициализация ORB. Производится вызовом статического метода 
  init класса ORB 
   ORB orb = ORB.init(); Создание экземпляра класса удаленного объекта и регистрация его в ORB testServant testRef = new testServant(); 
   orb.connect(testRef); Получение контекста имен (NamingContext) org.omg.CORBA.Object objRef = 
   orb.resolve_initial_references("NameService"); 
   NamingContext ncRef = NamingContextHelper.narrow(objRef); 
   в первой строчке мы получаем объектую ссылку на службу имен (NameService). 
  Но фактически это обыкновенный CORBA-объект и для того, чтобы использовать его 
  как контекст имен (NamingContext), необходимо вызвать метод narrow 
  класса NamingContextHelper, который как бы конкретизирует данный 
  CORBA-объект. Регистрация имени удаленного объекта (testServant) Как было сказано раньше регистрация имени производится для того чтобы 
  клиент смог найти удаленный объект. Этой цели служит функция 
  rebind(NameComponent[] nc, Object obj) интерфейса NamingContext.     NameComponent nc = new NameComponent("test", "");
     //первый параметр
     //указывает имя объекта,
     //второй нам использовать не обязательно
    NameComponent path[] = {nc};
    ncRef.rebind(path, testRef);
  Ожидание запросов от клиента. java.lang.Object sync = new java.lang.Object();
           synchronized (sync) {
                sync.wait();
           }
   После того как сервер обработает запрос от клиента и выполнит метод 
  count он снова перейдет в состояние ожидания. Теперь сервер готов к работе 
 Листинг 1. testServer.java import testApp.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
import java.lang.*;
class testServant extends _testImplBase
{
    public int count(String msg)
    {
return msg.length();
    }
}
public class testServer {
    public static void main(String args[])
    {
	try
	{
    	ORB orb = ORB.init(args, null);
    	testServant testRef = new testServant();
    	orb.connect(testRef);
    	org.omg.CORBA.Object objRef =
         orb.resolve_initial_references("NameService");
    	NamingContext ncRef =
    	 NamingContextHelper.narrow(objRef);
 	NameComponent nc = new NameComponent("test", "");
    	NameComponent path[] = {nc};
    	ncRef.rebind(path, testRef);
    	java.lang.Object sync = new java.lang.Object();
    	synchronized (sync) {
        sync.wait()
	}
	}
	catch (Exception e) {
    	System.err.println("ERROR: " + e);
    	e.printStackTrace(System.out);
	}
    }
}
 Обратите внимание на то, что все операции выполняемые над CORBA-объектами 
заключены в try-catch блок. 
 Перейдем к написанию кода для клиента. 
 Основные шаги написания клиентского приложения 
  Создание и инициализация ORB 
  Получение контекста службы имен (NamingContext) 
  Нахождение удаленного объекта 
  Вызов метода count.
 Как видно, первые два пункта совпадают с этапами создания серверного 
приложения, поэтому рассматривать их не будем. 
 Третий пункт реализуется тоже достаточно просто. Создается объект 
NameComponent. Вызывается метод resolve(NameComponent[] path), 
который отыскивает по имени удаленный объект (стандартный CORBA-объект). При 
помощи метода narrow(org.omg.CORBA.Object obj) класса testHelper 
(сгенерированного idltojava компилятором) получаем объектную ссылку на 
интерфейс test. 	NameComponent nc = new NameComponent("test", "");
	NameComponent path[] = {nc};
	org.omg.CORBA.Object obj= ncRef.resolve(path);
	test testRef = testHelper.narrow(obj);
 Теперь можно вызывать метод count 	String msg = "try to count";
	int count = testRef.count(msg);
 Листинг 2. testClient.java import testApp.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
import java.lang.*;
public class testClient
{
    public static void main(String args[])
    {
	try
	{
	  ORB orb = ORB.init(args, null);
	  org.omg.CORBA.Object objRef =
           orb.resolve_initial_references("NameService");
	  NamingContext ncRef =
	       NamingContextHelper.narrow(objRef);
	  NameComponent nc = new NameComponent("test", "");
	  NameComponent path[] = {nc};
	  test testRef =
	       testHelper.narrow(ncRef.resolve(path));
	  String msg = "try to count";
	  int count = testRef.count(msg);
	  System.out.println
	      (“number of chars in message is:” + count);
	}
	catch (Exception e)
	{
	  System.out.println("ERROR : " + e) ;
	  e.printStackTrace(System.out);
	}
	}
}
 Запуск приложения 
  Запуск сервера имен (входит в поставку с JDK1.2). Это делается, чтобы мы 
  смогли получить ссылку на службу имен     tnameserv 
   по умолчанию сервер запускается по порту 900. Это значение можно изменить, 
  указав параметр запуска -ORBInitialPort, например     tnameserv –ORBInitialPort 1024
  Запуск сервера testServer     java testServer –ORBInitialPort 1024
         // указывается тот порт
         //по которому работает сервер имен
  Запуск клиента testClient java testClient
        –ORBInitialHost javas.stu.neva.ru
        –ORBInitialPort 1024
   параметр -ORBInitialHost указывает хост на котором работает 
  testServer после выполнения этого приложения, на консоль будет выведено  number of chars in message is:12
 Соединение с сервером без использования службы имен 
 Основная идея этого метода состоит в том, что сервер сохраняет экземпляр 
класса удаленного объекта (testServant) в виде текстового файла в любом 
месте, доступном клиенту. Клиент загружает из файла данные (в объект 
String) и преобразует специальными методами в объектную ссылку на 
удаленный объект. 
 Все это реализуется следующим образом 
 Удалим некоторую часть кода – это касается и клиента (testServer.java 
и testClient.java) 
  Исключим из import библиотеки 	org.omg.CosNaming.*;
	org.omg.CosNaming.NamingContextPackage.*;
  Удалим код соответствующий п.3-п.4Вместо удаленного кода вставим – 
для сервера:    //преобразуем объект в строку
   String ior = orb.object_to_string(testRef);
   String filename = System.getProperty("user.home") +
   System.getProperty("file.separator")+"test_file";
   //создаем файл test_file
   FileOutputStream fos = new FileOutputStream(filename);
   PrintStream ps = new PrintStream(fos);
   //записываем в него данные
   ps.print(ior);
   ps.close();
 для клиента:    String filename = System.getProperty("user.home") +
   System.getProperty("file.separator")+"test_file";
   //открываем файл
   FileInputStream fis = new FileInputStream(filename);
   DataInputStream dis = new DataInputStream(fis);
   //читаем данные
   String ior = dis.readLine();
   //преобразуем в объект CORBA
   org.omg.CORBA.Object obj = orb.string_to_object(ior);
   //получаем ссылку на удаленный объект
   test testRef = testHelper.narrow(obj);
 Скомпилируем приложения, запустим сервер и клиент аналогично тому, как мы 
делали это раньше (сервер имен запускать в данном случае не надо).
 
Автор: Александр Годин, E-Mail: alexgoldd@mail.ru
 |