|
Прохожу курс "Построение распределенных систем на Java" в третьей лекции где описывается TCPServer вылетает эта ошибка
"Connection cannot be resolved to a type" Java version 1.7.0_05 |
CORBA. Третий пример. DII и DSI
Рабочий каталог расположен в Practice.
Приложения, рассматриваемые в предыдущих разделах, строились исходя из предположения о том, что интерфейсы объектов заранее известны. Собственно, иначе и быть не могло, поскольку именно эти интерфейсы и описывались на IDL перед началом разработки приложений.
Однако CORBA позволяет строить приложения, оперирующие объектами, интерфейсы которых неизвестны на момент компиляции приложения. Более того, возможно создание объектов, интерфейс которых будет изменяться в процессе их жизни (под интерфейсом мы понимаем совокупность методов объекта, которые может вызывать клиент). Данные возможности активно применяются при решении задач интеграции приложений, когда CORBA выступает в качестве "клея", связующего компоненты, которые выполнены в различных технологиях.
Соответствующие элементы технологии CORBA носят названия Dynamic Invocation Interface (DII) и Dynamic Skeleton Interface (DSI).
С помощью первой технологии ( DII ) клиенты могут формировать динамические вызовы методов объектов - формировать не в момент компиляции, а в процессе работы.
С помощью второй технологии ( DSI ) серверные объекты могут регистрировать в системе новые методы, которые они будут реализовать, или изменять спецификацию старых. Для написания объектов с использованием этих технологий IDL уже не применяется, и многие из задач, которые раньше решались автоматически сгенерированным кодом, при таком подходе придется решать самостоятельно.
В качестве примера, на котором будет проиллюстрировано использование этих технологий, возьмем уже использованный ранее "Первый пример" из данного раздела. Перепишем клиентский класс таким образом, чтобы он формировал динамические вызовы к серверу (т.е. не использовал клиентскую заглушку), а серверный - так, чтобы он сам регистрировал реализуемые им методы в системе (т.е. не использовал автоматически сгенерированный скелетон).
Сами сигнатуры методов серверного объекта оставим без изменений. Соответственно, для реализации этого примера IDL -файл с описанием интерфейсов не нужен.
Класс BillingServiceImpl
Прежде всего, следует отметить, что поскольку теперь невозможно использовать автоматически сгенерированные классы (их попросту нет), серверный класс должен наследовать от DynamicImplementation и перекрывать его метод invoke,который вызывается при любом обращении клиента.
Диспетчеризацию сообщений теперь придется выполнять вручную, соответствующий код реализован в методе invoke.
Итак, серверный класс будет содержать огромный метод invoke,в котором будет определяться то, какой метод сервера хочет вызвать клиент, и будут извлекаться параметры, переданные клиентом. Соответствующие методы, реализующие операции с картами и изменяющие баланс, полностью аналогичны рассмотренным ранее в предыдущем примере.
1 package com.asw.corba.ex3;
2
3 import java.util.*;
4 import org.omg.CORBA.*;
5
6 class BillingServiceImpl extends DynamicImplementation {
7
8 static String[] myIDs = { "IDL:JavaIDL/DSIBillingService:1.0" };
9
10 ORB orb;
11
12 Hashtable hash;
13
14 BillingServiceImpl(ORB orb) {
15 this.orb = orb;
16 hash = new Hashtable();
17 }
18
19 public void invoke(ServerRequest request) {
20 try {
21 System.out.println("DSI: invoke called, op = " + request.op_name());
22 if (request.op_name().equals("addNewCard") == true) {
23 /*String personName, String card*/
24 NVList nvlist = orb.create_list(0);
25 Any any1 = orb.create_any();
26 any1.insert_string("");
27 nvlist.add_value("arg1", any1, ARG_IN.value);
28 Any any2 = orb.create_any();
29 any2.insert_string("");
30 nvlist.add_value("arg2", any2, ARG_IN.value);
31 // pass the NVList to the request to get values
32 request.params(nvlist);
33 addNewCard(nvlist.item(0).value().extract_string(), nvlist.item(1).value().extract_string());
34 TypeCode result_tc = orb.get_primitive_tc(TCKind.tk_void);
35 Any result_any = orb.create_any();
36 result_any.type(result_tc);
37 request.result(result_any);
38 } else if (request.op_name().equals("addMoney") == true) {
39 /*String card, double money*/
40 NVList nvlist = orb.create_list(0);
41 Any any1 = orb.create_any();
42 any1.insert_string("");
43 nvlist.add_value("arg1", any1, ARG_IN.value);
44 Any any2 = orb.create_any();
45 any2.insert_double(0);
46 nvlist.add_value("arg2", any2, ARG_IN.value);
47 // pass the NVList to the request to get values
48 request.params(nvlist);
49 addMoney(nvlist.item(0).value().extract_string(), nvlist.item(1).value().extract_double());
50 TypeCode result_tc = orb.get_primitive_tc(TCKind.tk_void);
51 Any result_any = orb.create_any();
52 result_any.type(result_tc);
53 request.result(result_any);
54 } else if (request.op_name().equals("subMoney") == true) {
55 /*String card, double money*/
56 NVList nvlist = orb.create_list(0);
57 Any any1 = orb.create_any();
58 any1.insert_string("");
59 nvlist.add_value("arg1", any1, ARG_IN.value);
60 Any any2 = orb.create_any();
61 any2.insert_double(0);
62 nvlist.add_value("arg2", any2, ARG_IN.value);
63 // pass the NVList to the request to get values
64 request.params(nvlist);
65 subMoney(nvlist.item(0).value().extract_string(), nvlist.item(1).value().extract_double());
66 TypeCode result_tc = orb.get_primitive_tc(TCKind.tk_void);
67 Any result_any = orb.create_any();
68 result_any.type(result_tc);
69 request.result(result_any);
70 } else if (request.op_name().equals("getCardBalance") == true) {
71 /*String card, double money*/
72 NVList nvlist = orb.create_list(0);
73 Any any1 = orb.create_any();
74 any1.insert_string("");
75 nvlist.add_value("arg1", any1, ARG_IN.value);
76 // pass the NVList to the request to get values
77 request.params(nvlist);
78 double d = getCardBalance(nvlist.item(0).value().extract_string());
79 TypeCode result_tc = orb.get_primitive_tc(TCKind.tk_double);
80 Any result_any = orb.create_any();
81 result_any.insert_double(d);
82 request.result(result_any);
83 }
84 } catch (Exception ex) {
85 ex.printStackTrace();
86 System.out.println("DSIExample: Exception thrown: " + ex);
87 }
88 }
89
90 // implement an _ids method to return repository ID of interface
91 public String[] _ids() {
92 return myIDs;
93 }
94
95 public void addNewCard(String personName, String card) {
96 hash.put(card, new Double(0.0));
97 }
98
99 public void addMoney(String card, double money) {
100 synchronized (hash) {
101 Double d = (Double) hash.get(card);
102 if (d != null)
103 hash.put(card, new Double(d.doubleValue() + money));
104 }
105 }
106
107 public void subMoney(String card, double money) {
108 Double d = (Double) hash.get(card);
109
110 if (d != null)
111 hash.put(card, new Double(d.doubleValue() - money));
112 }
113
114 public double getCardBalance(String card) {
115 Double d = (Double) hash.get(card);
116 if (d != null)
117 return d.doubleValue();
118 else
119 return 0;
120 }
121 }
Листинг
9.1.
Класс BillingServiceImpl
Итак, метод invoke вызывается брокером запросов при вызове любого метода объекта, и его единственным параметром является ServerRequest - объект, содержащий всю необходимую информацию о вызове: имя вызываемого метода, список параметров и их типы. Поэтому в первую очередь проверяется имя вызываемого метода - оно может быть получено с помощью вызова op_name(),примененного к переданному ServerRequest.Далее, поскольку методы, как правило, принимают и возвращают аргументы, необходимо, во-первых, извлечь аргументы, переданные клиентом, а во-вторых, возвратить клиенту результат, если это необходимо.
Для извлечения из ServerRequest значений переданных клиентом аргументов необходимо выполнить следующие действия.
Создать список, в который затем будут считаны значения аргументов:
NVList nvlist = orb.create_list(0);
Заполнить список объектами, в которые будут считаны значения переданных клиентом аргументов. В данном случае список заполняется двумя объектами типа Any (это специальный тип CORBA, совместимый со всеми типами), которым присваиваются некоторые начальные значения (пустые строки) и которые заносятся в список аргументов как принимаемые аргументы (направление передачи параметров - in).
Any any1 = orb.create_any();
any1.insert_string("");
nvlist.add_value("arg1", any1, ARG_IN.value);
Any any2 = orb.create_any();
any2.insert_double(0);
nvlist.add_value("arg2", any2, ARG_IN.value);Затем подготовленный список аргументов передается в ServerRequest и с помощью вызова request.params(nvlist) заполняется значениями, переданными клиентом.
Для того чтобы получить доступ к этим значениям, можно воспользоваться методом extract_<datatype> (например, для получения значения первого переданного аргумента, при условии, что он является строковым, можно воспользоваться вызовом nvlist.item(0).value().extract_string()).Следует обратить внимание, что для получения значения аргумента необходимо явно указывать его тип, вызывая соответствующий метод семейства extract*.
После того как все эти операции проделаны, имя вызываемого метода определено и переданные ему клиентом аргументы получены, серверный класс может их обработать. После обработки, в случае если вызываемый клиентом метод предполагает возврат результата, необходимо его сформировать:
TypeCode result_tc = orb.get_primitive_tc(TCKind.tk_double); Any result_any = orb.create_any(); result_any.insert_double(d); request.result(result_any);
Сначала формируется TypeCode соответствующего типа (в данном случае предполагается, что метод возвращает результат типа double).Затем создается объект для результата (типа Any).Затем в этот объект помещается результат (с помощью одного из методов семейства insert*),после чего объект помещается в ServerRequest для возврата клиенту.
Следует обратить внимание, что даже если метод никакого результата не возвращает (имеет тип возврата void),возврат все равно должен быть сформирован, только в качестве его типа должно быть указано TCKind.tk_void.