Построение распределенных систем на Java

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

Разбить на страницы
Показывать лекцию целиком

Рабочий каталог расположен в Practice.

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

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

Файл BillingService.idl

Файл BillingService.idl содержит описание двух интерфейсов: Card и BillingService.Интерфейс Card содержит три метода: addMoney (добавляет денежные средства на карту), subMoney (снимает денежные средства с карты), getCardBalance (показывает текущий баланс карты). Интерфейс BillingService включает два метода: addNewCard (добавляет новую карту) и getCard (возвращает объектную ссылку на карту с указанным номером).

В примере 8.1 приведено IDL -описание сервера BillingService.

1  // BillingService.idl
2  // IDL-описание BillingService
3  module    BillingServiceModule 
4  {
5  interface Card 
6  {
7  void addMoney(in double money);
8  void subMoney(in double money);
9  double getBalance();
10  };
11  interface BillingService
12  {
13  Card getCard(in string card);
14  Card addNewCard(in string personName, in string card);
15  };
16  };

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

После компиляции файла BillingService.idl компилятор Java-IDL создает следующие файлы на стороне сервера в вновь созданной директории BillingServiceModule:

BillingService.java,
BillingServiceHelper.java,
BillingServiceHolder.java,
BillingServiceOperations.java,
BillingServicePOA.java,
_BillingServiceStub.java,
Card.java,
CardHelper.java,
CardHolder.java,
CardOperations.java,
CardPOA.java,
_CardStub.java.

Рассмотрим подробнее эти файлы (в этих файлах определены классы и интерфейсы языка java ) и то, как мы можем их использовать при создании нашего приложения.

BillingService.java и BillingServiceOperations.java - интерфейсы. BillingService.java (пример 8.2) представляет собой интерфейс BillingService.

1  package com.asw.corba.ex2.BillingServiceModule;
2
3
4 /**
5 * com/asw/corba/ex2/BillingServiceModule/BillingService.java . 
6 * Generated by the IDL-to-Java compiler (portable), version "3.1" 
7 * from com/asw/corba/ex2/BillingService.idl
8 * 16 Июль 2006 г. 15:01:11 MSD
9 */
10
11  public interface BillingService extends BillingServiceOperations,
12  org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity
13  {
14  } // interface BillingService

В строках 11 и 12 объявлены интерфейс BillingService и три интерфейса, от которых наследует BillingService.Как уже говорилось, два из этих трех интерфейсов являются определенными в CORBA типами, от которых должны наследовать все CORBA -совместимые объекты, org.omg.CORBA.Object и org.omg.CORBA.portable.IDLEntity.Третий интерфейс - BillingServiceOperations (пример 8.3) - создается на основе IDL -описания и объявляет открытые операции данного сервера. BillingService определяет базовый класс, который наследует от BillingServiceOperations и от CORBA -интерфейсов, упомянутых ранее. BillingServiceOperations объявляет два метода, изначально определенные в IDL.

1  package com.asw.corba.ex2.BillingServiceModule;
2 
3
4 /**
5 * com/asw/corba/ex2/BillingServiceModule/BillingServiceOperations.java . 
6 * Generated by the IDL-to-Java compiler (portable), version "3.1" 
7 * from com/asw/corba/ex2/BillingService.idl
8 * 16 Июль 2006 г. 15:01:11 MSD
9 */
10
11  // определение CORBA-совместимого сервиса
12  public interface BillingServiceOperations
13  {
14  com.asw.corba.ex2.BillingServiceModule.Card getCard (String card);
15  com.asw.corba.ex2.BillingServiceModule.Card addNewCard 
  (String personName, String card);
16  } // interface BillingServiceOperations

Файлы BillingServiceHelper.java (пример 8.4) и BillingServiceHolder.java (пример 8.5) содержат методы приведения типов и методы маршаллинга/демаршаллинга сообщений.

1  package com.asw.corba.ex2.BillingServiceModule;
2 
3
4 /**
5 * com/asw/corba/ex2/BillingServiceModule/BillingServiceHelper.java
6 * Generated by the IDL-to-Java compiler (portable), version "3.1" 
7 * from com/asw/corba/ex2/BillingService.idl 
8 * 16 Июля 2006 г. 15:01:11 MSD 
9 */
10
11  // определение класса BillingServiceHelper
12  abstract public class BillingServiceHelper
13  {
14  private static String _id = 
  "IDL:BillingServiceModule/BillingService:1.0";
15
16  public static void insert (org.omg.CORBA.Any a, 
  com.asw.corba.ex2.BillingServiceModule.BillingService that)
17  {
18  org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
19  a.type (type ());
20  write (out, that);
21  a.read_value (out.create_input_stream (), type ());
22  }
23
24  public static com.asw.corba.ex2.BillingServiceModule.BillingService 
  extract (org.omg.CORBA.Any a)
25  {
26  return read (a.create_input_stream ());
27  }
28
29  private static org.omg.CORBA.TypeCode__typeCode = null;
30
31  synchronized public static org.omg.CORBA.TypeCode type ()
32  {
33  if (__typeCode == null)
34  {
35  __typeCode = org.omg.CORBA.ORB.init ().create_interface_tc
  (com.asw.corba.ex2.BillingServiceModule.BillingServiceHelper.id (), 
  "BillingService");
36  }
37  return __typeCode;
38  }
39
40  public static String id ()
41  {
42  return _id;
43  }
44
45  public static com.asw.corba.ex2.BillingServiceModule.BillingService 
  read (org.omg.CORBA.portable.InputStream istream)
46  {
47  return narrow (istream.read_Object (_BillingServiceStub.class));
48  }
49
50  public static void write (org.omg.CORBA.portable.OutputStream ostream, 
  com.asw.corba.ex2.BillingServiceModule.BillingService value)
51  {
52  ostream.write_Object ((org.omg.CORBA.Object) value);
53  }
54
55  public static com.asw.corba.ex2.BillingServiceModule.BillingService 
  narrow (org.omg.CORBA.Object obj)
56  {
57  if (obj == null)
58  return null;
59  else if (obj instanceof 
  com.asw.corba.ex2.BillingServiceModule.BillingService)
60  return (com.asw.corba.ex2.BillingServiceModule.BillingService)obj;
61  else if (!obj._is_a (id ()))
62  throw new org.omg.CORBA.BAD_PARAM ();
63  else
64  {
65  org.omg.CORBA.portable.Delegate delegate = 
  ((org.omg.CORBA.portable.ObjectImpl)obj)._get_delegate ();
66  com.asw.corba.ex2.BillingServiceModule._BillingServiceStub stub = 
  new com.asw.corba.ex2.BillingServiceModule._BillingServiceStub ();
67  stub._set_delegate(delegate);
68  return stub;
69  }
70  }
71  }
1  package com.asw.corba.ex2.BillingServiceModule;
2
3 /**
4 *  com/asw/corba/ex2/BillingServiceModule/BillingServiceHolder.java .
5 *  Generated by the IDL-to-Java compiler (portable), version "3.1"
6 *  from com/asw/corba/ex2/BillingService.idl
7 *  16 Июль 2006 г. 15:01:11 MSD
8 */
9
10  // определение класса BillingServiceHolder
11  public final class BillingServiceHolder implements 
  org.omg.CORBA.portable.Streamable
