4. díl - Java RMI - Vysvětlení pojmů a popis tříd

Java Pro pokročilé RMI Java RMI - Vysvětlení pojmů a popis tříd

Unicorn College ONEbit hosting Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci o volání vzdálených metod v Javě jsme si ukázali použití portu 2020. Dnes si vysvětlíme další pojmy a třídy spojené s problematikou RMI.

RMI - Vzdálené volání metod

Zde na obrázku si abstraktně nakreslíme o co vlastně jde. Existují prakticky dvě třídy (příp. projekty, programy) jako u socketu, a to klient a server. Sdílená referenční vrstva provede své napojení přes localhost/LAN/MAN/WA­N. Samozřejmě je nutno znát adresu IPv4, IPv6 nebo URL. Serverová třída si vyrobí instanci (sdílený referenční objekt) a nasdílí jej do sdílené referenční vrstvy (RMI registru). Sdílený referenční objekt musí mít implementované rozhraní java.rmi.Remote. Jakmile jej server nasdílí (zaregistruje) přes RMI registry vzniká tzv. skeleton.

Klientská třída se připojí přes na RMI registry serveru. Pokud disponuje identifikátorem sdíleného referenčního objektu, pak si daný objekt může vytvořit. Tímto vzniká tzv. stub. Tento stub má k dispozici metody definované rozhraním. Transportní vrstva je již řešená přímo JVM bez naší možnosti ovlivňovat ji.

Takto to ovšem funguje v tom nejjednodušším případě. Jak jsme viděli v příkladu č.2, není problém, aby i server měl jak skeleton i stub a to samé i klient. To svým způsobem udělalo z klienta server a ze serveru klienta. Samozřejmě je nutné si uvědomit i bezpečnostní hledisko. Kdokoliv kdo bude znát IP a port, na kterém RMI registry poběží. Velmi snadno získá výpis všech RMI objektů (viz. java.rmi.Namin­g.list(String name)) a může si tedy poté metody zavolat. Možná si na konci seriálu předvedeme nějaké verze zabezpečení rmiregistrů.

Schéma RMI komunikace v Javě

java.rmi.* balíčky(knihovny)

Nejdůležitějšími balíčky tříd pro RMI jsou:

  • java.rmi
  • java.rmi.registry
  • java.rmi.server

RMI jmenná služba (Naming service)

Naming třída (java.rmi.Naming) poskytuje metody pro ukládání a získávání vzdálených objektů (tvorbu stubů/skeletonů) z RMI registrů. Každá metoda Naming třídy bere parametr typu java.lang.String ve formátu URL a v tvaru rmi://host:port/jmenoRMIobjektu.

Části adresy jsou následující:

  • host - IP adresa nebo URL, lokální nebo vzdálených RMI registrů
  • port - Port, na kterém RMI registry běží (defaultně 1099)
  • jmenoRMIobjektu - Jméno sdíleného objektu na serveru. (tzv. identifikátor skeletonu)

Metody máme k dispozici následující:

package java.rmi.server;
public final class Naming {
        public static Remote lookup(String name) throws NotBoundException,MalformedURLException, UnknownHostException, RemoteException;
        public static void bind(String name,Remote obj) throws AlreadyBoundException,MalformedURLException, UnknownHostException, RemoteException;
        public static void rebind(String name,Remote obj) throws MalformedURLException, UnknownHostException, RemoteException;
        public static void unbind(String name) throws NotBoundException,MalformedURLException, UnknownHostException, RemoteException;
        public static String[] list(String name) throws MalformedURLException, UnknownHostException, RemoteException;
}

Jedná se o nejdůležitější aplikační rozhraní RMI ke jmenné službě (Naming service) v RMI registrech. Metody si popišme:

  • lookup(String name) - Vrací referenci na stub objektu (vzdálený objekt). V případě, že vzdálený objekt tohoto jména není na daném počítači registrován, je vyhozena výjimka.
  • bind(String name, Remote obj) - Zaregistruje vzdálený objekt (skeleton) se zadaným jménem a převezme odkaz na objekt, který ji reprezentuje. Parametr obj je tedy instance vzdáleného rozhraní. Pokud již služba tohoto jména existuje, vyhodí výjimku java.rmi.AlreadyBoundException.
  • rebind(String name, Remote obj) - Od metody bind() se liší tím, že pokud již vzdálený objekt tohoto jména existuje, je starší registrace přepsána touto novou.
  • String[] list(String name) - Vrací pole se jmény zaregistrovaných vzdálených objektů.
  • unbind(String name) - Zruší registraci vzdáleného objektu daného jména.

