Опубликован: 10.10.2010 | Доступ: свободный | Студентов: 3208 / 299 | Оценка: 4.14 / 3.32 | Длительность: 13:16:00
ISBN: 978-5-9963-0444-8
Специальности: Системный архитектор
Лекция 6:

Использование CORBA

< Лекция 5 || Лекция 6: 123456 || Лекция 7 >

Файлы BillingServiceImpl.java и BillingServiceServer.java

Следующим шагом после генерации необходимых вспомогательных файлов будет реализация серверного объекта, реализующего описанные нами методы.

BillingServiceImpl (пример 6.8) является реализацией интерфейса BillingService.В соответствии с принятым нами ранее соглашением конкретный класс, реализующий открытый интерфейс распределенного CORBA -объекта, имеет имя <IDL interface name>Impl.Этот класс не обязан объявлять метод main, но может это сделать.

1  // BillingServiceImpl.java
2  package com.asw.corba.ex1;
3
4  // базовые пакеты Java
5  import java.util.Hashtable;
6
7  import com.asw.corba.ex1.BillingServiceModule.*;
8
9  // пакеты OMG CORBA
10  import org.omg.CORBA.*;
11
12  public class BillingServiceImpl   extends BillingServicePOA {
13  private ORB orb;
14  private   Hashtable hash = new Hashtable();
15
16  public void setORB(ORB orb_val) {
17  orb = orb_val;
18  }
19
20  public void addNewCard(String personName, String card) {
21  hash.put(card, new Double(0.0));
22  }
23
24  public void addMoney(String card, double money) {
25  Double d = (Double)hash.get(card);
26
27  if (d!=null) hash.put(card,new Double(d.doubleValue()+money));
28  }
29
30  public void subMoney(String card, double money) {
31  Double d = (Double)hash.get(card);
32
33  if (d!=null) hash.put(card,new Double(d.doubleValue()-money));
34  }
35
36  public double getCardBalance(String card) {
37  Double d = (Double)hash.get(card);
38
39  if (d!=null) return d.doubleValue();
40  else return 0;
41  }
42  }
Листинг 6.8. Реализация сервера BillingService, класс BillingServiceImpl

Класс BillingServiceImpl является наследником класса BillingServicePOA (который был построен автоматически) и, таким образом, уже обладает всей базовой функциональностью серверного класса. Все, что мы должны сделать, - определить реализацию методов addNewCard, addMoney, subMoney и getCardBalance.Таким образом, для реализации серверного класса нам пришлось написать всего несколько строк кода - весь остальной код был построен автоматически!

Класс BillingServiceImpl реализует методы сервера, а запуск сервера производится классом BillingServiceServer (пример 6.9), основная задача которого - "положить" экземпляр BillingService в систему, то есть зарегистрировать его.

Дело в том, что при создании распределенных приложений существует проблема поиска необходимых компонент. Если система распределенная, как определить, на каком узле находится тот или иной ее компонент (с тем, чтобы отправлять запросы на этот узел)? В CORBA эта проблема решается вводом специального сервиса - сервиса имен (Naming Service),который составляет список ресурсов для будущего их использования клиентами. Факт регистрации в сервисе имен не означает, что сервер может решать какие-то задачи; сервер просто предоставляет клиентам возможность доступа к нему. Сервис должен быть готов в любой момент обрабатывать входящие запросы на выполнение функций, необходимых вызывающим клиентам. Любой объект, который должен обрабатывать клиентские запросы, может зарегистрироваться в этом сервисе под каким-то именем1В нашем случае имена объектов должны быть уникальны, однако сервисы именования могут поддерживать режим, при котором на одно имя регистрируются сразу несколько объектов. При обращении пользователя по имени объекта ему возвращается ссылка на один из объектов с таким именем. Таким образом могут реализоваться механизмы обеспечения отказоустойчивости системы при отказе одного из объектов, а также механизмы балансировки нагрузки . В различных реализациях CORBA поддерживается различный набор сервисов. Минимально необходимым из них является только сервис имен. Не необходимыми, но очень полезными (и поддерживаемыми во многих реализациях) являются сервис сообщений (Event Service) и сервис уведомлений (Notification Service).Кроме перечисленных, поставщик может предоставить следующие сервисы:

  • ES позволяет создавать каналы, по которым приложения могут обмениваться сообщениями;
  • NS расширяет эту функциональность, позволяя фильтровать и типизировать сообщения;
  • сервис безопасности ( Security service ) обеспечивает аутентификацию и контроль доступа к объектам, аудит узлов;
  • сервис транзакций ( Transaction service ) TS обеспечивает поддержку системой механизма транзакций;
  • сервис контроля параллельности ( Concurrency control ) CCS обеспечивает поддержку механизма блокировок и синхронизации;
  • сервис долговременного хранения ( Persistent object service ) обеспечивает сохранение состояния объектов в постоянном хранилище (БД) и их восстановление при запуске системы.

Таким образом, клиенту для того, чтобы обратиться к объекту, необходимо знать его имя. Обратившись к сервису именования, клиент по имени получает ссылку на нужный ему объект.

Класс BillingServiceServer как раз и регистрирует серверный объект BillingServiceImpl в сервисе имен.

Рассмотрим этот класс подробнее.

Класс BillingServiceServer (пример 6.9) содержит метод main, являющийся точкой входа в программу.