12  {
13  public com.asw.corba.ex2.BillingServiceModule.BillingService value
  = null;
14
15  public BillingServiceHolder ()
16  {
17  }
18
19  public BillingServiceHolder 
  (com.asw.corba.ex2.BillingServiceModule.BillingService initialValue)
20  {
21  value = initialValue;
22  }
23
24  public void _read (org.omg.CORBA.portable.InputStream i)
25  {
26  value =
  com.asw.corba.ex2.BillingServiceModule.BillingServiceHelper.read (i);
27  }
28
29  public void _write (org.omg.CORBA.portable.OutputStream o)
30  {
31  com.asw.corba.ex2.BillingServiceModule.BillingServiceHelper.write 
  (o, value);
32  }
33
34  public org.omg.CORBA.TypeCode _type ()
35  {
36  return
  com.asw.corba.ex2.BillingServiceModule.BillingServiceHelper.type ();
37  }
38  }

Файл _BillingServiceStub.java (пример 8.6) содержит клиентскую заглушку. Класс BillingServiceStub наследует от org.omg.CORBA.portable. ObjectImpl и реализует интерфейс BillingService.При вызове клиентом методов этого класса происходит упаковка вызова (и параметров) и их передача по сети серверному классу.

1  package com.asw.corba.ex2.BillingServiceModule;
2
3 /**
4 * com/asw/corba/ex2/BillingServiceModule/_BillingServiceStub.java. 
5 * Generated by the IDL-to-Java compiler (portable), version "3.1" 
6 * from com/asw/corba/ex2/BillingService.idl
7 * 16 Июль 2006 г. 15:01:11 MSD
8 */
9
10  // определение класса _BillingServiceStub
11  public class _BillingServiceStub extends org.omg.CORBA.
  portable.ObjectImpl implements
  com.asw.corba.ex2.BillingServiceModule.BillingService
12  {
13  public com.asw.corba.ex2.BillingServiceModule.Card getCard (String card)
14  {
15  org.omg.CORBA.portable.InputStream $in = null;
16  try {
17  org.omg.CORBA.portable.OutputStream $out = 
  _request ("getCard", true);
18  $out.write_string (card);
19  $in = _invoke ($out);
20  com.asw.corba.ex2.BillingServiceModule.Card $result = 
  com.asw.corba.ex2.BillingServiceModule.CardHelper.read ($in);
21  return $result;
22  } catch (org.omg.CORBA.portable.ApplicationException $ex) {
23  $in = $ex.getInputStream ();
24  String _id = $ex.getId ();
25  throw new org.omg.CORBA.MARSHAL (_id);
26  } catch (org.omg.CORBA.portable.RemarshalException $rm) {
27  return getCard (card  );
28  } finally {
29  _releaseReply ($in);
30  }
31  } // getCard
32
33  public com.asw.corba.ex2.BillingServiceModule.Card addNewCard 
  (String personName, String card)
34  {
35  org.omg.CORBA.portable.InputStream $in = null;
36  try {
37  org.omg.CORBA.portable.OutputStream $out = 
  _request ("addNewCard", true);
38  $out.write_string (personName);
39  $out.write_string (card);
40  $in = _invoke ($out);
41  com.asw.corba.ex2.BillingServiceModule.Card $result = 
  com.asw.corba.ex2.BillingServiceModule.CardHelper.read ($in);
42  return $result;
43  } catch (org.omg.CORBA.portable.ApplicationException $ex) {
44  $in = $ex.getInputStream ();
45  String _id = $ex.getId ();
46  throw new org.omg.CORBA.MARSHAL (_id);
47  } catch (org.omg.CORBA.portable.RemarshalException $rm) {
48  return addNewCard (personName, card  );
49  } finally {
50  _releaseReply ($in);
51  }
52  } // addNewCard
53
54  // Type-specific CORBA::Object operations
55  private static String[]__ids = {
56  "IDL:BillingServiceModule/BillingService:1.0"};
57  public String[] _ids ()
58  {
59  return (String[])__ids.clone ();
60  }
61
62  private void readObject (java.io.ObjectInputStream s) 
  throws java.io.IOException
63  {
64  String str = s.readUTF ();
65  String[] args = null;
66  java.util.Properties props = null;
67  org.omg.CORBA.Object obj = org.omg.CORBA.ORB.init 
  (args, props).string_to_object (str);
68  org.omg.CORBA.portable.Delegate delegate = 
  ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate ();
69  _set_delegate (delegate);
70  }
71
72  private void writeObject (java.io.ObjectOutputStream s) 
  throws java.io.IOException
73  {
74  String[] args = null;
75  java.util.Properties props = null;
76  String str = org.omg.CORBA.ORB.init (args, props).object_to_string
  (this);
77  s.writeUTF (str);
78  }
79  } // class _BillingServiceStub

И последний файл BillingServicePOA.java (пример 8.7) содержит класс, выполняющий всю техническую работу по диспетчеризации сообщений клиента, - этот класс будет являться предком для нашего серверного класса, в котором мы переопределим методы, выполняющие содержательные операции. Класс BillingServicePOA наследует от org.omg.PortableServer.Servant и реализует CORBA -интерфейс (InvokeHandler) и интерфейс BillingServiceOperations.Интерфейс InvokeHandler объявляет метод invoke, который является реализацией BillingServicePOA.

1  package com.asw.corba.ex2.BillingServiceModule;
2
3 /**
4 * com/asw/corba/ex2/BillingServiceModule/BillingServicePOA.java .
5 * Generated by the IDL-to-Java compiler (portable), version "3.1" 
6 * from com/asw/corba/ex2/BillingService.idl 
7 * 16 Июль 2006 г. 15:01:11 MSD
8 */ 
9
10  // определение класса BillingServicePOA
11  public abstract class BillingServicePOA extends 
  org.omg.PortableServer.Servant
12  implements
  com.asw.corba.ex2.BillingServiceModule.BillingServiceOperations, 
  org.omg.CORBA.portable.InvokeHandler
