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

CORBA. Второй пример

< Лекция 7 || Лекция 8: 1234 || Лекция 9 >

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

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

BillingServiceImpl (пример 8.14) является реализацией интерфейса BillingService. Этот класс не объявляет метод main, этот метод объявляется в файле BillingServiceServer.java.

1  // BillingServiceImpl.java
2  package com.asw.corba.ex2;
3
4  //AccountManagerImpl.java
5  import com.asw.corba.ex2.BillingServiceModule.*;
6  // базовые пакеты Java
7  import java.util.*;
8
9  public class BillingServiceImpl   extends BillingServicePOA {
10  public synchronized Card addNewCard
    (String personName, String cardCode) {
11  // Lookup the account in the account dictionary.
12  Card card = (Card) _cards.get(cardCode);
13  // If there was no account in the dictionary, create one.
14  if(card == null) {
15  // Make up the account's balance, between 0 and 1000 dollars.
16  // Create the account implementation, given the balance.
17  CardImpl cardServant = new CardImpl(personName,0.0);
18  try {
19  // Activate it on the default POA which is root POA for this servant
20  card = CardHelper.narrow(_default_POA().servant_to_reference 
    (cardServant));
21  } catch (Exception e) {
22  e.printStackTrace();
23  }
24  // Print out the new account.
25  System.out.println("Created " + cardCode + 
    "'s account: " + card);
26  // Save the account in the account dictionary
27  _cards.put(cardCode, card);
28  }
29  // Return the account.
30  return card;
31  }
32  private Dictionary _cards = new Hashtable();
33  private Random _random = new Random();
34  public Card getCard(String cardCode) {
35  // TODO Auto-generated method stub
36  Card card = (Card) _cards.get(cardCode);
37  return card;
38  }
39  }
Листинг 8.14. Реализация сервера BillingService, класс BillingServiceImpl

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

Класс BillingServiceImpl реализует методы сервера, а запуск сервера производится классом BillingServiceServer (пример 8.16).

Прежде чем рассматривать класс BillingServiceServer,рассмотрим реализацию класса CardImpl (пример 8.15). Класс CardImpl наследует от класса CardPOA (построен автоматически) и реализует методы addMoney, subMoney и getBalance.

1  // CardImpl.java
2  package com.asw.corba.ex2;
3
4  import com.asw.corba.ex2.BillingServiceModule.*;
5
6  //AccountImpl.java
7  public class CardImpl extends CardPOA {
8  public CardImpl(String personName,double balance) {
9  _personName = personName;
10  _balance = balance;
11  }
12
13  private double _balance;
14  private String _personName;
15
16  public void addMoney(double money) {
17  _balance += money;
18  }
19
20  public void subMoney(double money) {
21  _balance -= money;
22  }
23
24  public double getBalance() {
25  // TODO Auto-generated method stub
26  return _balance;
27  }
28  }
Листинг 8.15. Реализация класса CardImpl

И наконец, класс BillingServiceServer содержит метод main, являющийся точкой входа в программу.

1  // BillingServiceServer.java
2  package com.asw.corba.ex2;
3
4  // пакеты OMG CORBA
5  import org.omg.CosNaming.*;
6  import org.omg.PortableServer.*;
7
8  public class BillingServiceServer {
9  public static void main(String args[]) {
10  try{
11  // Initialize the ORB.
12  org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);
13  // get a reference to the root POA
14  POA rootPOA = POAHelper.narrow(orb.resolve_initial_references
  ("RootPOA"));
15  // get a reference to the Naming Service root_context
16  org.omg.CORBA.Object rootObj = 
    orb.resolve_initial_references ("NameService");
17  NamingContextExt root = NamingContextExtHelper.narrow(rootObj);
18
19  // Create policies for our persistent POA
20  org.omg.CORBA.Policy[] policies = {
21  rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT)
22  };
23  // Create myPOA with the right policies
24  POA myPOA = rootPOA.create_POA( "billing_agent_poa", 
  rootPOA.the_POAManager(), policies );
25  // Create the servant
26  BillingServiceImpl managerServant = new BillingServiceImpl();
27  // Decide on the ID for the servant
28  byte[] managerId = "BillingService".getBytes();
29  // Activate the servant with the ID on myPOA
30  myPOA.activate_object_with_id(managerId, managerServant);
31
32  // Activate the POA manager
33  rootPOA.the_POAManager().activate();
34
35  // Associate the bank manager with the name at the root context
36  // Note that casting is needed as a workaround for a JDK 1.1.x bug.
37  ((NamingContext)root).bind(root.to_name("BillingService"), 
  myPOA.servant_to_reference(managerServant));
38
39  System.out.println(myPOA.servant_to_reference(managerServant) +
40  " is ready.");
41  // Wait for incoming requests
42  orb.run();
43  }
44  catch (Exception e) {
45  e.printStackTrace();
46  }
47  }
48  }
Листинг 8.16. Запуск сервера BillingService, класс BillingServiceServer

