Sie sind auf Seite 1von 13

Invocarea la distan a metodelor

n mod normal un sistem software bazat pe RMI const din dou programe: un program server i un program client. Programul server creeaz aa numitele obiecte aflate la distan, asigur faptul c referinele ctre aceste obiecte sunt accesibile i ateapt clienii care invoc metode ale obiectelor aflate la distan. Programul client obine o referin la unul din obiectele aflate la distan de pe server i invoc metode ale acelui obiect. O aplicaie care folosete obiecte distribuite trebuie s realizeze urmtoarele aciuni: !ocalizarea obiectului aflat la distan " pot fi folosite diferite mecanisme pentru a se obine referine la obiecte aflate la distan. #e e$emplu: o aplicaie poate %nregistra obiectele aflate la distan utiliz&nd facilitatea simpl de localizare pus la dispoziie de RMI, alt aplicaie poate returna referine la obiecte aflate la distan ca i rezultat al unui alt apel la distan' (omunicarea cu obiectele aflate la distan " detaliile comunicrii %ntre obiectele aflate la distan sunt tratate la nivelul infrastructurii RMI. Pentru programator invocarea unei metode ce aparine unui obiect aflat la distan este similar cu invocarea unei metode )ava obinuite. ncrcarea claselor care sunt transmise " RMI ofer mecanisme prin care se poate transmite definiia unei clase sau datele corespunztoare unui obiect. n *ig. +., sunt ilustrate canalele de comunicare care e$ist %n cazul unei aplicaii care folosete RMI registr- pentru a localiza referine la obiecte aflate la distan. .erverul comunic cu RMI registr- pentru a asocia un nume cu un obiect aflat la distan /gzduit de server0. (lientul comunic cu RMI registr- pentru a obine o referin ctre un obiect aflat la distan pe baza unui nume. #up ce a obinut o referin la un obiect aflat la distan clientul poate s invoce metode ale acelui obiect. n plus %n figur mai apar dou servere 1eb, aceste servere sunt folosite pentru %ncrcarea claselor pentru obiectele trimise de la client la server, respectiv de la server la client.

(a orice alte aplicaii )ava i aplicaiile RMI sunt create din clase i interfee. Interfeele declar metode. (lasele implementeaz metode declarate de interfee i eventual alte metode. Obiectele care conin metode ce pot fi invocate din maini virtuale )ava diferite sunt denumite obiecte la distan. 2n obiect devine obiect la distan dac:

implementeaz o interfaa la distan, o interfa care e$tinde interfaa Remote' toate metodele declarate de interfa, declar e$cepia de tipul java.rmi.RemoteException %n clauza throws. RMI trateaz diferit obiectele la distan atunci c&nd sunt transmise %ntre maini virtuale diferite fa de obiectele )ava normale. n loc de a se transmite o copie a obiectului se transmite un stub. 2n stub acioneaz ca i un proxy pentru obiectul aflat la distan. 3tunci c&nd o metod a unui stub este invocat, apelul este transmis ctre obiectul aflat la distan. 2n stub permite invocarea doar a metodelor care au fost declarate %ntr o interfa derivat din interfaa Remote. Pentru crearea unei aplicaii distribuite utiliz&nd RMI trebuie urmrii urmtorii pai: proiectarea i implementarea componentelor distribuite ale aplicaiei: o definirea interfeelor la distan " aceste interfee definesc metodele care pot fi invocate la distan' o implementarea obiectelor la distan " obiectele la distan trebuie s implementeze una sau mai multe interfee la distan' o implementarea clienilor " aplicaii care invoc metode ale obiectelor la distan' compilarea codului surs " compilarea codului se realizeaz cu a4utorul compilatorului 4avac /%naintea versiunii 5.6 a platformei )ava era necesar un pas suplimentar pentru invocarea utilitarului rmic, acest lucru nu mai este necesar %n prezent0' publicarea claselor pe reea " de obicei publicarea claselor se realizeaz prin intermediul serverelor 1eb' pornirea aplicaiei " presupune pornirea utilitarului RMI remote ob4ect registr-, pornirea serverului i a clientului. . presupunem c de pe o ma7in )ava dorim s comandm e$ecutarea unui cod pe o alt ma7in. Putem presupune c acest cod constituie o metod a unei clase' metoda urmeaz a fi e$ecutat de un obiect de tipul clasei, obiect aflat pe a doua ma7in. 3tunci pe prima ma7in trebuie s avem informa8ii despre acest obiect, numit obiect (aflat) la distan, pentru a putea s invocm prin el metoda respectiv. *olosind modelul (lient .erver, trebuie fcute urmtoarele presupuneri: clientul trebuie s cunoasc o referin8 la obiectul la distan8' invocarea este fcut de client, dar realizat efectiv de server prin intermediul obiectului, care este 9gata s primeasc9 cererea' clientul 7i serverul trebuie s fie conecta8i, pentru a permite serverului s primeasc informa8ii despre metoda ce trebuie invocat 7i argumentele ce trebuie folosite la invocare' av&nd aceste informa8ii, serverul poate comanda obiectului s invoce metoda pentru argumentele date /primite0. Ce trebuie s cunoasc clientul despre obiectul aflat la distan : 2n minim %l constituie numele 7i signatura metodelor ce urmeaz a fi invocate /av&nd deci %ncredere c obiectul de pe server respect contractul stabilit la scrierea clasei a crei instan8iere este0 7i c&mpurile ce sunt adresate. n acest scop, structura cea mai adecvat este o interfa8 care s cuprind aceste informa8ii.