13  {
14  // Constructors
15  private static java.util.Hashtable _methods = new java.util.Hashtable ();
16  static
17  {
18  _methods.put ("getCard", new java.lang.Integer (0));
19  _methods.put ("addNewCard", new java.lang.Integer (1));
20  }
21
22  public org.omg.CORBA.portable.OutputStream _invoke (String $method,
23  org.omg.CORBA.portable.InputStream in,
24  org.omg.CORBA.portable.ResponseHandler $rh)
25  {
26  org.omg.CORBA.portable.OutputStream out = null;
27  java.lang.Integer __method = (java.lang.Integer)_methods.get ($method);
28  if (__method == null)
29  throw new org.omg.CORBA.BAD_OPERATION (0,
  org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
30
31  switch __method.intValue ())
32  {
33  case 0:   // BillingServiceModule/BillingService/getCard
34  {
35  String card = in.read_string ();
36  com.asw.corba.ex2.BillingServiceModule.Card $result = null;
37  $result = this.getCard (card);
38  out = $rh.createReply();
39  com.asw.corba.ex2.BillingServiceModule.CardHelper.write (out, $result);
40  break;
41  }
42
43  case 1:   // BillingServiceModule/BillingService/addNewCard
44  {
45  String personName = in.read_string ();
46  String card = in.read_string ();
47  com.asw.corba.ex2.BillingServiceModule.Card $result = null;
48  $result = this.addNewCard (personName, card);
49  out = $rh.createReply();
50  com.asw.corba.ex2.BillingServiceModule.CardHelper.write (out, $result);
51  break;
52  }
53
54  default:
55  throw new org.omg.CORBA.BAD_OPERATION 
  (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
56  }
57  return out;
58  } // _invoke
59
60  // Type-specific CORBA::Object operations
61  private static String[] __ids = 
  {"IDL:BillingServiceModule/BillingService:1.0"};
62
63  public String[] _all_interfaces 
  (org.omg.PortableServer.POA poa, byte[] objectId)
64  {
65  return (String[]) __ids.clone ();
66  }
67
68  public BillingService _this()
69  {
70  return BillingServiceHelper.narrow(super._this_object());
71  }
72
73  public BillingService _this(org.omg.CORBA.ORB orb)
74  {
75  return BillingServiceHelper.narrow(super._this_object(orb));
76  }
77
78  } // class BillingServicePOA

Теперь перейдем к рассмотрению интерфейса Card.В файле Card.java (пример 8.8) определен интерфейс Card, наследующий от созданного idlj интерфейса CardOperations (пример 8.9) и двух интерфейсов - они являются определенными в CORBA типами, от которых должны наследовать все CORBA -совместимые объекты, - org.omg.CORBA.Object и org.omg.CORBA.portable.IDLEntity.

1  package com.asw.corba.ex2.BillingServiceModule;
2 
3
4 /**
5 * com/asw/corba/ex2/BillingServiceModule/Card.java .
6 * Generated by the IDL-to-Java compiler (portable), version "3.1"
7 * from com/asw/corba/ex2/BillingService.idl
8 * 16 Июль 2006 г. 15:01:11 MSD
9 */
10
11  public interface Card extends CardOperations,
12  org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity
13  {
14  } // interface Card

CardOperations, ни от кого не наследуя, объявляет три метода, изначально определенные в IDL.

1  package com.asw.corba.ex2.BillingServiceModule;
2 
3
4 /**
5 * com/asw/corba/ex2/BillingServiceModule/CardOperations.java . 
6 * Generated by the IDL-to-Java compiler (portable), version "3.1" 
7 * from com/asw/corba/ex2/BillingService.idl
8 * 16 Июль 2006 г. 15:01:11 MSD
9 */
10
11  // определение CORBA-совместимого сервиса
12  public interface CardOperations
13  {
14  void addMoney (double money);
15  void subMoney (double money);
16  double getBalance ();
17  } // interface CardOperations

Файлы CardHelper.java (пример 8.10) и CardHolder.java (пример 8.11) содержат вспомогательные классы.

1  package com.asw.corba.ex2.BillingServiceModule;
2
3
4 /**
5 *  com/asw/corba/ex2/BillingServiceModule/CardHelper.java .
6 *  Generated by the IDL-to-Java compiler (portable), version "3.1"
7 *  from com/asw/corba/ex2/BillingService.idl
8 *  16 Июля 2006 г. 15:01:11 MSD
9 */
10
11  // определение класса CardHelper
12  abstract public class CardHelper
13  {
14  private static String _id = "IDL:BillingServiceModule/Card:1.0";
15
16  public static void insert (org.omg.CORBA.Any a, 
  com.asw.corba.ex2.BillingServiceModule.Card that)
17  {
18  org.omg.CORBA.portable.OutputStream out = a.create_output_stream();
19  a.type (type ());
20  write (out, that);
21  a.read_value (out.create_input_stream (), type ());
22  }
23
24  public static com.asw.corba.ex2.BillingServiceModule.Card extract 
  (org.omg.CORBA.Any a)
25  {
26  return read (a.create_input_stream ());
27  }
28
29  private static org.omg.CORBA.TypeCode __typeCode = null;
30  synchronized public static org.omg.CORBA.TypeCode type ()
31  {
32  if (__typeCode == null)
33  {
34  __typeCode = org.omg.CORBA.ORB.init ().create_interface_tc
  (com.asw.corba.ex2.BillingServiceModule.CardHelper.id (), 
   "Card");
35  }
36  return  __typeCode;
37  }
38
39  public static String id ()
40  {
41  return _id;
42  }
43
44  public static com.asw.corba.ex2.BillingServiceModule.Card read 
    (org.omg.CORBA.portable.InputStream istream)
45  {
46  return narrow (istream.read_Object (_CardStub.class));
47  }
48
49  public static void write (org.omg.CORBA.portable.OutputStream ostream, 
    com.asw.corba.ex2.BillingServiceModule.Card value)
50  {
51  ostream.write_Object ((org.omg.CORBA.Object) value);
52  }
53
54  public static com.asw.corba.ex2.BillingServiceModule.Card 
    narrow (org.omg.CORBA.Object obj)
55  {
56  if (obj == null)
57  return null;
58  else if (obj instanceof com.asw.corba.ex2.BillingServiceModule.Card)
59  return (com.asw.corba.ex2.BillingServiceModule.Card)obj;
60  else if (!obj._is_a (id ()))
61  throw new org.omg.CORBA.BAD_PARAM ();
62  else
63  {
64  org.omg.CORBA.portable.Delegate delegate = 
    ((org.omg.CORBA.portable.ObjectImpl)obj)._get_delegate ();
65  com.asw.corba.ex2.BillingServiceModule._CardStub stub = 
    new com.asw.corba.ex2.BillingServiceModule._CardStub ();
66  stub._set_delegate(delegate);
67  return stub;
68  }
69  }
70  }
1  package com.asw.corba.ex2.BillingServiceModule;
2 
3 /**
4 *  com/asw/corba/ex2/BillingServiceModule/CardHolder.java .
5 * Generated by the IDL-to-Java compiler (portable), version "3.1"
6 *  from com/asw/corba/ex2/BillingService.idl
7 *  16 Июль 2006 г. 15:01:11 MSD
8 */
9
10  // определение класса CardHolder
11  public final class CardHolder implements org.omg.CORBA. 
  portable.Streamable
12  {
13  public com.asw.corba.ex2.BillingServiceModule.Card value = null;
14
15  public CardHolder ()
16  {
17  }
18
19  public CardHolder (com.asw.corba.ex2.BillingServiceModule.Card 
  initialValue)
20  {
21  value = initialValue;
22  }
23
24  public void _read (org.omg.CORBA.portable.InputStream i)
25  {
26  value = com.asw.corba.ex2.BillingServiceModule.CardHelper.read (i);
27  }
28
29  public void _write (org.omg.CORBA.portable.OutputStream o)
30  {
31  com.asw.corba.ex2.BillingServiceModule.CardHelper.write (o, value);
32  } 
33
34  public org.omg.CORBA.TypeCode _type ()
35  {
36  return com.asw.corba.ex2.BillingServiceModule.CardHelper.type ();
37  }
38  }

Файл _CardStub.java (пример 8.12) содержит клиентскую заглушку. Класс CardStub наследует от org.omg.CORBA.portable.ObjectImpl и реализует интерфейс Card.При вызове клиентом методов этого класса происходит упаковка вызова (и параметров) и их передача по сети серверному классу.

1  package com.asw.corba.ex2.BillingServiceModule;
2
3 /**
4 * com/asw/corba/ex2/BillingServiceModule/_CardStub.java .
5 * Generated by the IDL-to-Java compiler (portable), version "3.1"
6 * from com/asw/corba/ex2/BillingService.idl
7 * 16 Июль 2006 г. 15:01:11 MSD
8 */
9
10    // определение класса _CardStub
11  public class _CardStub extends org.omg.CORBA.portable.ObjectImpl 
  implements com.asw.corba.ex2.BillingServiceModule.Card
12  {
13  public void addMoney (double money)
14  {
15  org.omg.CORBA.portable.InputStream $in = null;
16  try {
17  org.omg.CORBA.portable.OutputStream $out = 
    _request ("addMoney", true);
18  $out.write_double (money);
19  $in = _invoke ($out);
20  return;
21  } catch (org.omg.CORBA.portable.ApplicationException $ex) {
22  $in = $ex.getInputStream ();
23  String _id = $ex.getId ();
24  throw new org.omg.CORBA.MARSHAL (_id);
25  } catch (org.omg.CORBA.portable.RemarshalException $rm) {
26  addMoney (money  );
27  } finally {
28  _releaseReply ($in);
29  }
30  } // addMoney
31
32  public void subMoney (double money)
33  {
34  org.omg.CORBA.portable.InputStream $in = null;
35  try {
36  org.omg.CORBA.portable.OutputStream $out = 
    _request ("subMoney", true);
37  $out.write_double (money);
38  $in = _invoke ($out);
39  return;
40  } catch (org.omg.CORBA.portable.ApplicationException $ex) {
41  $in = $ex.getInputStream ();
42  String _id = $ex.getId ();
43  throw new org.omg.CORBA.MARSHAL (_id);
44  } catch (org.omg.CORBA.portable.RemarshalException $rm) {
45  subMoney (money  );
46  } finally {
47  _releaseReply ($in);
48  }
49  } // subMoney
50
51  public double getBalance ()
52  {
53  org.omg.CORBA.portable.InputStream $in = null;
54  try {
55  org.omg.CORBA.portable.OutputStream $out = 
  _request ("getBalance", true);
56  $in = _invoke ($out);
57  double $result = $in.read_double ();
58  return $result;
59  } catch (org.omg.CORBA.portable.ApplicationException $ex) {
60  $in = $ex.getInputStream ();
61  String _id = $ex.getId ();
62  throw new org.omg.CORBA.MARSHAL (_id);
63  } catch (org.omg.CORBA.portable.RemarshalException $rm) {
64  return getBalance (  );
65  } finally {
66  _releaseReply ($in);
67  }
68  } // getBalance
69
70  // Type-specific CORBA::Object operations
71  private static String[] __ids =
  {"IDL:BillingServiceModule/Card:1.0"};
72
73  public String[] __ids ()
74  {
75  return (String[]) __ids.clone ();
76  }
77
78  private void readObject (java.io.ObjectInputStream s) 
    throws java.io.IOException
79  {
80  String str = s.readUTF ();
81  String[] args = null;
82  java.util.Properties props = null;
83  org.omg.CORBA.Object obj = 
    org.omg.CORBA.ORB.init (args, props).string_to_object (str);
84  org.omg.CORBA.portable.Delegate delegate = 
    ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate ();
85  _set_delegate (delegate);
86  }
87
88  private void writeObject (java.io.ObjectOutputStream s) 
  throws java.io.IOException
89  {
90  String[] args = null;
91  java.util.Properties props = null;
92  String str = org.omg.CORBA.ORB.init (args, props).object_to_string
  (this);
93  s.writeUTF (str);
94  }
95  } // class _CardStub

И, наконец, файл CardPOA.java (пример 8.13) содержит класс, выполняющий всю рутинную работу по диспетчеризации сообщений клиента, - этот класс будет являться предком для нашего серверного класса, в котором мы переопределим нужные методы. Класс CardPOA наследует от org.omg.PortableServer.Servant и реализует CORBA -интерфейс InvokeHandler и интерфейс CardOperations.

1  package com.asw.corba.ex2.BillingServiceModule;
2
3 /**
4 * com/asw/corba/ex2/BillingServiceModule/CardPOA.java .
5 * Generated by the IDL-to-Java compiler (portable), version "3.1"
6 * from com/asw/corba/ex2/BillingService.idl
7 * 16 Июль 2006 г. 15:01:11 MSD
8 */ 
9
10  // определение класса CardPOA
11  public abstract class CardPOA extends org.omg.PortableServer.Servant
12  implements com.asw.corba.ex2.BillingServiceModule.CardOperations, 
    org.omg.CORBA.portable.InvokeHandler
13  {
14  // Constructors
15  private static java.util.Hashtable _methods = 
    new java.util.Hashtable ();
16  static
17  {
18  _methods.put ("addMoney", new java.lang.Integer (0));
19  _methods.put ("subMoney", new java.lang.Integer (1));
20  _methods.put ("getBalance", new java.lang.Integer (2));
21  }
22
23  public org.omg.CORBA.portable.OutputStream _invoke (String $method,
24  org.omg.CORBA.portable.InputStream in,
25  org.omg.CORBA.portable.ResponseHandler $rh)
26  {
27  org.omg.CORBA.portable.OutputStream out = null;
28  java.lang.Integer __method = (java.lang.Integer)_methods.get 
  ($method);
29  if (__method == null)
30  throw new org.omg.CORBA.BAD_OPERATION 
    (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
31
32  switch __method.intValue ())
33  {
34  case 0:   // BillingServiceModule/Card/addMoney
35  {
36  double money = in.read_double ();
37  this.addMoney (money);
38  out = $rh.createReply();
39  break;
40  }
41
42  case 1:   // BillingServiceModule/Card/subMoney
43  {
44  double money = in.read_double ();
45  this.subMoney (money);
46  out = $rh.createReply();
47  break;
48  }
49
50  case 2:   // BillingServiceModule/Card/getBalance
51  {
52  double $result = (double)0;
53  $result = this.getBalance ();
54  out = $rh.createReply();
55  out.write_double ($result);
56  break;
57  }
58
59  default:
60  throw new org.omg.CORBA.BAD_OPERATION 
    (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
61  }
62  return out;
63  } // _invoke
64
65  // Type-specific CORBA::Object operations
66  private static String[] __ids = 
    {"IDL:BillingServiceModule/Card:1.0"};
67
68  public String[] _all_interfaces 
    (org.omg.PortableServer.POA poa, byte[] objectId)
69  {
70  return (String[])__ids.clone ();
71  }
72
73  public Card _this()
74  {
75  return CardHelper.narrow(super._this_object());
76  }
77
78  public Card _this(org.omg.CORBA.ORB orb)
79  {
80  return CardHelper.narrow(super._this_object(orb));
81  }
82
83  } // class CardPOA

Файлы 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  }

Класс 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  }