Первое, что делает это класс, - создает ссылку на orb (брокер объектных запросов) (строка 12), передавая в статический метод init переданные ему аргументы командной строки. Параметры метода init могут иметь значения null.

Затем идут несколько строчек (строки 14-17), отвечающих за получение и активизацию ссылки на корневой POA ( Portable Object Adapter ). Строка "RootPOA" является стандартным именем, определенным в спецификации CORBA (вместе со списком других имен). Статический метод narrow класса POAHelper используется для преобразования возвращенной объектной ссылки в объект нужного типа.

В строке 26 создается экземпляр нашего класса BillingServiceImpl.

Затем задается имя для нашего объекта, и метод bind (строка 37) вводит NameComponent в сервисе имен.

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

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

Следует обратить внимание на то, что при создании объекта он был определен как персистентный (строка 20), что приведет к особенностям при его запуске.

Персистентным называется такой объект, получив ссылку на который, клиент может воспользоваться им независимо от того, активен этот объект в настоящий момент или нет (загружен он в память или нет); к тому же, независимо от того, сколько циклов загрузки/выгрузки пережил персистентный объект, объектная ссылка изменяться не будет. Для клиента это выглядит следующим образом: клиент получает объектную ссылку, вызывает метод объекта, и если объект присутствует в памяти (активен), все происходит обычным образом, а вот если объекта в памяти нет - система его загружает, инициирует и после этого передает ему запрос клиента.

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

Файл BillingServiceClient.java

BillingServiceClient (пример 8.17) представляет собой клиент, который соединяется с BillingService. Клиент содержит один метод main, который добавляет денежные средства на карту с номером 1 и затем выводит текущий баланс этой карты (строки 29-30).

1  // BillingServiceClient.java
2  package com.asw.corba.ex2;
3
4  // пакеты OMG CORBA
5  import org.omg.CORBA.ORB;
6  import org.omg.CosNaming.NamingContextExt;
7  import org.omg.CosNaming.NamingContextExtHelper;
8
9  import com.asw.corba.ex2.BillingServiceModule.*;;
10
11  public class BillingServiceClient {
12  static BillingService BSImpl;
13
14  public static void main(String args[])
15  {
16  try{
17  // create and initialize the ORB
18  ORB orb = ORB.init(args, null);
19
20  // get the root naming context
21  org.omg.CORBA.Object objRef =
22  orb.resolve_initial_references("NameService");
23
24  // Use NamingContextExt instead of NamingContext. This is
25  // part of the Interoperable naming Service.
26  NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
27
28  // resolve the Object Reference in Naming
29  String name = "BillingService";
30  System.out.println("1");
31  BSImpl = BillingServiceHelper.narrow(ncRef.resolve_str(name));
32
33  System.out.println("Obtained a handle on server object: " + BSImpl);
34  Card card = BSImpl.addNewCard("Ivan","1");
35  card.addMoney(10);
36  System.out.println(card.getBalance());
37  } catch (Exception e) {
38  System.out.println("ERROR : " + e) ;
39  e.printStackTrace(System.out);
40  }
41  }
42  }
Листинг 8.17. Клиентский класс BillingServiceClient

В строке 18 вызывается статический метод init класса ORB для создания брокера объектных запросов. Массив args типа String позволяет динамически настраивать брокер объектных запросов во время выполнения (массив получен из командной строки). После того как клиент получает ORB, в строках 21-22 вызывается метод resolve_initial_references этого брокера объектных запросов, чтобы получить объектную ссылку на сервис имен. В строке 26 осуществляется приведение полученной объектной ссылки к объекту типа NamingContextExt с помощью метода NamingContextExtHelper.narrow.

Клиент должен запросить у сервиса имен объектную ссылку на сервис, который он разыскивает, - сервис BillingService,имеющий имя "BillingService" (объявлен в классе BillingServiceServer).Статический метод BillingServiceHelper.narrow осуществляет приведение объектной ссылки к требуемому типу производного класса. С этого момента у клиента есть ссылка на серверный объект.

Выполнение примера

Если исходный код находится в каталоге C:\src,командная строка будет выглядеть следующим образом (исходя из IDL -описания, представленного в примере 8.1):

