RMI - ćwiczenie trzecie

Przykład aplikacji - serwer z modułami typu plug-in

Przykładem ciekawszej aplikacji wykorzystującej RMI oraz dynamiczne ładowanie kodu jest serwer, do którego można dynamicznie ładować pluginy i wykonywać w nich obliczenia na wirtualnej maszynie serwera.

Interfejs Serializable

Do tej pory korzystaliśmy z interfejsu java.rmi.Remote, który umożliwiał wywoływanie zdalnie metod na pewnym obiekcie. Jako argumenty tych metod mogły być używane wszystkie proste typy języka Java (int, String itp.), również ich tablice.

Żeby móc przekazać jako parametr zdalnej metody dowolny obiekt, musi on implementować interfejs java.IO.Serializable. Wówczas obiekt ten jest przekazywany przez wartość, czyli jego wartość jest kopiowana, serializowana (marshalling) i przesyłana przez sieć do obiektu, który implementuje metodę (do serwera).

Jeżeli parametrem zdalnej metody jest nie klasa, lecz interfejs, wówczas wirtualna maszyna, na której znajduje się serwer, nie musi wcześniej znać definicji obiektu, który otrzyma w czasie działania od klienta. Wystarczy tylko, że obiekt ten implementuje znany interfejs. Oznacza to, że pliki .class tego obiektu mogą nie być dostępne w momencie uruchomienia serwera. Żeby klient mógł przekazać obiekt nie znany wcześniej w wirtualnej maszynie serwera, musi on podać lokalizację, skąd można definicję obiektu pobrać. W tym celu ponownie używamy opcji

java.rmi.server.codebase=<URL>

Gdzie <URL> wskazuje na miejsce, z którego można pobrać pliki .class. W szczególności możemy skorzystać z protokołu HTTP aby pobrać pliki poprzez sieć.

Aplikacja

Prosty diagram klas aplikacji.

Potrzebne będą następujące pliki

Wskazówki przy implementacji klienta:

  1. Utworzyć obiekt klasy FibPlugin przekazując do konstruktora numer żądanego wyrazu ciągu Fibonacciego
  2. Znaleźć serwer w rejestrze Naming Service
  3. Wywołać metodę run serwera przekazując utworzony obiekt pluginu jako parametr wywołania

Wskazówki przy implementacji serwera:

  1. Metoda main - podobna jak poprzednio
  2. W metodzie run wywołać metodę compute otrzymanego Pluginu i wynik jej działania zwrócić klientowi

Pliki należy skompilować

Uruchomienie przykładu

Należy przetestować działanie programów na dwóch różnych komputerach.

  1. Na komputerze A działa rmiregistry oraz w osobnym katalogu znajdują się pliki serwera:
  2. Pliki należy umieścić w katalogu ~/../pub/server_classes i ustawić odpowiednie prawa dostępu (chmod a+r *). Wówczas codebase dla serwera będzie mieć postać: http://artemis.wszib.edu.pl/~userA/server_classes
  3. Należy uruchomić serwer na komputerze A poleceniem

    java -Djava.rmi.server.useCodebaseOnly=false -Djava.rmi.server.codebase="https://artemis.wszib.edu.pl:443/~userA/server_classes/" -Djava.security.policy=java.policy AppServer appserver

    gdzie hostA to nazwa domenowa komputera A. Flaga -Djava.rmi.server.useCodebaseOnly=false jest niezbędna ze względu na zmianę wprowadzoną w JDK7, począwszy od JDK7 Update 21. Więcej informacji można znaleść pod następującym adresem.
  4. Na komputerze B muszą być pliki klienta
  5. Plik FibPlugin.class należy umieścić w katalogu ~/../pub/client_classes i ustawić odpowiednie prawa dostępu. Wówczas codebase dla klienta będzie mieć postać http://artemis.wszib.edu.pl/~userB/client_classes
  6. Uruchomić na komputerze B klienta poleceniem

    java -Djava.rmi.server.codebase="https://artemis.wszib.edu.pl:443/~userB/client_classes/" -Djava.security.policy=java.policy AppClient hostA appserver 8

    To polecenie powinno zwrócić ósmy wyraz ciągu Fibonacciego.

Zadanie

Proszę wymyślić i napisać nowy plugin do tego serwera, który będzie wykonywał inną operację niż FibPlugin. Ile plików trzeba zmienić i rekompilować?

Tomasz Gubała, Marek Kasztelnik