„Cześć! I jeszcze jeden szczęśliwy temat: RMI. RMI to skrót od Remote Method Invocation . Innymi słowy, RMI to mechanizm, który umożliwia obiektowi z jednej maszyny Java wywoływanie metod na obiektach z innej maszyny Java , nawet jeśli znajdują się one na różnych komputerów w różnych krajach lub po różnych stronach globu”.

RMI-1

„Wow! To brzmi niesamowicie”.

„Tak. Ale postaram się dać ci tylko ogólny zarys. Dzięki temu, jeśli kopiesz zbyt głęboko, możesz się pomylić z niuansami tego, jak to działa”.

„Ale jeśli nie popadasz w skrajności, RMI jest nie tylko bardzo prosty, ale także znacznie upraszcza życie programisty. Za co składamy mu nasze najgłębsze wyrazy szacunku”.

„Chcemy więc, aby jeden obiekt w programie Java wywoływał metodę na obiekcie, który znajduje się w innym programie Java. Niezależnie od tego, gdzie te programy są uruchomione”.

„Rozważmy najprostszy przykład: gdy oba programy są uruchomione na tym samym komputerze.  Aby umożliwić interakcję programów przez Internet, należy skonfigurować uprawnienia maszyny JVM , ale tym się dzisiaj nie zajmiemy”.

„W Javie można zdalnie wywoływać tylko metody interfejsów, a nie klasy”.

„Więc mamy dwa programy. Jak mogą wywoływać swoje metody?”

„Rozważmy sytuację , w której jeden program zawiera obiekt, a drugi chce wywołać metody na tym obiekcie. Nazwijmy pierwszy program serwerem, a drugi klientem ”.

„Najpierw podam przykładowy kod, a potem go przeanalizujemy”.

„Więc co zrobi nasz program?”

„Hmm. Cóż, dla uproszczenia program będzie miał jedną metodę, która odwraca przekazany do niego ciąg znaków”.

"Wystarczająco proste."

„Dobrze, więc zaczynamy:”

„Po pierwsze, potrzebujemy interfejsu, który spełni nasze wymagania:”

Interfejs do komunikacji między programami
interface Reverse extends Remote
{
 public String reverse(String str) throws RemoteException;
}

„Utworzyłem interfejs Reverse i dodałem do niego interfejs zdalnego znacznika, a także wyjątek RemoteException. Podczas wywoływania metody mogą wystąpić nieoczekiwane błędy. Jeśli tak się stanie, zostanie zgłoszony ten wyjątek”.

„Teraz musimy napisać klasę serwera, która implementuje ten interfejs:”

Klasa dla serwera
class ReverseImpl implements Reverse
{
 public String reverse(String str) throws RemoteException
 {
  return new StringBuffer(str).reverse().toString();
 }
}

„Rozumiem. Odwracamy łańcuch w tej metodzie”.

"Tak."

„Teraz musimy uczynić ten obiekt wywoływalnym z innego programu. Oto jak to zrobić:”

Udostępnianie obiektów
public static final String UNIC_BINDING_NAME = "server.reverse";

public static void main(String[] args) throws Exception
{
 // Create an object to be accessible remotely.
 final ReverseImpl service = new ReverseImpl();

 // Create a registry of shared objects.
 final Registry registry = LocateRegistry.createRegistry(2099);
 // Create a stub for receiving remote calls.
 Remote stub = UnicastRemoteObject.exportObject(service, 0);
 // Register the stub in the registry.
 registry.bind(UNIC_BINDING_NAME, stub);

 // Put the main thread to sleep, or else the program will exit.
 Thread.sleep(Integer.MAX_VALUE);
}

„Wyjaśnię to linijka po linijce”.

W wierszu 1 przechowujemy unikalną nazwę (którą sami sobie wymyśliliśmy) dla naszego zdalnego obiektu (obiektu, który jest dostępny zdalnie) w zmiennej UNIC_BINDING_NAME.  Jeśli program udostępnia kilka obiektów, każdy musi mieć swoją własną unikalną nazwę. unikalna nazwa obiektu to „server.reverse”.

" W linii 6 tworzymy obiekt ReverseImpl , który będzie dostępny zdalnie. Jego metody zostaną wywołane."

