Java RMI
HelloWorld
-
Utworzyć plik z interfejsem programu HelloWorld
import java.rmi.Remote; import java.rmi.RemoteException; public interface HelloWorld extends Remote { String getString(String name) throws RemoteException; }
-
Napisać aplikację klienta odwołującego się do zdalnego obiektu implementującego interfejs HelloWorld:
- rejestr, w którym zarejestrowany został zdalny obiekt znajduje się pod adresem wskazanym przez prowadzącego
- program klienta pobiera z rejestru referencję na zdalny obiekt korzystając z metody Naming.lookup(String name);
- program klienta wywołuje zdalną metodę getString jako argument podając tekst pobrany z linii komend przy uruchamianiu programu
- napis zwrócony przez metodę getString należy wypisać na standardowe wyjście
-
skompilować program klienta
javac *.java
-
utworzyć plik client.policy z definicją polityk bezpieczeństwa
grant { permission java.security.AllPermission; };
-
uruchomić program klienta
java -Djava.security.policy=client.policy HelloWorldClient
-
Napisać własną implementację serwera HelloWorld
- przygotować klasę HelloWorldObj rozszerzający klasę UnicastRemoteObject oraz implementujący interfejs HelloWorld
-
przygotować klasę HelloWorldServer, która w metodzie main utworzy instancję klasy HelloWorldObj, a następnie zarejestruje ten obiekt w rejestrze przy użyciu metody:
Naming.rebind("//127.0.0.1:2100/HelloWorld")
- skompilować program
-
uruchomić rejestr RMI
rmiregistry nr_portu
-
uruchomić i przetestować serwer
java -Djava.rmi.server.hostname=127.0.0.1 -Djava.security.policy=server.policy HelloWorldServer
-
Przerobić program serwera tak, aby uruchamiał swój własny rejestr
Registry registry = LocateRegistry.createRegistry(2100); registry.rebind("HelloWorld", obj);
Przekazywanie obiektów przez wartość i przez referencję
- Zaimplementować klasę ArgumentObject zawierającą prywatne pole value typu int oraz metody umożliwiające odczyt i nadpisanie wartości tego pola. Klasa powinna implementować interfejs java.io.Serializable
- Umieścić implementację ArgumentObject w classpath klienta i serwera
- Przerobić implementację HelloWorldObj, tak aby metoda getString przyjmowała jako argument obiekt klasy ArgumentObject, odczytywała wartość zdefiniowanego w tej klasie pola, nadpisywała wartość tego pola i zwracała odczytaną wcześniej wartość w postaci obiektu typu String
- Przerobić program klienta, tak aby tworzył obiekt ArgumentObject i podawał go jako argument wywołania metody getString ze zdalnego obiektu HelloWorldObj; następnie klient powinien wypisać odczytany String oraz aktualną wartość pola value z klasy ArgumentObject
- Sprawdzić rezultat działania programu
-
Przerobić program, tak aby ArgumentObject przekazywany był przez referencję; w tym celu należy:
- zdefiniować interfejs Argument rozszerzający interfejs Remote i umieścić go w classpath serwera i klienta,
- przerobić implementację ArguentObject, tak aby rozszerzał UnicastRemoteObjet oraz implementował interfejs Argument,
- usunąć klasę ArgumentObject z classpath serwera
- Uruchomić program i zaobserwować zmiany w działaniu
RemoteComputation
Zadanie: przygotować program umożliwiający wykonywanie po stronie serwera dowolnych obliczeń zleconych przez klienta:
-
Serwera udostępnia zdalny obiekt implementujący interfejs Compute
public interface Compute { Object runTask(Task task, Args args); }
- Task jest interfejsem reprezentującym zadanie obliczeniowe, posiada metodę run(Args args), która jest wywoływana wewnątrz metody runTask
- Klient dostarcza co najmniej dwie implementacje interfejsu Task, np. wykonujące dodawanie i mnożenie; obie klasy muszą implementować interfejs Serializable
- Klient korzystając z rejestru pobiera referencję na zdalny obiekt Compute i wywołuje metodę runTask podając jako argument jedną z implementacji interfejsu Task; wynik zwrócony przez runTask jest wypisywany na standardowe wyjście
-
Klient dostarcza serwerowi klasy z implementacją Task poprzez http lub system plików, przykładowe wywołanie programu klienta wygląda wówczas następująco:
java -Djava.rmi.server.codebase=file:///path/to/Task/implementation/ -Djava.security.policy=client.policy ComputeClient
Accounts
Zadanie: zaimplementować program do zdalnego wykonywania operacji na kontach bankowych
-
Serwer udostępnia zdalny obiekt umożliwiający pobranie listy kont bankowych
public interface AccountList extends Remote { List
getList() throws RemoteException; } -
Interfejs Account rozszerza interfejs Remote i umożliwia przeprowadzenie podstawowych operacji na koncie
public interface Account extends Remote { public Integer getBalance() throws RemoteException; //pobranie stanu konta public Integer add(Integer amount) throws RemoteException; //dodanie określonej kwoty do stanu konta public Integer withdraw(Integer amount) throws RemoteException; //pobranie określonej kwoty z konta }
- Klient korzystając ze zdalnego obiektu implementującego AccountList pobiera listę zdalnych referencji na obiekty typu Account
- Do wybranego konta klient dopisuje określoną kwotę i sprawdza aktualny stan tego konta
- Sprawdzenie, czy modyfikacja stanu konta zapamiętywana jest między kolejnymi uruchomieniami programu klienta