Ce trebuie s cuprind clasa de pe server a crei instan este obiectul : Rspunsul este clar: clasa trebuie s fie o implementare /direct sau indirect0 a interfe8ei folosite de client. Invocarea la distan8 poate fi realizat cu a4utorul soc;et urilor %n modul urmtor: - clientul implementeaz interfa8a' ac8iunea fiecrei metode const %n plasarea %n flu$ul de ie7ire a numelui metodei 7i a argumentelor 7i citirea din flu$ul de intrare a eventualului rezultat %ntors' - serverul define7te o clas care implementeaz interfa8a 7i creaz un obiect de tipul acestei clase' apoi cite7te din flu$ul de intrare un set nume<metod = argumente, prin intermediul obiectului invoc metoda cu argumentele respective 7i plaseaz %n flu$ul de ie7ire eventualul rezultat %ntors. Exemplul 1. (lasa cu care lucrm con8ine un c&mp 7i dou metode: pune /care incrementeaz valoarea c&mpului cu valoarea primit ca argument0 7i curent /care %ntoarce valoarea curent a c&mpului0. Putem g&ndi aceste ac8iuni ca urmrind eviden8a unui cont, ini8ial egal cu zero. (lientul actualizeaz contul prin depuneri>retrageri 7i poate cere valoarea sumei din cont. .f&r7itul activit8ii clientului are loc atunci c&nd el actualizeaz contul cu valoarea 6. 3t&t clientul c&t 7i serverul vor folosi interfa8a Interf ce anun8 metodele pune 7i curent' implementrile metodelor vor urma ac8iunile descrise mai sus. (lientul 7i serverul vor fi conecta8i printr un soc;et. (lientul trimite %n mod repetat serverului fie mesa4ul "pune" urmat de suma cu care actualizeaz contul, fie mesa4ul "curent" /caz %n care a7teapt s i soseasc o valoare0. .erverul prime7te %n mod repetat c&te un mesa4 de la client. #ac acesta este "pune", atunci mai cite7te o valoare din flu$ul de intrare 7i o adaug contului curent' %n caz contrar %ntoarce valoarea contului curent. Pe ma7ina gazd pentru client se afl interfa8a Interf :
public interface Interf { void pune(int i); int curent(); }

7i clasele ClientSocket 7i Client:


// unitatea de compilare ClientSocket.java import java.io.*; import java.net.*; public cla ClientSocket implement Interf { Socket c ; !ata"utputStream o ; !ataInputStream i ; ClientSocket() t#ro$ I"%&ception { c ' ne$ Socket("local#o t"()*+,); o ' ne$ !ata"utputStream(c .-et"utputStream()); i ' ne$ !ataInputStream(c .-etInputStream()); } public void pune(int i) { tr. { o .$rite/01("pune"); o .$riteInt(i); } catc#(I"%&ception e) { } } public int curent() { int k ' ,,,,;

tr. { o .$rite/01("curent"); k ' i .readInt(); } catc#(I"%&ception e) { } return k;

public void terminare() t#ro$ I"%&ception { o .clo e(); i .clo e(); c .clo e(); } } // unitatea de compilare Client.java public cla Client { public tatic void main(Strin-23 ir) t#ro$ %&ception { int val; ClientSocket CS ' ne$ ClientSocket(); for ( ; ; ) { val ' (int) I".read(); if (val''4) break; CS.pune(val); } I".$riteln("5aloarea curenta ' " 6 CS.curent()); CS.pune(4); CS.terminare(); } }

Pe ma7ina gazd pentru server se afl clasele Cla a /care implementeaz implicit interfa8a Interf0 7i Server:
// unitatea de compilare Cla a.java cla Cla a { private int val; Cla a(int i) { val ' i;} void pune(int i) { val 6' i;} int curent() { return val; } } // unitatea de compilare Server.java import java.io.*; import java.net.*; cla Server { public tatic void main(Strin-23 ir) t#ro$ %&ception { ServerSocket ' ne$ ServerSocket()*+,); Socket c ' .accept(); Cla a "b ' ne$ Cla a(4); !ata"utputStream o ' ne$ !ata"utputStream(c .-et"utputStream()); !ataInputStream i ' ne$ !ataInputStream(c .-etInputStream()); Strin- metoda; int inc ' 4; do { metoda ' i .read/01(); if ( metoda.e7ual ("pune") ) { inc ' i .readInt(); if (inc''4) continue; "b.pune(inc); I".$riteln("Clientul a pu "6inc6 ". Suma din cont e te "6"b.curent()); } el e if ( metoda.e7ual ("curent") ) o .$riteInt( "b.curent() ); el e {

I".$riteln("8etoda ine&i tenta9"); S. tem.e&it(4);

} }

} $#ile (inc 9' 4); o .clo e(); i .clo e(); c .clo e();

.clo e();

bservaii: %n clasa Cla a apare c&mpul val declarat cu private, ce nu apare /bine%n8eles0 %n Interf' s a folosit mecanismul de comunicare prin intermediul soc;et urilor' %n metoda principal a clasei Server s a prevzut un mecanism de terminare a ac8iunii sale /7i anume atunci c&nd se cere s se incrementeze cu 4 valoarea curent val a obiectului "b0 numai pentru a verifica programul' %n mod normal serverul %7i continu ac8iunea.

RMI
Invocarea la distan8 a metodelor este un model larg folosit %n programarea concurent. )ava preia acest model 7i %l e$tinde la programarea distribuit. 3m vzut c aceast invocare la distan8 poate fi realizat 9manual9 cu a4utorul soc;et urilor %n modul urmtor: clientul implementeaz interfa8a' ac8iunea fiecrei metode const %n punerea %n flu$ul de ie7ire a numelui metodei 7i a argumentelor 7i citirea din flu$ul de intrare a eventualului rezultat %ntors' serverul define7te o clas care implementeaz interfa8a 7i creaz un obiect de tipul acestei clase' apoi cite7te din flu$ul de intrare un set nume metod = parametri, prin intermediul obiectului invoc metoda cu parametrii respectivi 7i plaseaz %n flu$ul de ie7ire eventualul rezultat %ntors. !odelul R!" /Remote !ethod "nvocation0 urmre#te ca invocarea la distan a unei metode s apar $n cod sub o form asemntoare invocrii locale. !a baz st tot utilizarea soc;et urilor, dar acest lucru devine transparent pentru utilizator, datorit nivelului superior de abstractizare. Ideea de baz este simpl: serverul creeaz un obiect 7i %l %nscrie %ntr un registru' clientul acceseaz acel registru, regse7te obiectul 7i invoc prin intermediul su metode ale clasei a crei instan8 este obiectul. *acilit8ile )ava pentru invocarea la distan8 apar %n pac?etul java.rmi. 2n re%istru de nume pune la dispozi8ie facilit8i de stocare 7i regsire a referin8elor la obiectele /aflate0 la distan8. 2n astfel de registru ia na7tere de e$emplu ca rezultat al e$ecutrii comenzii rmire-i tr., ce are una dintre urmtoarele forme:
:rmire-i tr. :rmire-i tr. port