idlj -td c:\src -pkgPrefix BillingServiceModule com.asw.corba.ex2 
   -fall BillingService.idl

Эта командная строка создает и серверные, и клиентские файлы CORBA-Java. После реализации сервера и клиента следует скомпилировать серверный и клиентский код. При компиляции никаких особенностей нет:

javac *.java

Так же как и в предыдущем примере, необходимо проследить, чтобы пакет org.omg.*,содержащий реализацию поддержки CORBA, присутствовал в путях classpath.

Поскольку созданное нами приложение является персистентным объектом, для его функционирования потребуется сервис orbd,который предоставляет клиентам CORBA возможность прозрачной работы с персистентными объектами. Этот сервис, будучи запущенным, автоматически запускает сервис имен.

Запуск сервиса orbd по умолчанию не требует указания дополнительных параметров и выглядит следующим образом:

G:\jdk\bin\orbd

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

Работа утилиты servertool

Рис. 8.1. Работа утилиты servertool

Для первоначальной регистрации объектов используется утилита servertool.

Утилита servertool способна выполнять различные команды, полный список которых можно получить, набрав команду help в появившемся после ее запуска приглашении. Для нас сейчас наибольшую ценность представляет команда регистрации серверного объекта. В нашем случае эта команда выглядит так:

servertool > register -server
com.asw.corba.ex2.BillingServiceServer -classpath h:\servers\BS

где ключ - server определяет название запускающего класса (в данном случае - com.asw.corba.ex2.BillingServiceServer)параметр -classpath указывает, где этот класс следует искать.

Список зарегистрированных объектов может быть получен с помощью команды list.Ниже приведен пример вывода утилиты servertool.

После регистрации объект готов к работе.

Далее мы запускаем клиента:

G:\ BillingService>java com.asw.corba.ex2.BillingServiceClient2

Выполнение команды приводит к следующему результату:

1
Obtained a handle on server object:
IOR:000000000000002c49444c3a42696c6c696e67536572766963654d6f64756c 
652f42696c6c696e67536572766963653a312e30000000000100000000000000a2 
000102000000000c3139322e3136382e312e3100041900000000004fafabcb0000 
0000220000010100000001000000000000000200000008526f6f74504f41000000 
001262696c6c696e675f6167656e745f706f610000000000000e42696c6c696e67 
536572766963651400000000020000000100000020000000000001000100000002
050100010001002000010109000000010001010000000026000000020002 
10.0

Клиент получает объектную ссылку, распечатывает ее, вызывает метод addNewCard,который создает новую карту и возвращает объектную ссылку на вновь созданный объект. Полученная объектная ссылка может быть использована самым обычным образом - в данном случае клиент вызывает методы addMoney и getBalance и распечатывает баланс карты после выполнения операции, после чего прекращает работу.

Вывод сервера перехватывается orbd и перенаправляется в файлы <serverid>.err и <serverid>.out,располагающиеся в директории logs структуры файлов orbd.

В нашем случае файл 259.out будет иметь следующий вид:

[Sat Dec 30 17:09:15 MSK 2005]  Server started
[Sat Dec 30 17:09:16 MSK 2005]  Install starting
[Sat Dec 30 17:09:16 MSK 2005]  Install completed
IOR:000000000000002c49444c3a42696c6c696e67536572766963654d6f64756c6 
52f42696c6c696e67536572766963653a312e30000000000100000000000000a200 
0102000000000c3139322e3136382e312e3100041900000000004fafabcb0000000 
0220000010100000001000000000000000200000008526f6f74504f410000000012 
62696c6c696e675f6167656e745f706f610000000000000e42696c6c696e6753657 
2766963651400000000020000000100000020000000000001000100000002050100 
010001002000010109000000010001010000000026000000020002 is ready.
Created 1's account:
IOR:000000000000002249444c3a42696c6c696e67536572766963654d6f64756c 
652f436172643a312e30000000000000010000000000000086000102000000000c 
3139322e3136382e312e31000f58000000000031afabcb0000000020d3b1664d00 
000001000000000000000100000008526f6f74504f410000000008000000010000 
000014000000000000020000000100000020000000000001000100000002050100 
010001002000010109000000010001010000000026000000020002
< Лекция 7 || Лекция 8: 1234 || Лекция 9 >
Алмаз Мурзабеков
Алмаз Мурзабеков
Прохожу курс "Построение распределенных систем на Java" в третьей лекции где описывается TCPServer вылетает эта ошибка
"Connection cannot be resolved to a type"


Java version 1.7.0_05