Прохожу курс "Построение распределенных систем на 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.