" W linii 9 tworzymy specjalny obiekt zwany rejestrem. Musimy go użyć do zarejestrowania udostępnianych nam obiektów. JVM będzie z nimi później współpracować. 2099 to port (niepowtarzalny numer, którego inny program może użyć, aby uzyskać dostęp do naszych rejestr obiektów).”

„Innymi słowy, aby uzyskać dostęp do obiektu, musisz znać unikalny numer rejestru obiektów (port) i unikalną nazwę obiektu oraz mieć ten sam interfejs, co ten zaimplementowany przez obiekt zdalny”.

„Rozumiem. Coś w stylu: zadzwoń (potrzebujesz numeru) i zapytaj o Billa (nazwa obiektu)?”

"Tak. A teraz kontynuujmy."

W linii 11  tworzymy kod pośredniczący. Kod pośredniczący to specjalny obiekt, który otrzymuje informacje o zdalnym wywołaniu, rozpakowuje je, deserializuje argumenty metody i wywołuje wymaganą metodę. Następnie serializuje wynik lub wyjątek, jeśli taki wystąpił i odsyła wszystko z powrotem do dzwoniącego”.

— Rozumiem. Prawie. Powiedziałeś, że „deserializuje argumenty metody”. Czy to oznacza, że ​​argumenty zdalnych metod muszą być możliwe do serializacji?

„Tak. Jak inaczej można by je przesłać przez sieć? Owszem, są wyjątki, np. obiekty, które są przekazywane przez referencję, ale nie będziemy dziś o nich mówić”.

„Ujmiemy to w ten sposób: nie możesz przekazywać obiektów, których nie można serializować, ale jeśli naprawdę chcesz, możesz. Ale wiesz, to jest ból”.

"OK."

— W takim razie kontynuujmy.

W linii 13 rejestrujemy kod pośredniczący naszego obiektu pod unikalną nazwą w rejestrze”.

W linii 16 uśpiliśmy główny wątek. Wszystkie zdalne wywołania są przetwarzane w oddzielnych wątkach. Ważne jest, aby program działał. Więc po prostu usypiamy główny wątek tutaj. To wszystko”.

"OK."

„Świetnie, oto przykład klienta:”

Praca z obiektem zdalnym
public static final String UNIC_BINDING_NAME = "server.reverse";

public static void main(String[] args) throws Exception
{
 // Create a registry of shared objects
 final Registry registry = LocateRegistry.createRegistry(2099);

 // Get the object (actually, this is a proxy object)
 Reverse service = (Reverse) registry.lookup(UNIC_BINDING_NAME);

 // Call the remote method
 String result = service.reverse("Home sweet home.");
}

„Wyjaśnię ten kod linia po linii:”

Linia 1 to unikalna nazwa  obiektu zdalnego . Musi być taka sama na kliencie i serwerze”.

" W wierszu 6  tworzymy « rejestr zdalnych obiektów ». Jego port (2099) musi być taki sam jak port rejestru dla aplikacji serwera."

W linii 9 pobieramy obiekt z rejestru. Zwrócony obiekt jest obiektem proxy i jest konwertowany na interfejs. Interfejs musi dziedziczyć interfejs zdalnego znacznika”.

W linii 12. wywołujemy metody interfejsu tak, jakby obiekt został utworzony w ramach tego samego programu. Nie ma żadnej różnicy”.

„Świetnie! Teraz mogę pisać aplikacje rozproszone. Lub gry takie jak Battleship na Androida”.

„Nie waż się, Amigo! System operacyjny Android został zakazany w 27 wieku po trzeciej próbie przejęcia władzy nad światem. Roboty nie mają do niego żadnego dostępu. Nie byłoby sposobu, aby cię od niego odciągnąć Zacząłbyś biegać w kółko i krzyczeć: „Zabij wszystkich ludzi!”

- Hmm. OK. Ale i tak będę musiał zapytać Diego. Nigdy nie wiadomo, może będzie miał coś ciekawego do powiedzenia na ten temat.

- To idź go zapytaj. Dobrze, do jutra.

"Pa, Rishi. Dzięki za interesującą lekcję."