Documente Academic
Documente Profesional
Documente Cultură
Facultatea de MatematicaInformatica
Catedra de Informatica
ERNEST SCHEIBER
IN
PROGRAMARE DISTRIBUITA
JAVA
Brasov
Introducere
Obiectivele cursului
Retelele locale, internetul, raspandirea pe o arie geografica a resurselor si a
locatiilor n care se petrec actiuni ce tin de o activitate bine definita sau sunt
urm
arite, gestionate din alte locuri au drept consecinta existenta aplicatiilor
distribuite. Termenul distribuit se refera tocmai la faptul ca componente ale
aplicatiei se afl
a pe calculatoare diferite dar ntre care au loc schimburi de date.
Dac
a p
artile unei aplicatii sau resursele utilizate se gasesc pe calculatoare distincte atunci aplicatia se numeste distribuita.
Intre p
artile sau resursele unei aplicatii distribuite au loc schimburi de date,
ceea ce se face utiliz
and diferite mecanisme la realizarea carora concura sistemul
de calcul, sistemul de operare si limbajul de programare.
Astfel se vorbeste de programare distribuita ca mijloc de realizare a aplicatiilor
distribuite. Pe l
ang
a algortm, structuri de date, limbaj de programare, la realizarea unei aplicatii distribuite intervin comunicatiile: schimbul de date dintre
dou
a componente aflate pe calculatoare diferite.
Punem n evident
a doua modele de aplicatii distribuite:
client-server: Programul server executa cererile clientilor. Amintim urm
atoarele
tehnologii Java pentru realizarea aplicatiilor client-server:
RMI (Remote Method Invocation)
CORBA (Common Object Request Brocker Arhitecture)
JMS (Java Message Service)
2
3
Servlet si JSP (Java Server Pages)
Portlet
dispecer-lucr
ator: Programul dispecer distribuie sarcinile de executat
lucr
atorilor si le coordoneaz
a activitatea.
Obiectivul acestui curs este prezentarea tehnologiilor de programare Java care
permit programarea aplicatiilor client - server:
socluri Java;
apelarea metodelor de la distanta (Remote Method Invocation - RMI );
mesageria Java;
servlet;
Java server Pages - JSP;
Portlet si Portal.
Modelul dispecer-lucr
ator nu face parte din obiectivul cursului.
Competente conferite
Se dezvolt
a deprinderile de programare distribuita.
Structura cursului
1. Modulul 1: Programare distribuita cu comunicatii ce nu folosesc pe protocolul http - HyperText Transfer Protocol.
5
(a) UI 1. Socluri TCP.
(b) UI 2. Datagrame si canale de comunicatii.
(c) UI 3. Reg
asirea obiectelor prin servicii de nume.
(d) UI 4. RMI.
(e) UI 5. Tipare de programare RMI.
(f) UI 6. CORBA.
(g) UI 7. JMS cu comunicatie punctuala.
(h) UI 8. JMS cu comunicatie bazata pe subiect si protocolul AMPQ.
2. Modulul 2: Programare distribuita cu comunicatii bazate pe protocolul
http.
(a) UI 9. Servlet.
(b) UI 10. Facilit
ati de programare cu servlet.
(c) UI 11. JSP.
(d) UI 12. Portlet.
Cerinte preliminare
Intelegerea cursului presupune cunostinte si deprinderi de programare n limbajul Java.
Evaluarea
Evaluarea se termin
a cu un examen care consta din
6
1. Test scris alc
atuit din 10 intrebari, cu calificative (foarte bine (8-10 raspunsuri
corecte), bine (6-7), satisfator (4-5) si nesatisfacator (0-3),) avand rol orientator pentru aprecierea probei practice. Durata testului este de 12-15
minute
2. Proba practic
a consta din prezentarea unui aplicatii din fiecare din tehnologiile studiate (socluri, RMI sau CORBA, mesagerie, servlet, JSP, portlet),
in total sapte aplicatii. Temele aplicatiilor cat si detalii tehnice privind
tehnologia de programare se stabilesc de comun acord cu ndrumatorul laboratorului.
Toate aplicatiile se executa pe calculatoarele unui laborator.
Programele nu contin comentarii explicative. Pentru examen tema si textele
surs
a ale programelor vor fi listate.
Ponderea examenului este 100%.
Materialul de fat
a este orientativ. Documentatia la zi este disponibila prin
intranetul din corpul P al universitatii.
Cuprins
I
Programare distribuit
a f
ar
a HTTP
. . . . .
. . . . .
. . . . .
socluri
.
.
.
.
.
.
.
.
10
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
12
12
13
14
16
.
.
.
.
22
22
27
31
35
3 Reg
asirea obiectelor prin servicii de nume
47
3.1 Java Naming and Directory Interface . . . . . . . . . . . . . . . . . 48
3.1.1 LDAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
4 Remote Method Invocation - RMI
56
4.1 Remote Method Invocation . . . . . . . . . . . . . . . . . . . . . . 57
4.1.1 Crearea unei aplicatii RMI . . . . . . . . . . . . . . . . . . 60
5 Tipare de programare RMI
66
5.1 Fabrica de obiecte . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
5.2 Apelul invers Callback . . . . . . . . . . . . . . . . . . . . . . . . 69
6 CORBA
6.1 CORBA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.1.1 Conexiunea RMI - CORBA . . . . . . . . . . . . . . . . . .
6.1.2 Aplicatie Java prin CORBA . . . . . . . . . . . . . . . . . .
7
73
73
74
79
CUPRINS
.
.
.
.
.
.
.
84
85
86
87
87
87
92
94
97
97
97
98
II
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Programare distribuit
a cu HTTP
9 Servlet
9.1 Marcajul <form> . . . . . . . . .
9.2 Server Web - container de servlet .
9.3 Realizarea unui servlet . . . . . . .
9.3.1 Codul unui servlet . . . . .
9.4 Procesare asincrona n Java Servlet
. .
. .
. .
. .
3.0
10 Facilit
ati de programare cu servlet
10.1 Program client al unui servlet . . . . .
10.2 Servlete nl
antuite . . . . . . . . . . .
10.3 Sesiune de lucru . . . . . . . . . . . .
10.4 Cookie . . . . . . . . . . . . . . . . . .
10.5 Servlet cu conexiune la o baza de date
10.6 Imagini furnizate de servlet . . . . . .
10.7 Filtru . . . . . . . . . . . . . . . . . .
101
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
103
. 104
. 105
. 107
. 109
. 116
.
.
.
.
.
.
.
120
. 120
. 123
. 125
. 126
. 128
. 130
. 132
.
.
.
.
.
.
.
.
.
136
. 136
. 142
. 143
. 144
. 145
. 145
. 149
. 149
. 154
CUPRINS
12 Portlet
12.1 Apache-pluto . . . . . .
12.2 Dezvoltarea unui portlet
12.3 Elemente de programare
12.4 Produse Portal . . . . .
12.4.1 uPortal . . . . .
12.4.2 Jetspeed-2 . . . .
Bibliografie
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
157
159
160
164
173
173
177
179
Modulul I
Programare distribuit
a cu
comunicatii ce nu folosesc
protocolul HTTP
10
11
Introducere
Se prezint
a programarea Java bazate pe
Protocoalele TCP si UDP;
modelul de apel de procedura la distanta (Remote Procedure Call) RMI si
CORBA;
serviciul de mesagerie java.
Unitatea de nv
atare 1
Durata: 3 ore.
Introducere
Limbajul de programare Java ofera facilitati de elaborare ale unor programe
care utilizeaz
a si interactioneaza cu resurse din Internet si din World Wide Web.
In plus limbajul Java permite utilizarea URL-ului (Universal Resource Locator adresa resurselor n Internet), a soclurilor (socket) si a datagramelor.
1.1
1.2. NOT
IUNI DESPRE RET
ELE
13
Autentificare si autorizare
Uzual, pentru a folosi serviciul unui server, un client trebuie sa se nregistreze,
moment n care i se stabilesc drepturile de care dispune la utilizarea serviciilor
oferite de server.
La apelarea serverului, clientul este autentificat - adica i se recunoaste identitatea - si apoi i se asigur
a accesul la servicii n limita drepturilor pe care le
are.
1.2
Calculatoarele ce ruleaz
a n Internet comunica ntre ele folosind protocolul
TCP (Transport Control Protocol) sau UDP (User Datagram Protocol).
Intr-un program Java se utilizeaza clasele pachetului java.net prin intermediul c
arora se acceseaz
a nivelele deservite de protocoalele TCP sau UDP. In
felul acesta se pot realiza comunicatii independente de platforma de calcul. Pentru a alege care clas
a Java s
a fie utilizata trebuie cunoscuta diferenta dintre TCP
si UDP.
TCP C
and dou
a aplicatii comunica ntre ele se stabileste o conexiune prin
intermediul c
areia se schimb
a date. Folosind protocolul TCP, comunicatia garanteaza ca datele trimise dintr-un capat ajung n celalalt capat cu pastrarea ordinii
n care au fost trimise. Acest tip de comunicatie seamana cu o convorbire telefonica. TCP furnizeaz
a un canal sigur de comunicatie ntre aplicatii.
UDP Utilizarea protocolului UDP presupune trimiterea unor pachete de date
numite datagrame de la o aplicatie la alta fara sa se asigure faptul ca data-
14
gramele ajung la destinatie si nici ordinea lor de sosire. Acest tip de comunicatie
seam
an
a cu trimiterea scrisorilor prin posta.
1.3
Soclu TCP
Clasa java.net.Socket
Resursele clasei Socket sunt destinate clientului.
Constructori
public Socket(String host, int port) throws UnknownHostException,
IOException
Creaz
a un soclu conectat la calculatorul cu portul specificat.
public Socket(InetAddress host, int port) throws IOException
Creaz
a un soclu conectat la calculatorul cu portul specificat.
Metode
15
Clasa java.net.ServerSocket
Resursele clasei ServerSocket sunt destinate serverului.
Constructori
public ServerSocket(int port) throws IOException
Creaz
a un soclu la portul specificat. Daca port=0, atunci va fi utilizat
orice port disponibil. Capacitatea sirului (tamponului) de asteptare pentru
cererile de conectare se fizeaza la valoarea implicita 50. Cererile n exces
vor fi refuzate.
public ServerSocket(int port, int lung) throws IOException
In plus fixeaz
a lungimea sirului (tamponului) de asteptare.
public ServerSocket(int port, int lung, InetAddress adr )
throws IOException
Se specific
a n plus calculatorul de la care se asteapta cereri. Daca adr =null,
atunci se accept
a cereri de la orice calculator.
Metode
public Socket accept() throws IOException
Metoda blocheaz
a procesul (firul de executie) apelant pana la sosirea unei
cereri de conectare si creaz
a un soclu client prin care se va desfasura comunicarea cu solicitantul acceptat.
public synchronized void close() throws IOException
nchide soclul de referint
a.
16
1.4
Serverul trebuie s
a satisfaca simultan solicitarile mai multor clienti. Fiecare
client apeleaz
a programul server la acelasi port si n consecinta cererile de conectare
sunt receptionate de acelasi ServerSocket. Serverul receptioneaza apelurile secvential.
La un apel, se creaz
a de partea severului un soclu prin care se va face schimbul
de date cu clientul. Cererile clientilor pot fi satisface concurent/paralel, utilizand
fire de executie ce implementeaza serviciul oferit sau secvential - n cazul unor
servicii de durat
a scurt
a.
Exemplul 1.4.1 Sistem client - server pentru calculul celui mai mare divizor
comun a dou
a numere naturale. Portul obiectului de tip ServerSocket este 7999.
Programul client CmmdcClient se conecteaza la server, transmite serverului
cele dou
a numere naturale si receptioneaza rezultatul pe care apoi l afiseaza.
In esent
a orice program client trebuie sa execute:
1. Deschide/creaz
a un soclu.
2. Deschide/creaz
a fluxuri de date pentru comunicatia cu serverul.
3. Transmite si receptioneaza date potrivit specificului aplicatiei (protocolului
serverului). Acest pas variaza de la un program client la altul.
4. Inchiderea fluxurilor de date.
5. Inchiderea soclului.
1
2
3
5
6
7
8
9
10
11
12
13
14
15
17
18
19
20
21
22
23
import j a v a . i o . ;
import j a v a . n e t . ;
import j a v a . u t i l . S c a n n e r ;
public c l a s s CmmdcClient {
public s t a t i c void main ( S t r i n g [ ] a r g s ) throws IOException {
S t r i n g h o s t= l o c a l h o s t ;
i n t p o r t =7999;
i f ( a r g s . l e n g t h >0)
h o s t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
S o c k e t cmmdcSocket = n u l l ;
DataInputStream i n=n u l l ;
DataOutputStream out=n u l l ;
try {
cmmdcSocket = new S o c k e t ( hos t , p o r t ) ;
out=new DataOutputStream ( cmmdcSocket . getOutputStream ( ) ) ;
i n=new DataInputStream ( cmmdcSocket . g e t I n p u t S t r e a m ( ) ) ;
}
catch ( E x c e p t i o n e ) {
System . e r r . p r i n t l n ( C o n n e c t i o n E r r o r : +e . g e t M e s s a g e ( ) ) ;
1.4. APLICAT
IE CLIENT SERVER CU SOCLURI
System . e x i t ( 1 ) ;
24
25
27
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
long m, n , r ;
System . out . p r i n t l n ( m= ) ;
m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
n=s c a n n e r . nextLong ( ) ;
28
29
30
31
32
try {
out . w r i t e L o n g (m) ;
out . w r i t e L o n g ( n ) ;
r=i n . readLong ( ) ;
System . out . p r i n t l n ( Cmmdc : +r ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( Comunication e r r o r +e . g e t M e s s a g e ( ) ) ;
}
34
35
36
37
38
39
40
41
42
out . c l o s e ( ) ;
in . close ( ) ;
cmmdcSocket . c l o s e ( ) ;
44
45
46
47
48
17
Se presupune c
a programul server ruleaza pe calculatorul local si utilizeaza
portul 7999. Dac
a acesti parametri se modifica - de exemplu serverul ruleaza n
retea pe calculatorul atlantis la portul 8200 - atunci la apelare transmitem acesti
parametri prin java CmmdcClient atlantis 8200
Partea server este alc
atuit
a din mai multe clase:
Clasa MyMServer, independenta de un serviciu anume, preia apelurile clientilor
si lanseaz
a satisfacerea cererii.
1
2
4
5
6
7
8
9
10
11
12
13
14
15
16
18
19
20
21
22
import j a v a . n e t . ;
import j a v a . i o . ;
public c l a s s MyMServer {
public s t a t i c void main ( S t r i n g [ ] a r g s ) throws IOException {
i n t p o r t =7999;
boolean l i s t e n i n g=true ;
ServerSocket s e r v e r S o c k e t = null ;
try {
s e r v e r S o c k e t = new S e r v e r S o c k e t ( p o r t ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( Could not l i s t e n on p o r t : +p o r t ) ;
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 1 ) ;
}
while ( l i s t e n i n g )
// v a r i a n t a 1
new AppThread ( s e r v e r S o c k e t . a c c e p t ( ) ) . s t a r t ( ) ;
// v a r i a n t a 2
/
18
23
S o c k e t s o c k e t=s e r v e r S o c k e t . a c c e p t ( ) ;
try {
DataOutputStream o u t=
new DataOutputStream ( s o c k e t . g e t O u t p u t S t r e a m ( ) ) ;
DataInputStream i n=
new DataInputStream ( s o c k e t . g e t I n p u t S t r e a m ( ) ) ;
l o n g m=0,n=0, r ;
App app=new App ( ) ;
m=i n . readLong ( ) ;
n=i n . readLong ( ) ;
r=app . cmmdc(m, n ) ;
out . writeLong ( r ) ;
out . c l o s e ( ) ;
in . c l o s e ( ) ;
socket . close ();
}
c a t c h ( IOException e ) {
System . e r r . p r i n t l n ( S e r v e r c o m u n i c a t i o n e r r o r : +
e . getMessage ( ) ) ;
}
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
}
/
serverSocket . close ( ) ;
44
45
46
47
48
import j a v a . n e t . ;
import j a v a . i o . ;
public c l a s s AppThread extends Thread {
S o c k e t s o c k e t=n u l l ;
public AppThread ( S o c k e t s o c k e t ) {
t h i s . s o c k e t=s o c k e t ;
}
public void run ( ) {
1.4. APLICAT
IE CLIENT SERVER CU SOCLURI
try {
DataOutputStream out=new DataOutputStream ( s o c k e t . getOutputStream ( ) ) ;
DataInputStream i n=new DataInputStream ( s o c k e t . g e t I n p u t S t r e a m ( ) ) ;
long m=0 ,n=0 , r ;
App app=new App ( ) ;
m=i n . readLong ( ) ;
n=i n . readLong ( ) ;
r=app . cmmdc(m, n ) ;
out . w r i t e L o n g ( r ) ;
out . c l o s e ( ) ;
in . close ( ) ;
socket . close ( ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( S e r v e r c o m u n i c a t i o n e r r o r : +e . g e t M e s s a g e ( ) ) ;
}
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
19
public c l a s s App{
public long cmmdc( long m, long n ) { . . . }
}
package i s e r v e r ;
import j a v a . n e t . S e r v e r S o c k e t ;
public i n t e r f a c e IMyMServer {
public S e r v e r S o c k e t g e t S e r v e r S o c k e t ( i n t p o r t ) ;
public void myAction ( S e r v e r S o c k e t s e r v e r S o c k e t ) ;
}
Implementarea interfetei
1
2
3
package s e r v e r . impl ;
import s e r v e r . ;
import i s e r v e r . IMyMServer ;
20
import j a v a . n e t . ;
import j a v a . i o . ;
import j a v a . u t i l . c o n c u r r e n t . ;
4
5
public S e r v e r S o c k e t g e t S e r v e r S o c k e t ( i n t p o r t ) {
ServerSocket s e r v e r S o c k e t = null ;
try {
s e r v e r S o c k e t = new S e r v e r S o c k e t ( p o r t ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( Could not l i s t e n on p o r t : +p o r t ) ;
System . e r r . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 1 ) ;
}
System . out . p r i n t l n ( S e r v e r S o c k e t i s r e a d y . . . ) ;
return s e r v e r S o c k e t ;
}
10
11
12
13
14
15
16
17
18
19
20
21
22
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package s e r v e r ;
import j a v a . n e t . S e r v e r S o c k e t ;
import s e r v e r . impl . MyMServer ;
import i s e r v e r . IMyMServer ;
public c l a s s AppServer {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
i n t p o r t =7999;
i f ( a r g s . l e n g t h >0)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 0 ] ) ;
IMyMServer myMServer=new MyMServer ( ) ;
S e r v e r S o c k e t s e r v e r S o c k e t=myMServer . g e t S e r v e r S o c k e t ( p o r t ) ;
myMServer . myAction ( s e r v e r S o c k e t ) ;
}
}
1.4. APLICAT
IE CLIENT SERVER CU SOCLURI
21
Unitatea de nv
atare 2
Datagrame si canale de
comunicatii
Durata: 4 ore.
2.1
Datagrame
2.1. DATAGRAME
23
Clasa java.net.DatagramPacket.
Trimiterea unui pachet UDP necesita crearea unui obiect
DatagramPacket care contine corpul mesajului si adresa destinatiei. Apoi acest
obiect DatagramPacket poate fi pus n retea n vederea trimiterii sale. Primirea unui pachet UDP necesit
a crearea unui obiect DatagramPacket si apoi acceptarea unui pachet UDP din retea. Dupa primire, se poate extrage din obiectul
DatagramPacket adresa surs
a si continutul mesajului.
Constructori
Exist
a doi constructori pentru datagrame UDP. Primul constructor este folosit
pentru primirea de pachete si necesita doar furnizarea unei memorii tampon, iar
celalalt este folosit pentru trimiterea de pachete si necesita specificarea adresei
destinatarului.
DatagramPacket(byte[ ] buffer ,int lung)
Acest contructor este folosit pentru primirea pachetelor. Un pachet se memoreaz
a n tamponul buffer avand lung octeti. Daca lungimea pachetului
dep
aseste aceast
a lungime, atunci pachetul este trunchiat iar octetii n plus
se pierd.
DatagramPacket(byte[ ] buffer ,int lung ,InetAddress adresa ,int port)
Acest constructor este folosit pentru crearea unui pachet n vederea expedierii. Corpul pachetului este continut n tamponul buffer avand lung
octeti. Pachetul va fi trimis catre adresa si portul specificat. Trebuie sa
existe un server UDP care asculta la portul specificat pentru trimiterea
pachetelor. Un server UDP poate coexista cu un server TCP care asculta
acelasi port.
Metode
InetAddress getAddress()
returneaz
a adresa IP a expeditorului.
int getPort()
returneaz
a portul expeditorului.
byte[] getData()
returneaz
a continutul pachetului.
int getLength()
returneaz
a lungimea pachetului.
void setAddress(InetAddress adresa)
fixeaz
a adresa IP a pachetului.
24
ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II
Clasa java.net.DatagramSocket
Aceast
a clas
a se foloseste atat pentru trimiterea, cat si pentru primirea obiectelor
DatagramPacket. Un obiect DatagramSocket asculta la un port cuprins ntre 1
si 65535 (porturile cuprinse ntre 1 si 1023 sunt rezervate pentru aplicatiile sistem). Deoarece UDP nu este orientat pe conexiune, se va crea un singur obiect
DatagramSocket pentru trimiterea pachetelor catre diferite destinatii si primirea
pachetelor de la diferite surse.
Constructori
DatagramSocket() throws SocketException
Creaz
a un obiect DatagramSocket cu un numar de port aleator;
DatagramSocket(int port) throws SocketException
Creaz
a un obiect DatagramSocket cu numarul de port specificat;
DatagramSocket(int port, InetAddress adres
a ) throws SocketException
Creaz
a un obiect DatagramSocket la adresa si portul specificat.
Metode
Clasa DatagramSocket contine metode pentru trimiterea si primirea de obiecte
DatagramPacket, nchiderea soclului, determinarea informatiilor adresei locale
si setarea timpului de primire.
void send(DatagramPacket pachet) throws IOException
Trimite pachetul prin retea. Daca se trimit pachete la o destinatie necunoscut
a sau care nu asculta, n cele din urma se genereaza o exceptie
IOException.
void receive(DatagramPacket pachet) throws IOException
Metoda primeste un singur pachet UDP n obiectul pachet specificat. Apoi,
pachetul poate fi inspectat pentru determinarea adresei IP sursa, portul
surs
a si lungimea mesajului. Executia metodei este blocata pana cand se
primeste cu succes un pachet sau se scurge timpul de asteptare.
2.1. DATAGRAME
25
InetAddress getLocalAddress()
Returneaz
a adresa local
a c
atre care este legat acest DatagramSocket;
int getLocalPort()
Returneaz
a num
arul de port unde asculta DatagramSocket.
void close()
Inchide DatagramSocket.
void setSoTimeout(int timpDeAsteptere) throws SocketException
Metoda fixeaz
a timpul de asteptare (n milisecunde) a soclului. Metoda
receive() se va bloca pentru timpul de asteptare specificat pentru primirea
unui pachet UDP, dup
a care va arunca o exceptie Interrupted Exception.
Dac
a valoarea parametrului este 0, atunci soclul este blocat.
int getSoTimeout() throws SocketException
Returneaz
a timpul de asteptare.
void setSendBufferSize(int lungime) throws SocketException
Fixeaz
a lungimea tamponului de trimitere a soclului la valoarea specificata.
Nu poate fi trimis mesaj UDP de lungime mai mare de aceasta valoare.
int getSendBufferSize() throws SocketException
Returneaz
a lungimea tamponului de trimitere a soclului.
void setReceiveBufferSize(int lungime) throws SocketException
Fixeaz
a lungimea tamponului de primire a soclului la valoarea specificata.
Nu poate fi primit un mesaj UDP de lungime mai mare de aceasta valoare.
int getReceiveBufferSize() throws SocketException
Returneaz
a lungimea tamponului de primire a soclului.
void connect(InetAddress adresa, int port) throws SocketException
Conecteaz
a soclul la adresa si portul specificat. Aceasta metoda nu este
cerut
a pentru operatiile uzuale UDP.
void disconnect()
Deconecteaz
a soclul conectat.
InetAddress getInetAddress()
Returneaz
a obiectul InetAddress catre care este conectat soclul sau null
dac
a acesta nu este conectat.
26
ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II
int getPort()
Returneaz
a portul la care este conectat soclul sau -1 daca acesta nu este
conectat.
Clasa java.net.InetAddress
Datele pot fi trimise prin retea indicand adresa IP corespunzatoare masinii
destinatie. Clasa InetAddress furnizeaza acces la adresele IP.
Nu exist
a constructori pentru aceasta clasa. Instantele trebuie create folosind
metodele statice:
InetAddress getLocalHost() throws UnknownHostException
Returneaz
a un obiect InetAddress corespunzator masinii locale.
InetAddress getByName(String host) throws UnknownHostException
Returneaz
a un obiect InetAddress corespunzator masinii host, parametru
care poate fi specificat prin nume (de exemplu atlantis) sau prin adresa
IP (168.192.0.1).
InetAddress [ ]getAllByName(String host)
throws UnknownHostException
Returneaz
a un sir de obiecte InetAddress corespunzator fiecarei adrese IP
a masinii host.
Metodele clasei InetAddress
byte [ ] getAddress()
Returneaz
a sirul de octeti corespunzator obiectului InetAddress de referint
a.
String getHostName()
Returneaz
a numele masinii gazda.
String getHostAddress()
Returneaz
a adresa IP a masinii gazda.
boolean isMulticastAddress()
Returneaz
a true daca obiectul InetAddress reprezinta o adresa IP multicast (cuprins ntre 224.0.0.0 si 239.255.255.255).
Exemplul urm
ator afiseaza numele si adresa calculatorului gazda cat si acela
al calculatoarelor ale c
aror nume este transmis programului ca parametru.
Exemplul 2.1.1
27
2.1. DATAGRAME
import j a v a . n e t . ;
public c l a s s AdreseIP {
public s t a t i c void main ( S t r i n g a r g [ ] ) {
I n e t A d d r e s s a d r e s a=n u l l ;
try {
a d r e s a=I n e t A d d r e s s . g e t L o c a l H o s t ( ) ;
System . out . p r i n t l n ( C a l c u l a t o r u l gazda a r e : ) ;
System . out . p r i n t l n ( numele : +a d r e s a . getHostName ( ) ) ;
System . out . p r i n t l n ( a d r e s a IP : +a d r e s a . g e t H o s t A d d r e s s ( ) ) ;
}
catch ( UnknownHostException e ) {
System . out . p r i n t l n ( UnknownHostException : +e . g e t M e s s a g e ( ) ) ;
}
i f ( a r g . l e n g t h >0){
f o r ( i n t i =0; i <a r g . l e n g t h ; i ++){
try {
a d r e s a=I n e t A d d r e s s . getByName ( a r g [ i ] ) ;
System . out . p r i n t l n ( C a l c u l a t o r u l +a r g [ i ]+ a r e : ) ;
System . out . p r i n t l n ( a d r e s a IP \ getByName \ : +a d r e s a ) ;
byte [ ] b=a d r e s a . g e t A d d r e s s ( ) ;
f o r ( i n t j =0; j <b . l e n g t h ; j ++)
i f ( b [ j ] <0)
System . out . p r i n t (256+b [ j ]+ . ) ;
else
System . out . p r i n t ( b [ j ]+ . ) ;
System . out . p r i n t l n ( ) ;
}
catch ( UnknownHostException e ) {
System . out . p r i n t l n ( UnknownHostException : +
e . getMessage ( ) ) ;
}
}
}
}
}
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2.1.1
Object
ObjectInputStream
ByteArrayInputStream
input - DatagramPacket
ObjectOutputStream
ByteArrayOutputStream
output - DatagramPacket
?
6
6
6
6
28
ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II
package s e r v e r ;
import j a v a . i o . ;
public c l a s s P r o t o c o l implements S e r i a l i z a b l e {
long x , y ;
P r o t o c o l ( long x , long y ) {
t h i s . x=x ;
t h i s . y=y ;
}
}
2.1. DATAGRAME
29
package i s e r v e r ;
import j a v a . n e t . DatagramSocket ;
public i n t e r f a c e IMyMServer {
public DatagramSocket getDatagramSocket ( i n t p o r t ) ;
public void myAction ( DatagramSocket datagramSocket ) ;
}
Implementarea interfetei
package s e r v e r . impl ;
import s e r v e r . ;
import i s e r v e r . IMyMServer ;
import j a v a . n e t . ;
import j a v a . i o . ;
import j a v a . u t i l . c o n c u r r e n t . ;
1
2
3
4
5
10
11
12
13
14
15
16
17
18
19
20
21
22
24
25
26
27
28
29
30
31
32
33
34
35
36
37
30
ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II
Clasa AppThread
1
2
3
5
6
package s e r v e r ;
import j a v a . n e t . ;
import j a v a . i o . ;
public c l a s s AppThread extends Thread {
DatagramSocket s o c k e t=n u l l ;
public AppThread ( DatagramSocket s o c k e t ) {
t h i s . s o c k e t=s o c k e t ;
}
8
9
10
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Clas
a de lansare a serverului
1
2
3
4
6
7
8
9
10
11
12
13
14
15
package s e r v e r ;
import j a v a . n e t . DatagramSocket ;
import s e r v e r . impl . MyMServer ;
import i s e r v e r . IMyMServer ;
public c l a s s AppServer {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
i n t p o r t =7999;
i f ( a r g s . l e n g t h >0)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 0 ] ) ;
IMyMServer myMServer=new MyMServer ( ) ;
DatagramSocket datagramSocket=myMServer . getDatagramSocket ( p o r t ) ;
myMServer . myAction ( datagramSocket ) ;
}
}
2.1. DATAGRAME
31
Aplicatia client
1
2
3
4
5
package c l i e n t ;
import j a v a . n e t . ;
import j a v a . i o . ;
import s e r v e r . P r o t o c o l ;
import j a v a . u t i l . S c a n n e r ;
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
2.1.2
public c l a s s CmmdcClient {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
S t r i n g h o s t S e r v e r= l o c a l h o s t ;
i n t p o r t S e r v e r =7999;
i f ( a r g s . l e n g t h >0)
h o s t S e r v e r=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t S e r v e r=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
try {
DatagramSocket s o c k e t=new DatagramSocket ( ) ;
P r o t o c o l p=new P r o t o c o l ( 0 , 0 ) ;
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( I n t r o d u c e t i p r i m u l numar : ) ;
p . x=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( I n t r o d u c e t i a l d o i l e a numar : ) ;
p . y=s c a n n e r . nextLong ( ) ;
ByteArrayOutputStream baos=new ByteArrayOutputStream ( 2 5 6 ) ;
ObjectOutputStream out=new ObjectOutputStream ( baos ) ;
out . w r i t e O b j e c t ( p ) ;
byte [ ] bout=baos . toByteArray ( ) ;
I n e t A d d r e s s a d d r e s s=I n e t A d d r e s s . getByName ( h o s t S e r v e r ) ;
DatagramPacket p a c k e t =
new DatagramPacket ( bout , bout . l e n g t h , a d d r e s s , p o r t S e r v e r ) ;
s o c k e t . send ( p a c k e t ) ;
byte [ ] b i n=new byte [ 4 0 4 8 ] ;
p a c k e t=new DatagramPacket ( bin , b i n . l e n g t h ) ;
socket . r e c e i v e ( packet ) ;
ByteArrayInputStream b a i s=new ByteArrayInputStream ( b i n ) ;
O b j e c t I n p u t S t r e a m i n=new O b j e c t I n p u t S t r e a m ( b a i s ) ;
p=( P r o t o c o l ) i n . r e a d O b j e c t ( ) ;
System . out . p r i n t l n ( Cmmdc = +p . x ) ;
socket . close ( ) ;
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}
}
}
Clasa java.net.MulticastSocket
Prin intermediul unui soclu de tip MulticastSocket se pot receptiona datagrame expediate de un server c
atre toti clientii cu un asemenea soclu.
Constructori
MulticastSocket(int port) throws SocketException
32
ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II
Metode
void joinGroup(InetAddress adres
a ) throws SocketException
Soclul se conecteaza la grupul definit de adresa IP (de tip D, adica cuprins
ntre 224.0.0.0 si 239.255.255.255).
void leaveGroup(InetAddress adres
a ) throws SocketException
Soclul se deconecteaza la grupul definit de adresa IP.
void close()
Preg
atirea clientului n vederea receptionarii datagramelor printr-un soclu de
tip MulticastSocket consta din
MulticastSocket socket= new MulticastSocket(port);
InetAddress adresa=InetAddress.getByName("230.0.0.1");
socket.joinGroup(adresa);
In final, clientul se deconecteaza si nchide soclul.
socket.leaveGroup(adresa);
socket.close();
Pachetele trimise de programul server trebuie sa se adreseze grupului, identificat prin adresa IP de tip D.
Astfel prin multicast serverul trimite pachete la o adresa de grup si la un
port fixat. Pachetele emise de server sunt receptionate de orice client ce creaz
a
un soclu de tip MulticastSocket pentru portul la care emite serverul si care se
al
atur
a grupului.
Prin broadcast serverul emite datagrame catre orice calculator al retelei locale
la un anumit port. Faptul ca emiterea datagramelor este de tip broadcast se indic
a
prin
DatagramSocket.setBroadcast(true)
Orice client care si creaza un soclu la portul la care emite serverul receptioneaz
a
datagramele trimise de server. Adresa utilizata de server la crearea datagramelor
trebuie s
a identifice reteaua.
Observatie. In cazul unui calculator izolat este nevoie de instalarea driverului Microsoft Loopback Adapter, care simuleaza existenta unei placi de retea active.
Exemplul 2.1.3 Multicast
si Broadcast: programele server emit din cinci n
cinci secunde ora exact
a. Un client va receptiona c
ate cinci datagrame.
Codurile sunt date n Fig. 2.1 si Fig. 2.2, respectiv pentru partea de server
si cea de client.
33
2.1. DATAGRAME
MulticastServer
import java.io.*;
import java.net.*;
import java.util.*;
import java.text.DateFormat;
BroadcastServer
import java.io.*;
import java.net.*;
import java.util.*;
import java.text.DateFormat;
socket.send(packet);
// sleep for a while
Thread.sleep(FIVE_SECONDS);
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
socket.close();
}
}
InetAddress group =
InetAddress.getByName("192.168.0.255");
packet=new DatagramPacket(buf,
buf.length,group,clientPort);
socket.setBroadcast(true);
socket.send(packet);
Thread.sleep(FIVE_SECONDS);
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
socket.close();
}
}
34
ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II
MulticastClient
import java.io.*;
import java.net.*;
BroadcastClient
import java.io.*;
import java.net.*;
int i=-1;
do{
i++;
packet=new DatagramPacket(buf, buf.length);
socket.receive(packet);
String received=new String(packet.getData());
System.out.println("Am primit: "+received);
}
while(i<5);
socket.close();
}
}
2.2
35
Canale de comunicatie
Odat
a cu versiunea j2sdk1.4 apar clase noi pentru operatii de intrare - iesire
n pachetele java.nio si java.nio.channels. Pachetul java.nio.channels
contine clase pentru comunicatia n retea, si anume canalele de comunicatie.
Utiliz
am clasele java.nio.channels.SocketChannel, java.nio.channel.
DatagramChannel. Informatia transportata n aceste canale de comunicatie trebuie nglobat
a n obiecte container de tip Buffer.
Clasa java.nio.Buffer
Ierarhia claselor Buffer
abstract Buffer
ByteBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
CharBuffer
Un obiect de tip typeBuffer este un tampon (container) care contine date
de tipul specificat de denumirea clasei.
Un obiect de tip Buffer este caracterizat de
capacitate (capacity) num
arul elementelor care pot fi nmagazitate n tampon;
limit
a (limit) marginea superiora a indicelui;
indice (position) valoarea curenta a indicelui, ce corespunde unui cursor
ce indic
a nceputul zonei unde se introduc sau de unde se extrag date din
tampon.
Metode generale
clear() permite unui obiect de tip Buffer sa fie rencarcat. Fixeaza limita =
capacitate si indice = 0.
flip() preg
ateste obiectul de tip Buffer pentru consultare (citire). Fixeaza
limita =num
arul elementelor din tampon si indice = 0.
rewind() preg
ateste obiectul de tip Buffer pentru re-citire.
36
ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II
Clasa java.nio.ByteBuffer
Instantierea unui obiect se obtine prin metoda statica
static ByteBuffer allocate(capacitate)
Introducerea si extragerea datelor din tampon se poate face n mod
relativ - implic
a modificarea indicelui tamponului;
absolut - far
a modificarea indicelui.
Metode
Introducerea datelor n mod relativ:
ByteBuffer put(byte b)
ByteBuffer putTip(tip x )
Extragerea datelor n mod relativ:
byte get()
tip getTip()
Introducerea datelor n mod absolut:
ByteBuffer put(int index ,byte b)
ByteBuffer putTip(int index ,tip x )
Extragerea datelor n mod absolut:
byte get(int index )
tip getTip(int index )
unde tip poate fi char, short, int, long, float, double.
Alte metode
public final boolean hasRemaining()
Dac
a indicele nu este egal cu limita atunci returneaza true, semnaland
existenta n tampon a unor octeti.
static ByteBuffer wrap(byte[] array)
public static ByteBuffer wrap(byte[] array,int offset,int length)
Converteste sirul de octeti ntr-un obiect Bytebuffer.
37
Clasa java.net.InetSocketAddress
Clasa InetSocketAddress extinde clasa SocketAddress si ncapsuleaza adresa
unui calculator din Internet mpreuna cu un port n vederea leg
arii la un ServerSocket.
Constructori:
InetSocketAddress(InetAddress addr ,int port)
InetSocketAddress(String numeCalculator ,int port)
InetSocketAddress(int port)
Clasa java.nio.channels.ServerSocketChannel
Crearea unui obiect de tip ServerSocketChannel se realizeaza prin
static ServerSocketChannel open() throws IOException
Unui asemenea obiect i se asociaza un ServerSocket prin metoda
ServerSocket socket() throws IOException.
Obiectul de tip ServerSocket trebuie leagat la un port de comunicatie prin
metoda
void bind(InetSocketAddress endpoint) throws IOException.
Sablonul de utilizare este
try{
ServerSocketChannel ssc=ServerSocketChannel.open();
ServerSocket ss=ssc.socket();
InetSocketAddress isa=new InetSocketAddress(addr,port);
ss.bind(isa);
}
catch(Exception e){. . .}
La apelul unui client, serverul trebuie sa genereze un obiect de tip Socket
Channel prin care se vor derula comunicatiile cu clientul. Acest canal de comunicatie
se obtine cu metoda accept().
38
ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II
Clasa java.nio.channels.SocketChannel
Crearea unui obiect de tip SocketChannel se realizeaza prin
static SocketChannel open() throws IOException
Acest obiect trebuie conectat la obiectul ServerSocketChannel al serverului cu
metoda connect(InetSocketAddress addr ).
Datele vehiculate printr-un SocketChannel sunt de tip ByteBuffer. Datele
se transmit prin metoda
int write(ByteBuffer surs
a)
si se receptioneaz
a prin metoda
int read(ByteBuffer destinatie)
Valoarea returnat
a de cele doua metode reprezinta numarul octetilor trimisi
/ receptionati.
Doar octetii unui obiect de tip ByteBuffer cuprinsi ntre indice si limita sunt
transmisi prin canal. Astfel, dupa ncarcarea unui obiectului ByteBuffer cu
metode relative trebuie apelata metoda flip().
Canalul se nchide cu metoda close().
Exemplul 2.2.1 Calculul celui mai mare divizor comun a dou
a numere naturale.
Aplicatie client-server bazat pe canale de comunicatie prin socluri se compune
din:
Aplicatia server alcatuita din:
Interfat
a
1
2
3
4
5
6
package i s e r v e r ;
import j a v a . n i o . c h a n n e l s . S e r v e r S o c k e t C h a n n e l ;
public i n t e r f a c e IMyMServer {
public S e r v e r S o c k e t C h a n n e l g e t S e r v e r S o c k e t C h a n n e l ( i n t p o r t ) ;
public void myAction ( S e r v e r S o c k e t C h a n n e l s e r v e r S o c k e t C h a n n e l ) ;
}
Implementarea interfetei
package s e r v e r . impl ;
import s e r v e r . ;
import i s e r v e r . IMyMServer ;
import j a v a . n e t . ;
import j a v a . n i o . ;
import j a v a . n i o . c h a n n e l s . S e r v e r S o c k e t C h a n n e l ;
import j a v a . u t i l . c o n c u r r e n t . ;
import j a v a . i o . IOException ;
10
1
2
3
4
5
6
7
public S e r v e r S o c k e t C h a n n e l g e t S e r v e r S o c k e t C h a n n e l ( i n t p o r t ) {
S e r v e r S o c k e t C h a n n e l s e r v e r S o c k e t C h a n n e l=n u l l ;
try {
s e r v e r S o c k e t C h a n n e l = S e r v e r S o c k e t C h a n n e l . open ( ) ;
I n e t S o c k e t A d d r e s s i s a=new I n e t S o c k e t A d d r e s s ( p o r t ) ;
S e r v e r S o c k e t s s=s e r v e r S o c k e t C h a n n e l . s o c k e t ( ) ;
s s . bind ( i s a ) ;
}
catch ( IOException e ) {
System . out . p r i n t l n ( S e r v e r S o c k e t C h a n n e l E r r o r : +
e . getMessage ( ) ) ;
System . e x i t ( 0 ) ;
}
System . out . p r i n t l n ( S e r v e r r e a d y . . . ) ;
return s e r v e r S o c k e t C h a n n e l ;
}
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Clasa AppThread
1
2
3
4
5
7
8
10
11
12
14
15
16
17
18
19
20
21
22
23
24
39
package s e r v e r ;
import j a v a . n e t . ;
import j a v a . i o . ;
import j a v a . n i o . c h a n n e l s . S o c k e t C h a n n e l ;
import j a v a . n i o . ;
public c l a s s AppThread extends Thread {
S o c k e t C h a n n e l s o c k e t C h a n n e l=n u l l ;
public AppThread ( S o c k e t C h a n n e l s o c k e t C h a n n e l ) {
t h i s . s o c k e t C h a n n e l=s o c k e t C h a n n e l ;
}
public void run ( ) {
try {
B y t e B u f f e r bb = B y t e B u f f e r . a l l o c a t e ( 1 6 ) ;
// L o n g B u f f e r l b = bb . a s L o n g B u f f e r ( ) ;
s o c k e t C h a n n e l . r e a d ( bb ) ;
// V a r i a n t a 1
long m=bb . getLong ( 0 ) ;
long n=bb . getLong ( 8 ) ;
// V a r i a n t a 2
// l o n g m=l b . g e t ( 0 ) ;
// l o n g n=l b . g e t ( 1 ) ;
40
ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II
25
26
27
28
29
30
31
32
33
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( S e r v e r c o m u n i c a t i o n e r r o r : +
e . getMessage ( ) ) ;
}
34
35
36
37
38
39
40
Clas
a de lansare a serverului
1
2
3
4
6
7
8
9
10
11
12
13
14
15
16
package s e r v e r ;
import j a v a . n i o . c h a n n e l s . S e r v e r S o c k e t C h a n n e l ;
import s e r v e r . impl . MyMServer ;
import i s e r v e r . IMyMServer ;
public c l a s s AppServer {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
i n t p o r t =7999;
i f ( a r g s . l e n g t h >0)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 0 ] ) ;
IMyMServer myMServer=new MyMServer ( ) ;
ServerSocketChannel serverSocketChannel =
myMServer . g e t S e r v e r S o c k e t C h a n n e l ( p o r t ) ;
myMServer . myAction ( s e r v e r S o c k e t C h a n n e l ) ;
}
}
Aplicatia client
1
2
3
4
5
6
8
9
10
11
12
13
14
15
16
17
18
19
20
package c l i e n t ;
import j a v a . i o . ;
import j a v a . n e t . ;
import j a v a . n i o . ;
import j a v a . n i o . c h a n n e l s . ;
import j a v a . u t i l . S c a n n e r ;
public c l a s s CmmdcClient {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
S t r i n g h o s t= l o c a l h o s t ;
i n t p o r t =7999;
i f ( a r g s . l e n g t h >0)
h o s t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
S o c k e t C h a n n e l s c=n u l l ;
try {
I n e t S o c k e t A d d r e s s i s a=new I n e t S o c k e t A d d r e s s ( ho st , p o r t ) ;
s c=S o c k e t C h a n n e l . open ( ) ;
sc . connect ( i s a ) ;
}
catch ( UnknownHostException e ) {
System . e r r . p r i n t l n ( S e r v e r n e c u n o s c u t : +h o s t+ +e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 1 ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( C o n e c t a r e i m p o s i b i l a l a : +
h o s t+ pe p o r t u l +p o r t+ +e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 1 ) ;
}
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
long m, n , r ;
System . out . p r i n t l n ( m= ) ;
m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
n=s c a n n e r . nextLong ( ) ;
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
B y t e B u f f e r bb=B y t e B u f f e r . a l l o c a t e ( 1 6 ) ;
// V a r i a n t a 1
bb . putLong ( 0 ,m) . putLong ( 8 , n ) ;
// V a r i a n t a 2
// L o n g B u f f e r l b=bb . a s L o n g B u f f e r ( ) ;
// l b . p u t ( 0 ,m) . p u t ( 1 , n ) ;
try {
s c . w r i t e ( bb ) ;
bb . c l e a r ( ) ;
s c . r e a d ( bb ) ;
// V a r i a n t a 1
r=bb . getLong ( 0 ) ;
// V a r i a n t a 2
// r=l b . g e t ( 0 ) ;
System . out . p r i n t l n ( Cmmdc : +r ) ;
sc . clos e ( ) ;
}
catch ( E x c e p t i o n e ) {
System . e r r . p r i n t l n ( E r o a r e de c o m u n i c a t i e +e . g e t M e s s a g e ( ) ) ;
}
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
41
Varianta comentat
a corespunde cazului n care se utilizeara clasa acoperitoare
LongBuffer.
Clasa java.nio.channels.DatagramChannel
Sablonul de programare pentru instantierea unui obiect de tip DatagramChannel
este
DatagramChannel dc=null;
InetSocketAddress isa=new InetSocketAddress(port);
try{
dc=DatagramChannel.open();
DatagramSocket datagramSocket=dc.socket();
datagramSocket.bind(isa);
42
ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II
}
catch(Exception e){. . .}
unde port este portul folosit de DatagramChannel. Daca port=0 atunci se alege
aleator un port disponibil.
Transmiterea unui obiect ByteBuffer se face cu metoda
public int send(ByteBuffer src, SocketAddress target) throws
IOException
Metoda returneaz
a numarul de octeti expediati. Receptia unui ByteBuffer se
obtine cu metoda
public SocketAddress receive(ByteBuffer dst) throws IOException
Obiectul returnat reprezinta adresa expeditorului.
Exemplul 2.2.2 Calculul celui mai mare divizor comun a dou
a numere naturale.
Aplicatia server este alcatuita din:
Interfat
a
1
2
3
4
5
6
package i s e r v e r ;
import j a v a . n i o . c h a n n e l s . DatagramChannel ;
public i n t e r f a c e IMyMServer {
public DatagramChannel getDatagramChannel ( i n t p o r t ) ;
public void myAction ( DatagramChannel datagramChannel ) ;
}
Implementarea interfetei
1
2
3
4
5
6
7
8
10
12
13
14
15
16
17
18
19
20
21
22
package s e r v e r . impl ;
import s e r v e r . ;
import i s e r v e r . IMyMServer ;
import j a v a . n e t . ;
import j a v a . n i o . ;
import j a v a . n i o . c h a n n e l s . DatagramChannel ;
import j a v a . u t i l . c o n c u r r e n t . ;
import j a v a . i o . IOException ;
public c l a s s MyMServer implements IMyMServer {
public DatagramChannel getDatagramChannel ( i n t p o r t ) {
DatagramChannel datagramChannel=n u l l ;
I n e t S o c k e t A d d r e s s i s a=new I n e t S o c k e t A d d r e s s ( p o r t ) ;
try {
datagramChannel = DatagramChannel . open ( ) ;
DatagramSocket datagramSocket=datagramChannel . s o c k e t ( ) ;
datagramSocket . bind ( i s a ) ;
}
catch ( IOException e ) {
System . out . p r i n t l n ( DatagramChannelError : +e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 0 ) ;
43
}
System . out . p r i n t l n ( S e r v e r r e a d y . . . ) ;
return datagramChannel ;
23
24
25
26
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Clasa AppThread
1
2
3
4
5
7
8
10
11
12
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package s e r v e r ;
import j a v a . n e t . S o c k e t A d d r e s s ;
import j a v a . i o . IOException ;
import j a v a . n i o . c h a n n e l s . DatagramChannel ;
import j a v a . n i o . ;
public c l a s s AppThread extends Thread {
DatagramChannel datagramChannel=n u l l ;
public AppThread ( DatagramChannel datagramChannel ) {
t h i s . datagramChannel=datagramChannel ;
}
public void run ( ) {
App app=new App ( ) ;
try {
B y t e B u f f e r bb = B y t e B u f f e r . a l l o c a t e ( 1 6 ) ;
// L o n g B u f f e r l b = bb . a s L o n g B u f f e r ( ) ;
S o c k e t A d d r e s s s a=datagramChannel . r e c e i v e ( bb ) ;
// V a r i a n t a 1
long m=bb . getLong ( 0 ) ;
long n=bb . getLong ( 8 ) ;
// V a r i a n t a 2
// l o n g m=l b . g e t ( 0 ) ;
// l o n g n=l b . g e t ( 1 ) ;
long r=app . cmmdc(m, n ) ;
bb . c l e a r ( ) ;
// V a r i a n t a 1
bb . putLong ( 0 , r ) ;
// V a r i a n t a 2
// l b . p u t ( r ) ;
datagramChannel . send ( bb , s a ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( S e r v e r c o m u n i c a t i o n e r r o r : +
e . getMessage ( ) ) ;
}
44
ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II
38
39
Clas
a de lansare a serverului
1
2
3
4
6
7
8
9
10
11
12
13
14
15
16
package s e r v e r ;
import j a v a . n i o . c h a n n e l s . DatagramChannel ;
import s e r v e r . impl . MyMServer ;
import i s e r v e r . IMyMServer ;
public c l a s s AppServer {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
i n t p o r t =7999;
i f ( a r g s . l e n g t h >0)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 0 ] ) ;
IMyMServer myMServer=new MyMServer ( ) ;
DatagramChannel datagramChannel =
myMServer . getDatagramChannel ( p o r t ) ;
myMServer . myAction ( datagramChannel ) ;
}
}
Aplicatia client
1
2
3
4
5
6
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package c l i e n t ;
import j a v a . i o . ;
import j a v a . n e t . ;
import j a v a . n i o . ;
import j a v a . n i o . c h a n n e l s . ;
import j a v a . u t i l . S c a n n e r ;
public c l a s s CmmdcClient {
public s t a t i c void main ( S t r i n g [ ] a r g s ) throws IOException {
S t r i n g s e r v e r H o s t= l o c a l h o s t ;
i n t p o r t =7999;
i f ( a r g s . l e n g t h >0)
s e r v e r H o s t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
I n e t S o c k e t A d d r e s s s e r v e r=null , i s a=n u l l ;
try {
s e r v e r=
new I n e t S o c k e t A d d r e s s ( I n e t A d d r e s s . getByName ( s e r v e r H o s t ) , p o r t ) ;
}
catch ( UnknownHostException e ) {
System . out . p r i n t l n ( Unknown h o s t : +e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 1 ) ;
}
i s a=new I n e t S o c k e t A d d r e s s ( 0 ) ;
DatagramChannel dc=n u l l ;
try {
dc=DatagramChannel . open ( ) ;
DatagramSocket s o c k e t = dc . s o c k e t ( ) ;
s o c k e t . bind ( i s a ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( Couldn t open t h e DatagramChannel +
e . getMessage ( ) ) ;
System . e x i t ( 1 ) ;
}
long m, n , r ;
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( m= ) ;
m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
n=s c a n n e r . nextLong ( ) ;
B y t e B u f f e r bb=B y t e B u f f e r . a l l o c a t e ( 1 6 ) ;
// V a r i a n t a 1
bb . putLong ( 0 ,m) . putLong ( 8 , n ) ;
// V a r i a n t a 2
// L o n g B u f f e r l b=bb . a s L o n g B u f f e r ( ) ;
// l b . p u t ( 0 ,m) . p u t ( 1 , n ) ;
try {
dc . send ( bb , s e r v e r ) ;
bb . c l e a r ( ) ;
dc . r e c e i v e ( bb ) ;
// V a r i a n t a 1
r=bb . getLong ( 0 ) ;
// V a r i a n t a 2
// r=l b . g e t ( 0 ) ;
System . out . p r i n t l n ( Cmmdc = +r ) ;
}
catch ( E x c e p t i o n e ) {
System . e r r . p r i n t l n ( C l i e n t e r r o r : +e . g e t M e s s a g e ( ) ) ;
}
finally {
i f ( dc != n u l l ) dc . d i s c o n n e c t ( ) ;
}
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
45
46
ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II
6. In ce const
a participarea unui client la receptia broadcast ?
7. Care este rolul unui obiect de tip DatagramPacket ?
8. Precizati metodele clasei DatagramSocket utilizate la expedierea si la receptia
unui datagram.
9. Ce parametri caracterizeaza un obiect de tip Buffer ?
10. Ce asem
anare exista ntre comunicatia bazata de datagrame si cea prin
intermediul canalelor ?
Unitatea de nv
atare 3
Reg
asirea obiectelor prin
servicii de nume
Durata: 2 ore.
Introducere
Oric
arui obiect i sunt asociate un nume si o referinta. Regasirea / cautarea
obiectului se face pornind de la numele obiectului, prin referinta se ajunge la
obiect.
Exemple date prin sablonul (Nume Referinta Obiect)
1. Accesul la o carte ntr-o biblioteca:
Titlul c
artii Referint
a c
artii din biblioteca Carte
2. Contactul telefonic cu o persoana:
47
48
ARE 3. REGASIREA
UNITATEA DE INVAT
OBIECTELOR PRIN SERVICII DE NUME
Nume persoan
a Numar telefon Persoana
Un serviciu de nume contine asocieri dintre nume de obiecte si obiecte si poate
oferi facilit
ati de reg
asire a obiectelor.
3.1
Interfata javax.naming.Context
Printr-un context se va ntelege o multime de asocieri nume - obiect. Corespunz
ator unui context, JNDI defineste interfata Context, cu metodele
void bind(String nume,Object object)
void rebind(String nume,Object object)
49
50
ARE 3. REGASIREA
UNITATEA DE INVAT
OBIECTELOR PRIN SERVICII DE NUME
sau
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,...);
Atribut n fisierul de proprietati jndi.properties.
In aceste ultime doua cazuri, contextul initial se creaza prin
Context ctx=new InitialContext();
Functie de serviciul de nume, clasa care creaza contextul initial este dat n
tabelul
Serviciul de nume
Filesystem
COS
RMI
DNS
LDAP
Clasa
com.sun.jndi.fscontext.RefFSContextFactory
com.sun.jndi.cosnaming.CNCtxFactory
com.sun.jndi.rmi.registry.RegistryContextFactory
com.sun.jndi.dns.DnsContextFactory
com.sun.jndi.ldap.LdapCtxFactory
import
import
import
import
j a v a x . naming . ;
java . io . F i l e ;
java . u t i l . Hashtable ;
java . u t i l . Scanner ;
c l a s s Lookup {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
Context c t x=n u l l ;
/
// V a r i a n t a 1
H a s h t a b l e env = new H a s h t a b l e ( 1 1 ) ;
env . p u t ( C o n t e x t . INITIAL CONTEXT FACTORY,
com . sun . j n d i . f s c o n t e x t . RefFSContextFactory ) ;
try {
c t x = new I n i t i a l C o n t e x t ( env ) ;
}
c a t c h ( NamingException e ) {
System . o u t . p r i n t l n ( I n i t i a l C o n t e x t E r r o r : +e . g e t M e s s a g e ( ) ) ;
}
/
/
// V a r i a n t a 2
System . s e t P r o p e r t y ( j a v a . naming . f a c t o r y . i n i t i a l ,
com . sun . j n d i . f s c o n t e x t . RefFSContextFactory ) ;
try {
c t x = new I n i t i a l C o n t e x t ( ) ;
}
c a t c h ( NamingException e ) {
System . o u t . p r i n t l n ( I n i t i a l C o n t e x t E r r o r : +e . g e t M e s s a g e ( ) ) ;
29
}
/
30
31
// V a r i a n t a 3
try {
c t x = new I n i t i a l C o n t e x t ( ) ;
}
catch ( NamingException e ) {
System . out . p r i n t l n ( I n i t i a l C o n t e x t E r r o r : +e . g e t M e s s a g e ( ) ) ;
}
33
34
35
36
37
38
39
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( I n t r o d u c e t i r e f e r i n t a a b s o l u t a a unui c a t a l o g : ) ;
S t r i n g myName=s c a n n e r . n e x t ( ) ;
try {
System . out . p r i n t l n ( \n c t x . l o o k u p ( +myName+ ) p r o d u c e ) ;
System . out . p r i n t l n ( c t x . l o o k u p (myName ) ) ;
41
42
43
44
45
46
48
49
50
51
52
53
55
56
57
58
59
60
61
}
catch ( NamingException e ) {
System . out . p r i n t l n ( Lookup f a i l e d : + e . g e t M e s s a g e ( ) ) ;
}
62
63
64
65
66
67
51
sau
java
Lookup
52
ARE 3. REGASIREA
UNITATEA DE INVAT
OBIECTELOR PRIN SERVICII DE NUME
3.1.1
LDAP
53
import
import
import
import
import
import
java . u t i l . Hashtable ;
java . u t i l . Scanner ;
j a v a x . naming . Context ;
j a v a x . naming . NamingException ;
j a v a x . naming . d i r e c t o r y . D i r C o n t e x t ;
j a v a x . naming . d i r e c t o r y . I n i t i a l D i r C o n t e x t ;
public c l a s s LDAPServerCmmdc {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( A l e g e t i f u r n i z o r u l LDAP: ) ;
System . out . p r i n t l n ( 1 : OpenDS ) ;
System . out . p r i n t l n ( 2 : Apache D i r e c t o r y S e r v i c e ) ;
i n t p r o v i d e r=s c a n n e r . n e x t I n t ( ) ;
H a s h t a b l e env = new H a s h t a b l e ( ) ;
env . put ( Context . INITIAL CONTEXT FACTORY,
com . sun . j n d i . l d a p . LdapCtxFactory ) ;
i f ( p r o v i d e r ==1){
env . put ( Context . PROVIDER URL,
l d a p : / / l o c a l h o s t : 3 8 9 / dc=example , dc=com ) ;
env . put ( Context . SECURITY PRINCIPAL , cn=D i r e c t o r y Manager ) ;
env . put ( Context . SECURITY CREDENTIALS, 1 q2w3e ) ;
}
else {
env . put ( Context . PROVIDER URL,
l d a p : / / l o c a l h o s t : 1 0 3 8 9 / u i d=admin , ou=system ) ;
env . put ( Context . SECURITY PRINCIPAL , u i d=admin , ou=system ) ;
env . put ( Context . SECURITY CREDENTIALS, s e c r e t ) ;
}
DirContext ctx = null ;
System . out . p r i n t l n ( A l e g e t i o p e r a t i a : 1 bind ; 2 unbind ) ;
i n t o p e r=s c a n n e r . n e x t I n t ( ) ;
54
System . out . p r i n t l n ( I n t r o d u c e t i v a l o a r e a a t r i b u t u l u i \ cn \ +
+ a o b i e c t u l u i Cmmdc ) ;
System . out . p r i n t l n ( cn= ) ;
S t r i n g cmmdcObj=s c a n n e r . n e x t ( ) . t r i m ( ) ;
34
35
36
37
try {
c t x = new I n i t i a l D i r C o n t e x t ( env ) ;
i f ( o p e r ==1){
Cmmdc o b j=new Cmmdc ( ) ;
S t r i n g s t r= cn=+cmmdcObj ;
c t x . bind ( s t r , o b j ) ;
}
else {
c t x . unbind ( cn=+cmmdcObj ) ;
}
ctx . c l o s e ( ) ;
}
catch ( NamingException e ) {
System . out . p r i n t l n ( LDAPserverCmmdc :
}
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
+e . g e t M e s s a g e ( ) ) ;
54
55
ARE 3. REGASIREA
UNITATEA DE INVAT
OBIECTELOR PRIN SERVICII DE NUME
import
import
import
import
import
import
java . u t i l . Hashtable ;
j a v a x . naming . Context ;
j a v a x . naming . NamingException ;
j a v a x . naming . d i r e c t o r y . D i r C o n t e x t ;
j a v a x . naming . d i r e c t o r y . I n i t i a l D i r C o n t e x t ;
java . u t i l . Scanner ;
public c l a s s LDAPClientCmmdc {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( A l e g e t i f u r n i z o r u l LDAP: ) ;
System . out . p r i n t l n ( 1 : OpenDS ) ;
System . out . p r i n t l n ( 2 : Apache D i r e c t o r y S e r v i c e ) ;
i n t p r o v i d e r=s c a n n e r . n e x t I n t ( ) ;
H a s h t a b l e env = new H a s h t a b l e ( ) ;
env . put ( Context . INITIAL CONTEXT FACTORY,
com . sun . j n d i . l d a p . LdapCtxFactory ) ;
i f ( p r o v i d e r ==1){
19
20
21
22
}
else {
env . put ( Context . PROVIDER URL,
l d a p : / / l o c a l h o s t : 1 0 3 8 9 / u i d=admin , ou=system ) ;
env . put ( Context . SECURITY PRINCIPAL , u i d=admin , ou=system ) ;
env . put ( Context . SECURITY CREDENTIALS, s e c r e t ) ;
}
DirContext ctx = null ;
try {
c t x=new I n i t i a l D i r C o n t e x t ( env ) ;
i f ( c t x != n u l l ) {
System . out . p r i n t l n ( I n t r o d u c e t i v a l o a r e a a t r i b u t u l u i \ cn \ +
a o b i e c t u l u i Cmmdc ) ;
System . out . p r i n t l n ( cn= ) ;
S t r i n g cmmdcObj=s c a n n e r . n e x t ( ) . t r i m ( ) ;
O b j e c t o b j e c t = c t x . l o o k u p ( cn=+cmmdcObj ) ;
System . out . p r i n t l n ( Primul numar ) ;
long a=s c a n n e r . n e x t I n t ( ) ;
System . out . p r i n t l n ( Al d o i l e a numar ) ;
long b=s c a n n e r . n e x t I n t ( ) ;
Cmmdc o b j =(Cmmdc) o b j e c t ;
System . out . p r i n t l n ( R e z u l t a t u l cmmdc e s t e : +o b j . cmmdc( a , b ) ) ;
}
}
catch ( NamingException e ) {
System . out . p r i n t l n ( LDAPClientCmmdc : +e . g e t M e s s a g e ( ) ) ;
}
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
55
Unitatea de nv
atare 4
Durata: 3 ore.
Introducere
Invocarea procedurilor la distanta (Remote Procedure Call RPC ) nseamn
a
apelarea unei metode a unui obiect aflat pe un alt calculator ca si cum acesta
s-ar afla pe calculatorul local.
Se vor prezenta dou
a cazuri:
Invocarea procedurilor la distanta n cazul mediului omogen Java. Denumirea tehnologiei n acest caz este Invocarea metodelor la distant
a Remote
Method Invocation (RMI). Prin mediu omogen se ntelege faptul ca at
at
compontenta server cat si componenta client sunt programate n acelasi
56
57
4.1
Reg
asirea obiectelor la distant
a. Ideea gasirii unui obiect la distanta
este ca serverul nscrie un reprezentant al sau numit stub (ciot) ntr-un obiect
registry - registru. Acest obiect se creaza cu programul rmiregistry.exe din
distributia java si se lanseaz
a n executie prin
start rmiregistry [port]
unde valoarea implicit
a a portului este 1099. Comanda start apartine sistemului
de operare. rmiregistry este un serviciu de nume JNDI.
Un client obtine din registry stub-ul serverului, prin intermediul caruia realizeaza comunicatia cu programul server.
Cand un obiect al clientului apeleaza o metoda a unui obiect aflat la distanta,
se va face, de fapt, un apel de metoda a unui obiect care reprezinta serverul.
Acesta este stub-ul, aflat pe aceasi masina cu clientul.
Rolul acestui obiect este s
a mpacheteze (marshalling) parametrii de apel ai
metodei ntr-un mesaj ce va fi transferat prin retea. Impachetarea se face ntr-o
maniera independent
a de calculator, mai precis sirurile de caractere si obiecte
sunt transmise ntr-un format care nu se bazeaza pe referinte. Pentru obiecte se
utilizeaz
a serializarea obiectelor Java.
Serializarea datelor reprezint
a transformarea acestora din tipuri de date diferite
ntr-un sir de octeti care va fi transportat prin retea fara interpretare, dar care
pastreaz
a informatiile despre structura initiala a datelor.
Deserializarea este procesul invers de refacere a structurilor trimise prin retea.
Mesajul asamblat este transmis catre server, care stie sa desfaca mesajul
receptionat invoc
and n mod corespunzator metoda referita de client.
Atunci c
and clientul face apel la o metoda aflata pe o alta masina, este invocat stub-ul client, care ncepe conversatia cu serverul. Acest lucru este complet
transparent utilizatorului, care are impresia ca invoca o metoda locala.
Metodele apelate la distant
a trebuie declarate ca apartinand unei interfete ce
extinde interfata java.rmi.Remote. Fiecare asemenea metoda trebuie sa arunce
o exceptie java.rmi.RemoteException. Obiectele care circula prin retea trebuie
sa implementeze interfata java.io.Serializable.
Structura unei aplicatii RMI. O aplicatie RMI este alcatuita din trei
componente:
1. O interfat
a la distant
a (remote) n care se declara serviciile puse la dispozitie
de server;
58
Varianta direct
a, f
ar
a a folosi facilit
atile JNDI pentru rmiregistry.
59
60
4.1.1
Exemplific
am construirea unei aplicatii RMI n care serviciul asigurat de
server este calculul celui mai mare divizor comun a doua numere naturale.
Pentru exemplele2 care urmeaza, presupunem ca textele sursa se retin n
subcataloage ale unui catalog src, la care are acces doar programatorul, iar clasele
obtinute prin compilare se depun n subcataloagele unui catalog public\classes,
accesibil prin retea.
Dezvoltarea unei aplicatii se va face pe un calculator. In acest sens, celor 3
componente li se asociaza cataloagele \i - pentru interfata la distanta, \s - pentru
componenta server si \c - pentru componenta client. Pasi necesari compilarii si
desf
asur
arii componentelor aplicatiei se vor realiza prin intermediul lui ant.
Pentru fiecare componenta se vor executa succesiv obiectivele:
1. Install - creaz
a o structura de cataloage src si public\classes.
2. Init - creaz
a structura de cataloage specifica aplicatiei.
3. Compile - compileaza programele sursa.
Dezvoltarea unei aplicatii RMI consta din parcurgerea urmatorilor pasi:
1. Definitea interfetei la distanta.
1
2
3
4
package cmmdc ;
public i n t e r f a c e ICmmdc extends j a v a . rmi . Remote{
long cmmdc( long a , long b ) throws j a v a . rmi . RemoteException ;
}
8
9
10
11
12
13
2
14
15
17
18
19
20
21
22
24
25
26
27
28
29
30
31
32
<mkdir d i r= p u b l i c / c l a s s e s />
</ target>
<target name= I n i t >
< ! C r e a t e t h e time stamp >
<tstamp/>
<mkdir d i r= s r c /${ package } />
<mkdir d i r= p u b l i c / c l a s s e s /${ package } />
</ target>
<target name= Compile depends= I n i t
description= c o m p i l e t h e s o u r c e >
<javac s r c d i r= s r c i n c l u d e s= ${ package }/
d e s t d i r= p u b l i c / c l a s s e s />
<j a r b a s e d i r= p u b l i c / c l a s s e s
d e s t f i l e = p u b l i c / c l a s s e s /${ package }/${ package } . j a r
i n c l u d e s= ${ package } / . c l a s s />
</ target>
</ project>
package s e r v e r ;
import cmmdc . ;
import j a v a . rmi . ;
import j a v a . rmi . s e r v e r . ;
// V a r i a n t a d i r e c t a
// i m p o r t j a v a . rmi . r e g i s t r y . ;
// V a r i a n t a JNDI
import j a v a x . naming . ;
4
5
6
7
8
9
11
public c l a s s CmmdcImpl
implements ICmmdc{
13
15
16
17
18
19
20
21
22
23
24
26
27
28
29
30
32
33
34
// V a r i a n t a d i r e c t a
/
R e g i s t r y r e g i s t r y=L o c a t e R e g i s t r y . g e t R e g i s t r y ( h o s t , p o r t ) ;
r e g i s t r y . b i n d ( CmmdcServer , s t u b ) ;
/
// V a r i a n t a JNDI
S t r i n g s P o r t =(new I n t e g e r ( p o r t ) ) . t o S t r i n g ( ) ;
System . s e t P r o p e r t y ( Context . INITIAL CONTEXT FACTORY,
61
62
35
36
37
38
40
41
42
43
44
45
46
Textul surs
a al programului server CmmdcImpl.java se retine n catalogul
\s\src\server
4. (a) Compilarea programului server;
(b) Crearea obiectului registry;
(c) Lansarea serverului n lucru
se obtin cu ant cu
1
2
3
4
5
7
8
9
10
11
12
14
15
16
17
18
19
20
21
22
23
24
26
27
28
29
30
32
33
34
35
36
37
38
40
41
42
43
44
46
47
48
49
50
51
52
53
54
63
package c l i e n t ;
import cmmdc . ;
import j a v a . u t i l . S c a n n e r ;
// V a r i a n t a d i r e c t a
// i m p o r t j a v a . rmi . r e g i s t r y . ;
// V a r i a n t a JNDI
import j a v a x . naming . ;
4
5
6
7
8
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public c l a s s CmmdcClient {
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
S t r i n g h o s t= l o c a l h o s t ;
i n t p o r t =1099;
i f ( a r g s . l e n g t h >0)
h o s t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( Primul numar : ) ;
long m=Long . par se Lon g ( s c a n n e r . n e x t ( ) ) ;
System . out . p r i n t l n ( Al d o i l e a numar : ) ;
long n=Long . p ars eL ong ( s c a n n e r . n e x t ( ) ) ;
long x =0;
try {
// V a r i a n t a d i r e c t a
/
R e g i s t r y r e g i s t r y=L o c a t e R e g i s t r y . g e t R e g i s t r y ( h o s t , p o r t ) ;
64
28
29
30
31
32
33
34
35
36
x=o b j . cmmdc(m, n ) ;
System . out . p r i n t l n ( Cmmdc=+x ) ;
38
39
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( CmmdcClient e x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}
40
41
42
43
44
45
35
36
37
38
39
40
41
42
43
44
45
65
Unitatea de nv
atare 5
Durata: 3 ore.
5.1
Fabrica de obiecte
Tiparul fabrica de obiecte va permite crearea dinamica a unui server, fapt care
nu este posibil pe schema prezentata n paragraful precedent. Prin aceea schem
a,
se va crea o clas
a - fabrica de obiecte - care implementeaza cate o metoda get, ce
returneaz
a o instant
a de server. Aceste metode sunt declarate ntr-o interfata la
distant
a. Un client, apeland o asemenea metoda, va instantia serverul dorit si va
obtine stub-ul corespunzator.
Programarea unui server care poate fi lansat dinamic trebuie sa satisfac
a
restrictiile:
Clasa serverului extinde clasa UnicastRemoteObject.
Exist
a un constructor fara argumente ce arunc
a exceptia java.rmi.Remote
Exception.
Pentru exemplificarea tehnicii de lucru reluam aplicatia pentru calculul celui
mai mare divizor comun a doua numere naturale, considerand interfata
1
2
package cmmdc0 ;
im po rt j a v a . rmi . ;
66
3
4
5
67
p u b l i c i n t e r f a c e ICmmdc0 e x t e n d s Remote{
p u b l i c l o n g compute ( l o n g m, l o n g n ) throws RemoteException ;
}
Aceas
a interfat
a va fi implementata de clasa ServerCmmdc. Metoda compute
este o metod
a de calcul a celui mai mare divizor comun a doua numere.
Obiecte de tip ServerCmmdc se creaza, de la distanta prin fabrica de obiecte
FabObiecte, o clas
a ce implementeaza interfata
1
2
3
4
5
package cmmdc0 ;
im po rt j a v a . rmi . ;
p u b l i c i n t e r f a c e I F a b O b i e c t e e x t e n d s Remote{
p u b l i c ICmmdc0 getCmmdc ( ) throws RemoteException ;
}
package cmmdc0 ;
im po rt j a v a . rmi . ;
im po rt j a v a . rmi . s e r v e r . ;
im po rt j a v a . i o . ;
im po rt j a v a . u t i l . ;
1
2
3
4
11
12
13
14
respectiv
package cmmdc0 ;
im po rt j a v a . rmi . ;
im po rt j a v a . rmi . s e r v e r . ;
im po rt j a v a . rmi . r e g i s t r y . ;
p u b l i c c l a s s FabObiecte implements I F a b O b i e c t e {
1
2
3
8
9
10
11
13
14
15
16
17
18
19
20
21
22
23
24
68
System . out . p r i n t l n ( O b j e c t F a c t o r y r e a d y ) ;
}
catch ( Exception e ){
System . out . p r i n t l n ( F a c t o r y e r r +e . g e t M e s s a g e ( ) ) ;
}
25
26
27
28
29
30
31
package cmmdc0 ;
im po rt j a v a . rmi . ;
im po rt j a v a . rmi . s e r v e r . ;
im po rt j a v a . rmi . r e g i s t r y . ;
p u b l i c c l a s s RemoteClient e x t e n d s UnicastRemoteObject {
1
2
3
ICmmdc0 remote=n u l l ;
8
10
12
13
14
15
16
17
18
19
20
21
22
23
2. ClientCmmdc0
Apeleaz
a metoda compute a obiectului remote.
2
package cmmdc0 ;
im po rt j a v a . u t i l . S c a n n e r ;
p u b l i c c l a s s ClientCmmdc0 {
6
7
8
9
10
11
12
13
14
p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) {
S t r i n g h o s t= l o c a l h o s t ;
i n t p o r t =1099;
i f ( a r g s . l e n g t h >0)
h o s t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
try {
15
16
17
18
19
20
21
}
catch ( Exception e ){
System . out . p r i n t l n ( C l i e n t E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}
System . e x i t ( 0 ) ;
22
23
24
25
26
27
28
5.2
69
package cmmdc0 ;
im po rt j a v a . rmi . ;
p u b l i c i n t e r f a c e ICmmdc0 e x t e n d s Remote{
p u b l i c l o n g compute ( l o n g m, l o n g n ) throws RemoteException ;
p u b l i c v o i d setMethod ( ICallbackCmmdc o b j ) throws RemoteException ;
}
package cmmdc0 ;
im po rt j a v a . rmi . ;
p u b l i c i n t e r f a c e ICallbackCmmdc e x t e n d s Remote{
p u b l i c S t r i n g getMethod ( ) throws RemoteException ;
}
ce va fi implementat
a n clasa RemoteClient.
Programul ServerCmmdc devine
70
1
2
3
4
6
7
8
package cmmdc0 ;
im po rt j a v a . rmi . ;
im po rt j a v a . rmi . s e r v e r . ;
im po rt j a v a . i o . ;
p u b l i c c l a s s ServerCmmdc e x t e n d s UnicastRemoteObject
implements ICmmdc0{
p r i v a t e S t r i n g method=n u l l ;
10
12
p u b l i c l o n g compute ( l o n g m, l o n g n ) {
l o n g x =0;
i f ( method . e q u a l s ( NERECURSIV ) )
x=n e r e c u r s i v (m, n ) ;
i f ( method . e q u a l s ( RECURSIV ) )
x=r e c u r s i v (m, n ) ;
return x ;
}
13
14
15
16
17
18
19
21
22
23
25
26
27
28
29
30
31
32
33
p r i v a t e l o n g n e r e c u r s i v ( l o n g m, l o n g n ) {
long r , c ;
do {
c=n ;
r=m%n ;
m=n ;
n=r ;
}
while ( r !=0);
return c ;
}
35
36
37
38
39
40
41
42
43
44
45
46
Dup
a obtinerea stub-ului, clientul apeleaza metoda setMethod a serverului
remote, care, prin apel invers, apeleaza metoda getMethod din RemoteClient.
Clientul stabileste metoda de calcul si apeleaza metoda compute a lui remote.
Programele client devin
1
2
3
4
5
package cmmdc0 ;
im po rt j a v a . rmi . ;
im po rt j a v a . rmi . s e r v e r . ;
im po rt j a v a . rmi . r e g i s t r y . ;
im po rt j a v a . u t i l . S c a n n e r ;
7
8
9
p u b l i c c l a s s RemoteClient e x t e n d s UnicastRemoteObject
implements ICallbackCmmdc {
ICmmdc0 remote=n u l l ;
11
13
p u b l i c S t r i n g getMethod ( ) {
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( A l e g e t i v a r i a n t a a l g o r i t m u l u i l u i E u c l i d ) ;
System . out . p r i n t l n ( 1 a l g o r i t m u l ner e c u r s i v ) ;
System . out . p r i n t l n ( 2 a l g o r i t m u l r e c u r s i v ) ;
i n t x=s c a n n e r . n e x t I n t ( ) ;
S t r i n g method=n u l l ;
i f ( x==1)
method=NERECURSIV ;
else
method=RECURSIV ;
r e t u r n method ;
}
14
15
16
17
18
19
20
21
22
23
24
25
27
28
29
30
31
32
33
34
35
36
37
38
si
1
2
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package cmmdc0 ;
im po rt j a v a . u t i l . S c a n n e r ;
p u b l i c c l a s s ClientCmmdc0 {
p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) {
S t r i n g h o s t= l o c a l h o s t ;
i n t p o r t =1099;
i f ( a r g s . l e n g t h >0)
h o s t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
try {
RemoteClient c t=new RemoteClient ( ho st , p o r t ) ;
c t . remote . setMethod ( c t ) ;
System . out . p r i n t l n ( m= ) ;
l o n g m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
l o n g n=s c a n n e r . nextLong ( ) ;
l o n g x=c t . remote . compute (m, n ) ;
System . out . p r i n t l n ( Cmmdc=+x ) ;
}
catch ( Exception e ){
System . out . p r i n t l n ( C l i e n t E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
71
72
}
System . e x i t ( 0 ) ;
25
26
27
28
Unitatea de nv
atare 6
CORBA
Durata: 4 ore.
Introducere
6.1
CORBA
74
ARE 6. CORBA
UNITATEA DE INVAT
6.1.1
75
6.1. CORBA
package cmmdciiop ;
im po rt j a v a x . rmi . P o r t a b l e R e m o t e O b j e c t ;
im po rt cmmdc . ;
im po rt j a v a . rmi . ;
// Se e x t i n d e c l a s a P o r t a b l e R e m o t e O b j e c t
// s i nu UnicastRemoteObject
p u b l i c c l a s s CmmdcImpl e x t e n d s P o r t a b l e R e m o t e O b j e c t implements ICmmdc{
// C o n s t r u c t o r u l c l a s e i
p u b l i c CmmdcImpl ( ) throws RemoteException {}
p u b l i c l o n g cmmdc( l o n g a , l o n g b ) { . . . }
13
14
6
7
8
9
10
11
12
13
14
15
16
18
19
20
21
package cmmdciiop ;
im po rt j a v a x . naming . I n i t i a l C o n t e x t ;
im po rt j a v a x . naming . Context ;
p u b l i c c l a s s CmmdcServer {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
S t r i n g h o s t= l o c a l h o s t ;
S t r i n g p o r t= 1050 ;
i f ( a r g s . l e n g t h >0)
h o s t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t=a r g s [ 1 ] ;
try {
// 1 : C r e a r e a u n e i i n s t a n t e CmmdcImpl
CmmdcImpl cmmdcRef = new CmmdcImpl ( ) ;
// 2 : I n r e g i s t r a r e a u n e i r e f e r i n t e a s e r v i c i u l u i
// u t i l i z a n d JNDI API
System . s e t P r o p e r t y ( j a v a . naming . f a c t o r y . i n i t i a l ,
com . sun . j n d i . cosnaming . CNCtxFactory ) ;
76
ARE 6. CORBA
UNITATEA DE INVAT
System . s e t P r o p e r t y ( j a v a . naming . p r o v i d e r . u r l ,
i i o p : // +h o s t+ : +p o r t ) ;
Context c t x = new I n i t i a l C o n t e x t ( ) ;
c t x . r e b i n d ( CmmdcService , cmmdcRef ) ;
System . out . p r i n t l n ( Cmmdc S e r v e r : Ready . . . ) ;
22
23
24
25
26
}
catch ( Exception e ) {
System . out . p r i n t l n ( CmmdcServer: + e . g e t M e s s a g e ( ) ) ;
}
27
28
29
30
31
32
6.1. CORBA
26
27
28
29
30
31
32
34
35
36
37
38
39
40
41
42
43
44
46
47
48
49
50
52
53
54
55
56
57
58
59
60
61
1
2
3
4
5
6
7
9
10
11
12
13
14
15
16
77
package cmmdciiop ;
import j a v a . rmi . ;
import j a v a x . rmi . ;
import j a v a . n e t . MalformedURLException ;
import j a v a x . naming . ;
import j a v a . u t i l . S c a n n e r ;
import cmmdc . ;
public c l a s s CmmdcClient {
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
S t r i n g h o s t= l o c a l h o s t ;
S t r i n g p o r t= 1050 ;
i f ( a r g s . l e n g t h >0)
h o s t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t=a r g s [ 1 ] ;
78
ARE 6. CORBA
UNITATEA DE INVAT
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( Primul numar : ) ;
long m=Long . par se Lon g ( s c a n n e r . n e x t ( ) ) ;
System . out . p r i n t l n ( Al d o i l e a numar : ) ;
long n=Long . p ars eL ong ( s c a n n e r . n e x t ( ) ) ;
try {
System . s e t P r o p e r t y ( j a v a . naming . f a c t o r y . i n i t i a l ,
com . sun . j n d i . cosnaming . CNCtxFactory ) ;
System . s e t P r o p e r t y ( j a v a . naming . p r o v i d e r . u r l ,
i i o p : / / +h o s t+ : +p o r t ) ;
Context c t x = new I n i t i a l C o n t e x t ( ) ;
18
19
20
21
22
23
24
25
26
27
28
30
31
32
33
35
36
37
38
39
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( E x c e p t i o n + e . g e t M e s s a g e ( ) ) ;
}
40
41
42
43
44
45
11
12
13
14
15
17
18
19
20
21
22
<property
<property
<property
<property
6.1. CORBA
23
</ target>
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
43
44
45
46
47
49
50
51
52
53
54
55
56
57
58
79
6.1.2
Scopul acestei sectiuni este prezentarea dezvoltarii unei aplicatii pe baza unei
interfete bazat pe IDL.
Pentru dezvoltarea aplicatiilor n limbajul de programare Java, translatarea
interfetei IDL n Java se realizeaz
a cu utilitarul idlj din distributia jdk.
Corespondenta ntre entit
atile IDL si Java este data n Tabelul 6.1
Legarea cererii unui client de codul serviciului care satisface cererea utilizeaza
componenta CORBA Portable Object Adapter (POA).
80
ARE 6. CORBA
UNITATEA DE INVAT
Tip IDL
module
boolean
char, wchar
octet
string, wstring
short, unsigned short
long, unsigned long
long long, unsigned long long
float
double
fixed
enum, struct, union
sequence, array
interface (non-abstract)
Any
Tip Java
package
boolean
char
byte
java.lang.String
short
int
long
float
double
java.math.BigDecimal
class
array
signature interface,
operations interface,
helper class, holder class
org.omg.CORBA.Any
module CmmdcApp{
i n t e r f a c e Cmmdc{
long long cmmdc( i n long long a , i n long long b ) ;
};
};
Salv
am acest text ntr-un fisier denumit Cmmdc.idl.
Cmmdc va fi numele serviciului cautat de un client si implementat de
server. Serviciul contine o singura metoda cmmdc.
(b) Translatarea n Java
idlj -fall Cmmdc.idl
Programul idlj creaza un subcatalog CmmdcApp cu un pachet Java CmmdcApp
contin
and fisierele:
81
6.1. CORBA
Cmmdc.java
CmmdcPOA.java ;
CmmdcOperations.java;
CmmdcStub.java;
CmmdcHelper.java;
CmmdcHolder.java.
2. Realizarea programelor server. Punem n evidenta programul servant CmmdcImpl.java ce implementeaza interfata Cmmdc.
1
2
4
5
im po rt CmmdcApp . ;
im po rt o r g . omg .CORBA. ;
p u b l i c c l a s s CmmdcImpl e x t e n d s CmmdcPOA {
p r i v a t e ORB orb ;
p u b l i c CmmdcImpl (ORB orb ) {
t h i s . orb = orb ;
}
7
8
9
p u b l i c l o n g cmmdc( l o n g a , l o n g b ) { . . . }
11
12
im po rt
im po rt
im po rt
im po rt
im po rt
CmmdcApp . ;
o r g . omg . CosNaming . ;
o r g . omg . CosNaming . NamingContextPackage . ;
o r g . omg .CORBA. ;
o r g . omg . P o r t a b l e S e r v e r . ;
p u b l i c c l a s s CmmdcServer {
p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) {
try {
// c r e a r e a s i i n i t i a l i z a r e a ORB
ORB orb = ORB. i n i t ( a r g s , n u l l ) ;
// o b t i n e r e a u n e i r e f e r i n t e r o o t p o a s i a c t i v a r e a m a n a g e r u l u i POAManager
POA r o o t p o a = POAHelper . narrow ( orb . r e s o l v e i n i t i a l r e f e r e n c e s ( RootPOA ) ) ;
r o o t p o a . the POAManager ( ) . a c t i v a t e ( ) ;
// c r e a r e a unui s e r v a n t
CmmdcImpl cmmdcImpl = new CmmdcImpl ( orb ) ;
// o b t i n e r e a u n e i r e f e r i n t e a s e r v a n t u l u i
o r g . omg .CORBA. O b j e c t r e f = r o o t p o a . s e r v a n t t o r e f e r e n c e ( cmmdcImpl ) ;
Cmmdc h r e f = CmmdcHelper . narrow ( r e f ) ;
// O b t i n e r e a s e r v i c i u l u i NameService
o r g . omg .CORBA. O b j e c t o b j R e f =
orb . r e s o l v e i n i t i a l r e f e r e n c e s ( NameService ) ;
82
ARE 6. CORBA
UNITATEA DE INVAT
27
29
32
// l e g a r e a r e f e r i n t e i s e r v a n t u l u i i n s e r v i c i u l NameService
S t r i n g name = CmmdcService ;
NameComponent path [ ] = ncRef . to name ( name ) ;
ncRef . r e b i n d ( path , h r e f ) ;
34
36
// i n a s t e p t a r e a c l i e n t i l o r
orb . run ( ) ;
30
31
37
}
catch ( Exception e ) {
System . e r r . p r i n t l n ( ERROR: + e ) ;
e . p r i n t S t a c k T r a c e ( System . out ) ;
}
System . out . p r i n t l n ( CmmdcServer E x i t i n g
38
39
40
41
42
43
. . . );
44
45
. . . );
im po rt
im po rt
im po rt
im po rt
im po rt
CmmdcApp . ;
o r g . omg . CosNaming . ;
o r g . omg . CosNaming . NamingContextPackage . ;
o r g . omg .CORBA. ;
java . u t i l . Scanner ;
p u b l i c c l a s s CmmdcClient {
s t a t i c Cmmdc cmmdcImpl ;
p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) {
try {
// c r e a r e a s i i n i t i a l i z a r e a unui r e p r e z e n t a n t ORB
ORB orb = ORB. i n i t ( a r g s , n u l l ) ;
// o b t i n e r e a u n e i r e f e r i n t e p e n t r u s e r v i c i u l d e n u m i r i l o r
// s e r v i c i i l o r i n r e g i s t r a t e
o r g . omg .CORBA. O b j e c t o b j R e f =
orb . r e s o l v e i n i t i a l r e f e r e n c e s ( NameService ) ;
NamingContextExt ncRef = NamingContextExtHelper . narrow ( o b j R e f ) ;
// o b t i n e r e a u n e i r e f e r i n t e l a s e r v i c i u l d o r i t
S t r i n g name = CmmdcService ;
cmmdcImpl = CmmdcHelper . narrow ( ncRef . r e s o l v e s t r ( name ) ) ;
System . out . p r i n t l n ( Obtained a h a n d l e on s e r v e r o b j e c t : + cmmdcImpl ) ;
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
l o n g m, n ;
System . out . p r i n t l n ( m= ) ;
m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
n=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( Cmmdc=+cmmdcImpl . cmmdc(m, n ) ) ;
}
catch ( Exception e ) {
System . out . p r i n t l n ( ERROR : + e ) ;
e . p r i n t S t a c k T r a c e ( System . out ) ;
}
6.1. CORBA
38
39
83
Programele se compileaz
a
javac CmmdcApp\*.java
4. Pornirea serviciului de intregistrare a numelor cu programul orbd.exe din
distributia jdk.
start orbd -ORBInitialHost localhost -ORBInitialPort 1050
5. Pornirea programului server prin
start java CmmdcServer -ORBInitialHost localhost -ORBInitialPort 1050
6. Lansarea programului client prin
java CmmdcClient -ORBInitialHost localhost -ORBInitialPort 1050
Unitatea de nv
atare 7
Durata: 4 ore.
Introducere
Comunicatia prin apelul la distanta - inclusiv RMI - este sincron: programul
apelant se blocheaz
a si asteapta ca metoda apelata sa se termine si sa furnizeze
rezultatul cerut. Cu alte cuvinte apelul de procedura la distanta cere atat clientului c
at si serverului s
a fie simultan disponibile.
Comunicatiile asincrone ntre programe permit realizarea unor sisteme de programe cu un grad mult mai scazut de cuplare. Asemenea aplicatii se pot realiza
prin comunicatii de mesaje, mesaje care sunt retinute de un intermediar (serviciu
de mesagerie, server, broker, messaging middleware).
In prezent protocolul pentru realizarea aplicatiilor bazate pe comunicatii de
mesaje este Advanced Message Queue Protocol - AMQP. AMQP este un protocol
dezvoltat de mai multe firme bazat pe standardele World Wide Web Consortium
84
85
7.1
86
UNITATEA DE INVAT
IE PUNCTUALA
7.2
87
7.3
Apache ActiveMQ
In cazul unui calculator izolat este nevoie de instalarea driver-ului Microsoft loopback Adaptor care sinuleaz
a existenta functonarii unei placi de retea active.
Distributia apache-activemq-5.*.* contine, ca exemplu, clasa EmbeddedBroker.java care lanseaz
a serverul JMS n lucru.
Compilarea unui program necesita prezenta n variabila de sistem classpath
a referintei c
atre fisierul ACTIVEMQ HOME\activemq-all-*.*.*.jar. Pentru executie,
variabila de sistem classpath nevoie sa contina referintele catre fisierele jar din
catalogul ACTIVEMQ HOME\lib.
7.4
7.4.1
88
UNITATEA DE INVAT
IE PUNCTUALA
ConnectionFactory cf=
new com.sun.messaging.ConnectionFactory();
Clasa com.sun.messaging.ConnectionFactory contine metoda
setProperty( String name, String value) prin intermediul careia
se precizeaz
a calculatorul si portul furnizorului de servicii JMS, fixand
atributele "imqBrokerHostName" si respectiv "imqBrokerHostPort".
Utiliz
and apache-activemq, fabrica de conexiuni se obtine prin
org.apache.activemq.ActiveMQConnectionFactory cf=
new org.apache.activemq.ActiveMQConnectionFactory
("tcp://host:61616");
2. Generarea conexiunii.
Se realizeaz
a prin
Connection conn=cf.createConnection();
Pentru realizarea acestui obiectiv se utilizeaza metoda createConnection,
dup
a caz, dintr-una din clasele
class ConnectionFactory{
Connection createConnection() throws JMSException;
Connection createConnection(String userName,String password)
throws JMSException;
}
class QueueConnectionFactory{
QueueConnection createQueueConnection() throws JMSException;
QueueConnection createQueueConnection(String userName,
String password) throws JMSException;
}
class TopicConnectionFactory{
TopicConnection createTopicConnection() throws JMSException;
TopicConnection createTopicConnection(String userName,
String password) throws JMSException;
}
unde Connection, QueueConnection, TopicConnection sunt interfete.
Amintim urm
atoarele metode ale unei interfete Connection
interface Connection{
Session createSession(boolean transacted,
89
90
UNITATEA DE INVAT
IE PUNCTUALA
|
TextMessage createTextMessage(String s);
|
StreamMessage createStreamMessage();
|
MapMessage createMapMessage();
|
ObjectMessage createObjectMessage();
|
ObjectMessage createObjectMessage(Serializable object);
|
BytesMessage createBytesMessage();
|
}
|->interface QueueSession{
|
QueueSender createQueueSender(Queue queue);
|
QueueReceiver createQueueReceiver(Queue queue);
|
}
|->interface TopicSession{
TopicPublisher createPublisher(Topic topic);
TopicSubscriber createSubscriber(Topic topic);
TopicSubscriber createDurableSubscriber(Topic topic,
String name);
}
4. Generarea obiectului destinatie.
In cazul comunicatiilor punctuale obiectul destinatie este de tip Queue, iar
crearea se face prin
Destination numeDestinatie=sesssion.createQueue(String numeCoada)
iar pentru comunicatii axate pe subiect obiectul destinatie, de tip Topic se
instantiaz
a prin
Destination numeDestinatie=sesssion.createTopic(String numeSubiect)
Sunt definite arborescentele:
interface Destination
|
|->interface Queue
|
|->interface Topic
class Destination implements Destination
|
|->class Queue implements Destination, Queue, Serializable
|
|->class Topic implements Destination, Topic, Serializable
91
Utiliz
and Oracle-Sun Java System Message Queue obiecte de tip Queue sau
Topic se pot crea si prin
Queue q=new com.sun.messaging.Queue(String numeCoada);
Topic t=new com.sun.messaging.Topic(String numeSubiect);
5. Generarea produc
atorului de mesaje. Se realizeaza prin
MessageProducer producer=session.createProducer(obiectDestinatie);
Sunt definite interfetele
interface MessageProducer{
void send(Message mesaj);
}
interface QueueSender{
void send(Message mesaj);
}
interface TopicPublisher{
void publish(Message mesaj);
}
6. Generarea mesajelor. Un mesaj de tip TextMessage se poate crea prin
TextMessage m=session.createTextMessage();
m.setText(string);
7. Expedierea mesajelor se face cu metoda send(...) a producatorului de
mesaje.
Exemplul 7.4.1 Clasa urm
atoare genereaz
a ntr-un fir de executie, un num
ar
de mesaje de tip TextMessage ntr-o comunicatie punctual
a. Sf
arsitul expedierii mesajelor se indic
a prin generarea unui mesaj de tip Message. Num
arul
mesajelor este indicat de un parametru al constructorului.
1
import j a v a x . jms . ;
4
5
7
8
9
10
MsgSenderT ( S t r i n g queueName , i n t n ) {
t h i s . queueName=queueName ;
t h i s . n=n ;
}
92
UNITATEA DE INVAT
IE PUNCTUALA
12
13
14
15
16
// s e t P r o p e r t y e s t e metoda a c l a s e i
// com . sun . m e s s a g i n g . QueueConnnectionFactory
// ce i m p l e m e n t e a z a i n t e r f a t a QueueConnectionFactory
// dar nu a i n t e r f e t e i QueueConnectionFactory .
// c f . s e t P r o p e r t y ( imqBrokerHostName , h o s t ) ;
// c f . s e t P r o p e r t y ( imqBrokerHostPort , 7 6 7 6 ) ;
18
19
20
21
22
23
30
// V a r i a n t a ApacheMessageQueue
// o r g . apache . a c t i v e m q . ActiveMQConnectionFactory c f=
//new o r g . apache . a c t i v e m q .
//
ActiveMQConnectionFactory ( t c p : / / l o c a l h o s t : 6 1 6 1 6 ) ;
C o n n e c t i o n conn=c f . c r e a t e C o n n e c t i o n ( ) ;
S e s s i o n s e s s i o n=conn . c r e a t e S e s s i o n ( f a l s e , S e s s i o n .AUTO ACKNOWLEDGE) ;
32
D e s t i n a t i o n q=s e s s i o n . c r e a t e Q u e u e ( queueName ) ;
34
MessageProducer p r o d u c e r=s e s s i o n . c r e a t e P r o d u c e r ( q ) ;
36
TextMessage m=s e s s i o n . c r e a t e T e x t M e s s a g e ( ) ;
f o r ( i n t i =0; i <n ; i ++){
m. s e t T e x t ( H e l l o +i ) ;
p r o d u c e r . send (m) ;
}
// indicam s f a r s i t u l t r i m i t e r i i m e s a j e l o r
p r o d u c e r . send ( s e s s i o n . c r e a t e M e s s a g e ( ) ) ;
session . close ();
conn . c l o s e ( ) ;
25
26
27
28
29
37
38
39
40
41
42
43
44
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( JMSException : +e . g e t M e s s a g e ( ) ) ;
}
System . out . p r i n t l n ( Sen de r f i n i s h e d ) ;
45
46
47
48
49
50
51
7.4.2
Receptia sincron
a a unui mesaj
Primele patru actiuni sunt identice cu cele de la trimiterea unui mesaj, adic
a
1. Generarea unei fabrici de conexiuni.
2. Generarea conexiunii.
3. Crearea unei sesiuni de lucru.
4. Generarea obiectului destinatie.
5. Generarea consumatorului de mesaje. Se realizeaza prin
93
MessageConsumer consumer=session.createConsumer(q);
q desemn
and obiectul destinatie.
Sunt definite interfetele
interface MessageConsumer{
|
Message receive();
|
Message receive(long timeout);
|
Message receiveNoWait();
|
}
|-> interface QueueReceiver
|
|-> interface TopicSubscriber
6. Receptia mesajelor se face cu una din metodele consumatorului de mesaje:
Message receive()
Message receive(long timeout)
Message receiveNoWait()
Exemplul 7.4.2 Receptia de tip sincron a mesajelor ntr-un fir de executie este
efectuat de clasa urm
atoare:
1
import j a v a x . jms . ;
4
6
7
8
10
11
12
13
14
15
16
17
18
19
21
22
23
24
25
26
SyncMsgReceiverT ( S t r i n g queueName ) {
t h i s . queueName=queueName ;
}
public void run ( ) {
try {
// V a r i a n t a OracleSun Message Queue
com . sun . m e s s a g i n g . QueueConnectionFactory c f=
new com . sun . m e s s a g i n g . QueueConnectionFactory ( ) ;
// s e t P r o p e r t y e s t e metoda a c l a s e i QueueConnnectionFactory
// ce i m p l e m e n t e a z a i n t e r f a t a QueueConnectionFactory
// dar nu e s t e a i n t e r f e t e i .
// c f . s e t P r o p e r t y ( imqBrokerHostName , h o s t ) ;
// c f . s e t P r o p e r t y ( imqBrokerHostPort , 7 6 7 6 ) ;
// V a r i a n t a ApacheMessageQueue
// o r g . apache . a c t i v e m q . ActiveMQConnectionFactory c f=
//new o r g . apache . a c t i v e m q .
//
ActiveMQConnectionFactory ( t c p : / / l o c a l h o s t : 6 1 6 1 6 ) ;
C o n n e c t i o n conn=c f . c r e a t e C o n n e c t i o n ( ) ;
S e s s i o n s e s s i o n=conn . c r e a t e S e s s i o n ( f a l s e , S e s s i o n .AUTO ACKNOWLEDGE) ;
94
UNITATEA DE INVAT
IE PUNCTUALA
D e s t i n a t i o n q=s e s s i o n . c r e a t e Q u e u e ( queueName ) ;
MessageConsumer consumer=s e s s i o n . createConsumer ( q ) ;
conn . s t a r t ( ) ;
Message msg=n u l l ;
while ( ( msg=consumer . r e c e i v e ( ) ) ! = n u l l ) {
i f ( msg instanceof TextMessage ) {
TextMessage m=(TextMessage ) msg ;
System . out . p r i n t l n (m. g e t T e x t ( ) ) ;
}
else
break ;
}
session . close ();
conn . c l o s e ( ) ;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( JMSException : +e . g e t M e s s a g e ( ) ) ;
}
System . out . p r i n t l n ( Consumer f i n i s h e d ) ;
41
42
43
44
45
46
47
c l a s s MsgHelloT {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
i n t n=3;
S t r i n g queueName=MyQueue ;
i f ( a r g s . l e n g t h >0)
queueName=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
n=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
MsgSenderT s e n d e r=new MsgSenderT ( queueName , n ) ;
SyncMsgReceiverT r e c e i v e r =new SyncMsgReceiverT ( queueName ) ;
receiver . start ();
sender . s t a r t ( ) ;
}
}
7.4.3
Receptia asincron
a a unui mesaj
Receptia asincron
a a mesajelor presupune implementarea interfetei
MessageListener ce contine o singura metoda
public void onMessage(Message mesaj);
care fixeaz
a prelucrarea mesajului.
Metoda MessageConsumer.setMessageListener(MessageListener obj ) fixeaz
a obiectul ce implementeaza interfata Messagelistener.
Astfel, caracterul asincron consta din faptul ca mesajele sunt preluate de
ascult
ator - adic
a obiectul ce implementeaza interfata MessageListener si nu de
clientul JMS.
95
import j a v a x . jms . ;
public c l a s s AsyncMsgReceiverT extends Thread {
S t r i n g queueName ;
AsyncMsgReceiverT ( S t r i n g queueName ) {
t h i s . queueName=queueName ;
}
5
6
7
9
10
11
12
13
14
15
16
17
18
// V a r i a n t a ApacheMessageQueue
// o r g . apache . a c t i v e m q . ActiveMQConnectionFactory c f=
//new o r g . apache . a c t i v e m q .
//
ActiveMQConnectionFactory ( t c p : / / l o c a l h o s t : 6 1 6 1 6 ) ;
20
21
22
23
C o n n e c t i o n conn=c f . c r e a t e C o n n e c t i o n ( ) ;
S e s s i o n s e s s i o n=conn . c r e a t e S e s s i o n ( f a l s e , S e s s i o n .AUTO ACKNOWLEDGE) ;
D e s t i n a t i o n q==s e s s i o n . c r e a t e Q u e u e ( queueName ) ;
MessageConsumer consumer=s e s s i o n . createConsumer ( q ) ;
T e x t L i s t e n e r t e x t L i s t e n e r=new T e x t L i s t e n e r ( ) ;
consumer . s e t M e s s a g e L i s t e n e r ( t e x t L i s t e n e r ) ;
conn . s t a r t ( ) ;
t e x t L i s t e n e r . run ( ) ;
conn . c l o s e ( ) ;
25
26
27
28
29
30
31
32
33
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}
System . out . p r i n t l n ( Consumer f i n i s h e d ) ;
34
35
36
37
38
39
40
mpreun
a cu ascult
atorul
1
2
3
4
5
6
7
8
9
10
11
12
import j a v a x . jms . ;
public c l a s s
T e x t L i s t e n e r implements M e s s a g e L i s t e n e r {
boolean s f a r s i t =f a l s e ;
public void onMessage ( Message message ) {
i f ( message instanceof TextMessage ) {
TextMessage m=(TextMessage ) message ;
try {
System . out . p r i n t l n (m. g e t T e x t ( ) ) ;
}
catch ( JMSException e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}
96
UNITATEA DE INVAT
IE PUNCTUALA
}
else
s f a r s i t =true ;
13
14
15
16
18
19
20
21
Unitatea de nv
atare 8
Durata: 2 ore.
8.1
8.1.1
Publicarea mesajelor
Publicarea mesajelor
import j a v a x . jms . ;
4
5
7
8
9
10
MsgPublisherT ( S t r i n g s u b i e c t , i n t n ) {
t h i s . n=n ;
t h i s . s u b i e c t=s u b i e c t ;
}
97
98
12
13
14
15
16
17
18
// V a r i a n t a ApacheMessageQueue
// o r g . apache . a c t i v e m q . ActiveMQConnectionFactory c f=
//
new o r g . apache . a c t i v e m q .
//
ActiveMQConnectionFactory ( t c p : / / l o c a l h o s t : 6 1 6 1 6 ) ;
20
21
22
23
T o p i c C o n n e c t i o n conn=c f . c r e a t e T o p i c C o n n e c t i o n ( ) ;
TopicSession session =
conn . c r e a t e T o p i c S e s s i o n ( f a l s e , S e s s i o n .AUTO ACKNOWLEDGE) ;
Destination t = session . createTopic ( subiect ) ;
MessageProducer p r o d u c e r = s e s s i o n . c r e a t e P r o d u c e r ( t ) ;
25
26
27
28
29
31
32
TextMessage m=s e s s i o n . c r e a t e T e x t M e s s a g e ( ) ;
f o r ( i n t i =0; i <n ; i ++){
m. s e t T e x t ( Despre +s u b i e c t+ +i ) ;
p r o d u c e r . send (m) ;
// p u b l i s h e r . p u b l i s h (m) ;
}
p r o d u c e r . send ( s e s s i o n . c r e a t e M e s s a g e ( ) ) ;
// p u b l i s h e r . p u b l i s h ( s e s s i o n . c r e a t e M e s s a g e ( ) ) ;
session . close ();
conn . c l o s e ( ) ;
34
35
36
37
38
39
40
41
42
43
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( JMSException : +e . g e t M e s s a g e ( ) ) ;
}
System . out . p r i n t l n ( P u b l i s h e r f i n i s h e d ) ;
44
45
46
47
48
49
50
Varianta comentat
a este o solutie specifica implementarii Oracle Java System
Message Queue.
8.1.2
Dac
a t este obiectul de tip Destination, clientii se aboneaza - subscriu unui subiect prin
TopicSubscriber consumer=session.createSubscriber((Topic)t);
Subscrierea este este valabila atata timp cat clientul este activ. Pentru a primi
toate mesajele specifice subiectului, chiar si cand clientul este inactiv, acesta
trebuie s
a fie durabil, adica crearea consumatorului sa se faca prin
99
conn.setClientID("myID");
TopicSubscriber consumer=
session.createDurableSubscriber((Topic)t,"nameClient");
In ambele cazuri, clientul primeste doar mesajele publicate din momentul subscrierii.
Exemplul 8.1.2
1
import j a v a x . jms . ;
4
5
6
8
9
10
11
12
14
15
16
17
18
19
20
22
23
24
25
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
MsgSubscriberT ( S t r i n g s u b i e c t , S t r i n g c l i e n t I D , S t r i n g c l i e n t N a m e ) {
t h i s . s u b i e c t=s u b i e c t ;
t h i s . c l i e n t I D=c l i e n t I D ;
t h i s . c l i e n t N a m e=c l i e n t N a m e ;
}
public void run ( ) {
try {
//
V a r i a n t a O r a c l e Message Queue
com . sun . m e s s a g i n g . T o p i c C o n n e c t i o n F a c t o r y c f=
new com . sun . m e s s a g i n g . T o p i c C o n n e c t i o n F a c t o r y ( ) ;
// c f . s e t P r o p e r t y ( imqBrokerHostName , h o s t ) ;
// c f . s e t P r o p e r t y ( imqBrokerHostPort , 7 6 7 6 ) ;
//
V a r i a n t a ApacheMessageQueue
// o r g . apache . a c t i v e m q . ActiveMQConnectionFactory c f=
//new o r g . apache . a c t i v e m q .
//
ActiveMQConnectionFactory ( t c p : / / l o c a l h o s t : 6 1 6 1 6 ) ;
T o p i c C o n n e c t i o n conn=c f . c r e a t e T o p i c C o n n e c t i o n ( ) ;
conn . s e t C l i e n t I D ( c l i e n t I D ) ;
T o p i c S e s s i o n s e s s i o n=
conn . c r e a t e T o p i c S e s s i o n ( f a l s e , S e s s i o n .AUTO ACKNOWLEDGE) ;
Destination t = session . createTopic ( subiect ) ;
T o p i c S u b s c r i b e r consumer=
s e s s i o n . c r e a t e D u r a b l e S u b s c r i b e r ( ( Topic ) t , c l i e n t N a m e ) ;
conn . s t a r t ( ) ;
Message msg=n u l l ;
while ( ( msg=consumer . r e c e i v e ( ) ) ! = n u l l ) {
i f ( msg instanceof TextMessage ) {
TextMessage m=(TextMessage ) msg ;
System . out . p r i n t l n ( c l i e n t N a m e+ r e c e i v e d : +m. g e t T e x t ( ) ) ;
}
else
break ;
}
session . close ();
conn . c l o s e ( ) ;
}
catch ( E x c e p t i o n e ) {
100
48
49
50
51
c l a s s MsgPS{
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
S t r i n g s u b i e c t=JMS ;
i n t n=3 , noAbonati =3;
i f ( a r g s . l e n g t h >0)
s u b i e c t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
n=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
MsgPublisherT p u b l i s h e r=new MsgPublisherT ( s u b i e c t , n ) ;
MsgSubscriberT [ ] abonat=new MsgSubscriberT [ noAbonati ] ;
publisher . start ( ) ;
f o r ( i n t i =0; i <noAbonati ; i ++){
abonat [ i ]=new MsgSubscriberT ( s u b i e c t , ID+i , i d +i ) ;
abonat [ i ] . s t a r t ( ) ;
}
}
}
Modulul II
Programare distribuit
a cu
comunicatii bazate pe
protocolul HTTP
101
102
Introducere
Se prezint
a tehnologiile de baza pentru aplicatiile Web
Servlet;
Java Server Pages (JSP);
Portlet.
Competente
Se descrie instalarea unui server Web container de servlet si JSP, instalarea
si utilizarea unui servlet, pagini JSP si portlet. Accentul se pune pe explicarea
arhitecturii programelor Java pentru fiecare tehnologie n parte.
Unitatea de nv
atare 9
Servlet
Durata: 3 ore.
Introducere
Printre aplicatiile distribuite de tip client-server, n care comunicatiile se
bazeaza pe protocolul http, se disting
Aplicatii Web (site): Cererea adresata serverului este lansata de o persoana
prin intermediul unui site, utilizand un program navigator: Google Chrome,
Mozilla Firefox, Microsoft InternetExplorer, Opera, Apple Safari, etc.
Servicii Web: Cererea c
atre server se face de un program. Aplicatia server
si client se programeaz
a utilizand interfete de programare specifice.
Un servlet este
un program Java care se excuta pe un server Web, compatibil;
103
104
ARE 9. SERVLET
UNITATEA DE INVAT
9.1
Marcajul <form>
Intr-un document html introducerea datelor se poate obtine utilizand marcajul <form> ...</form> .
Atribute ale marcajului <form> . Reamintim ca atributele se prezint
a
ca perechi (nume, valoare) si se scriu n antetul marcajului sub forma nume =
valoare.
Nume
action
method
Valoare
adresa tip URL
GET
POST
id
name
onSubmit
Semnificatia valorii
Resursa care prelucreaza formularul.
Mesajul trimis serverului Web contine dup
a
adresa URL numele si valorile parametrilor
introdusi. Adaugarea se face potrivit sintaxei
?numeParam1=valoare&numeParam2=valoare. . .
Lungimea mesajului nu poate depasi 255 caractere.
Transmisia datelor se face n fluxuri de date.
Permite transferul unor fisiere de pe masina
clientului pe masina serverului.
Parametru de identificare a formularului (optional).
Nume atribuit formularului (optional).
Metoda JavaScript executata naintea apelarii
serverului Web (optional).
105
<select>
<textarea>
Atributele marcajului < input> sunt:
Nume
type
Valoare
text
password
submit
reset
file
hidden
Semnificatie
Se asteapta introducerea unui text
Se asteapta introducerea unei parole
Se marcheaza sfarsitul completarii formularului
Se reinitializeaza formularul
Permite selectarea unui fisier
Transmite mai departe un atribut fara vizualizarea lui
numele controlului
valoarea (initiala) a controlului
num
arul caracterelor atasat controlului
name
value
size
In cazul marcajului < select> utilizarea este
<select name="nume">
<option value="valoare"> Valoare
. . . . . . . . . . . . . . . .
</select>
9.2
In prezent sunt disponibile mai multe servere Web n care poate fi instalat
un servlet si un fisier JSP Java Server Pages. Se spune ca serverul Web este
container de servlet si JSP. Dintre produsele gratuite amintim
apache-tomcat
jetty
glassfish
Acest server Web este utilizat n Glassfishv3 - o implementare JEE (Java
Enterprise Edition) de la Oracle.
JBoss
Geronimo, o alta implementare JEE dezvoltata de apache, poate utiliza containerul apache-tomcat sau jetty.
106
ARE 9. SERVLET
UNITATEA DE INVAT
Numele si num
arul cataloagelor este dependent de distributia apache-tomcat.
9.3
107
108
ARE 9. SERVLET
UNITATEA DE INVAT
109
<welcome-file-list>
<welcome-file>
fisier.html sau jsp
</welcome-file>
</welcome-file-list>
cu precizarea fisierelor html sau jsp care apeleaza aplicatia Web. Declaratia
fisierului index.html este implicit
a.
Compilarea clasei servlet necesita completarea variabilei de mediu classpath
cu fisierul TOMCAT HOME\lib\servlet-api.jar.
Odat
a completat
a structura de cataloage si fisiere ale aplicatiei servlet aceasta
structur
a trebuie copiat
a n catalogul TOMCAT HOME\webapps. Aceasta operatie
se numeste desf
asurarea (deployment) sau instalarea servlet-ului. Copierea se
poate executa si cu serverul Web pornit.
Pentru instalarea unui servlet exista mai multe alternative:
Din catalogul catalogAppServlet se realizeaza arhiva catalogAppServlet.war
jar cfv catAppServlet.war WEB-INF\ index.html
care se copiaz
a n catalogul TOMCAT HOME\webapps.
Serverul Web tomcat va dezarhiveaza arhiva. Astfel servlet-ul este instalat.
Aceast
a instalare se numeste instalare dinamic
a - hot deployment.
Dac
a fisierul war este creat, atunci n locul copierii, instalarea se poate face
prin componenta manager a lui tomcat.
O alt
a posibilitate de instalare a unui servlet n serverul web tomcat este
prin intermediul produsului apache-tomcat-deployer. apache-tomcat-deployer
permite instalarea unui servlet de la distanta cat si instalarea comandata
dintr-un program.
9.3.1
Un servlet implementeaz
a interfata Servlet sau extinde una din clasele GenericServlet
sau HttpServlet. GenericServlet implementeaza interfata Servlet, iar HttpServlet
extinde clasa GenericServlet. Extinzand clasa GenericServlet nu este nevoie
de rescrierea tuturor metodelor abstracte ale intrefetei Servlet.
Metodele interfetei Servlet sunt
abstract public void init(ServletConfig config)
Se apeleaz
a o singur
a dat
a la lansarea servlet-ului.
abstract public void service(ServletRequest req, ServletResponse
res)throws ServletException,IOException
Metoda este apelat
a de serverul Web pentru rezolvarea cererii unui client.
110
ARE 9. SERVLET
UNITATEA DE INVAT
111
1. Stabilirea naturii r
aspunsului:
res.setContentType(String tip)
unde tip specific
a tipul MIME - Multipurpose Internet Mail Extensions al
raspunsului:
"text/html" - pagin
a html;
"text/xml" - document xml;
"text/plain" - text;
"image/jpg" - imagine gif;
"image/gif" - imagine jpg.
2. Se obtine o referinta c
atre un obiect care realizeaza transmisia datelor catre
navigatorul clientului:
ServletOutputStream out = res.getOutputStream();
sau
PrintWriter out=res.getWriter();
3. Se preiau datele cererii cu una din metodele:
String getParameter(String numeParapetru)
java.util.Enumeration getParameterNames()
4. Rezolv
a cererea clientului;
5. Formeaz
a si scrie r
aspunsul;
6. Inchide conexiunea obiectului prin care s-a realizat transmisia datelor catre
navigatorul clientului prin out.close().
Un utilizator lanseaz
a o cerere catre servlet. De obicei acest lucru se realizeaza
prin completarea unui formular al unui document html. Programul navigator
trimite cererea serverului Web prin intermediul caruia este lansat servlet-ul n
actiune.
Ciclul de viat
a al unui servlet. Cand un servlet este apelat prima data
de catre serverul Web se execut
a metoda init. Dupa aceasta, fiecarei cereri
lansate de un utilizator i se asociaza un fir de executie n care se apeleaza metoda
service. Metoda service apeleaza apoi metodele doGet(), doPost().
Exemplul 9.3.1 Servlet-ul Hello: Clientul transmite numele servet-ului care i
r
aspunde cu mesajul de salut Hi + nume!.
Formularul html prin care clientul introduce numele este (index.html )
112
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ARE 9. SERVLET
UNITATEA DE INVAT
<html>
<head>
< t i t l e> S e r v l e t u l H e l l o </ t i t l e>
</head>
<body>
<center>
<h1> Pagina de a p e l a r e a s e r v l e t u l u i H e l l o S e r v l e t </h1>
<form method= p o s t action= h e l l o >
<p>I n t r o d u c e t i numele :
<input type= t e x t name=name s i z e =20>
<p>
<input type= submit >
</form>
</ center>
</body>
</html>
import
import
import
import
@WebServlet ( u r l P a t t e r n s = / h e l l o )
public c l a s s H e l l o S e r v l e t extends H t t p S e r v l e t {
public void doGet ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
r e s . setContentType ( t e x t / html ) ;
S e r v l e t O u t p u t S t r e a m out=r e s . getOutputStream ( ) ;
S t r i n g nume=r e q . g e t P a r a m e t e r ( name ) ;
out . p r i n t l n ( <html> ) ;
out . p r i n t l n ( <head><t i t l e >H e l l o S e r v l e t </ t i t l e ></head> ) ;
out . p r i n t l n ( <body> ) ;
out . p r i n t l n ( <h1>H e l l o S e r v l e t </h1> ) ;
out . p r i n t l n ( <p> ) ;
out . p r i n t l n ( Hi + nume+ ! ) ;
out . p r i n t l n ( </p> ) ;
out . p r i n t l n ( </body> ) ;
out . p r i n t l n ( </html> ) ;
out . c l o s e ( ) ;
}
public void doPost ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
doGet ( req , r e s ) ;
}
25
26
27
28
29
java . io . ;
javax . s e r v l e t . ;
javax . s e r v l e t . http . ;
j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
9
10
11
12
13
113
<s e r v l e t mapping>
<s e r v l e t name> h e l l o</ s e r v l e t name>
<u r l p a t t e r n>/ h e l l o</ u r l p a t t e r n>
</ s e r v l e t mapping>
</webapp>
Compilarea si arhivarea servlet-ului o vom realiza prin intermediul lui apacheant. In acest scop se creaz
a structura:
hello
|
|---> src
|
|
|
HelloServlet.java
|
|---> lib
|
|---> web
|
|
|
web.xml
|
|---> web-files
|
|
|
index.html
|
build.xml
si se utilizeaz
a fisierul build.xml
1
2
3
4
5
7
8
9
10
11
12
14
15
16
17
18
19
20
21
23
24
25
26
27
28
30
31
32
33
34
35
36
37
114
38
39
40
41
42
43
44
ARE 9. SERVLET
UNITATEA DE INVAT
< f i l e s e t d i r= ${ b a s e d i r }/ l i b >
<i n c l u d e name= . j a r />
</ f i l e s e t>
</ copy>
<j a r d e s t f i l e = ${ d i s t . d i r }/${ d i s t . name } . war b a s e d i r= ${ b u i l d . d i r } />
</ t a r g e t>
</ p r o j e c t>
import
import
import
import
@WebServlet ( u r l P a t t e r n s = /cmmdc )
public c l a s s CmmdcServlet extends H t t p S e r v l e t {
public long cmmdc( long m, long n ) { . . . }
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
35
36
37
38
39
java . io . ;
javax . s e r v l e t . ;
javax . s e r v l e t . http . ;
j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<html>
<head>
<s c r i p t l a n g u a g e= J a v a S c r i p t >
< !
function checkIt (){
var sm=document . cmmdc .m. value ;
var sn=document . cmmdc . n . value ;
i f (sm== ) {
a l e r t ( L i p s e s t e p r i m u l numar ! ) ;
return f a l s e ;
}
i f ( sn== ) {
a l e r t ( L i p s e s t e a l d o i l e a numar ! ) ;
return f a l s e ;
}
i f ( ! IsNumeric (sm ) ) {
a l e r t ( Primul numar e s t e g r e s i t i n t r o d u s ! ) ;
return f a l s e ;
}
i f ( ! IsNumeric ( sn ) ) {
a l e r t ( Al d o i l e a numar e s t e g r e s i t i n t r o d u s ! ) ;
return f a l s e ;
}
return true ;
}
f u n c t i o n IsNumeric ( s T e x t ) {
// J e f f Anderson
// A j a v a s c r i p t v a l i d a t i o n f u n c t i o n t o c h e c k w h e t h e r t h e d e t a i l s
// e n t e r e d by a u s e r a r e numeric ( 2 0 0 2 )
var V a l i d C h a r s = 0 1 2 3 4 5 6 7 8 9 . ;
var IsNumber=t r u e ;
var Char ;
f o r ( i = 0 ; i < sText . l e n g t h && IsNumber == t r u e ; i ++){
Char = sText . charAt ( i ) ;
i f ( V a l i d C h a r s . i n d e x O f ( Char ) == 1){
IsNumber = f a l s e ;
}
}
r e t u r n IsNumber ;
}
//>
</ s c r i p t>
< t i t l e>Cmmdc S e r v l e t</ t i t l e>
</head>
<body bgcolor=#c c b b c c >
<center>
<h1> Cmmdc S e r v l e t </h1>
<form method= g e t
action= h t t p : / / l o c a l h o s t : 8 0 8 0 / m y s e r v l e t /cmmdc
name=cmmdc onSubmit= r e t u r n c h e c k I t ( ) >
<p>Primul numar e s t e <input type= t e x t name=m s i z e=5>
<p>Al d o i l e a numar e s t e <input type= t e x t name=n s i z e=5>
<p><input type= submit value= C a l c u l e a z a >
<input type= h id de n name= t i p value= t e x t / html >
</form>
</ center>
</body>
</html>
115
116
ARE 9. SERVLET
UNITATEA DE INVAT
9.4
Procesare asincron
a n Java Servlet 3.0
1
2
3
4
5
6
7
9
10
11
12
13
14
15
16
17
18
19
package m y s e r v l e t ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;
import j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
import j a v a . u t i l . c o n c u r r e n t . ;
import j a v a . i o . IOException ;
import l i s t e n e r s . ;
@WebServlet ( u r l P a t t e r n s= /cmmdc , a s y n c S u p p o r t e d=true )
public c l a s s A s y n c S e r v l e t extends H t t p S e r v l e t {
public void doGet ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
AsyncContext asyncCtx=r e q . s t a r t A s y n c ( req , r e s ) ;
asyncCtx . a d d L i s t e n e r (new MyAsyncListener ( ) ) ;
E x e c u t o r e x e c u t o r=new ThreadPoolExecutor ( 1 0 , 1 0 , 5 0 0 0 0 ,
TimeUnit . MILLISECONDS,
new LinkedBlockingQueue<Runnable > ( 1 0 0 ) ) ;
e x e c u t o r . e x e c u t e (new AsyncWebService ( asyncCtx ) ) ;
}
public void doPost ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
doGet ( req , r e s ) ;
}
21
22
23
24
25
package m y s e r v l e t ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;
import j a v a . i o . ;
public c l a s s AsyncWebService implements Runnable {
AsyncContext asyncCtx ;
public AsyncWebService ( AsyncContext asyncCtx ) {
t h i s . asyncCtx=asyncCtx ;
9
10
11
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
117
118
}
catch ( IOException e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}
32
33
34
35
36
38
39
ARE 9. SERVLET
UNITATEA DE INVAT
package l i s t e n e r s ;
import j a v a x . s e r v l e t . AsyncEvent ;
import j a v a x . s e r v l e t . A s y n c L i s t e n e r ;
import j a v a x . s e r v l e t . S e r v l e t R e q u e s t ;
1
2
3
public MyAsyncListener ( ) { }
10
11
12
13
14
16
17
18
19
20
22
23
24
25
26
28
29
30
31
32
33
2. Unde se instaleaz
a o aplicatie cu servlet?
3. Cum se poate apela un servlet?
4. Extinz
and clasa HttpServlet, ce trebuie sa faca programatorul?
119
Unitatea de nv
atare 10
Facilit
ati de programare cu
servlet
Durata: 4 ore.
10.1
Apelarea unui servlet dintr-un program Java adica lansarea unei cereri
si receptionarea r
aspunsului furnizat de servlet se poate realiza cu produsul
commons-httpclient dezvoltat de apache.
Intr-un asemenea caz, din punctul de vedere al clientului este mai avantajos
ca r
aspunsul servlet-ului fie text/plain, n loc de text/html.
Pe l
ang
a commons-httpclient este nevoie de urmatoarele produse soft:
commons-codec de la apache;
commons-logging de la apache;
Pentru compilare trebuie declarata n variabila de sistem classpath referinta
c
atre commons-httpclient, dar pentru executie este nevoie si de referintele catre
celelalte dou
a produse.
Dezvoltarea unui client presupune:
120
121
122
5. Lansarea cererii.
int statusCode = client.executeMethod(method);
6. Preluarea r
aspunsului. Exista trei cai de realizare a acestui obiectiv:
Ca sir de octeti:
byte[] method.getResponseBody();
Ca String:
String method.getResponseBodyAsString();
Prin intermediul unui flux:
InputStream method.getResponseBodyAsStream();
7. Inchiderea conexiunii cu servlet-ul.
method.releaseConnection();
Exemplul 10.1.1 Dezvolt
am un program client pentru servlet-ul CmmdcServlet.
java . u t i l . ;
o r g . apache . commons . h t t p c l i e n t . ;
o r g . apache . commons . h t t p c l i e n t . methods . ;
o r g . apache . commons . h t t p c l i e n t . params . HttpMethodParams ;
import
import
import
import
import j a v a . i o . ;
public c l a s s ClientCmmdcServlet {
private s t a t i c S t r i n g u r l = h t t p : / / l o c a l h o s t : 8 0 8 0 / m y s e r v l e t /cmmdc ;
1
2
3
9
11
12
13
14
15
16
18
19
21
22
23
25
26
27
28
29
30
UITE
10.2. SERVLETE INLANT
i f ( s t a t u s C o d e != H t t p S t a t u s . SC OK) {
System . e r r . p r i n t l n ( Method f a i l e d : + method . g e t S t a t u s L i n e ( ) ) ;
System . e x i t ( 0 ) ;
}
byte [ ] r e s p o n s e B o d y = method . getResponseBody ( ) ;
System . out . p r i n t l n ( Cmmdc = +(new S t r i n g ( r e s p o n s e B o d y ) ) ) ;
32
33
34
35
36
37
}
catch ( H t t p E x c e p t i o n e ) {
System . e r r . p r i n t l n ( Http e r r o r : + e . g e t M e s s a g e ( ) ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( I /O e r r o r : + e . g e t M e s s a g e ( ) ) ;
}
finally {
method . r e l e a s e C o n n e c t i o n ( ) ;
}
38
39
40
41
42
43
44
45
46
47
48
49
123
10.2
Servlete nl
antuite
Un servlet apeleaz
a la un moment dat alt servlet. Sablonul de lucru este
RequestDispatcher dispatcher=
getServletContext().getRequestDispatcher("/url_pattern_servlet_apelat");
if(dispatcher!=null)
dispatcher.include(request,response);
Exemplul 10.2.1 Un servlet VerifServlet verific
a parametri cererii. Pentru problema calculului celui mai mare divizor comun a dou
a numere, dac
a cei doi parametri
sunt numere ntregi, atunci se apeleaz
a servletul ComputeServlet, altfel se formeaz
a
un mesaj de eroare.
Codurile celor dou
a servlete sunt:
VerifServlet.java
package cmmdc ;
import j a v a . i o . ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;
public c l a s s V e r i f S e r v l e t extends H t t p S e r v l e t {
1
2
3
8
9
10
11
12
13
14
15
124
message=Numar a b s e n t ;
}
else {
try {
m=Long . par se Lon g ( sm ) ;
}
catch ( NumberFormatException e ) {
message=Nu e s t e numar ;
}
}
i f ( ( sn==n u l l ) | | ( sn . e q u a l s ( ) ) ) {
message=Numar a b s e n t ;
}
else {
try {
n=Long . p ars eL ong ( sn ) ;
}
catch ( NumberFormatException e ) {
message=Nu e s t e numar ;
}
}
out . p r i n t l n ( <html><body> ) ;
i f ( message . e q u a l s ( ) ) {
out . p r i n t l n ( <h3> R e z u l t a t u l obţ i n u t </h3> ) ;
R e q u e s t D i s p a t c h e r d i s p a t c h e r=
getServletContext ( ) . getRequestDispatcher ( / c a l c u l ) ;
i f ( d i s p a t c h e r != n u l l )
d i s p a t c h e r . i n c l u d e ( req , r e s ) ;
}
else {
out . p r i n t l n ( <h3> Date e r o n a t e </h3> ) ;
out . p r i n t l n ( message ) ;
}
out . p r i n t l n ( </body></html> ) ;
out . c l o s e ( ) ;
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
53
54
55
56
57
ComputeServlet.java
package cmmdc ;
import j a v a . i o . ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;
1
2
3
8
10
11
12
13
14
15
16
18
19
20
21
22
125
10.3
Sesiune de lucru
In cazul protocolului HTTP, de fiecare data cand un client deschide sau revine
la o pagin
a Web se deschide o nou
a conexiune cu serverul Web iar acesta nu retine
informatiile referitoare la client pe perioada conexiunii respective. Perioada de
timp cat un client este n conexiune cu o pagina Web se numeste sesiune.
Exist
a posibilitatea p
astr
arii unor informatii pe durata unei sesiuni (prin
mecanismul denumit Session Tracking).
Inaintea satisfacerii unei cereri, servletul verifica existenta unui obiect HttpSession.
Acest obiect se creaz
a la prima apelare de catre un client a servletului prin
HttpSession sesiune=request.getSession(true);
Un obiect HttpSession poate retine atribute, adica perechi de forma (nume,
valoare). Introducerea unui atribut se realizeaza prin
void setAttribute(String nume, Object valoare)
iar extragerea valorii unui atribut se obtine prin
Object getAttribute(String nume)
Metoda String nume[ ] getValueNames() returneaza numele tuturor
atributelor definite.
Un atribut se elimin
a cu metoda void removeAttribute(String nume).
Exemplul 10.3.1 Exemplul urm
ator num
ar
a de c
ate ori se apeleaz
a servletul ntr-o sesiune. Se defineste un atribut noAcces, care la prima apelare este
initializat iar apoi este m
arit cu c
ate o unitate la fiecare nou
a apelare a servletului.
import j a v a . i o . ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;
public c l a s s S e s i u n e extends H t t p S e r v l e t {
1
2
7
8
126
r e s . setContentType ( t e x t / html ) ;
S t r i n g mesaj ;
P r i n t W r i t e r out=r e s . g e t W r i t e r ( ) ;
H t t p S e s s i o n s e s s i o n=r e q . g e t S e s s i o n ( true ) ;
I n t e g e r c o n t o r =( I n t e g e r ) s e s s i o n . g e t A t t r i b u t e ( noAcces ) ;
i f ( c o n t o r==n u l l ) {
c o n t o r=new I n t e g e r ( 1 ) ;
mesaj= S a l u t ! ;
}
else {
c o n t o r=new I n t e g e r ( c o n t o r . i n t V a l u e ( ) + 1 ) ;
mesaj= Bine a t i r e v e n i t ! ;
}
s e s s i o n . s e t A t t r i b u t e ( noAcces , c o n t o r ) ;
out . p r i n t l n ( <html><body> ) ;
out . p r i n t l n ( <h1>+mesaj+</h1> ) ;
out . p r i n t l n ( Numarul de a c c e s a r i a l a c e a s t e i p a g i n i e s t e +
contor . intValue ( ) ) ;
out . p r i n t l n ( </body></html> ) ;
out . c l o s e ( ) ;
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
31
32
33
34
35
<html>
<head>
< t i t l e> S e s i u n e </ t i t l e>
</head>
<body>
<h1> Formular de a c c e s </h1>
<form method= g e t
action= h t t p : / / l o c a l h o s t : 8 0 8 0 / m y s e r v l e t / s e s i u n e >
<p>
<input type= submit value= A c c e s e a z a >
</form>
</body>
</html>
10.4
Cookie
10.4. COOKIE
127
1
2
3
import j a v a . i o . ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;
128
public c l a s s A p e l a r i extends H t t p S e r v l e t {
public void doGet ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
r e s . setContentType ( t e x t / html ) ;
S t r i n g mesaj= ;
P r i n t W r i t e r out=r e s . g e t W r i t e r ( ) ;
Cookie myCookie=n u l l ;
i n t c o n t o r =1;
Cookie [ ] c o o k i e s=r e q . g e t C o o k i e s ( ) ;
i f ( c o o k i e s != n u l l ) {
f o r ( i n t i =0; i <c o o k i e s . l e n g t h ; i ++){
S t r i n g name=c o o k i e s [ i ] . getName ( ) ;
i f ( name . e q u a l s ( u r m a r i r e ) ) {
c o n t o r=I n t e g e r . p a r s e I n t ( c o o k i e s [ i ] . g e t V a l u e ( ) ) ;
c o n t o r ++;
mesaj= Bine a t i r e v e n i t ! ;
}
}
}
else {
mesaj= S a l u t ! ;
}
myCookie=new Cookie ( u r m a r i r e , (new I n t e g e r ( c o n t o r ) ) . t o S t r i n g ( ) ) ;
myCookie . setMaxAge ( 1 0 0 0 0 0 0 ) ;
r e s . addCookie ( myCookie ) ;
out . p r i n t l n ( <html><body> ) ;
out . p r i n t l n ( <h1>+mesaj+</h1> ) ;
out . p r i n t l n ( Numarul de a c c e s a r i a l a c e a s t e i p a g i n i e s t e +c o n t o r ) ;
out . p r i n t l n ( </body></html> ) ;
out . c l o s e ( ) ;
}
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
38
39
40
41
42
10.5
import
import
import
import
import
java . io . ;
javax . s e r v l e t . ;
javax . s e r v l e t . http . ;
java . s q l . ;
java . net . ;
DE DATE
10.5. SERVLET CU CONEXIUNE LA O BAZA
7
8
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
32
33
34
35
36
public c l a s s A g e n d a E M a i l S e r v l e t extends H t t p S e r v l e t {
Statement i n s t r u c t i u n e=n u l l ;
public void i n i t ( S e r v l e t C o n f i g c o n f i g ) throws S e r v l e t E x c e p t i o n {
super . i n i t ( c o n f i g ) ;
// SGBD Derby
S t r i n g j d b c D r i v e r= o r g . apache . derby . j d b c . C l i e n t D r i v e r ;
S t r i n g URLBazaDate= j d b c : derby : / / l o c a l h o s t : 1 5 2 7 / AgendaEMail ;
C o n n e c t i o n con=n u l l ;
try {
C l a s s . forName ( j d b c D r i v e r ) . n e w I n s t a n c e ( ) ;
con=DriverManager . g e t C o n n e c t i o n ( URLBazaDate ) ;
i n s t r u c t i u n e=con . c r e a t e S t a t e m e n t ( ) ;
}
catch ( ClassNotFoundException e ) {
System . out . p r i n t l n ( D r i v e r i n e x i s t e n t JDBC : +j d b c D r i v e r ) ;
}
catch ( SQLException e ) {
System . out . p r i n t l n ( Baza de d a t e i n e x i s t e n t a +URLBazaDate ) ;
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( E r o a r e : +e . g e t M e s s a g e ( ) ) ;
}
}
public void doGet ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
S t r i n g myAtribut , myVal ;
r e s . setContentType ( t e x t / html ) ;
S e r v l e t O u t p u t S t r e a m out = r e s . getOutputStream ( ) ;
myAtribut=r e q . g e t P a r a m e t e r ( c r i t e r i u ) ;
myVal=r e q . g e t P a r a m e t e r ( termen ) ;
myVal= \ +myVal+ \ ;
try {
S t r i n g s q l= s e l e c t from a d r e s e where + myAtribut+ = +myVal ;
R e s u l t S e t r s=i n s t r u c t i u n e . e x e c u t e Q u e r y ( s q l ) ;
out . p r i n t l n ( <html> ) ;
out . p r i n t l n ( <head><t i t l e >AgendaEMail</ t i t l e ></head> ) ;
out . p r i n t l n ( <body> ) ;
out . p r i n t l n ( <h1>Agenda de Adrese em a i l </h1> ) ;
out . p r i n t l n ( <p/> ) ;
out . p r i n t l n ( <b>
Nume
<>
Adresa em a i l </b> ) ;
out . p r i n t l n ( <br/> ) ;
while ( r s . n e x t ( ) ) {
out . p r i n t ( r s . g e t S t r i n g ( nume)+ <> +r s . g e t S t r i n g ( e m a i l ) ) ;
out . p r i n t l n ( <br/> ) ;
}
out . p r i n t l n ( </body> ) ;
out . p r i n t l n ( </html> ) ;
out . c l o s e ( ) ;
}
catch ( SQLException e ) {
System . out . p r i n t l n ( SQLException : +e . g e t M e s s a g e ( ) ) ;
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( E r o a r e : +e . g e t M e s s a g e ( ) ) ;
}
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
129
130
67
68
69
70
71
<html>
<body>
<h1> Cautare i n baza de d a t e AgendaEMail</h1>
<form method= g e t
action= h t t p : / / l o c a l h o s t : 8 0 8 0 / agendae / a d r e s e >
<p>C r i t e r i u de c a u t a r e :
<s e l e c t name= c r i t e r i u >
<option value=nume>dupa Nume
<option value= e m a i l >dupa Email
</ s e l e c t>
<br>
<p>E n t i t a t e a c a u t a t a
<input type= t e x t name= termen s i z e =30>
<p><input type= submit value= Cauta >
</form>
</body>
</html>
10.6
Indic
am dou
a modalitati prin care un client obtine o imagine furnizata de
un servlet. Imaginea poate proveni dintr-un fisier extern sau poate fi creata de
servlet.
Imaginea este transmisa direct clientului n fluxul de iesire de tip
ServletOutputStream, tipul MIME al raspunsului fiind
response.setContentType("image/ext");
131
1
2
3
5
6
7
8
9
import j a v a . i o . ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;
public c l a s s MyGraphG extends H t t p S e r v l e t {
public void doGet ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
r e s . setContentType ( image / g i f ) ;
S e r v l e t O u t p u t S t r e a m out = r e s . getOutputStream ( ) ;
// R e f e r i n t a l a f i s i e r u l g r a f i c
String f =
d : \ \ apachetomcat 6 . 0 . 2 0 \ \ webapps \\ m y s e r v l e t \\WEBINF\\ +
c l a s s e s \\ w a l k i n g s a n t a . g i f ;
// T r a n f e r a r e a f i s i e r u l u i g r a f i c
F i l e I n p u t S t r e a m f i s = new F i l e I n p u t S t r e a m ( f ) ;
B u f f e r e d I n p u t S t r e a m b i s = new B u f f e r e d I n p u t S t r e a m ( f i s ) ;
byte [ ] b y t e s = new byte [ b i s . a v a i l a b l e ( ) ] ;
i n t nread = 0 ;
while (1 != ( nread = b i s . r e a d ( b y t e s ) ) ) {
out . w r i t e ( b y t e s , 0 , nread ) ;
}
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1
2
3
4
5
6
7
8
10
11
12
13
14
15
mport j a v a . i o . ;
import j a v a . awt . ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;
import j a v a x . i m a g e i o . ;
import j a v a . awt . image . ;
import j a v a x . i m a g e i o . stream . ;
import j a v a . u t i l . ;
public c l a s s MyGraphP extends H t t p S e r v l e t {
public void doGet ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
r e s . setContentType ( t e x t / html ) ;
P r i n t W r i t e r out=r e s . g e t W r i t e r ( ) ;
S t r i n g f i l e R e f=d : \ \ apachetomcat 6 . 0 . 2 0 \ \ webapps \\ m y s e r v l e t \\ ;
132
S t r i n g numeFis= d e s e n ;
S t r i n g e x t= j p g ;
// sau png
// Formarea i m a g i n i i
Frame frame = n u l l ;
Graphics g = null ;
B u f f e r e d I m a g e image=n u l l ;
try {
frame = new Frame ( ) ;
frame . a d d N o t i f y ( ) ;
image = ( B u f f e r e d I m a g e ) frame . c r e a t e I m a g e ( 8 0 0 , 6 0 ) ;
g = image . g e t G r a p h i c s ( ) ;
// F i x a r e a f o n t u l u i
g . s e t F o n t (new Font ( S e r i f , Font . ITALIC , 4 8 ) ) ;
// E d i t a r e a unui t e x t
g . d r a w S t r i n g ( T e h n o l o g i i d i s t r i b u i t e i n Java , 1 0 , 5 0 ) ;
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// S a l v a r e a i m a g i n i i i n t r un f i s i e r j p g sau png
F i l e f=new F i l e ( f i l e R e f+numeFis+ . +e x t ) ;
ImageIO . w r i t e ( image , j p g , f ) ;
32
33
34
// Raspunsul c a t r e c l i e n t
out . p r i n t l n ( <HTML><BODY> ) ;
out . p r i n t l n ( <h2>Imagine p r e l u a t a de pe s e r v e r </h2> ) ;
out . p r i n t l n ( <p><a h r e f =\ h t t p : / / l o c a l h o s t : 8 0 8 0 / m y s e r v l e t / +
numeFis+ . +e x t+\> ) ;
out . p r i n t l n ( V i z u a l i z a r e a i m a g i n i i </a> ) ;
out . p r i n t l n ( </BODY></HTML> ) ;
out . c l o s e ( ) ;
36
37
38
39
40
41
42
43
}
finally {
// E l i b e r a r e a r e s u r s e l o r
i f ( g != n u l l ) g . d i s p o s e ( ) ;
i f ( frame != n u l l ) frame . r e m o v e N o t i f y ( ) ;
}
44
45
46
47
48
49
50
51
Dac
a tipul fisierului grafic va fi gif atunci linia 34 se nlocuieste cu
FileOutputStream fos=new FileOutputStream(f);
GifEncoder encoder = new GifEncoder(image,fos);
encoder.encode();
Clasa GifEncoder care realizeaza codarea, face parte din pachetul Acme.JPM.Encoders,
disponibil gratuit la adresa web http://www.acme.com.
10.7
Filtru
10.7. FILTRU
133
<filter>
<filter-name>nume_filtru</filter-name>
<filter-class>clasa_filtrului</filter-class>
</filter>
<filter-mapping>
<filter-name>nume_filtru</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
. . .
</web-app>
Clasa filtrului implementeaz
a interfata Filter, adica metodele
public void init(FilterConfig filterConfig) throws ServletException
public void destroy()
public void doFilter(ServletRequest request,
ServletResponse response, FilterChain filterChain)
throws IOException, ServletException
Exemplul 10.7.1 Contextul myservlet contine doi servleti HelloServlet si CmmdcServlet, apelabili respectiv din hello.html, cmmdc.html. S
a se programeze un
filtru care
Redirecteaz
a solicitarea /myservlet/hello c
atre /cmmdc.html.
Dac
a se cere ca natura r
aspunsului s
a fie text/xml atunci invalideaz
a
cererea.
Servletii HelloServlet si CmmdcServlet sunt cei dezvoltati la nceputul acestui
capitol. Filtrul are codul
1
2
3
5
6
8
9
10
import j a v a . i o . IOException ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;
public c l a s s M y F i l t e r D i s p a t c h e r implements F i l t e r {
private F i l t e r C o n f i g f i l t e r C o n f i g ;
public void i n i t ( F i l t e r C o n f i g f i l t e r C o n f i g ) throws S e r v l e t E x c e p t i o n {
this . f i l t e r C o n f i g = f i l t e r C o n f i g ;
}
14
public void d e s t r o y ( ) {
this . f i l t e r C o n f i g = null ;
}
16
public void d o F i l t e r ( S e r v l e t R e q u e s t r e q u e s t , S e r v l e t R e s p o n s e r e s p o n s e ,
12
13
134
F i l t e r C h a i n f i l t e r C h a i n ) throws IOException , S e r v l e t E x c e p t i o n {
HttpServletRequest req = ( HttpServletRequest ) request ;
HttpServletResponse res = ( HttpServletResponse ) response ;
S t r i n g u r i = r e q . getRequestURI ( ) ;
i f ( u r i . equals ( / myservlet ) | | u r i . equals ( / myservlet / ) )
f i l t e r C h a i n . doFilter ( request , response ) ;
else {
i f ( u r i . equals ( / myservlet / h e l l o )){
S t r i n g d i s p a t c h e r U r i= /cmmdc . html ;
R e q u e s t D i s p a t c h e r rd=r e q u e s t . g e t R e q u e s t D i s p a t c h e r ( d i s p a t c h e r U r i ) ;
rd . f o r w a r d ( r e q u e s t , r e s p o n s e ) ;
}
else {
i n t i n d e x=u r i . l a s t I n d e x O f ( . ) ;
i f ( i n d e x==1){
S t r i n g t i p=r e q . g e t P a r a m e t e r ( t i p ) ;
i f ( t i p . e q u a l s ( t e x t /xml ) ) {
r e s . s e n d E r r o r ( H t t p S e r v l e t R e s p o n s e . SC FORBIDDEN ) ;
}
}
f i l t e r C h a i n . doFilter ( request , response ) ;
}
}
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
30
<s e r v l e t mapping>
<s e r v l e t name> h e l l o</ s e r v l e t name>
<u r l p a t t e r n>/ h e l l o</ u r l p a t t e r n>
</ s e r v l e t mapping>
32
<s e r v l e t mapping>
27
28
29
10.7. FILTRU
33
34
35
37
<html>
<head>
< t i t l e>
Cmmdc S e r v l e t
</ t i t l e>
</head>
<body bgcolor=#c c b b c c >
<center>
<h1> Cmmdc S e r v l e t </h1>
<form method= g e t
action= h t t p : / / l o c a l h o s t : 8 0 8 0 / m y s e r v l e t /cmmdc>
<table border= 1 >
<tr>
<td> Primul numar </td>
<td> <input type= t e x t name=m s i z e =10> </td>
</ tr>
<tr>
<td> Al d o i l e a numar </td>
<td> <input type= t e x t name=n s i z e =10> </td>
</ tr>
<tr>
<td> Natura r a s p u n s u l u i </td>
<td> <s e l e c t name= t i p >
<option value= t e x t / html > t e x t / html
<option value= t e x t / p l a i n > t e x t / p l a i n
<option value= t e x t /xml> t e x t /xml
</ s e l e c t> </td>
</ tr>
<tr>
<td> <input type= submit value= C a l c u l e a z a > </td>
<td></td>
</ tr>
</ table>
</form>
</ center>
</body>
</html>
135
Unitatea de nv
atare 11
Durata: 4 ore.
Introducere
11.1
Tehnologia JSP
137
http://host:port/cale/doc.jsp
referint
a html
<a href="http://host:port/cale/doc.jsp">
valoare a atributului action ntr-un marcaj form
<form action="http://host:port/cale/doc.jsp" ...
>
<html>
<body>
Hello
</body>
</html>
n Hello.jsp si plas
andu-l n catalogul jsp se obtine acelasi efect, dar prelucrarea
paginilor / documentelor este diferita. Fisierul html este prelucrat doar de programul navigator si poate fi deschis ca fisier, n timp ce fisierul JSP este prelucrat de
serverul Web cu afisarea prin intermediul navigatorului. Prelucrarea efectuata
de serverul Web const
a din transformarea paginii / documentului JSP ntr-un
servlet, care este compilat si lansat n executie. Din aceastra cauza prima invocare a paginii / documentului JSP dureaza mai mult decat apelarile ulterioare.
Apelarea paginii / documentului JSP se face prin
http://localhost:8080/JSPApp/jsp/Hello.jsp
Exist
a dou
a moduri de a include elemente JSP ntr-un text html:
prin elemente specifice JSP.
Fisierul are extensia jsp si se numeste pagin
a JSP.
prin marcaje xml apartin
and spatiului de nume
http://java.sun.com/JSP/Page
138
Fisierul poate avea extensia jsp sau jspx si se numeste document JSP.
Comentariile JSP se scriu de forma
<%-- Comentariu --%>
Consider
am urm
atorul exemplu introductiv:
Exemplul 11.1.1 Putem afisa valoarea unei variabile Java (de exemplu data
calendaristic
a) prin
Varianta paginii JSP
1
2
3
4
5
7
8
9
10
12
13
14
15
16
17
<html>
<body>
<p>
Data c a l e n d a r i s t i c a 1 :
<%= new j a v a . u t i l . Date ( ) %>
<p>
<% j a v a . u t i l . Date data1=new j a v a . u t i l . Date ( ) ; %>
Data c a l e n d a r i s t i c a 2 :
<%= data1 %>
<p>
<% j a v a . u t i l . Date data2=new j a v a . u t i l . Date ( ) ; %>
Data c a l e n d a r i s t i c a 3 :
<% out . p r i n t ( data2 ) ; %>
</body>
</html>
Dac
a se utilizeaz
a operatorul de afisare = atunci dupa expresia de afisat nu
se pune ;.
Variabila predefinita out este de tip javax.servlet.jsp.JspWriter.
Varianta documentului JSP
1
2
3
4
5
6
7
8
9
Codul Java inglobat ntr-un text html se numeste scriptlet. Sintaxa utilizat
a
este
Varianta paginii JSP
139
Domeniu de valabilitate
pagina curent
a
n pagina curenta,
n paginile incluse si
n paginile c
atre care se face o redirectare
session
n sesiunea curenta
application pe durata rul
arii aplicatiei
In orice pagin
a
Variabila
out
request
response
session
page
pageContext
application
exception
Astfel
String request.getParameter(String numeParametru)
furnizeaz
a valoarea parametrului numeParametru dintr-un formular html.
Exemplul 11.1.2 Pagina JSP Hello: Clientul transmite numele paginii care i
r
aspunde cu mesajul de salut Hi + nume + !.
Codul paginii JPS (hello.jsp) este
1
2
3
4
5
6
<html>
<head>
< t i t l e> j s p h e l l o </ t i t l e>
</head>
<body>
<center>
140
7
8
9
10
11
12
13
14
<html>
<head>
< t i t l e> JSP H e l l o </ t i t l e>
</head>
<body bgcolor=#bbeebb >
<center>
<h1> Pagina de a p e l a r e JSP </h1>
<form method= p o s t
action= h t t p : / / l o c a l h o s t : 8 0 8 0 / j s p h e l l o / j s p / h e l l o . j s p >
<p> Numele :
<input type= t e x t name=name s i z e =20>
<p>
<input type= submit >
</form>
</ center>
</body>
</html>
Compilarea si arhivarea servlet-ului o vom realiza prin intermediul lui apacheant. In acest scop se creaza structura:
jsphello
|
|--> jsp
|
|
|
hello.jsp
|
|--> lib
|
|--> src
|
|--> web
|
|
|
web.xml
|
|--> web-files
|
|
|
index.html
|
build.xml
4
5
7
8
9
10
11
12
<webapp>
<welcomef i l e l i s t>
<welcome f i l e >i n d e x . html</ welcome f i l e >
<welcome f i l e >i n d e x . j s p</ welcome f i l e >
</ welcomef i l e l i s t>
</webapp>
1
3
4
5
6
8
9
10
11
12
13
15
16
17
18
19
20
21
22
23
25
26
27
28
29
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
141
<path i d= m y c l a s s p a t h >
< f i l e s e t d i r= l i b >
<include name= . j a r />
</ f i l e s e t>
<pathelement path= ${TOMCAT HOME}/ l i b / s e r v l e t a p i . j a r />
</path>
<target name= i n i t >
<delete d i r= ${ d i s t . d i r } />
<mkdir d i r= ${ b u i l d . d i r } />
<mkdir d i r= ${ d i s t . d i r } />
<mkdir d i r= ${ b u i l d . d i r }/ j s p />
<mkdir d i r= ${ b u i l d . d i r }/WEBINF />
<mkdir d i r= ${ b u i l d . d i r }/WEBINF/ c l a s s e s />
<mkdir d i r= ${ b u i l d . d i r }/WEBINF/ l i b />
</ target>
<target name= c o m p i l e depends= i n i t >
<javac c l a s s p a t h r e f= m y c l a s s p a t h
s r c d i r= ${ b a s e d i r }/ s r c
d e s t d i r= ${ b u i l d . d i r }/WEBINF/ c l a s s e s />
</ target>
<target name= g e n e r a t e . war depends= c o m p i l e >
<copy t o d i r= ${ b u i l d . d i r } >
< f i l e s e t d i r= ${ b a s e d i r }/web f i l e s >
<include name= . html />
</ f i l e s e t>
</copy>
<copy t o d i r= ${ b u i l d . d i r }/ j s p >
< f i l e s e t d i r= ${ b a s e d i r }/ j s p >
<include name= . j s p />
<include name= . j s p x />
</ f i l e s e t>
</copy>
<copy t o d i r= ${ b u i l d . d i r }/WEBINF >
< f i l e s e t d i r= ${ b a s e d i r }/web >
<include name= . xml />
</ f i l e s e t>
</copy>
<copy t o d i r= ${ b u i l d . d i r }/WEBINF/ l i b >
< f i l e s e t d i r= ${ b a s e d i r }/ l i b >
<include name= . j a r />
</ f i l e s e t>
</copy>
<copy t o d i r= ${ b u i l d . d i r } >
< f i l e s e t d i r= ${ b a s e d i r } >
<include name= . p r o p e r t i e s />
</ f i l e s e t>
</copy>
<j a r d e s t f i l e = ${ d i s t . d i r }/${ d i s t . name } . war b a s e d i r= ${ b u i l d . d i r } />
</ target>
142
60
</ project>
11.1.1
Declaratii JSP
<html>
<body>
<H1> CMMDC </H1>
<%!
l o n g cmmdc( l o n g m, l o n g n ) {
long c , r ;
do {
c=n ;
r=m%n ;
m=n ;
n=r ;
} while ( r !=0);
return c ;
}
%>
Rezultatul este
<%
String sm=r e q u e s t . g e t P a r a m e t e r ( m ) ;
String sn=r e q u e s t . g e t P a r a m e t e r ( n ) ;
l o n g m=Long . pa rse Lo ng ( sm ) , n=Long . pa rse Lo ng ( sn ) ;
out . p r i n t l n (cmmdc(m, n ) ) ;
%>
</body>
</html>
<html>
<body>
<h1> C a l c u l u l Cmmdc </h1>
<form method= p o s t
action= h t t p : / / l o c a l h o s t : 8 0 8 0 / JSPApp/ j s p /cmmdc . j s p >
<p>
Primul numar e s t e
<input type= t e x t name=m value= s i z e=5>
143
9
10
11
12
13
14
15
16
17
<p>
Al d o i l e a numar e s t e
<input type= t e x t name=n value= s i z e=5>
<p>
<input type= submit value= C a l c u l e a z a >
<input type= r e s e t value=Abandon>
</form>
</body>
</html>
Exist
a dou
a metode jspInit() - utilizata pentru initializarea datelor -, si
jspDestroy() - utilizat
a pentru eliberarea resurselor -, care daca sunt declarate
de programator atunci sunt executate la nceputul si la sfarsitul ciclului de executie
a paginii / documentului JSP.
11.1.2
Directive JSP
list
a de pachete separate prin ,
text Informatia se poate regasi apeland metoda
getServletInfo()
adresa url a paginii ce trateaz
a exceptia
"true | false"
Directiva include permite includerea unor fisiere .html sau .jsp n document
<%@ include file=fisier html, jsp %>
Includerea are loc n locul n care apare directiva.
Referinta la fisierul html sau jsp se face relativ la catalogul paginii JSP
initiale (adic
a cea n care apare directiva).
Directiva taglib indic
a bibliotecile de marcaje utilizate n documentul jsp,
av
and atributele
uri=
uri - Universal Resource Identifier - a bibliotecii de marcaje
prefix= prefixul marcajului
144
11.1.3
<jsp :
useBean id=numeComponent
aJava
class=numeClasa
scope=domeniu />
setProperty name=numeComponent
aJava
property=numeProp
value=valoare/>
145
getProperty name=numeComponent
aJava
property=numeProp/>
Preia si afiseaz
a valoarea c
ampului numeComponent
aJava.numeProp.
11.1.4
Component
a Java (Java Bean)
O component
a Java este o clasa care poate interactiona cu alte componente
Java, cu un document jsp, etc.
O componenta Java contine cel putin
Un constructor f
ar
a nici un argument;
O multime de c
ampuri declarate private;
Pentru fiecare asemenea c
amp
private Tip xyz;
trebuie definite metodele
public void setXyz(Tip xyz){
this.xyz=xyz;
}
public Tip getXyz(){
return xyz;
}
11.1.5
Clasa componentei Java care se va utiliza ntr-o pagina JSP trebuie inclusa
ntr-un pachet.
Relu
am exemplul 11.1.2 cu o componenta Java corespunzatoare numelui din
formularul index.html.
Exemplul 11.1.4
146
1
2
3
4
5
6
7
8
9
10
package j s p ;
public c l a s s H e l l o B e a n {
private S t r i n g name= ;
public S t r i n g getName ( ) {
return name ;
}
public void setName ( S t r i n g name ) {
t h i s . name=name ;
}
}
In vederea gener
arii arhivei war, desfasurarea aplicatiei va fi
jsphello
|
|
|
|
|
|
|
|
|
|
|
147
|---> jsp
|
|
hello.jsp
|---> lib
|---> src
|
|---> jsp
|
|
|
HelloBean.java
|---> web
|
|
web.xml
|---> web-files
|
|
index.html
build.xml
package cmmdc ;
public c l a s s CmmdcBean{
private S t r i n g m= ;
private S t r i n g n= ;
private S t r i n g cmmdc ;
public void setM ( S t r i n g m) {
t h i s .m=m;
}
public void setN ( S t r i n g n ) {
t h i s . n=n ;
}
public S t r i n g getM ( ) {
return m;
}
public S t r i n g getN ( ) {
return n ;
}
7
8
9
10
11
12
13
14
15
16
17
18
24
public S t r i n g getCmmdc ( ) {
long m=Long . par se Lo ng ( getM ( ) ) ;
long n=Long . pa rs eL ong ( getN ( ) ) ;
return (new Long (cmmdc(m, n ) ) ) . t o S t r i n g ( ) ;
}
26
20
21
22
23
28
148
7
8
9
10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
3
4
5
7
8
10
11
13
14
15
16
17
18
20
21
< !
Aceste comentarii sunt f o a r t e importante in c a z u l u t i l i z a r i i
n a v i g a t o r u l u i IE s i a l u i apachetomcat 5 . . . / 6 . . . In l i p s a
l o r nu s e g e n e r e a z a s a l t u l l a e x c e p t i e p r i n p a g i n a j s p .
R o l u l c o m e n t a r i i l o r e s t e marirea l u n g i m i i f i s i e r u l u i de f a t a .
O a l t e r n a t i v a e s t e ca d i n IE6 . . . O p t i o n s sa s e d e z a c t i v e z e
o p t i u n e a Show f r i e n d l y HTTP e r r o r message
Cu n a v i g a t o r u l F i r e f o x nu e x i s t a a c e a s t a problema .
>
<%@ page i s E r r o r P a g e= t r u e %>
<html>
<body>
<div a l i g n= c e n t e r >
<%= e x c e p t i o n . g e t M e s s a g e ( ) %>
</ div>
</body>
</html>
apelate prin
1
2
3
<html>
<body>
<form method=p o s t
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
149
action= h t t p : / / l o c a l h o s t : 8 0 8 0 / m y s e r v l e t / j s p / e r r h a n d l e r . j s p >
Care e s t e m a t e r i a p r e f e r a t a d i n a n i i de s t u d i u u n i v e r s i t a r ?
<p>
A l g o r i t m i c a s i programare
<input type= r a d i o name= m a t e r i a value=AP checked>
<p>
A n a l i z a numerica
<input type= r a d i o name= m a t e r i a value=AN>
<p>
Inteligenta artificiala
<input type= r a d i o name= m a t e r i a value=IA>
<p>
<input type=submit>
</form>
</body>
</html>
11.2
11.2.1
Biblioteca de baz
a
150
c:set Fixeaz
a o valoare ntr-o variabila.
Atribute ale marcajului:
Atribut
var
Fel
obligatoriu
value
optional
scope
optional
Descriere
Numele variabilei ce va stoca valoarea
expresiei.
Expresia care va fi evaluata si atribuita
variabilei
Domeniul de valabilitate al variabilei.
Unul din valorile:
page, request, session, application.
Fel
obligatoriu
optional
Descriere
Numele variabilei ce se sterge.
Domeniul de valabilitate al variabilei.
Unul din valorile:
page, request, session, application.
c:out Afiseaz
a o valoare.
Atribute ale marcajului:
Atribut
value
default
Fel
obligatoriu
optional
escapeXml
optional
151
Descriere
Valoarea ce se evalueaza si se afiseaza.
Cea ce se afiseaza n cazul n care
expresia nu poate fi evaluata.
true / false. Valoarea implicita este true.
Pe false interpreteaza caracterele din value
ca si cod html.
Fel
obligatoriu
optional
scope
optional
Descriere
Conditia de test.
Numele variabilei ce va stoca valoarea
testului.
Domeniul de valabilitate al variabilei
definita anterior.
<HTML>
<%@ t a g l i b u r i= h t t p : / / j a v a . sun . com/ j s p / j s t l / c o r e p r e f i x= c %>
<BODY>
<p>
<c : i f t e s t= $ {empty param . nume} var= testNume >
<c : out value=Numele l i p s e s t e ! />
</ c : i f>
<c : i f t e s t= $ { not testNume } >
Nume :<c : out value= $ {param . nume} />
</ c : i f>
<p>
<c : i f t e s t= $ {empty param . prenume } var= testPrenume >
<c : out value= Prenumele l i p s e s t e ! />
</ c : i f>
<c : i f t e s t= $ { not testPrenume } >
Prenume :<c : out value= $ {param . prenume } />
</ c : i f>
<p>
<c : i f t e s t= $ {empty param . e m a i l } var= t e s t E m a i l >
<c : out value= Adresa EMail l i p s e s t e ! />
</ c : i f>
<c : i f t e s t= $ { not t e s t E m a i l } >
Em a i l :<c : out value= $ {param . e m a i l } />
</ c : i f>
</BODY>
</HTML>
152
Fel
optional
optional
begin
end
step
varStatus
optional
optional
optional
optional
Descriere
Colectia care se parcurge.
Numele variabilei n care se stocheaza
valoarea elementului curent.
Valoarea initiala a variabilei var.
Valoarea finala a variabilei var.
Valoarea pasului de iterare. Implicit este 1.
Informatii despre elementul curent.
153
c:forTokens Asigur
a aceasi functionalitate ca si clasei java.util.String
Tokenizer.
Atribute ale marcajului:
Atribut
value
Fel
obligatoriu
default
optional
escapeXml
optional
Descriere
Valoarea ce se evalueaza si se afiseaza.
expresiei.
Cea ce se afiseaza n cazul n care
expresia nu poate fi evaluata.
true / false. Valoarea implicita este true.
Pe false interpreteaza caracterele din value
ca si cod html.
Fel
obligatoriu
optional
var
optional
scope
optional
Descriere
Adresa documentului importat.
Context-ul paginii / documentului importat.
Simbolul /, urmat de numele unei aplicatii
de pe acelasi server.
Numele variabilei n care va fi stocat
documentul importat.
Domeniul de valabilitate al variabilei var.
Unul din valorile:
page, request, session, application.
154
Atribut
url
context
Fel
obligatoriu
optional
Descriere
Adresa paginii catre care se face redirectarea.
Context-ul paginii catre care se face redirectarea.
Simbolul /, urmat de numele unei aplicatii
de pe acelasi server.
Fel
obligatoriu
optional
var
optional
scope
optional
11.2.2
Descriere
Adresa documentului de retinut.
Context-ul documentului.
Simbolul /, urmat de numele unei aplicatii
de pe acelasi server.
Numele variabilei n care va fi stocata
adresa documentului.
Domeniul de valabilitate al variabilei var.
Unul din valorile:
page, request, session, application.
Fel
optional
optional
optional
optional
optional
optional
optional
Descriere
Referinta la baza de date
Driver-ul bazei de date
url-ul bazei de date
nume utilizatorului bazei de date
parola de acces la baza de date
variabila cu referinta la baza de date
Domeniul de valabilitate al variabilei var.
Atribut
sql
dataSource
startRow
maxRows
var
Fel
obligatoriu
optional
optional
optional
obligatoriu
scope
optional
155
Descriere
Fraza sql
Referinta la baza de date
Linia de la care se ncepe interogarea
Numarul maxim de rezultate acceptate
Variabila cu rezultatele interogarii
bazei de date
Domeniul de valabilitate al variabilei var.
Fel
obligatoriu
optional
Descriere
Fraza sql
Referinta la baza de date
Exemplul 11.2.5 S
a se afiseze lista din agenda telefonic
a creat
a n exemplul
din Cap. Servlet.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<HTML>
<%@ t a g l i b u r i= h t t p : / / j a v a . sun . com/ j s p / j s t l / c o r e p r e f i x= c %>
<%@ t a g l i b u r i= h t t p : / / j a v a . sun . com/ j s p / j s t l / s q l p r e f i x= s q l %>
<BODY>
<p>
<s q l : s e t D a t a S o u r c e
d r i v e r= o r g . apache . derby . j d b c . C l i e n t D r i v e r
u r l= j d b c : derby : / / l o c a l h o s t : 1 5 2 7 / A g e n d a T e l e f o n i c a
var=db />
<s q l : query
d a t a S o u r c e= $ {db}
var= r e z u l t
s q l= s e l e c t from t e l e f />
<c : i f t e s t= $ { r e z u l t . rowCount g t 0} >
<table>
<tr>
<c : f o r E a c h i t e m s= $ { r e z u l t . columnNames} var= c o l >
<th>
<c : out value= $ { c o l } />
</th>
</ c : f o r E a c h>
</ tr>
<c : f o r E a c h i t e m s= $ { r e z u l t . rowsByIndex } var= l i n e >
<tr>
<c : f o r E a c h i t e m s= $ { l i n e } var= elem >
<td>
<c : out value= $ { elem } />
</td>
</ c : f o r E a c h>
</ tr>
</ c : f o r E a c h>
</ table>
156
33
34
35
</ c : i f>
</BODY>
</HTML>
Unitatea de nv
atare 12
Portlet
Durata: 3 ore.
Introducere
Prezentarea termenului de portlet se face mpreuna cu cea de portal. Portalul
ca si portletul sunt aplicatii Web. Practic, un portal accesat afiseaza portlete
n ferestre distincte, portletele fiind aplicatii pe care clientul le poate folosi (Fig.
12.1, Fig. 12.2).
O aplicatie portlet ndeplineste standardele JSR (Java Specification Request)
168 si JSR 286.
Portalul este o aplicatie Web cu functionalitatile:
Container de portleti. Containerul este responsabil de initializarea si distrugerea portletilor, de transmiterea cererilor catre portleti si de colectarea
raspunsurilor.
157
158
159
12.1. APACHE-PLUTO
Agregarea continuturilor (Content aggregator). Permite afisarea si gestionarea mai multor portlete.
Asigur
a servicii dintre care amintim:
acces la portal pe baz
a de autentificare si autorizare. Odata autorizat,
un client are acces la orice portlet.
posibilitatea personaliz
arii portletelor de catre clienti.
Varietatea serviciilor variaz
a de la un portal la altul.
Portletul este o aplicatie Web care se aseamana cu servletul prin:
Se instaleaz
a ntr-un container.
Genereaz
a continut dinamic.
Ciclul de viat
a este gestionat de container.
Interactioneaz
a cu clientul prin modelul request/reply.
Deosebirile unui portlet fat
a de un servlet sunt:
Portletul posed
a mai multe variante de tratare a cererilor.
Prin conceptul de mod (mode) se specifica variante distincte prin care
portletul reactioneaz
a. Sunt definite modurile VIEW, EDIT, HELP. Actiunile
corespunz
atoare sunt definite n metodele doView, doEdit, doHelp.
Prin WindowState se fixeaz
a spatiul utilizat de portlet. Valorile variabilei
WindowState sunt NORMAL, MAXIMIZED, MINIMIZED. In varianta MAXIMIZED portletul ocup
a ntreaga fereastra, n timp ce n varianta MINIMIZED portletul apare ntr-o bara de titluri.
12.1
Apache-pluto
Pentru dezvoltarea unui portlet vom folosi produsul Apache-pluto care genereaza
un portal n care se pot instala / dezinstala usor portlete.
Instalarea produsului. Daca se descarca varianta ncorporata n serverul
Web apache-tomcat, denumit
a pluto-bundle, atunci instalarea la dezarhivarea
fisierului desc
arcat.
Utilizarea produsului. Dintr-un navigator, portalul se apeleaza prin
http://host:8080/pluto/portal
Accesul se face cu User name = password = pluto.
Instalarea unui portlet se face n 2 pasi:
160
1. Desf
asurarea portlet-ului: Fisierul arhivat al portletului, avand extensia
war, se depune n catalogul PlutoDomain. Apeland managerul lui apachetomcat din componenta Pluto admin se obtine instalarea portletului.
Alternativ, desf
asurarea portlet-lui se va obtine cu apache-ant cu utilizarea
unui fisier build.xml dedicat.
2. Publicarea portlet-ului se face prin componenta Pluto admin.
12.2
43
44
45
46
47
48
49
50
51
53
54
55
56
57
58
59
60
62
63
64
65
66
78
80
< a n t c a l l t a r g e t= a s s e m b l e />
68
69
70
71
72
73
74
75
76
77
86
88
90
82
83
84
85
91
92
93
94
95
96
97
98
99
100
101
161
162
102
103
104
105
106
107
108
109
110
111
113
</ t a r g e t>
115
116
117
119
</ p r o j e c t>
Fisierul de propriet
ati build.properties este
1
2
4
5
7
8
9
11
12
14
15
16
17
19
20
22
23
25
26
28
29
32
33
#b u i l d . p r o p e r t i e s
#Standard p r o p e r t i e s f o r Ant b u i l d o f a P l u t o 1 . 1 p o r t l e t
#module name
app . name=NumePortlet
#D i r e c t o r y t h a t h o l d s s o u r c e code
s r c . d i r = s r c / main
j a v a . s r c . d i r = ${ s r c . d i r }/ j a v a
#D i r e c t o r y t h a t h o l d s documentation
doc . d i r = d o c s
#D i r e c t o r y t h a t h o l d s f i l e s t o be b u i l t i n t o a j a r , war o r e a r
build . dir = build
w e b b u i l d . d i r = ${ b u i l d . d i r }/ webapp
c l a s s b u i l d . d i r = ${ w e b b u i l d . d i r }/WEBINF/ c l a s s e s
#D i r e c t o r y t h a t h o l d s c o n f i g u r a t i o n
c o n f . d i r = ${ s r c . d i r }/ r e s o u r c e
files
#D i r e c t o r y t h a t h o l d s l i b r a r i e s r e q u i r e d t o b u i l d and run t h e c l a s s e s
lib . dir = lib
#D i r e c t o r y t h a t h o l d s webapp f i l e s
web . d i r = ${ s r c . d i r }/ webapp
#WEBINF d i r e c t o r y
webi n f . d i r = ${web . d i r }/WEBINF
#D i r e c t o r y t h a t h o l d s f i l e s t o b u i l d d i s t r i b u t i o n
d i s t . d i r = ${ b u i l d . d i r }/ d i s t
|-->
|
|
|
|
|
|
|
|
|
|-->
|
|
|
|
|
|
|
|
|
|
|
163
lib
| castor-1.1.1.jar
| commons-logging-1.0.4.jar
| pluto-ant-tasks-2.0.*.jar
| pluto-descriptor-api-1.1.6.jar
| pluto-descriptor-impl-1.1.6.jar
| pluto-util-2.0.*.jar
| pluto-container-2.0.0.jar
| jaxb-api-2.1.jar
| jaxb-impl-2.1.9.jar
src
|--> main
|
|--> java
|
|
|--> pachetul portletului
|
|--> resource
|
|
|
NumePortlet.xml
|
|--> webapp
|
|
|--> jsp
|
|
|
|
fisierele jsp ale portletului
|
|
|--> WEB-INF
|
|
|
|
portlet.xml
|
|
|
|
web.xml
5
6
7
8
10
</webapp>
164
12.3
Elemente de programare
165
package h e l l o ;
import j a v a . i o . ;
import j a v a x . p o r t l e t . ;
public c l a s s H e l l o W o r l d P o r t l e t extends G e n e r i c P o r t l e t {
protected void doView ( RenderRequest r e q u e s t , RenderResponse r e s p o n s e )
throws P o r t l e t E x c e p t i o n , IOException {
r e s p o n s e . setContentType ( t e x t / html ) ;
r e s p o n s e . g e t W r i t e r ( ) . p r i n t l n ( H e l l o World ! ) ;
}
// A l t a v a r i a n t a de programare
/
p u b l i c v o i d doView ( RenderRequest req , RenderResponse r e s )
t h r o w s P o r t l e t E x c e p t i o n , IOException {
r e s . s e t C o n t e n t T y p e ( t e x t / html ) ;
P r i n t W r i t e r o u t=r e s . g e t W r i t e r ( ) ;
o u t . p r i n t l n (<h2 >);
o u t . p r i n t l n ( H e l l o World ! ) ;
o u t . p r i n t l n (</h2 >);
}
/
12
13
14
15
16
17
18
19
20
21
22
23
166
1
2
3
5
6
7
8
9
10
11
package h e l l o p l u t o ;
import j a v a . i o . ;
import j a v a x . p o r t l e t . ;
public c l a s s H e l l o P l u t o P o r t l e t extends G e n e r i c P o r t l e t {
public void doView ( RenderRequest req , RenderResponse r e s )
throws P o r t l e t E x c e p t i o n , IOException {
r e s . setContentType ( t e x t / html ) ;
W r i t e r out=r e s . g e t W r i t e r ( ) ;
out . w r i t e ( <s t r o n g >H e l l o P l u t o i n view mode</s t r o n g > ) ;
}
public void doEdit ( RenderRequest req , RenderResponse r e s )
throws P o r t l e t E x c e p t i o n , IOException {
r e s . setContentType ( t e x t / html ) ;
W r i t e r out=r e s . g e t W r i t e r ( ) ;
out . w r i t e ( <i >H e l l o P l u t o i n e d i t mode</i > ) ;
}
13
14
15
16
17
18
20
21
22
23
24
25
26
<?xml v e r s i o n= 1 . 0 e n c o d i n g=UTF8?>
<p o r t l e t app xmlns= h t t p : / / j a v a . sun . com/xml/ ns / p o r t l e t / p o r t l e t a p p 2 0 . xsd
xmlns : x s i= h t t p : / /www. w3 . o r g /2001/XMLSchemai n s t a n c e
x s i : s c h e m a L o c a t i o n= h t t p : / / j a v a . sun . com/xml/ ns / p o r t l e t / p o r t l e t a p p 2 0 . xsd
h t t p : / / j a v a . sun . com/xml/ ns / p o r t l e t / p o r t l e t a p p 2 0 . xsd
i d= myPortletApp v e r s i o n= 2 . 0 >
<p o r t l e t >
<d e s c r i p t i o n >H e l l o P l u t o a s a p o r t l e t app</ d e s c r i p t i o n >
<p o r t l e t name>H e l l o P l u t o P o r t l e t </ p o r t l e t name>
<d i s p l a y name>H e l l o Pluto </ d i s p l a y name>
<p o r t l e t c l a s s >h e l l o p l u t o . H e l l o P l u t o P o r t l e t </ p o r t l e t c l a s s >
<s u p p o r t s >
<mimetype>t e x t / html</mimetype>
<p o r t l e t mode>VIEW</ p o r t l e t mode>
<p o r t l e t mode>EDIT</ p o r t l e t mode>
<p o r t l e t mode>HELP</ p o r t l e t mode>
</s u p p o r t s >
<p o r t l e t i n f o >
< t i t l e >H e l l o P l u t o P o r t l e t </ t i t l e >
</ p o r t l e t i n f o >
</ p o r t l e t >
</ p o r t l e t app>
package h e l l o n a m e ;
3
5
import j a v a . i o . ;
import j a v a x . p o r t l e t . ;
import j a v a . u t i l . Enumeration ;
public c l a s s H e l l o N a m e P o r t l e t extends G e n e r i c P o r t l e t {
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
34
35
36
37
38
39
40
41
42
43
44
167
168
13
</ div>
si respectiv
1
2
3
4
5
6
7
8
9
10
package cmmdc ;
3
5
import j a v a . i o . ;
import j a v a x . p o r t l e t . ;
import j a v a . u t i l . Enumeration ;
9
10
11
12
13
14
15
16
17
18
19
20
21
22
33
35
24
25
26
27
28
29
30
31
32
37
169
21
23
</ div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
si respectiv
1
2
4
5
6
7
8
10
11
12
13
Variant
a n care calculul este programat ntr-o component
a Java (bean)
si care este apelat n pagina jsp de afisare a rezultatului.
1
package cmmdc ;
3
5
import j a v a . i o . ;
import j a v a x . p o r t l e t . ;
import j a v a . u t i l . Enumeration ;
9
10
11
12
13
14
15
170
prd . i n c l u d e ( req , r e s ) ;
}
else {
prd=g e t P o r t l e t C o n t e x t ( ) . g e t R e q u e s t D i s p a t c h e r ( / j s p /outputCmmdc . j s p ) ;
prd . i n c l u d e ( req , r e s ) ;
}
16
17
18
19
20
21
22
24
25
26
27
28
29
30
31
32
33
34
35
36
public c l a s s CmmdcBean{
private S t r i n g m= ;
private S t r i n g n= ;
3
4
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Pagina outputCmmdc.jsp
1
2
171
< p o r t l e t : d e f i n e O b j e c t s />
<P>
<%
String r e s u l t=Cmmdc +myCmmdcBean . cmmdc ( ) ;
out . p r i n t l n ( r e s u l t ) ;
%>
<P>
<a href=< p o r t l e t : renderURL p o r t l e t M o d e= view windowState= normal />>
Reluare
</a>
8
9
10
11
12
13
14
15
Variant
a n care care calculul este programat ntr-un servlet. Servletul
utilizat este cel prezentat n capitolul Servlet, (9.3.2), dar inclus n pachetul
portlet-ului. Fisierul inputCmmdc.jsp are n plus linia
<input type="hidden" name="tip" value="text/html"/>
apare
prd=getPortletContext().getRequestDispatcher("/cmmdc");
4
5
6
7
9
10
11
12
14
15
16
17
18
< s e r v l e t>
<s e r v l e t name>CmmdcServlet</ s e r v l e t name>
<s e r v l e t c l a s s>cmmdc . CmmdcServlet</ s e r v l e t c l a s s>
</ s e r v l e t>
<s e r v l e t mapping>
<s e r v l e t name>CmmdcServlet</ s e r v l e t name>
<u r l p a t t e r n>/cmmdc</ u r l p a t t e r n>
</ s e r v l e t mapping>
</webapp>
Interfata PortletPreferences
Atribute, adic
a perechi de tip String (nume,valoare) definite n fisierul portlet.xml
prin
172
<portlet-preferences>
<preference>
<name>nume_atribut</name>
<value>valoare_atribut</value>
<read-only>true|false</read-only>
</preference>
. . .
</portlet-preferences>
Atributele se transmit metodelor doView, doEdit si doHelp. Suportul este
oferit prin interfata PortletPreferences.
Metode
String getValue(String key, String def )
Returneaz
a valoarea primului atribut avand numele key. In lipsa atributului
sau a valorii returneaza valoarea def.
String[] getValues(String key, String[] def )
Returneaz
a toate valorile atributului key.
Enumeration<String> getNames()
Suport pentru acces la numele atributelor care au valoare.
Map<String,String[]> getMap()
Suport pentru acces la atribute.
Un obiect care implementeaza interfata PortletPreferences se obtine prin
metoda getPreferences() a clasei RenderRequest.
Exemplul 12.3.5 Portlet n care se preiau si se afiseaz
a valori ale atributelor.
Codul portletului este
1
package p r e f ;
3
4
import j a v a . i o . ;
import j a v a x . p o r t l e t . ;
public c l a s s P r e f P o r t l e t extends G e n e r i c P o r t l e t {
public void doView ( RenderRequest req , RenderResponse r e s )
throws P o r t l e t E x c e p t i o n , IOException {
P o r t l e t P r e f e r e n c e s p r e f s = req . g e tP r e f e re n c e s ( ) ;
S t r i n g a t t r 1 = p r e f s . g e t V a l u e ( ATTR1 , a t t r 1 ) ;
S t r i n g a t t r 2 = p r e f s . g e t V a l u e ( ATTR2 , a t t r 2 ) ;
r e s . setContentType ( t e x t / html ) ;
W r i t e r out=r e s . g e t W r i t e r ( ) ;
out . w r i t e ( <s t r o n g >+a t t r 1+ <> +a t t r 2+</s t r o n g > ) ;
}
8
9
10
11
12
13
14
15
16
17
173
12.4
Produse Portal
12.4.1
uPortal
174
lib
|
portlet-api-1.0.jar
pachetul portlet-ului
|--> jsp
|
|
*.jsp
|--> WEB-INF
|
|--> classes
|
|
|
*.java
|
|
web.xml
|
|
portlet.xml
build.xml
175
39
41
43
36
37
38
44
45
47
</ p r o j e c t>
Desf
asurarea portlet-ului se face cu apache-ant utilizand fisierul build.xml
din uPortal HOME\uPortal-*.*.* prin
ant deployPortletApp -DportletApp=arhiva portlet-ului.war
In urma acestei operatii, portlet-ul se dezarhiveaza n uPortal HOME\apachetomcat-*.*.*\webapps iar fisierul web.xml este actualizat.
176
Canalul este
177
12.4.2
Jetspeed-2
178
Bibliografie
179