Прохожу курс "Построение распределенных систем на Java" в третьей лекции где описывается TCPServer вылетает эта ошибка
"Connection cannot be resolved to a type" Java version 1.7.0_05 |
Использование Java RMI
Реализация удаленного интерфейса
Следующим этапом является определение реализации удаленного объекта. В нашем случае класс реализации удаленного объекта имеет то же имя, что и удаленный интерфейс, но заканчивается на Impl.
Класс UnicastRemoteObject (пакет java.rmi.server ) представляет базовые функциональные возможности, которые необходимы удаленным объектам для обслуживания удаленных запросов.
Конструкторы и методы класса UnicastRemoteObject возбуждают контролируемое исключение RemoteException,поэтому подклассы класса UnicastRemoteObject должны определять конструкторы, которые также возбуждают исключение RemoteException.
Конструктор класса UnicastRemoteObject экспортирует объект, чтобы сделать его доступным для приема удаленных вызовов. Экспорт объекта дает возможность удаленному объекту ожидать соединений с клиентами на анонимном порте (т.е. порте, выбираемом компьютером, на котором выполняется удаленный объект). Это дает возможность объекту осуществлять однонаправленное взаимодействие (взаимодействие "точка-точка" между двумя объектами посредством вызовов методов) с использованием стандартных соединений через сокеты. Классам удаленных объектов не нужно расширять этот класс, если эти классы применяют статический метод exportObject класса UnicastRemoteObject для экспорта удаленных объектов. Предполагается, что клиенты RMI должны осуществлять соединение на порте 1099 при попытке найти удаленный объект в реестре RMI. Перегруженный конструктор для класса UnicastRemoteObject дает возможность задавать дополнительную информацию, такую как номер порта для экспорта удаленного объекта. Для этого необходимо определить URL, который клиент может использовать для получения удаленной ссылки на объект. Эта ссылка применяется для вызова методов удаленного объекта. URL обычно имеет форму
rmi://хост:порт/ИмяУдаленногоОбъекта,
где хост представляет собой имя компьютера, который выполняет сервер реестра ( rmiregistry ) для удаленных объектов (он также является компьютером, на котором выполняется удаленный объект), порт представляет собой номер порта, на котором выполняется сервер реестра на хост-компьютере, а ИмяУдаленногоОбъекта - имя, которое клиент будет предоставлять при попытках обнаружить удаленный объект в реестре. Утилита rmi-registry обслуживает реестр удаленных объектов и является составной частью J2SE. Номер порта реестра RMI по умолчанию - 1099.
Для связывания удаленного объекта с реестром используются методы bind или rebind.Метод rebind гарантирует, что если объект уже был зарегистрирован под заданным именем, новый удаленный объект заменит ранее зарегистрированный объект. Это может быть важно, если регистрируется новая версия существующего удаленного объекта.
Класс BillingServiceImpl (пример 5.2) представляет собой удаленный объект, который реализует удаленный интерфейс BillingService.Клиент взаимодействует с объектом класса BillingServiceImpl,вызывая методы addNewCard, addMoney, subMoney, getCardBalance интерфейса BillingService для обработки информации по пластиковым картам. Класс BillingServiceImpl хранит сведения о картах в хэш-таблице (Hashtable),содержащей баланс пластиковой карты с именем посетителя (personName) и номером пластиковой карты ( card ), где номер карты является ключом таблицы.
1 // BillingServicelmpl.java 2 // BillingServiceImpl реализует удаленный интерфейс BillingService для 3 // предоставления удаленного объекта BillingService 4 package com.asw.rmi.ex1; 5 6 // Набор базовых пакетов Java 7 import java.rmi.*; 8 import java.util.*; 9 import java.rmi.server.*; 10 11 public class BillingServiceImpl extends UnicastRemoteObject 12 implements BillingService { 13 14 private Hashtable hash; // хэш-таблица для хранения карт 15 // инициализация сервера 16 public BillingServiceImpl() throws RemoteException{ 17 super(); 18 hash = new Hashtable(); 19 } 20 21 // реализация метода addNewCard интерфейса BillingService 22 public void addNewCard(String personName, String card) 23 throws RemoteException { 24 25 hash.put(card, new Double(0.0)); 26 } 27 28 // реализация метода addMoney интерфейса BillingService 29 public void addMoney(String card, double money) throws RemoteException { 30 Double d = (Double)hash.get(card); 31 32 if (d!=null) hash.put(card,new Double(d.doubleValue()+money)); 33 else throw new NotExistsCardOperation(); 34 } 35 36 // реализация метода subMoney интерфейса BillingService 37 public void subMoney(String card, double money) throws RemoteException { 38 Double d = (Double)hash.get(card); 39 40 if (d!=null) hash.put(card,new Double(d.doubleValue()-money)); 41 else throw new NotExistsCardOperation(); 42 } 43 44 // реализация метода getCardBalance интерфейса BillingService 45 public double getCardBalance(String card) throws RemoteException { 46 Double d = (Double)hash.get(card); 47 if (d!=null) return d.doubleValue(); 48 else throw new NotExistsCardOperation(); 49 }; 50 51 // запуск удаленного объекта BillingService 52 public static void main (String[] args) throws Exception { 53 System.out.println("Initializing BillingService..."); 54 55 // создание удаленного объекта 56 BillingService service = new BillingServiceImpl(); 57 58 //задание имени удаленного объекта 59 String serviceName = "rmi://localhost/BillingService"; 60 // регистрация удаленного объекта BillingService в реестре rmiregistry 61 Naming.rebind(serviceName, service); 62 } 63 64 }Листинг 5.2. Класс BillingServiceImpl реализует удаленный интерфейс BillingService
Класс BillingServiceImpl реализует методы addNewCard (строки 22-26), addMoney (строки 29-34), subMoney (строки 37-42), getCardBalance (строки 45-49) интерфейса BillingService,чтобы отвечать на удаленные запросы.
Метод main (строки 52-62) создает удаленный объект BillingServiceImpl.Когда конструктор выполняется, он экспортирует удаленный объект, чтобы прослушивать удаленные запросы. В строке 59 определяется URL, который клиент может применить для получения удаленной ссылки на объект для вызова методов удаленного объекта.
В этой программе URL удаленного объекта имеет вид rmi://localhost/BillingService. Из этого следует, что реестр RMI выполняется на машине localhost (т.е. на локальном компьютере), а для обнаружения клиентом сервиса нужно использовать имя BillingService.Имя localhost является синонимом IP -адреса 127.0.0.1 ( loopback ).
В строке 61 вызывается статический метод rebind класса Naming (пакет java.rmi) для связывания удаленного объекта service класса BillingServiceImpl в реестре RMI с URL rmi://localhost/BillingService.
Класс NotExistsCardOperation (пример 5.3) расширяет класс RemoteException.
1 // NotExistsCardOperation.java 2 package com.asw.rmi.ex1; 3 4 // Набор базовых пакетов Java 5 import java.rmi.RemoteException; 6 7 public class NotExistsCardOperation extends RemoteException { 8 9 }Листинг 5.3. Класс NotExistsCardOperation реализует обработку исключений
Далее мы определяем клиентское приложение, которое будет обрабатывать запросы к пластиковым картам и пересылать их серверу. Для работы клиентского приложения необходимо знать URL вызываемого им удаленного объекта. Статический метод lookup класса Naming применяется для получения объектной ссылки на удаленный объект с заданным URL. Метод lookup осуществляет соединение с реестром RMI и возвращает удаленную ссылку на удаленный объект. Клиент может использовать эту удаленную ссылку, если она обращается к локальному объекту, выполняющемуся на той же виртуальной машине. Эта удаленная ссылка обращается к объекту-заглушке на клиенте. Заглушки дают возможность клиентам вызывать методы удаленного объекта. Объекты-заглушки принимают удаленные вызовы метода и передают эти вызовы RMI, который выполняет сетевые соединения, позволяющие клиентам взаимодействовать с удаленным объектом. Уровень RMI отвечает за сетевые соединения с удаленными объектами, поэтому обращения к удаленным объектам являются прозрачными для пользователя. RMI обслуживает соединение с удаленным объектом, передачу параметров и возврат значений.
Класс BillingClient (пример 5.4) является клиентским приложением, которое вызывает удаленные методы addNewCard, addMoney и getCardBa-lance интерфейса BillingService для работы с пластиковыми картами посетителей через RMI. В нашем примере мы не реализуем реальную работу касс столовых с пластиковыми картами. Для иллюстрации определения и работы клиентского приложения нам достаточно произвести несколько операций с несколькими картами, используя удаленные методы удаленного объекта. В данном случае клиент в цикле заносит денежные средства на три пластиковые карты и в конце печатает результирующий баланс по этим пластиковым картам. При первом проходе цикла в случае отсутствия карт с заданными номерами клиент их создает.
1 // BillingClient.java 2 // BillingClient использует удаленный объект BillingService для 3 // работы с информацией на пластиковых картах 4 package com.asw.rmi.ex1; 5 6 // Набор базовых пакетов Java 7 import java.rmi.*; 8 9 public class BillingClient { 10 // выполнение BillingClient 11 public static void main(String[] args) throws Exception] 12 // создание строки, содержащей URL удаленного объекта 13 String objectName = "rmi://"+args[0]+"/BillingService"; 14 System.out.println("Starting...\n"); 15 // соединение с реестром RMI и получение удаленной ссылки 16 // на удаленный объект 17 BillingService bs = (BillingService)Naming.lookup(objectName); 18 System.out.println("done"); 19 20 // начисление денежных средств на пластиковые карты 21 for (int i = 0; i < 10000; i++) { 22 try { 23 bs.addMoney("1", 1); 24 } catch (RemoteException e) { 25 bs.addNewCard("Piter", "1"); 26 } 27 28 try { 29 bs.addMoney("2", 1); 30 } catch (RemoteException e) { 31 bs.addNewCard("Stefan", "2"); 32 } 33 34 try { 35 bs.addMoney("3", 1); 36 } catch (RemoteException e) { 37 bs.addNewCard("Nataly", "3"); 38 } 39 } 40 // печать текущего баланса обработанных карт 41 System.out.println("1:"+bs.getCardBalance("1")); 42 System.out.println("2:"+bs.getCardBalance("2")); 43 System.out.println("3:"+bs.getCardBalance("3")); 44 } 45 }Листинг 5.4. Клиентское приложение BillingClient для удаленного объекта BillingService
Метод main (строки 11-44) принимает в качестве параметра имя компьютера, на котором выполняется удаленный объект BillingService.В строке 13 создается строка objectName,которая содержит URL для нашего удаленного объекта. В строке 17 вызывается метод lookup класса Naming для получения удаленной ссылки на удаленный объект BillingService с заданным URL. В строках 21-38 производится добавление денежных средств на карты, а в строках 41-43 - печать текущего баланса этих карт.