Registrul de nume furnizeaz un serviciu simplu de nume, care pune %n coresponden8 o referin8 a obiectului la distan8 cu numele obiectului' drept urmare, clientul poate ob8ine un obiect la distan8 cunosc&nd doar numele su. Registrul este pornit pe ma7ina server, dar 7i clientul trebuie s aib acces la el. (a orice instrument bazat pe @(P>IP, registrul a7teapt cererile la un port. Portul implicit este A6BB.

3ccesarea registrului pentru %nscrierea sau regsirea unui obiect se face prin intermediul metodelor clasei ;amin- din pac?etul java.rmi. n cele ce urmeaz vom nota prin I interfa8a comun /aflat at&t pe server, c&t 7i pe client0, prin C clasa de pe server care o implementeaz, prin "b obiectul de tipul clasei C pus la dispozi8ie de server, iar prin met metoda clasei C care urmeaz a fi invocat de client prin intermediul obiectului "b. Interfa8a I trebuie s e$tind interfa8a <emote din pac?etul java.rmi, iar toate metodele sale trebuie s con8in clauza t#ro$ <emote%&ception prin care se anun8 c poate fi lansat e$cep8ia <emote%&ception. n mod standard, pe server sunt %ntreprinse urmtoarele ac8iuni: clasa C trebuie s e$tind clasa /nica t<emote"bject din pac?etul java.rmi. erver' clasa /nica t<emote"bject furnizeaz elementele necesare /referitoare la invocri, parametri, rezultat %ntors0 pentru referin8e la obiecte, utiliz&nd flu$uri @(P' este creat obiectul "b ce urmez a fi folosit de la distan8' obiectul "b este %nscris %n registrul de nume, de e$emplu prin invocarea metodei statice rebind a clasei ;amin-. !a invocare trebuie s precizm at&t numele sub care dorim s %nscriem obiectul "b, c&t 7i acest obiect. (lientul %ntreprinde urmtoarele ac8iuni: ob8ine o referin8 la obiectul la distan8' aceasta se poate realiza invoc&nd metoda static lookup a clasei ;amin-, cu precizarea numelui sub care a fost %nscris obiectul "b %n registru' folose7te referin8a pentru a invoca metoda met a clasei C. Exemplul 2. Relum e$emplul anterior 7i descriem cum poate RMI s rezolve problema, fr a apela /e$plicit0 la soc;et uri. 2rmtoarea interfa8 trebuie s apar at&t pe client, c&t 7i pe server:
import java.rmi.*; public interface Inter<8I extends Remote { void pune(int i) throws RemoteException; int curent() t#ro$ <emote%&ception; }

&erverul folose7te clasa Server<8I :


import java.rmi.*; import java.rmi.server.*; public cla Server<8I extends UnicastRemoteObject implement Inter<8I { int val; public Server<8I(int i) t#ro$ <emote%&ception { val ' i; } public void pune(int i) t#ro$ <emote%&ception { if (i''4) e&it(4); val 6' i; I".$riteln("Clientul a pu "6i6 ". Suma din cont e te "6val); } public int curent() t#ro$ <emote%&ception { return val; }

public tatic void main(Strin-23 ar- ) t#ro$ Server<8I "b ' ne$ Server<8I(4); Naming.rebind("rmi:///Ob" Ob!; S. tem.out.println("Serverul a pornit"); } }

%&ception {

care implementeaz interfa8a Inter<8I 7i creeaz serverul efectiv. Clientul folose7te clasa Client<8I :
import java.rmi.*; public cla Client<8I { public tatic void main(Strin-23 ir) t#ro$ %&ception { int val; Inter<8I "b ' (Inter<8I) Naming."oo#$p("rmi:///Ob"!; for ( ; ; ) { val ' (int) I".read(); if (val''4) break; "b.pune(val); } I".$riteln("5al. curenta e te = " 6 "b.curent()); } }

care prevede /ca 7i %n e$emplul anterior0 citirea 7i transmiterea de valori nenule ctre server 7i apoi /dup ce a fost transmis serverului valoarea 40 afi7area valorii curente.

bservaii: dac e$ist mai mul8i clien8i, serverul va lansa pentru fiecare un nou fir de e$ecutare. (lien8ii vor folosi acela7i c&mp val al obiectului "b, deci valoarea tiprit ca efect al invocrii metodei curent va 8ine seam 7i de invocrile efectuate de al8i clien8i' cu alte cuvinte, clien8ii folosesc un cont comun' obiectul "b, 7i implicit serverul, vor rm&ne active 7i dup ce clien8ii 7i au %nc?eiat activitatea. 3cest lucru este normal, fiind vorba de un server, care nu 7tie c&nd mai poate aprea un nou client' serverul nu se opre7te dup ce este e$ecutat ultima instruc8iune a metodei principale din Server<8I, deoarece legtura stabilit prin invocarea metodei ;amin-.rebind rm&ne activ /au fost alocate resurse, care nu sunt dezalocate0. Oprirea serverului, care contrazice de fapt no8iunea de server, poate fi realizat prin invocarea metodei ;amin-.unbind sau %n mod for8at /de e$emplu prin S. tem.e&it(4);0' aplica8iile sunt evident mai simple dec&t %n e$emplul precedent, datorit nivelului superior de abstractizare la care lucrm. Pentru e$ecutarea aplica8iei trebuie procedat %n urmtoarea ordine: - desc?idem o fereastr %n care din directorul serverului e$ecutm comanda:
rmire-i tr.

din directorul serverului e$ecutm: din directorul clientului /directoarele clien8ilor0 e$ecutm:

java Server<8I java Client<8I

bservaie. #ac o metod invocat la distan8 are ca parametru un obiect /7i nu un tip primitiv ca %n cazul metodei pune0, atunci clasa de tipul creia este obiectul trebuie s fie serializabil. 3cela7i lucru este valabil pentru situa8ia %n care rezultatul %ntors de metod este un obiect.

Faciliti Java pentru invocarea la distan

public interface <emote

Interfaa Remote 3ceast interfa8 apare %n pac?etul java.rmi 7i este declarat prin:

Rolul su este de a identifica tipurile ale cror metode urmeaz a fi invocate de la distan8 /de pe o ma7in )ava virtual care nu este cea local0. Orice obiect aflat la distan8 trebuie s implementeze o interfa8 I ce e$tinde direct sau indirect interfa8a <emote' numai metodele anun8ate %n I pot fi invocate de la distan8. Clasa UnicastRemoteObject 3ceast clas, aflat %n pac?etul java.rmi. erver, ofer facilit8i pentru referin8e active biunivoce /unicast0' prin intermediul constructorului pot fi create obiecte la distan8, ale cror metode s poat fi invocate folosind flu$uri @(P. 2n obiect la distan8 are ca tip o clas ce e$tinde clasa /nica t<emote"bject.

public cla /nica t<emote"bject protected /nica t<emote"bject() t#ro$ <emote%&ception public tatic <emoteStub e&port"bject(<emote "b)

e$port obiectul la distan8, pentru a l face disponibil s primeasc apeluri, folosind un port anonim.

Clasa Naming

(lasa ;amin- din pac?etul java.rmi ofer metode publice 7i statice pentru accesarea registrului de nume. Parametrul nume din metodele prezentate mai 4os trebuie s fie o adres 2R! de forma:
rmi=//-a>da=port/nume?efectiv unde rmi este numele serviciului, iar -a>da este o adres IP numeric sau simbolic. 3t&t -a>da c&t 7i port pot lipsi, caz %n care este sunt considerate a fi local#o t, respectiv A6BB.

public final cla ;amin- e&tend "bject void rebind(Strin- nume( <emote "b) %nscrie %n registru numele nume, asociindu i obiectul "b 7i anul&nd o eventual

asociere anterioar'
void unbind(Strin- nume) <emote lookup(Strin- nume)

distruge asocierea precedent din registru a lui nume' %ntoarce o referin8 /un stub0 la obiectul la distan8 asociat %n registru lui nume.

Metodele de mai sus pot lansa e$cep8iile 8alformed/<@%&ception, <emote%&ception, ;otAound%&ception 7i Blread.Aound%&ception. O referin8 activ de8inut de client are asociat un timp de arendare, a crui valoare implicit este de A6 minute. @impul de arendare este controlat de proprietatea

sistemului cu numele java.rmi.d-c.lea e5alue. #ac %nainte de e$pirarea acestui timp clientul nu reface legtura, referin8a este considerat 9dep7it9 7i este pus la dispozi8ia colectorului de reziduuri. Pe server, obiectul la distan8 este pus 7i el la dispozi8ia colectorului de reziduuri dac nici un client nu mai de8ine referin8e ctre el 7i dac legtura ctre el %n registru dac este suspendat /prin unbind0. Exemplul 3. Crem ca %n Exemplul ' fiecare client s aib un cont separat. Pe fiecare ma7in client 7i pe server vom plasa urmtoarele interfe8e 7i clase: Client
Inter<8I InterBdauClient

Server
Inter<8I InterBdauServer<8I implement Inter<8I Bdau- implement InterBdauServer

.c?ema folosit este urmtoarea: metoda principal din Server creeaz un obiect "b de tipul Bdau- cu numele "b, cunoscut 7i de clien8i prin intermediul registrului de nume' fiecare client se folose7te referin8a la obiectul Ob pentru a invoca metoda adau- a clasei Bdau-, ca efect primind un obiect de tipul Server<8I' acesta va fi serverul su propriu, pe care %l va folosi la invocarea metodelor pune 7i curent.
// unitatea de compilare Inter<8I.java import java.rmi.*; public interface Inter<8I e&tend <emote { void pune(int i) t#ro$ <emote%&ception; int curent() t#ro$ <emote%&ception; } // unitatea de compilare InterBdau-.java import java.rmi.*; public interface InterBdau- e&tend <emote { Inter<8I adau-() t#ro$ %&ception; }

(lien8ii vor folosi clasa Client:


import java.rmi.*; public cla Client { public tatic void main(Strin-23 ar- ) t#ro$ %&ception { InterBdau- "b ' (InterBdau-) ;amin-.lookup("rmi=///"b"); Inter<8I "b;ou ' "b.adau-(); int val; for( ; ; ) { val'(int)I".read(); if(val''4)break; "b;ou.pune(val); } I".$riteln("5al. curenta e te= " 6 "b;ou.curent() ); } }

.erverul va utiliza clasele Bdau-, Server<8I 7i Server:


// unitatea de compilare Bdau-.java import java.rmi.*; import java.rmi. erver.*; public cla Bdau- e&tend /nica t<emote"bject implement InterBdau- { tatic int contor; Bdau-() t#ro$ <emote%&ception {} public Inter<8I adau-() t#ro$ %&ception { return ne$ Server<8I(4(contor66); } } // unitatea de compilare Server<8I.java import java.rmi.*; import java.rmi. erver.*; public cla Server<8I e&tend /nica t<emote"bject implement Inter<8I { private int val( nr?ordine; public Server<8I(int i(int nr) t#ro$ val ' i; nr?ordine ' nr; } <emote%&ception {

public void pune(int i) { val 6' i; I".$riteln(nr?ordine 6 "Ct= " 6 val); } } public int curent() { return val; }

// unitatea de compilare Server.java import java.rmi.*; public cla Server { public tatic void main(Strin-23 ar- ) t#ro$ %&ception { Bdau- "b ' ne$ Bdau-(); ;amin-.rebind("rmi=///"b"("b); I".$riteln("Serverul Da le-at la re-i trul <8I"); } } Com crea doi clien8i. *ie dir erver, dirclient4 7i dirclientE

directoarele %n care se afl clasele pentru server 7i clien8i. #esc?idem o fereastr %n care, din dir erver, e$ecutm:
dir erver:rmire-i tr. dir erver:java Server<8I

#esc?idem o a doua fereastr %n care, din dir erver, e$ecutm: Pentru fiecare client e$ecutm:

dirclient4:java Client<8I dirclientE:java Client<8I

(onstructorul Bdau- fr parametri 7i a crui ac8iune este nul trebuie totu7i specificat e$plicit, pentru c poate eventual lansa e$cep8ia: <emote%&ception. #e aceast dat fiecare client 9are serverul su9, deci valorile tiprite la invocarea metodei curent se refer numai la incrementrile fcute de el. @rebuie avut %n permanen8 gri4 ca serverul 7i clien8ii s foloseasc numai ceea ce cunosc. 3stfel, dac rezultatul %ntors de metoda adau- din clasa Bdau- ar fi precizat ca fiind de tipul Server<8I 7i nu Inter<8I, s ar semnala o eroare.

Apeluri inverse
3m vzut c )ava, prin mecanismul RMI, ofer posibilitatea ca de pe o ma7in client s invocm o metod metS care s fie e$ecutat de o ma7in server. Pentru aceasta, pe ma7ina server a fost creat un obiect "bS de tipul clasei care include metoda respectiv 7i a fost %ntoars clientului o referin8 la acest obiect la distan8. Prin intermediul acestei referin8e, de pe ma7ina client poate fi invocat metoda metS, care /bine%n8eles0 este e$ecutat pe ma7ina server. n programarea concurent, no8iunea de invocare la distan8 cuprinde 7i un aspect suplimentar: posibilitatea ca ma7ina server s 9%ntoarc un rspuns9, adic s determine e$ecutarea unei metode pe ma7ina client. 3ceast facilitate suplimentar poart numele de apel invers. D$emplul clasic care ilustreaz invocarea la distan8, inclusiv apelurile inverse, %l constituie transmiterea unui document prin fa$: dup recep8ionarea mesa4ului este %ntors un rspuns con8in&nd scurte informa8ii asupra transferul efectuat. )ava ofer 7i facilitatea de a folosi apeluri inverse. Principial, lucrurile decurg analog ca la invocarea la distan8 a unei metode. *ie metC metoda care trebuie invocat pe ma7ina client din cadrul metodei metS. Dste evident necesar ca pe ma7ina client s fie creat un obiect "bC de tipul clasei care include metoda metC, iar ma7ina server s primeasc o referin8 la acest obiect, pentru ca /pe baza acestei referin8e0 s poat invoca metoda metC, ce va fi e$ecutat pe ma7ina client. Implementarea apelurilor inverse va fi mai simpl, deoarece legtura %ntre ma7ini este de4a stabilit. ntr adevr, pentru realizarea apelurilor inverse, trebuie %ntreprinse doar urmtoarele dou ac8iuni: A0 crearea obiectului "bC 7i pregtirea lui pentru a fi e$portat' E0 transmiterea obiectul "bC ma7inii server. Prima ac8iune presupune c "bC este o instan8 a unei clase ce e$tinde interfa8a <emote. Pregtirea sa pentru e$port este realizat prin invocarea urmtoarei metode publice 7i statice a clasei /nica t<emote"bject:
<emoteStub e&port"bject(<emote "bC) t#ro$ <emote%&ception

3 doua ac8iune poate fi realizat simplu, comunic&nd serverului obiectul "bC prin includerea lui ca argument la invocarea unei metode prin intermediul referin8ei la obiectul "bS. .e presupune c obiectul "bC este de tipul unei clase serializabile. Exemplul 4. Revenim la Exemplul '. #orim ca o actualizare a contului /realizat printr o invocarea a metodei pune0 s fie posibil numai dac valoarea contului rm&ne pozitiv. Mai mult, clientul trebuie s tipreasc unul dintre mesa4ele "".F." sau "In uficient", dup cum actualizarea a fost sau nu efectuat. Prezentm modificrile ce intervin fa8 de Exemplul '. Dste adugat interfa8a Inter, at&t pe client c&t 7i pe server' ea anun8 metoda ra pun cu un parametru boolean. (lasa Client, prezent pe client, implementeaz interfe8ele Inter 7i Seriali>able. Metoda ra pun tipre7te unul dintre cele dou mesa4e de mai sus, %n func8ie de valoarea parametrului b.

Interfa8a Inter<8I anun8 %n plus metoda re-i ter cu un parametru de tipul Inter. n metoda principal a clasei Client<8I s au adugat instruc8iunile:
Client c ' ne$ Client(); /nica t<emote"bject.e&port"bject(c); "b.re-i ter(c);

care folosesc e$act tiparul prezentat la descrierea apelurilor inverse. n clasa Sever<8I intervin urmtoarele modificri: este adugat c&mpul ob de tipul Inter' este adugat metoda re-i ter prin care c&mpul ob prime7te o valoare' metoda pune din clasa Server<8I seteaz variabila boolean b prin:
b ' val6i :' 4;

7i realizeaz apelul invers prin: ob.ra pun (b);


// /nitatea de compilare Inter<8I.java import java.rmi.*; public interface Inter<8I e&tend <emote { void pune(int i) t#ro$ <emote%&ception; int curent() t#ro$ <emote%&ception; void re-i ter(Inter ob) t#ro$ <emote%&ception; } // /nitatea de compilare Inter.java import java.rmi.*; public interface Inter e&tend <emote { public void ra pun (boolean b) t#ro$ <emote%&ception; } // /nitatea de compilare Client.java import java.io.*; import java.rmi.*; public cla Client implement Inter( Seriali>able { public void ra pun (boolean b) { if (b) I".$riteln("".F."); el e I".$riteln("In uficient"); } } // /nitatea de compilare Client<8I.java import java.rmi.*; import java.rmi. erver.*; public cla Client<8I { public tatic void main(Strin-23 ir) t#ro$ %&ception { int val; Inter<8I "b ' (Inter<8I) ;amin-.lookup("rmi=///"b"); Client c ' ne$ Client(); /nica t<emote"bject.e&port"bject(c); "b.re-i ter(c); for ( ; ; ) { val ' (int) I".read(); if (val''4) break; "b.pune(val); } I".$riteln("5al.curenta e te = " 6 "b.curent()); S. tem.e&it(4); } } // /nitatea de compilare Server<8I.java import java.rmi.*; import java.rmi. erver.*;

public cla

Server<8I e&tend /nica t<emote"bject implement Inter<8I { private int val; Inter ob; public Server<8I(int i) t#ro$ <emote%&ception { val ' i; } public void pune(int i) t#ro$ <emote%&ception { boolean b; b ' val6i :' 4; if (b) val 6' i; I".$riteln("val = " 6val); ob.ra pun (b); } public int curent() { return val; } public void re-i ter(Inter ob) { t#i .ob ' ob; } public tatic void main(Strin-23 ir) t#ro$ Server<8I "b ' ne$ Server<8I(4); ;amin-.rebind("rmi=///"b"("b); } %&ception {

Das könnte Ihnen auch gefallen