Vzdálené objekty

Třídy používané pro vytvoření vzdálených objektů jsou následující:

UnicastRemoteObject

java.rmi.serve­rUnicastRemote­Object třída se používá pro export vzdálených objektu, pro získávání stubů, které komunikují se vzdáleným objektem. Stub je prakticky zrcadlový obraz objektu skeletonu. Generování stubů je prováděno rmic nástrojem. Existuje celkem 6 způsobů jak exportovat vzdálené objekty (více viz. API).

package java.rmi.server;
public class UnicastRemoteServer extends RemoteServer {
        // Protected konstruktory
        protected UnicastRemoteObject() throws java.rmi.RemoteException;
        protected UnicastRemoteObject(int port) throws java.rmi.RemoteException;
        protected UnicastRemoteObject(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws java.rmi.RemoteException;
        // Veřejné metody
        public Object clone() throws java.lang.CloneNotSupportedException;
        public static void exportObject(java.rmi.Remote obj) throws java.rmi.RemoteException;
        //Deprecated
        public static void exportObject(Remote obj, int port) throws java.rmi.RemoteException;
        public static void exportObject(Remote obj, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws java.rmi.RemoteException;
        public static boolean unexportObject(Remote obj, boolean force) throws java.rmi.RemoteException;
}

RemoteObject

java.rmi.server­.RemoteObject je třída implementující java.lang.Object chování pro vzdálené objekty. RemoteObject reimplementuje klíčové metody z typu Object, konkrétně hashCode(), equals(), a toString().

package java.rmi.server;
public abstract class RemoteObject implements Remote, java.io.Serializable {
        // Protected konstruktory
        protected RemoteObject();
        protected RemoteObject(RemoteRef newref);
        // Protected proměnná třídy
        transient protected RemoteRef >ref;
        // Veřejné metody
        public boolean equals(Object obj);
        public int hashCode();
        public String toString();
        public RemoteRef getRef();
        public static Remote toStub(Remote obj);
}

RemoteServer

java.rmi.server­.RemoteServer je třída, která dědí od RemoteObjekt a prakticky má sloužit a poskytovat podporu metody pro získání informací přes stub z klienta RMI.

package java.rmi.server;
public class RemoteServer extends RemoteObject {
        // Protected konstruktory
        protected RemoteServer();
        protected RemoteServer(RemoteRef newref);
        // Veřejné metody
        public static String getClientHost() throws ServerNotActiveException;
        public static void setLog(java.io.OutputStream out);
        public static java.io.PrintStream getLog();
}

RMI registry služba

Pokud chceme provádět RMI komunikaci, je nutno spustit RMI registry na serveru i na klientovi. Spuštění RMI registrů je nutno provést dříve, než začneme pracovat s RMI. Služba běží standardně na portu 1099, ale port lze při spuštění změnit. Spuštění lze provádět přes příkazový řádek (cmd u Windows), přímo v IDE nebo programově přes JAVA API, např. přes statickou metodu z java.rmi.regis­try.LocateRegis­try.createRegis­try(int port).

Program (služba RMIregistry) se nachází v adresáři "adresář instalace Java\bin\rmire­gistry.exe".

Třída LocateRegistry mám následující rozhraní:

package java.rmi.registry;
public final class LocateRegistry {
        // Veřejné metody
        public static Registry createRegistry(int port) throws RemoteException;
        public static Registry createRegistry(int port,RMIClientSocketFactory csf,RMIServerSocketFactory ssf) throws RemoteException;
        public static Registry getRegistry() throws RemoteException;
        public static Registry getRegistry(int port) throws RemoteException;
        public static Registry getRegistry(String host) throws RemoteException;
        public static Registry getRegistry(String host, int port) throws RemoteException;
        public static Registry getRegistry(String host, int port, RMIClientSocketFactory csf) throws RemoteException;
}

V příští lekci si předeme spuštění exportu a spuštění RMI server/klienta přes příkazový řádek.


 

  Aktivity (2)

Článek pro vás napsal Robert Michalovič
Avatar
viz. linkedin

Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!


 



 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!