И наконец, класс 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  }

Первое, что делает это класс, - создает ссылку на 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  }

В строке 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

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

(рис 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
Страницы:

Рабочий каталог расположен в Practice.

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

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

Файл BillingService.idl

Файл BillingService.idl содержит описание двух интерфейсов: Card и BillingService.Интерфейс Card содержит три метода: addMoney (добавляет денежные средства на карту), subMoney (снимает денежные средства с карты), getCardBalance (показывает текущий баланс карты). Интерфейс BillingService включает два метода: addNewCard (добавляет новую карту) и getCard (возвращает объектную ссылку на карту с указанным номером).

В примере 8.1 приведено IDL -описание сервера BillingService.

1  // BillingService.idl
2  // IDL-описание BillingService
3  module    BillingServiceModule 
4  {
5  interface Card 
6  {
7  void addMoney(in double money);
8  void subMoney(in double money);
9  double getBalance();
10  };
11  interface BillingService
12  {
13  Card getCard(in string card);
14  Card addNewCard(in string personName, in string card);
15  };
16  };

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

После компиляции файла BillingService.idl компилятор Java-IDL создает следующие файлы на стороне сервера в вновь созданной директории BillingServiceModule:

BillingService.java,
BillingServiceHelper.java,
BillingServiceHolder.java,
BillingServiceOperations.java,
BillingServicePOA.java,
_BillingServiceStub.java,
Card.java,
CardHelper.java,
CardHolder.java,
CardOperations.java,
CardPOA.java,
_CardStub.java.

Рассмотрим подробнее эти файлы (в этих файлах определены классы и интерфейсы языка java ) и то, как мы можем их использовать при создании нашего приложения.

BillingService.java и BillingServiceOperations.java - интерфейсы. BillingService.java (пример 8.2) представляет собой интерфейс BillingService.

1  package com.asw.corba.ex2.BillingServiceModule;
2
3
4 /**
5 * com/asw/corba/ex2/BillingServiceModule/BillingService.java . 
6 * Generated by the IDL-to-Java compiler (portable), version "3.1" 
7 * from com/asw/corba/ex2/BillingService.idl
8 * 16 Июль 2006 г. 15:01:11 MSD
9 */
10
11  public interface BillingService extends BillingServiceOperations,
12  org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity
13  {
14  } // interface BillingService

В строках 11 и 12 объявлены интерфейс BillingService и три интерфейса, от которых наследует BillingService.Как уже говорилось, два из этих трех интерфейсов являются определенными в CORBA типами, от которых должны наследовать все CORBA -совместимые объекты, org.omg.CORBA.Object и org.omg.CORBA.portable.IDLEntity.Третий интерфейс - BillingServiceOperations (пример 8.3) - создается на основе IDL -описания и объявляет открытые операции данного сервера. BillingService определяет базовый класс, который наследует от BillingServiceOperations и от CORBA -интерфейсов, упомянутых ранее. BillingServiceOperations объявляет два метода, изначально определенные в IDL.

1  package com.asw.corba.ex2.BillingServiceModule;
2 
3
4 /**
5 * com/asw/corba/ex2/BillingServiceModule/BillingServiceOperations.java . 
6 * Generated by the IDL-to-Java compiler (portable), version "3.1" 
7 * from com/asw/corba/ex2/BillingService.idl
8 * 16 Июль 2006 г. 15:01:11 MSD
9 */
10
11  // определение CORBA-совместимого сервиса
12  public interface BillingServiceOperations
13  {
14  com.asw.corba.ex2.BillingServiceModule.Card getCard (String card);
15  com.asw.corba.ex2.BillingServiceModule.Card addNewCard 
  (String personName, String card);
16  } // interface BillingServiceOperations

Файлы BillingServiceHelper.java (пример 8.4) и BillingServiceHolder.java (пример 8.5) содержат методы приведения типов и методы маршаллинга/демаршаллинга сообщений.

1  package com.asw.corba.ex2.BillingServiceModule;
2 
3
4 /**
5 * com/asw/corba/ex2/BillingServiceModule/BillingServiceHelper.java
6 * Generated by the IDL-to-Java compiler (portable), version "3.1" 
7 * from com/asw/corba/ex2/BillingService.idl 
8 * 16 Июля 2006 г. 15:01:11 MSD 
9 */
10
11  // определение класса BillingServiceHelper
12  abstract public class BillingServiceHelper
13  {
14  private static String _id = 
  "IDL:BillingServiceModule/BillingService:1.0";
15
16  public static void insert (org.omg.CORBA.Any a, 
  com.asw.corba.ex2.BillingServiceModule.BillingService that)
17  {
18  org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
19  a.type (type ());
20  write (out, that);
21  a.read_value (out.create_input_stream (), type ());
22  }
23
24  public static com.asw.corba.ex2.BillingServiceModule.BillingService 
  extract (org.omg.CORBA.Any a)
25  {
26  return read (a.create_input_stream ());
27  }
28
29  private static org.omg.CORBA.TypeCode__typeCode = null;
30
31  synchronized public static org.omg.CORBA.TypeCode type ()
32  {
33  if (__typeCode == null)
34  {
35  __typeCode = org.omg.CORBA.ORB.init ().create_interface_tc
  (com.asw.corba.ex2.BillingServiceModule.BillingServiceHelper.id (), 
  "BillingService");
36  }
37  return __typeCode;
38  }
39
40  public static String id ()
41  {
42  return _id;
43  }
44
45  public static com.asw.corba.ex2.BillingServiceModule.BillingService 
  read (org.omg.CORBA.portable.InputStream istream)
46  {
47  return narrow (istream.read_Object (_BillingServiceStub.class));
48  }
49
50  public static void write (org.omg.CORBA.portable.OutputStream ostream, 
  com.asw.corba.ex2.BillingServiceModule.BillingService value)
51  {
52  ostream.write_Object ((org.omg.CORBA.Object) value);
53  }
54
55  public static com.asw.corba.ex2.BillingServiceModule.BillingService 
  narrow (org.omg.CORBA.Object obj)
56  {
57  if (obj == null)
58  return null;
59  else if (obj instanceof 
  com.asw.corba.ex2.BillingServiceModule.BillingService)
60  return (com.asw.corba.ex2.BillingServiceModule.BillingService)obj;
61  else if (!obj._is_a (id ()))
62  throw new org.omg.CORBA.BAD_PARAM ();
63  else
64  {
65  org.omg.CORBA.portable.Delegate delegate = 
  ((org.omg.CORBA.portable.ObjectImpl)obj)._get_delegate ();
66  com.asw.corba.ex2.BillingServiceModule._BillingServiceStub stub = 
  new com.asw.corba.ex2.BillingServiceModule._BillingServiceStub ();
67  stub._set_delegate(delegate);
68  return stub;
69  }
70  }
71  }
1  package com.asw.corba.ex2.BillingServiceModule;
2
3 /**
4 *  com/asw/corba/ex2/BillingServiceModule/BillingServiceHolder.java .
5 *  Generated by the IDL-to-Java compiler (portable), version "3.1"
6 *  from com/asw/corba/ex2/BillingService.idl
7 *  16 Июль 2006 г. 15:01:11 MSD
8 */
9
10  // определение класса BillingServiceHolder
11  public final class BillingServiceHolder implements 
  org.omg.CORBA.portable.Streamable
12  {
13  public com.asw.corba.ex2.BillingServiceModule.BillingService value
  = null;
14
15  public BillingServiceHolder ()
16  {
17  }
18
19  public BillingServiceHolder 
  (com.asw.corba.ex2.BillingServiceModule.BillingService initialValue)
20  {
21  value = initialValue;
22  }
23
24  public void _read (org.omg.CORBA.portable.InputStream i)
25  {
26  value =
  com.asw.corba.ex2.BillingServiceModule.BillingServiceHelper.read (i);
27  }
28
29  public void _write (org.omg.CORBA.portable.OutputStream o)
30  {
31  com.asw.corba.ex2.BillingServiceModule.BillingServiceHelper.write 
  (o, value);
32  }
33
34  public org.omg.CORBA.TypeCode _type ()
35  {
36  return
  com.asw.corba.ex2.BillingServiceModule.BillingServiceHelper.type ();
37  }
38  }

Файл _BillingServiceStub.java (пример 8.6) содержит клиентскую заглушку. Класс BillingServiceStub наследует от org.omg.CORBA.portable. ObjectImpl и реализует интерфейс BillingService.При вызове клиентом методов этого класса происходит упаковка вызова (и параметров) и их передача по сети серверному классу.

1  package com.asw.corba.ex2.BillingServiceModule;
2
3 /**
4 * com/asw/corba/ex2/BillingServiceModule/_BillingServiceStub.java. 
5 * Generated by the IDL-to-Java compiler (portable), version "3.1" 
6 * from com/asw/corba/ex2/BillingService.idl
7 * 16 Июль 2006 г. 15:01:11 MSD
8 */
9
10  // определение класса _BillingServiceStub
11  public class _BillingServiceStub extends org.omg.CORBA.
  portable.ObjectImpl implements
  com.asw.corba.ex2.BillingServiceModule.BillingService
12  {
13  public com.asw.corba.ex2.BillingServiceModule.Card getCard (String card)
14  {
15  org.omg.CORBA.portable.InputStream $in = null;
16  try {
17  org.omg.CORBA.portable.OutputStream $out = 
  _request ("getCard", true);
18  $out.write_string (card);
19  $in = _invoke ($out);
20  com.asw.corba.ex2.BillingServiceModule.Card $result = 
  com.asw.corba.ex2.BillingServiceModule.CardHelper.read ($in);
21  return $result;
22  } catch (org.omg.CORBA.portable.ApplicationException $ex) {
23  $in = $ex.getInputStream ();
24  String _id = $ex.getId ();
25  throw new org.omg.CORBA.MARSHAL (_id);
26  } catch (org.omg.CORBA.portable.RemarshalException $rm) {
27  return getCard (card  );
28  } finally {
29  _releaseReply ($in);
30  }
31  } // getCard
32
33  public com.asw.corba.ex2.BillingServiceModule.Card addNewCard 
  (String personName, String card)
34  {
35  org.omg.CORBA.portable.InputStream $in = null;
36  try {
37  org.omg.CORBA.portable.OutputStream $out = 
  _request ("addNewCard", true);
38  $out.write_string (personName);
39  $out.write_string (card);
40  $in = _invoke ($out);
41  com.asw.corba.ex2.BillingServiceModule.Card $result = 
  com.asw.corba.ex2.BillingServiceModule.CardHelper.read ($in);
42  return $result;
43  } catch (org.omg.CORBA.portable.ApplicationException $ex) {
44  $in = $ex.getInputStream ();
45  String _id = $ex.getId ();
46  throw new org.omg.CORBA.MARSHAL (_id);
47  } catch (org.omg.CORBA.portable.RemarshalException $rm) {
48  return addNewCard (personName, card  );
49  } finally {
50  _releaseReply ($in);
51  }
52  } // addNewCard
53
54  // Type-specific CORBA::Object operations
55  private static String[]__ids = {
56  "IDL:BillingServiceModule/BillingService:1.0"};
57  public String[] _ids ()
58  {
59  return (String[])__ids.clone ();
60  }
61
62  private void readObject (java.io.ObjectInputStream s) 
  throws java.io.IOException
63  {
64  String str = s.readUTF ();
65  String[] args = null;
66  java.util.Properties props = null;
67  org.omg.CORBA.Object obj = org.omg.CORBA.ORB.init 
  (args, props).string_to_object (str);
68  org.omg.CORBA.portable.Delegate delegate = 
  ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate ();
69  _set_delegate (delegate);
70  }
71
72  private void writeObject (java.io.ObjectOutputStream s) 
  throws java.io.IOException
73  {
74  String[] args = null;
75  java.util.Properties props = null;
76  String str = org.omg.CORBA.ORB.init (args, props).object_to_string
  (this);
77  s.writeUTF (str);
78  }
79  } // class _BillingServiceStub

И последний файл BillingServicePOA.java (пример 8.7) содержит класс, выполняющий всю техническую работу по диспетчеризации сообщений клиента, - этот класс будет являться предком для нашего серверного класса, в котором мы переопределим методы, выполняющие содержательные операции. Класс BillingServicePOA наследует от org.omg.PortableServer.Servant и реализует CORBA -интерфейс (InvokeHandler) и интерфейс BillingServiceOperations.Интерфейс InvokeHandler объявляет метод invoke, который является реализацией BillingServicePOA.

1  package com.asw.corba.ex2.BillingServiceModule;
2
3 /**
4 * com/asw/corba/ex2/BillingServiceModule/BillingServicePOA.java .
5 * Generated by the IDL-to-Java compiler (portable), version "3.1" 
6 * from com/asw/corba/ex2/BillingService.idl 
7 * 16 Июль 2006 г. 15:01:11 MSD
8 */ 
9
10  // определение класса BillingServicePOA
11  public abstract class BillingServicePOA extends 
  org.omg.PortableServer.Servant
12  implements
  com.asw.corba.ex2.BillingServiceModule.BillingServiceOperations, 
  org.omg.CORBA.portable.InvokeHandler
13  {
14  // Constructors
15  private static java.util.Hashtable _methods = new java.util.Hashtable ();
16  static
17  {
18  _methods.put ("getCard", new java.lang.Integer (0));
19  _methods.put ("addNewCard", new java.lang.Integer (1));
20  }
21
22  public org.omg.CORBA.portable.OutputStream _invoke (String $method,
23  org.omg.CORBA.portable.InputStream in,
24  org.omg.CORBA.portable.ResponseHandler $rh)
25  {
26  org.omg.CORBA.portable.OutputStream out = null;
27  java.lang.Integer __method = (java.lang.Integer)_methods.get ($method);
28  if (__method == null)
29  throw new org.omg.CORBA.BAD_OPERATION (0,
  org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
30
31  switch __method.intValue ())
32  {
33  case 0:   // BillingServiceModule/BillingService/getCard
34  {
35  String card = in.read_string ();
36  com.asw.corba.ex2.BillingServiceModule.Card $result = null;
37  $result = this.getCard (card);
38  out = $rh.createReply();
39  com.asw.corba.ex2.BillingServiceModule.CardHelper.write (out, $result);
40  break;
41  }
42
43  case 1:   // BillingServiceModule/BillingService/addNewCard
44  {
45  String personName = in.read_string ();
46  String card = in.read_string ();
47  com.asw.corba.ex2.BillingServiceModule.Card $result = null;
48  $result = this.addNewCard (personName, card);
49  out = $rh.createReply();
50  com.asw.corba.ex2.BillingServiceModule.CardHelper.write (out, $result);
51  break;
52  }
53
54  default:
55  throw new org.omg.CORBA.BAD_OPERATION 
  (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
56  }
57  return out;
58  } // _invoke
59
60  // Type-specific CORBA::Object operations
61  private static String[] __ids = 
  {"IDL:BillingServiceModule/BillingService:1.0"};
62
63  public String[] _all_interfaces 
  (org.omg.PortableServer.POA poa, byte[] objectId)
64  {
65  return (String[]) __ids.clone ();
66  }
67
68  public BillingService _this()
69  {
70  return BillingServiceHelper.narrow(super._this_object());
71  }
72
73  public BillingService _this(org.omg.CORBA.ORB orb)
74  {
75  return BillingServiceHelper.narrow(super._this_object(orb));
76  }
77
78  } // class BillingServicePOA

Теперь перейдем к рассмотрению интерфейса Card.В файле Card.java (пример 8.8) определен интерфейс Card, наследующий от созданного idlj интерфейса CardOperations (пример 8.9) и двух интерфейсов - они являются определенными в CORBA типами, от которых должны наследовать все CORBA -совместимые объекты, - org.omg.CORBA.Object и org.omg.CORBA.portable.IDLEntity.

1  package com.asw.corba.ex2.BillingServiceModule;
2 
3
4 /**
5 * com/asw/corba/ex2/BillingServiceModule/Card.java .
6 * Generated by the IDL-to-Java compiler (portable), version "3.1"
7 * from com/asw/corba/ex2/BillingService.idl
8 * 16 Июль 2006 г. 15:01:11 MSD
9 */
10
11  public interface Card extends CardOperations,
12  org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity
13  {
14  } // interface Card

CardOperations, ни от кого не наследуя, объявляет три метода, изначально определенные в IDL.

1  package com.asw.corba.ex2.BillingServiceModule;
2 
3
4 /**
5 * com/asw/corba/ex2/BillingServiceModule/CardOperations.java . 
6 * Generated by the IDL-to-Java compiler (portable), version "3.1" 
7 * from com/asw/corba/ex2/BillingService.idl
8 * 16 Июль 2006 г. 15:01:11 MSD
9 */
10
11  // определение CORBA-совместимого сервиса
12  public interface CardOperations
13  {
14  void addMoney (double money);
15  void subMoney (double money);
16  double getBalance ();
17  } // interface CardOperations

Файлы CardHelper.java (пример 8.10) и CardHolder.java (пример 8.11) содержат вспомогательные классы.

1  package com.asw.corba.ex2.BillingServiceModule;
2
3
4 /**
5 *  com/asw/corba/ex2/BillingServiceModule/CardHelper.java .
6 *  Generated by the IDL-to-Java compiler (portable), version "3.1"
7 *  from com/asw/corba/ex2/BillingService.idl
8 *  16 Июля 2006 г. 15:01:11 MSD
9 */
10
11  // определение класса CardHelper
12  abstract public class CardHelper
13  {
14  private static String _id = "IDL:BillingServiceModule/Card:1.0";
15
16  public static void insert (org.omg.CORBA.Any a, 
  com.asw.corba.ex2.BillingServiceModule.Card that)
17  {
18  org.omg.CORBA.portable.OutputStream out = a.create_output_stream();
19  a.type (type ());
20  write (out, that);
21  a.read_value (out.create_input_stream (), type ());
22  }
23
24  public static com.asw.corba.ex2.BillingServiceModule.Card extract 
  (org.omg.CORBA.Any a)
25  {
26  return read (a.create_input_stream ());
27  }
28
29  private static org.omg.CORBA.TypeCode __typeCode = null;
30  synchronized public static org.omg.CORBA.TypeCode type ()
31  {
32  if (__typeCode == null)
33  {
34  __typeCode = org.omg.CORBA.ORB.init ().create_interface_tc
  (com.asw.corba.ex2.BillingServiceModule.CardHelper.id (), 
   "Card");
35  }
36  return  __typeCode;
37  }
38
39  public static String id ()
40  {
41  return _id;
42  }
43
44  public static com.asw.corba.ex2.BillingServiceModule.Card read 
    (org.omg.CORBA.portable.InputStream istream)
45  {
46  return narrow (istream.read_Object (_CardStub.class));
47  }
48
49  public static void write (org.omg.CORBA.portable.OutputStream ostream, 
    com.asw.corba.ex2.BillingServiceModule.Card value)
50  {
51  ostream.write_Object ((org.omg.CORBA.Object) value);
52  }
53
54  public static com.asw.corba.ex2.BillingServiceModule.Card 
    narrow (org.omg.CORBA.Object obj)
55  {
56  if (obj == null)
57  return null;
58  else if (obj instanceof com.asw.corba.ex2.BillingServiceModule.Card)
59  return (com.asw.corba.ex2.BillingServiceModule.Card)obj;
60  else if (!obj._is_a (id ()))
61  throw new org.omg.CORBA.BAD_PARAM ();
62  else
63  {
64  org.omg.CORBA.portable.Delegate delegate = 
    ((org.omg.CORBA.portable.ObjectImpl)obj)._get_delegate ();
65  com.asw.corba.ex2.BillingServiceModule._CardStub stub = 
    new com.asw.corba.ex2.BillingServiceModule._CardStub ();
66  stub._set_delegate(delegate);
67  return stub;
68  }
69  }
70  }
1  package com.asw.corba.ex2.BillingServiceModule;
2 
3 /**
4 *  com/asw/corba/ex2/BillingServiceModule/CardHolder.java .
5 * Generated by the IDL-to-Java compiler (portable), version "3.1"
6 *  from com/asw/corba/ex2/BillingService.idl
7 *  16 Июль 2006 г. 15:01:11 MSD
8 */
9
10  // определение класса CardHolder
11  public final class CardHolder implements org.omg.CORBA. 
  portable.Streamable
12  {
13  public com.asw.corba.ex2.BillingServiceModule.Card value = null;
14
15  public CardHolder ()
16  {
17  }
18
19  public CardHolder (com.asw.corba.ex2.BillingServiceModule.Card 
  initialValue)
20  {
21  value = initialValue;
22  }
23
24  public void _read (org.omg.CORBA.portable.InputStream i)
25  {
26  value = com.asw.corba.ex2.BillingServiceModule.CardHelper.read (i);
27  }
28
29  public void _write (org.omg.CORBA.portable.OutputStream o)
30  {
31  com.asw.corba.ex2.BillingServiceModule.CardHelper.write (o, value);
32  } 
33
34  public org.omg.CORBA.TypeCode _type ()
35  {
36  return com.asw.corba.ex2.BillingServiceModule.CardHelper.type ();
37  }
38  }

Файл _CardStub.java (пример 8.12) содержит клиентскую заглушку. Класс CardStub наследует от org.omg.CORBA.portable.ObjectImpl и реализует интерфейс Card.При вызове клиентом методов этого класса происходит упаковка вызова (и параметров) и их передача по сети серверному классу.

1  package com.asw.corba.ex2.BillingServiceModule;
2
3 /**
4 * com/asw/corba/ex2/BillingServiceModule/_CardStub.java .
5 * Generated by the IDL-to-Java compiler (portable), version "3.1"
6 * from com/asw/corba/ex2/BillingService.idl
7 * 16 Июль 2006 г. 15:01:11 MSD
8 */
9
10    // определение класса _CardStub
11  public class _CardStub extends org.omg.CORBA.portable.ObjectImpl 
  implements com.asw.corba.ex2.BillingServiceModule.Card
12  {
13  public void addMoney (double money)
14  {
15  org.omg.CORBA.portable.InputStream $in = null;
16  try {
17  org.omg.CORBA.portable.OutputStream $out = 
    _request ("addMoney", true);
18  $out.write_double (money);
19  $in = _invoke ($out);
20  return;
21  } catch (org.omg.CORBA.portable.ApplicationException $ex) {
22  $in = $ex.getInputStream ();
23  String _id = $ex.getId ();
24  throw new org.omg.CORBA.MARSHAL (_id);
25  } catch (org.omg.CORBA.portable.RemarshalException $rm) {
26  addMoney (money  );
27  } finally {
28  _releaseReply ($in);
29  }
30  } // addMoney
31
32  public void subMoney (double money)
33  {
34  org.omg.CORBA.portable.InputStream $in = null;
35  try {
36  org.omg.CORBA.portable.OutputStream $out = 
    _request ("subMoney", true);
37  $out.write_double (money);
38  $in = _invoke ($out);
39  return;
40  } catch (org.omg.CORBA.portable.ApplicationException $ex) {
41  $in = $ex.getInputStream ();
42  String _id = $ex.getId ();
43  throw new org.omg.CORBA.MARSHAL (_id);
44  } catch (org.omg.CORBA.portable.RemarshalException $rm) {
45  subMoney (money  );
46  } finally {
47  _releaseReply ($in);
48  }
49  } // subMoney
50
51  public double getBalance ()
52  {
53  org.omg.CORBA.portable.InputStream $in = null;
54  try {
55  org.omg.CORBA.portable.OutputStream $out = 
  _request ("getBalance", true);
56  $in = _invoke ($out);
57  double $result = $in.read_double ();
58  return $result;
59  } catch (org.omg.CORBA.portable.ApplicationException $ex) {
60  $in = $ex.getInputStream ();
61  String _id = $ex.getId ();
62  throw new org.omg.CORBA.MARSHAL (_id);
63  } catch (org.omg.CORBA.portable.RemarshalException $rm) {
64  return getBalance (  );
65  } finally {
66  _releaseReply ($in);
67  }
68  } // getBalance
69
70  // Type-specific CORBA::Object operations
71  private static String[] __ids =
  {"IDL:BillingServiceModule/Card:1.0"};
72
73  public String[] __ids ()
74  {
75  return (String[]) __ids.clone ();
76  }
77
78  private void readObject (java.io.ObjectInputStream s) 
    throws java.io.IOException
79  {
80  String str = s.readUTF ();
81  String[] args = null;
82  java.util.Properties props = null;
83  org.omg.CORBA.Object obj = 
    org.omg.CORBA.ORB.init (args, props).string_to_object (str);
84  org.omg.CORBA.portable.Delegate delegate = 
    ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate ();
85  _set_delegate (delegate);
86  }
87
88  private void writeObject (java.io.ObjectOutputStream s) 
  throws java.io.IOException
89  {
90  String[] args = null;
91  java.util.Properties props = null;
92  String str = org.omg.CORBA.ORB.init (args, props).object_to_string
  (this);
93  s.writeUTF (str);
94  }
95  } // class _CardStub

И, наконец, файл CardPOA.java (пример 8.13) содержит класс, выполняющий всю рутинную работу по диспетчеризации сообщений клиента, - этот класс будет являться предком для нашего серверного класса, в котором мы переопределим нужные методы. Класс CardPOA наследует от org.omg.PortableServer.Servant и реализует CORBA -интерфейс InvokeHandler и интерфейс CardOperations.

1  package com.asw.corba.ex2.BillingServiceModule;
2
3 /**
4 * com/asw/corba/ex2/BillingServiceModule/CardPOA.java .
5 * Generated by the IDL-to-Java compiler (portable), version "3.1"
6 * from com/asw/corba/ex2/BillingService.idl
7 * 16 Июль 2006 г. 15:01:11 MSD
8 */ 
9
10  // определение класса CardPOA
11  public abstract class CardPOA extends org.omg.PortableServer.Servant
12  implements com.asw.corba.ex2.BillingServiceModule.CardOperations, 
    org.omg.CORBA.portable.InvokeHandler
13  {
14  // Constructors
15  private static java.util.Hashtable _methods = 
    new java.util.Hashtable ();
16  static
17  {
18  _methods.put ("addMoney", new java.lang.Integer (0));
19  _methods.put ("subMoney", new java.lang.Integer (1));
20  _methods.put ("getBalance", new java.lang.Integer (2));
21  }
22
23  public org.omg.CORBA.portable.OutputStream _invoke (String $method,
24  org.omg.CORBA.portable.InputStream in,
25  org.omg.CORBA.portable.ResponseHandler $rh)
26  {
27  org.omg.CORBA.portable.OutputStream out = null;
28  java.lang.Integer __method = (java.lang.Integer)_methods.get 
  ($method);
29  if (__method == null)
30  throw new org.omg.CORBA.BAD_OPERATION 
    (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
31
32  switch __method.intValue ())
33  {
34  case 0:   // BillingServiceModule/Card/addMoney
35  {
36  double money = in.read_double ();
37  this.addMoney (money);
38  out = $rh.createReply();
39  break;
40  }
41
42  case 1:   // BillingServiceModule/Card/subMoney
43  {
44  double money = in.read_double ();
45  this.subMoney (money);
46  out = $rh.createReply();
47  break;
48  }
49
50  case 2:   // BillingServiceModule/Card/getBalance
51  {
52  double $result = (double)0;
53  $result = this.getBalance ();
54  out = $rh.createReply();
55  out.write_double ($result);
56  break;
57  }
58
59  default:
60  throw new org.omg.CORBA.BAD_OPERATION 
    (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
61  }
62  return out;
63  } // _invoke
64
65  // Type-specific CORBA::Object operations
66  private static String[] __ids = 
    {"IDL:BillingServiceModule/Card:1.0"};
67
68  public String[] _all_interfaces 
    (org.omg.PortableServer.POA poa, byte[] objectId)
69  {
70  return (String[])__ids.clone ();
71  }
72
73  public Card _this()
74  {
75  return CardHelper.narrow(super._this_object());
76  }
77
78  public Card _this(org.omg.CORBA.ORB orb)
79  {
80  return CardHelper.narrow(super._this_object(orb));
81  }
82
83  } // class CardPOA

Файлы 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  }

Класс 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  }

И наконец, класс 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  }

Первое, что делает это класс, - создает ссылку на 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  }

В строке 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

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

(рис 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
Вернуться к учебному плану