Tuesday, December 4, 2007

RMI – Remote Method Invocation

Prin RMI se poate apela cod de la distanta – metode ale obiectelor aflate pe un server pot fi apelate de clienti.

Stubs si Skeletons
Clientul cand doreste sa apeleze o metoda de la distanta, o apeleaza in mod oarecum transparent (apelul se face asupra unui obiect de tip stub). Stubul este un obiect ce se afla pe client. Rolul stubului este de a incapsula informatii ca parametrii metodei care se va apela pe server precum obiectul si metodele ce se vor apela. Pachetul trimis de client ajunge la server. Aici se afla un alt obiect, skeleton caruia ii revine rolul sa decodifice parametrii, sa apeleze metoda invocata de client, sa retina valoare returnata/sau exceptia si sa trimita inapoi un pachet cu rezultatul.

Exemplu de aplicatie care foloseste RMI
Serverul va creea un obiect Hello si clientul apeleaza o metoda a obiectului creeat pe server. Pentru a sti ce metoda a obiectului sa poate apela, clientul trebuie sa aiba la dispozitie o interfata cu aceste metode, interfata ce este implementata de obiectul de pe server. Aceasta interfata se afla atat pe server cat si pe client. Aceasta este :

import java.rmi.Remote;
import java.rmi.RemoteException;


public interface HelloInterface extends Remote {
public String say() throws RemoteException;
}


Dupa cum se vede , aceasta interfata extinde interfata Remote – ca de altfel toate interfetele care sunt implementate de obiecte aflate la distanta, iar metodele interfetelor pot arunca RemoteException.

Clasa Hello implementeaza interfata HelloInterface:

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class Hello extends UnicastRemoteObject implements HelloInterface {

private static final long serialVersionUID = 7896795898928782846L;
private String message;

public Hello (String msg) throws RemoteException {
message = msg;
}

public String say() throws RemoteException {
return message;
}
}


Singura metoda disponibila apelabila de catre client este say(); Hello extinde clasa UnicastRemotObject, care extinde la randul ei RemoteObject, astfel ca Hello e o clasa accesibila de la distanta.



Clasele care vor fi instantiate pe parte de server extinzand UnicastRemoteObject, extind implicit RemoteServer. RMI returneaza clientului o referinta la obiectul de pe server si nu obiectul propriuzis -> e necesar un mecanism de localizare/inregistrare a unui obiect existent pe server. Pe server inregistrarea obiectului se face cu bind(), iar clientul obtine o referinta a obiectului de pe server cu metoda lookup().

Pornire serviciului de inregistrare se face executand start rmregistry (rmiregistry & pe linux), cu portul implicit 1099.
rmic ne ajuta la generarea claselor skeleton si stub (Hello_Skel.class, Hello_Stub.class) .

Clientul:

import java.rmi.Naming;

public class Client {
public static void main (String[] argv) {
try {
HelloInterface hello = (HelloInterface) Naming.lookup ("//localhost/Hello");
System.out.println (hello.say());
} catch (Exception e) {
e.printStackTrace();
System.out.println ("HelloClient exception: " + e);
}
}

}


Serverul:

import java.rmi.Naming;

public class Server {
public static void main (String[] argv) {
try {
Naming.rebind ("Hello", new Hello ("Hello, world!"));
System.out.println ("Hello Server is ready.");
} catch (Exception e) {
e.printStackTrace();
System.out.println ("Hello Server failed: " + e);
}
}
}

No comments: