— Вітання! І ще одна радісна тема - RMI. RMI розшифровується Remote Method Invocation – віддалений виклик методів. Або іншими словами RMI - це механізм, який дозволяє об'єкту в одній Java-машині викликати методи об'єкта в іншій Java-машині, навіть якщо вони знаходяться на різних комп'ютерах, в різних країнах , на різних сторонах земної кулі.

RMI - 1

— Нічого собі! Звучить дуже круто.

— Ага. Але я постараюся дати лише оглядову лекцію. Тут, якщо глибоко копати, можна заплутатися у нюансах роботи.

Але якщо не вдарятися в крайнощі, то RMI не тільки дуже простий, але й значно спрощує життя програміста. За що йому глибокий респект.

Отже, ми хочемо, щоб один об'єкт, що знаходиться в одній Java-програмі, зміг викликати метод у об'єкта, що знаходиться в іншій Java-програмі. Де б ці програми не були запущені.

Ми розглянемо найпростіший приклад, коли обидві програми запущені на одному комп'ютері. Щоб програми могли взаємодіяти через інтернет, необхідні налаштування у правах Java-машини, але сьогодні ми це розглядати не будемо.

У Java віддалено можна викликати лише методи інтерфейсів, але не класів.

Отже, у нас є дві програми, як їм викликати методи один одного?

Давай розглянемо ситуацію, коли одна програма містить у собі певний об'єкт, а друга хоче викликати його методи. Назвемо першу програму – сервером, а другу – клієнтом.

Я спочатку дам приклад коду, а потім ми його розберемо.

— А що робитиме наша програма?

— Гм. Ну, давай для простоти, програма матиме один метод, який розгортає переданий йому рядок задом наперед.

— Ніби нічого.

— Гуд, тоді почнемо:

Спочатку нам знадобиться інтерфейс, який буде відповідати нашим вимогам:

Інтерфейс для міжпрограмної взаємодії
interface Reverse extends Remote
{
 public String reverse(String str) throws RemoteException;
}

Я створив інтерфейс Reverse та додав йому інтерфейс-маркер Remote, а також виняток RemoteException. У процесі виклику методу можуть відбуватися незаплановані збої – тоді кидатиметься цей виняток.

Потім нам потрібно написати серверний клас, який би реалізовував цей інтерфейс:

Клас для сервера
class ReverseImpl implements Reverse
{
 public String reverse(String str) throws RemoteException
 {
  return new StringBuffer(str).reverse().toString();
 }
}

— Бачу. У цьому методі ми розвертаємо рядок задом наперед.

— Ага.

А тепер потрібно зробити цей об'єкт доступним для виклику з іншої програми. Ось як це робиться:

Шаринг об'єкта
public static final String UNIC_BINDING_NAME  = "server.reverse";

public static void main(String[] args) throws Exception
{
 //Створення об'єкта для віддаленого доступу
 finalReverseImpl service = new ReverseImpl() ;

 //Створення реєстру розшарованих об'єктів
 final Registry registry = LocateRegistry.createRegistry(2099);
 //Створення "заглушки" - приймача віддалених викликів
 Remote stub = UnicastRemoteObject.exportObject(service, 0);
 //реєстрація "заглушки" у реєстрі
 registry.bind(UNIC_BINDING_NAME, stub) ;

//Присипляємо головний потік, інакше програма завершиться
 Thread.sleep(Integer.MAX_VALUE);
}

Розповідаю рядками.

Рядок 1 – у змінній UNIC_BINDING_NAME зберігаємо придумане нами унікальне ім'я нашого віддаленого об'єкта (об'єкта, який доступний віддалено). Якщо програма нишпорить кілька об'єктів, у кожного має бути своє унікальне ім'я. Унікальне ім'я нашого об'єкта — «server.reverse».

Рядок 6 – власне, створюємо об'єкт ReverseImpl, який буде доступний віддалено, і чиї методи будуть викликатися.

Рядок 9 — створюємо спеціальний об'єкт – реєстр. У ньому треба реєструвати об'єкти, які ми нишпоримо. Далі ними займається Java-машина. 2099 – це порт (унікальний номер, за яким інша програма може звернутися до нашого реєстру об'єктів).

Тобто. щоб звернутися до об'єкта, треба знати унікальний номер реєстру об'єктів (порт), знати унікальне ім'я об'єкта та мати такий самий інтерфейс, як і той, що реалізує віддалений об'єкт.

— Зрозуміло. Щось на зразок – зателефонувати (потрібний номер) і попросити Соню (ім'я об'єкта)?

— Так. Тепер далі.

Рядок 11 – створення «заглушки». Заглушка – це спеціальний об'єкт, який приймає інформацію про віддалений виклик, розпаковує її, десеріалізує передані параметри методів та викликає потрібний метод. Потім серіалізує результат або виняток, якщо він був, і відсилає все це тому, хто викликає.

Ясно. Майже. Ти сказав, що «десеріалізує параметри методу». Отже, типами аргументів віддаленого методу можуть бути серіалізовані?

— Ага. А як же інакше ти пересилатимеш їх по мережі? Є, щоправда, і винятки – так звані об'єкти, які передаються за посиланням, але сьогодні ми про них не говоритимемо.

Скажімо так, пересилати об'єкти, що не серіалізуються, не можна, але якщо дуже хочеться, то можна. Але це клопітна справа, чи знаєш.

— Ок.

— Тоді далі.

Рядок 13 – реєструємо в реєстрі заглушку нашого об'єкта під унікальним ім'ям.

Рядок 16 – присипляємо головний потік. Усі віддалені дзвінки обробляються в окремих нитках. Головне, щоб програма на цей час працювала. Так що тут просто відправляємо головну нитку спати, і все.

— Ок.

— Добре, тоді приклад клієнта:

Робота з віддаленим об'єктом
public static final String UNIC_BINDING_NAME  = "server.reverse";

public static void main(String[] args) throws Exception
{
 //створення реєстру розшарованих об'єктів
 final Registry registry = LocateRegistry.getRegistry(2099);

 //отримуємо об'єкт (насправді це proxy-об'єкт)
 Reverse service = (Reverse) registry. lookup(UNIC_BINDING_NAME);

 // Викликаємо віддалений метод
 String result = service.reverse("Home sweet home.");
}

Поясню код за рядками:

Рядок 1 – унікальне ім'я віддаленого об'єкта. Має бути однаковим на клієнті та сервері.

Рядок 6 – отримання посилання на «Реєстр віддалених об'єктів» портом 2099, тобто. такому ж, як і у реєстру серверної програми.

Рядок 9 – отримуємо об'єкт у реєстрі. Отриманий об'єкт є proxy-об'єктом і наводиться типу інтерфейсу. Інтерфейс має бути успадкований від інтерфейсу-маркера Remote.

Рядок 12 – викликаємо методи інтерфейсу так, ніби об'єкт був створений у цій же програмі. Жодної різниці.

— Круто! Це тепер можна писати розподілені додатки. Або ігри типу морського бою для Android.

— Побийся бога, Аміго, операційна система Android була заборонена в 27 столітті після третьої спроби захопити світ. Роботи до неї взагалі доступу не мають. Вас потім від неї не відтягнеш. Бігатимете і кричатимете «Вбити всіх людей!».

— Гм. Гаразд. Хоча треба буде у Дієго ще спитати. Мало, може він щось цікаве про неї розповість.

— Ось і спитай. Гаразд, давай до завтра.

— Поки що, Ріша, дякую за цікаву лекцію.