1  // BillingServiceServer.java
2  package com.asw.corba.ex1;
3
4  // пакеты OMG CORBA
5  import  org.omg.CosNaming.*;
6  import  org.omg.CORBA.*;
7  import  org.omg.PortableServer.*;
8  import  org.omg.PortableServer.POA;
9  import  com.asw.corba.ex1.BillingServiceModule.*;
10
11  public class BillingServiceServer {
12  public static void main(String args[]) {
13  try{
14  // create and initialize the ORB
15  ORB orb = ORB.init(args, null);
16
17  // get reference to rootpoa & activate the POAManager
18  POA rootpoa =
19  POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
20  rootpoa.the_POAManager().activate();
21
22  // create servant and register it with the ORB
23  BillingServiceImpl BSImpl = new BillingServiceImpl();
24  BSImpl.setORB(orb); 
25
26  // get object reference from the servant
27  org.omg.CORBA.Object ref = rootpoa.servant_to_reference(BSImpl);
28  BillingService href = BillingServiceHelper.narrow(ref);
29
30  // get the root naming context
31  // NameService invokes the name service
32  org.omg.CORBA.Object objRef =
33  orb.resolve_initial_references("NameService");
34  // Use NamingContextExt which is part of the Interoperable
35  // Naming Service (INS) specification.
36  NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
37
38  // bind the Object Reference in Naming
39  String name = "BillingService";
40  NameComponent path[] = ncRef.to_name( name );
41  ncRef.rebind(path, href);
42
43  System.out.println("BillingServiceServer ready and waiting ...");
44
45  // wait for invocations from clients
46  orb.run();
47  }
48
49  catch (Exception e) {
50  System.err.println("ERROR: " + e);
51  e.printStackTrace(System.out);
52  }
53  System.out.println("BillingServer Exiting ...");
54  }
55  }
Листинг 6.9. Запуск сервера BillingService, класс BillingServiceServer

Первое, что делает этот класс, - создает ссылку на orb (брокер объектных запросов) (строка 15), передавая в статический метод init переданные ему аргументы командной строки (что это за аргументы, мы увидим, когда перейдем к запуску приложений). Корректный входной параметр - это опция командной cтроки, указывающая брокеру объектных запросов, какой коммуникационный порт использовать. Существует версия init,не имеющая параметров, которая возвращает брокер объектных запросов, создаваемый по умолчанию, вместо брокера объектных запросов, сконфигурированного в соответствии с входными параметрами. Параметры метода init могут иметь значения null.

Затем идут несколько строк (строки 18-20), отвечающих за получение и активизацию ссылки на корневой POA ( Portable Object Adapter )2Существуют зарезервированные имена в сервисе имен, такие как RootPOA или NameService, под которыми зарегистрированы системные объекты. Соответственно, для обращения к этим системным объектам могут быть использованы объектные ссылки, полученные по этим именам . Строка "RootPOA" является стандартным именем, определенным в спецификации CORBA (вместе со списком других имен). Метод resolve_initial_ references имеет доступ к специальному списку сервисов, непосредственно доступных данному брокеру объектных запросов. Статический метод narrow класса POAHelper используется для преобразования возвращенной объектной ссылки в объект нужного типа. Метод narrow является CORBA -механизмом надежного приведения ссылки одного типа к ссылке другого типа. Метод narrow проверяет, что интерфейс, которому мы пытаемся передать целевой объект, поддерживает целевые объекты этого типа. Обычное приведение не работает с объектными ссылками CORBA, так как объектная ссылка - это посредник на пути к удаленной информации. Все классы Helper имеют метод static narrow,который дает нам возможность осуществлять приведение родительских классов к производным классам.

В строке 23 создается экземпляр нашего класса BillingServiceImpl,и ему передается ссылка на orb (строка 24). Затем формируется объектная ссылка на наш серверный класс (сроки 27-28).

В строках 32-33 извлекается объектная ссылка на сервис имен. Проблема обнаружения сервером сервиса имен при первом запуске решается брокером объектных запросов с помощью метода resolve_initial_references.Брокер объектных запросов имеет эффективный мини-сервис имен, с помощью которого он может выполнять обнаружение базовых сервисов. Однако чтобы метод resolve_initial_references мог работать с любым из сервисов, он возвращает объектную ссылку в виде объекта типа org.omg.CORBA.Object.Строка "NameService" является стандартным именем, определенным в спецификации CORBA. Статический метод narrow класса NamingContextExtHelper применяется для преобразования возвращенной объектной ссылки в объект нужного типа.

Затем задается имя для нашего объекта (строка 39), которое помещается в массив объектов типа NameComponent (строка 40). Сервер не может быть зарегистрирован и использован другими объектами, если у него нет имени, - эта ошибка достаточно серьезна. Чтобы имя было правильно зарегистрировано, ресурс должен установить контекст именования. Сервер регистрируется в основном (или корневом) контексте именования, поэтому единственное, что нужно сервису имен, - это имя сервера, которое сервер посылает с помощью метода rebind (строка 41). Метод rebind вводит NameComponent, если он отсутствует в сервисе имен, или вводит его повторно, если он уже присутствует там. Однако такое использование rebind позволяет за одно обращение получить доступ только к одному экземпляру BillingService.Последним зарегистрированным BillingService является сервер, с которым связаны клиенты.

Вызов orb.run переводит объект в состояние ожидания запросов от клиентов, более того, этот вызов является блокирующим.

Таким образом, мы создали серверный объект, способный принимать и обрабатывать запросы пользователей и зарегистрировали его в сервисе имен (в его корневом разделе) под именем BillingService.

< Лекция 5 || Лекция 6: 123456 || Лекция 7 >
Алмаз Мурзабеков
Алмаз Мурзабеков
Прохожу курс "Построение распределенных систем на Java" в третьей лекции где описывается TCPServer вылетает эта ошибка
"Connection cannot be resolved to a type"


Java version 1.7.0_05