Java RMI ======== Tworzenie i udostępnianie zdalnych obiektów przejściowych oraz aktywowalnych Slajdy do wykładu ----------------- Slajdy w formacie PDF w układzie `1 sl./str. `_, `2 sl./str. `_, `3 sl./str. `_, `4 sl./str. `_, `6 sl./str. `_. Zadania laboratoryjne --------------------- .. contents:: :depth: 1 :local: :backlinks: none Zadanie 1: licznik ++++++++++++++++++ #. Zaimplementować i przetestować zdalny licznik, czyli obiekt udostępniający wartość całkowitą poprzez operacje ``getNext``, ``getPrev`` i ``getCurr``, zgodnie z poniższym interfejsem:: import java.rmi.*; public interface Count extends Remote { int getNext() throws RemoteException; int getPrev() throws RemoteException; int getCurr() throws RemoteException; } #. "Spowolnić" operacje dostępu i sprowokować ich podzielność poprzez uśpienie wątku na kilka sekund i odpowiednie zdekomponowanie operacji zwiększania/zmniejszania z wykorzystaniem dodatkowej zmiennej lokalnej, np.:: public int getNext() throws RemoteException { int v = value + 1; try { Thread.sleep(5000); } catch(Exception e){}; value = v; return value; } #. Sprawdzić poprawność działania licznika poprzez uruchomienie kilku współbieżnie działających procesów/wątków. #. Zdefiniować (i przetestować) operacje dostępu do obiektu-licznika jako `synchronized`, np.:: public synchronized int getNext() throws RemoteException { int v = value + 1; try { Thread.sleep(5000); } catch(Exception e){}; value = v; return value; } #. Zdefniować własny rejestr po stronie serwera (zrezygnować z ``rmiregistry``), np.:: Registry r = LocateRegistry.createRegistry(6000); r.rebind(name, c1); **Uwagi** * Konieczne jest zdefiniowanie pliku polityki bezpieczeństwa, np.:: grant { permission java.security.AllPermission; }; * Plik polityki bezpieczeństwa musi zostać podany przy uruchomieniu maszyny wirtualnej, np. w przypadku pliku o nazwie ``policy`` byłoby to:: java -Djava.security.policy=policy Server * Jeśli ``rmiregistry`` uruchomione jest na innym porcie, po stronie klienta konieczne jest wsypecyfikowanie tego portu w URL'u z nazwą, np. ``"//localhost:6000/Counter"``. * Jeśli ``rmiregistry`` uruchomione jest w innym katalogu niż katalog zawierający pliki klas (z bajtkodem), to dla lokalizacji klas istotna jest własność `codebase`, którą należałoby zdefiniować przy uruchamianiu serwera. Zależnie od sposobu udostępniania i systemu operacyjnego byłoby to np.:: -Djava.rmi.server.codebase=file:/home/inf29582/java/rmi/ -Djava.rmi.server.codebase=http://sirius.cs.put.poznan.pl/~inf29582/java/rmi Zadanie 2: bufor 1-elementowy +++++++++++++++++++++++++++++ #. Zaimplementować i przetestować zdalny bufor jednoelementowy z odpowiednią synchronizacją dostępu w celu przekazywania danych (buforowania na raz jednej jednostki) od dostawcy (producenta) do odbiorcy (konsumenta). Jako typ elementu przyjąć wybrany interfejs, np. ``IItem``: .. include:: RMI\Buffer_1-item\IItem.java :literal: W praktyce oznacza, że przekazywany pomiędzy dostawcą a odbiorcą może być dowolny obiekt klasy, implementującej ten interfejs, np.: .. include:: RMI\Buffer_1-item\Item.java :literal: a) Bufor w wersji *pull* Odbiorca pobiera dane z bufora z własnej inicjatywy. Interfejs zdalnego bufora 1-elementowego: .. include:: RMI\Buffer_1-item\IBuffer.java :literal: Implementacja zdalnego bufora 1-elementowego: .. include:: RMI\Buffer_1-item\Buffer.java :literal: b) Bufor w wersji *push* Współdzielony bufor po otrzymaniu jednostki przekazuje ją do odbiorcy — wstawia do jego lokalnego bufora poprzez wywołanie zwrotne. Interfejs: .. include:: RMI\Buffer_1-item\IBufferCallBack.java :literal: Implementacja: .. include:: RMI\Buffer_1-item\BufferCallBack.java :literal: Przykład odbiorcy, współpracującego z buforem typu *push*: .. include:: RMI\Buffer_1-item\ConsumerCallBack.java :literal: