ProgramareDistribuitaJava PDF
ProgramareDistribuitaJava PDF
PROGRAMARE
IN JAVA
DISTRIBUITA
Volumul I
Brasov
Prefat
a
Scopul acestui curs este prezentarea tehnologiilor de programare Java care
permit realizarea aplicatiilor client - server:
socluri Java;
apelarea metodelor de la distanta
Remote Method Invocation - RMI ;
Common Object Request Brocker Arhitecture - CORBA;
mesageria Java;
servlet;
Java Server Pages - JSP;
Java Web Start;
WebSocket;
Enterprise Java Bean.
Accentul cade pe detaliile tehnice de realizare a comunicatiilor si pe arhitectura programelor / aplicatiilor care le utilizeaza. Trebuie semnalat faptul
ca exemplele date nu ncorporeaza aspecte indispensabile unei aplicatii informatice la standardele zilei:
securitate, autentificare si autorizare;
interfata grafica pentru componenta client;
utilizarea bazelor de date relationale / orientate obiect / NoSQL.
3
4
Metodele si instrumentele de programare vor fi exemplificate, de cele mai
multe ori, pe problema foarte simpla de calcul a celui mai mare divizor comun
a doua numere naturale. Codul acestei metode de calcul poate fi
Varianta imperativ
a ca metod
a
1
2
3
4
5
6
7
8
9
10
11
i n t e r f a c e CmmdcService {
long cmmdc( long m, long n ) ;
}
s t a t i c CmmdcService cmmdcService=(long m, long n ) > {
long r , c ;
do{
c=n ;
r=m % n ;
m=n ;
n=r ;
}
while ( r ! = 0 ) ;
return c ;
};
Varianta declarativ
a / recursiv
a
1
2
3
4
5
6
7
8
9
Guava: Google Core Libraries for Java poseda o metoda de calcul a celui mai
mare divizor a doua numere naturale com.google.common.math.LongMath.
gcd(...).
Pentru aplicatiile care utilizeaza o baza de date, sistemul de gestiune a
bazei de date (SGBD) va fi una dintre sistemele Derby/Javadb sau mysql.
Tiparul de nv
atare propus este
1. Se instaleaza toate resursele necesare (Se exemplifica la laborator).
5
2. Se executa aplicatia / aplicatiile din curs (Se exemplifica la laborator).
3. Pentru fiecare tehnologie, pe suportul oferit de curs, se programeaza o
alta aplicatie.
Propunem urmatoarele teme:
Conversia dintre grade Celsius si grade Fahrenheit (F = 1.8C + 32).
Crearea, ntretinerea si utilizarea unei agende de adrese de e-mail.
Agenda este o baza de date.
4. In final, se rezolva tema pentru examen.
Nu de putine ori metodele / tehnologiile utilizate presupun utilizarea unui
sablon de programare specific. Din acest punct de vedere, acest curs se doreste
a fi un suport metodic.
Utilizand sistemul de operare MS Windows propunem utilizarea urmatoarelor
produse informatice auxiliare:
Google Chrome Navigator
Notepad++ Editor de fisiere
MultiCommander Gestionar de fisiere
Sursele programele din curs sunt disponibile prin git:
https://github.com/e-scheiber/DistributedProgramming1.git
Probleme:
http2
Docker, Vagrant, Kubernetes
JSR 371 mvc
No.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Cuprins
1 Introducere
15
21
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
23
23
24
25
30
33
38
43
44
44
58
61
3 Reg
asirea obiectelor prin servicii de nume
69
3.1 Java Naming and Directory Interface . . . . . . . . . . . . . . . 69
3.1.1 LDAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
4 Invocarea procedurilor la distant
a
4.1 Remote Method Invocation . . . .
4.1.1 Crearea unei aplicatii RMI .
4.1.2 Tipare de programare . . . .
4.1.3 Obiect activabil la distanta
4.2 CORBA . . . . . . . . . . . . . . .
4.2.1 Conexiunea RMI - CORBA
4.2.2 Aplicatie Java prin CORBA
9
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
77
77
81
87
93
98
98
104
10
CUPRINS
5 Mesaje n Java
5.1 Java Message Service (JMS) . . . . . . . . . . . .
5.2 Open Message Queue 5 . . . . . . . . . . . . . . .
5.3 Elemente de programare - JMS-2 . . . . . . . . .
5.3.1 Modul programat: Trimiterea unui mesaj .
5.3.2 Receptia sincrona a unui mesaj . . . . . .
5.3.3 Receptia asincrona a unui mesaj . . . . . .
5.3.4 Publicarea mesajelor . . . . . . . . . . . .
5.3.5 Abonare si receptia mesajelor . . . . . . .
5.3.6 Cazul abonatului partajat . . . . . . . . .
5.3.7 Obiecte administrator prin JNDI . . . . .
5.3.8 Comunicatia prin coada - queue . . . . . .
5.3.9 Comunicatia pe baza de subiect - topic . .
5.3.10 Utilizarea mesajelor de tip StreamMessage
5.3.11 Aplicatie JMS slab cuplata . . . . . . . . .
5.3.12 Programare JMS prin glassfish . . . . . . .
II
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
COMUNICAT
II PRIN INTERNET
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
113
. 113
. 115
. 116
. 117
. 119
. 120
. 122
. 123
. 124
. 127
. 128
. 131
. 133
. 136
. 139
143
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
145
. 145
. 152
. 153
. 155
7 Conexiune simpl
a prin clase din java.net
157
7.1 Clasa java.net.URL . . . . . . . . . . . . . . . . . . . . . . . . 157
8 Servlet
8.1 Marcajul <form> . . . . . . . . . . . . . . . .
8.2 Realizarea unui servlet . . . . . . . . . . . . .
8.2.1 Codul unui servlet . . . . . . . . . . .
8.3 Procesare asincrona n servlet . . . . . . . . .
8.4 Dezvoltari n servlet-api 3.1 . . . . . . . . . .
8.4.1 Procesare asincrona neblocanta . . . .
8.4.2 Modificarea protocolului http: upgrade
8.5 Facilitati de programare cu servlet . . . . . . .
8.5.1 Program client al unui servlet . . . . .
8.5.2 Servlete nlantuite . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
159
. 160
. 162
. 164
. 171
. 177
. 177
. 179
. 185
. 185
. 194
11
CUPRINS
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
196
197
200
203
205
207
209
211
213
214
219
220
223
225
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
227
. 227
. 232
. 234
. 235
. 236
. 239
. 240
. 245
. 246
. 247
. 250
. 252
. 254
10 Desf
asurarea n nor
10.1 Servlet si JSP n Google App
10.2 Heroku . . . . . . . . . . . .
10.2.1 JSP n Heroku . . .
10.2.2 Servlet n Heroku . .
10.3 OpenShift . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Engine
. . . . .
. . . . .
. . . . .
. . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
263
264
266
267
270
273
12
CUPRINS
12 WebSocket
12.1 Protocolul WebSocket . . . . . . . . . . . . . . . . . .
12.2 Interfata de programare HTML5 de client WebSocket .
12.3 WebSocket n Java . . . . . . . . . . . . . . . . . . . .
12.3.1 Programare prin adnotari . . . . . . . . . . . .
12.3.2 Programare fara adnotari . . . . . . . . . . . .
12.3.3 Client Java pentru WebSocket . . . . . . . . . .
12.3.4 Transmiterea datelor prin adnotarea PathParam
12.3.5 Conversie si deconversie prin JSON / XML . . .
12.3.6 Streaming . . . . . . . . . . . . . . . . . . . . .
13 Enterprise Java Beans
13.1 Session EJB . . . . . . . . . . . . . . . . .
13.1.1 Componenta EJB sesiune stateless
13.1.2 Componenta cu metode asincrone .
13.1.3 Aplicatie JEE cu module EJB, Web
13.1.4 Componenta EJB sesiune singleton
13.1.5 Componenta EJB sesiune stateful .
13.2 Componenta EJB MessageDriven . . . . .
13.3 Componenta EJB Entity . . . . . . . . . .
.
.
.
.
.
.
.
.
.
283
. 283
. 284
. 285
. 286
. 291
. 293
. 294
. 297
. 304
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
si client RMI-IIOP
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
311
. 312
. 313
. 316
. 317
. 319
. 321
. 324
. 327
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
14 Aplicatie pe nivele
333
14.1 Nivelele unei variante de rezolvare . . . . . . . . . . . . . . . . . 334
III
ANEXE
A Unelte de dezvoltare
A.1 XML . . . . . . . .
A.2 apache-ant . . . . .
A.3 apache-maven . . .
A.4 Gradle pentru Java
339
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
341
. 341
. 344
. 346
. 359
365
C Testare cu junit
369
D Jurnalizare
373
E Component
a Java
377
CUPRINS
13
F Serializare f
ar
a XML
379
F.1 YAML Aint Markup Language - YAML . . . . . . . . . . . . . 380
F.2 JavaScript Object Notation - JSON . . . . . . . . . . . . . . . . 382
G Adnot
ari
G.1 Definirea unei adnotari . . . . . . . . . . . . . . . . . . . . . .
G.2 Declararea unei adnotari . . . . . . . . . . . . . . . . . . . . .
G.3 Procesarea unei adnotari . . . . . . . . . . . . . . . . . . . . .
389
. 389
. 390
. 391
395
. 395
. 396
. 398
Injectarea dependintelor
405
I.1 Weld . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
IV
TEME DE LABORATOR
409
J Teme de aplicatii
411
J.1 Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . . . . 411
Bibliografie
419
14
CUPRINS
Capitolul 1
Introducere
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
urmarite, gestionate din alte locuri au drept consecinta existenta aplicatiilor
distribuite. Termenul distribuit se refera tocmai la faptul ca componente ale
aplicatiei se afla pe calculatoare diferite dar ntre care au loc schimburi de
date. Daca partile unei aplicatii sau resursele utilizate se gasesc pe calculatoare
distincte atunci aplicatia se numeste distribuita.
Intre partile sau resursele unei aplicatii distribuite au loc schimburi de
date, ceea ce se face utilizand 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 langa algoritm, structuri de date, limbaj de programare, la
realizarea unei aplicatii distribuite intervin comunicatiile: schimbul de date
dintre doua componente aflate pe calculatoare diferite.
Transmisia datelor poate fi:
discreta - numarul datelor transmise este fixat;
n flux (streaming) - se transmit un volum de date n mod continuu.
In cadrul comunicatiilor, transmisia de date presupune transformarea acestora din formatul tipizat n sir de octeti si invers - serializarea datelor. In acest
scop tehnologiile de programare utilizeaza modalitati diverse, de la atribuirea
acestei sarcini catre programator pana la asigurarea unui cadru fix de realizare
a serializarii.
Punem n evidenta doua modele de aplicatii distribuite:
client-server: Programul server executa cererile clientilor.
15
16
CAPITOLUL 1. INTRODUCERE
Socluri
Remote Method Invocation (RMI)
Common Object Request Brocker Arhitecture (CORBA)
Java Message Service (JMS)
17
Servlet si Java Server Pages (JSP)
Java Web Start
WebSocket
dispecer-lucr
ator: Programul dispecer distribuie sarcinile de executat lucratorilor si le coordoneaza activitatea. Exista multe abordari de
programere a aplicatiilor dispecer-lucrator.
Exista diferente mari ntre o aplicatie care ruleaza pe un calculator si o
aplicatie distribuita1 :
latenta (latency) - exista mai multe definitii:
diferenta n timp ntre o operatie executata pe un calculator la
distanta de executia ei pe calculatorul local.
diferenta n timp ntre momentul receptionarii raspunsului la o
cerere si momentul lansarii ei.
diferenta n timp ntre momentul receptionarii unei cereri si momentul transmiterii raspunsului.
Receptia rezultatului unei operatii executate pe un calculator la distanta
se poate programa
sincron de obicei receptia blocheaza firul de executie al apelului
pana la sosirea rezultatului;
asincron concept care are mai multe materializari:
receptia se obtine ntr-un obiect dedicat care se executa n afara
firului de executie al apelului.
(JMS, servlet)
rezultatul solicitarii este un obiect de tip Future< T > si a
carui procesare se poate face dupa instantierea obiectului T.
(socluri cu canale de comunicatii, client servlet)
O preocupare continua este dezvoltarea de tehnologii hard si soft pentru
micsorarea latentei.
accesul la memorie (memory access). Instrumente de programare - cadre
de lucru (framework ) care mijlocesc realizarea aplicatiilor asigura accesul
la resursele aflate n memoria calculatoarelor (read, write, send, receive).
1
Waldo J., Wyant G., Wollrath A., Kendall S., 1994, A Note on Distributed Computing.
Sun Microsystems Corporation, Technical report, SMLI TR-94-29.
18
CAPITOLUL 1. INTRODUCERE
19
protocol://host[:port][cale][?cerere]
Un rol important n dezvoltarea tehnologiilor legate de limbajul Java revine
organizatiilor de standardizare:
Java Community Process JCP;
Organization for the Advancement of Structured Information Standards
OASIS;
The Internet Engineering Task Force IETF.
Intreb
ari recapitulative
1. Explicati notiunea de latenta.
2. Explicati termenul de protocol si dati exemple de protocoale de comunicatie.
3. Explicati notiunea de prabusire partiala.
4. Ce desemneaza denumirea Java Community Process?
5. Precizati sintaxa unui URI.
20
CAPITOLUL 1. INTRODUCERE
Partea I
TEHNOLOGII PENTRU
RET
ELE LOCALE
21
Capitolul 2
Programare cu socluri Java
Comunicatia bazata pe socluri Java constituie modalitatea de nivelul inferior pentru realizarea aplicatiilor distribuite. Din punct de vedere fizic un
soclu este o interfata de conectare la procesor. Soclurile se afla pe placa de
baza. Notiunea de soclu dintr-un mediu de programare este diferita de soclul
fizic. In cele ce urmeaza ne intereseaza soclul n mediul Java.
2.1
24
2.2
Soclu TCP
Clasa java.net.Socket
Resursele clasei Socket sunt destinate clientului.
Constructori
public Socket(String host, int port) throws UnknownHostException,
IOException
Creaza un soclu conectat la calculatorul cu portul specificat.
public Socket(InetAddress host, int port) throws IOException
Creaza un soclu conectat la calculatorul cu portul specificat.
Metode
public InputStream getInputStream() throws IOException
Returneaza un flux de intrare atasat soclului, pentru citirea (preluarea)
informatiilor de la soclu.
25
Clasa java.net.ServerSocket
Resursele clasei ServerSocket sunt destinate serverului.
Constructori
public ServerSocket(int port) throws IOException
Creaza 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 fixeaza la valoarea implicita 50. Cererile n
exces vor fi refuzate.
public ServerSocket(int port, int lung) throws IOException
In plus fixeaza lungimea sirului (tamponului) de asteptare.
Metode
public Socket accept() throws IOException
Metoda blocheaza procesul (firul de executie) apelant pana la sosirea
unei cereri de conectare si creaza un soclu client prin care se va desfasura
comunicarea cu solicitantul acceptat.
public synchronized void close() throws IOException
nchide soclul de referinta.
2.2.1
26
Exemplul 2.2.1 Sistem client - server pentru calculul celui mai mare divizor
comun a doua numere naturale. Portul obiectului de tip ServerSocket este
7999.
Programul client CmmdcClient se conecteaza la server, transmite serverului cele doua numere naturale si receptioneaza rezultatul pe care apoi l afiseaza.
In esenta orice program client trebuie sa execute:
1. Deschide/creaza un soclu.
2. Deschide/creaza 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
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
32
33
import
import
import
import
j a v a . i o . DataInputStream ;
j a v a . i o . DataOutputStream ;
java . net . Socket ;
java . u t i l . Scanner ;
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 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 ( ) ;
try ( S o c k e t cmmdcSocket = new S o c k e t ( hos t , p o r t ) ;
DataInputStream i n=new DataInputStream ( cmmdcSocket . g e t I n p u t S t r e a m ( ) ) ;
DataOutputStream out=
new DataOutputStream ( cmmdcSocket . getOutputStream ( ) ) ) {
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 ( R e q u i r e d r e s u l t : +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 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 ( ) ) ;
}
}
}
27
import
import
import
import
public c l a s s MyMServer {
s t a t i c f i n a l i n t NTHREADS=100;
s t a t i c E x e c u t o r S e r v i c e e x e c=E x e c u t o r s . newFixedThreadPool (NTHREADS) ;
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;
boolean l i s t e n i n g=true ;
AppThread appThread=new AppThread ( ) ;
try ( S e r v e r S o c k e t 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 ) ) {
System . out . p r i n t l n ( The s e r v e r i s l i s t e n i n g on p o r t 7999 ) ;
while ( l i s t e n i n g ) {
e x e c . e x e c u t e ( appThread . a c t i o n . s e r v i c e ( s e r v e r S o c k e t . a c c e p t ( ) ) ) ;
}
} catch ( IOException e ) {
e . printStackTrace ( ) ;
}
}
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import
import
import
import
public c l a s s AppThread{
// F i r u l de e x e c u t i e l a n s a t de s e r v e r
interface ServerSocketAction {
Thread s e r v i c e ( S o c k e t s o c k e t ) ;
}
s t a t i c S e r v e r S o c k e t A c t i o n a c t i o n =( S o c k e t s o c k e t )>{
return new Thread (()>{
try ( DataOutputStream out =
28
15
16
17
18
19
20
21
22
23
24
}
catch ( IOException e ) {
e . printStackTrace ( ) ;
}
});
25
26
27
28
29
};
30
31
Clasa App corespunzatoare calcului celui mai mare divizor comul a doua
numere naturale.
1
2
3
4
5
public c l a s s App{
// F u n c t i a i n d e p l i n i t a de s e r v e r
i n t e r f a c e CmmdcService {
long cmmdc( long m, long n ) ;
}
s t a t i c CmmdcService cmmdcService=(long m, long n ) > { . . . }
7
9
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 {
ServerSocket g e t S e r v e r S o c k e t ( int port ) ;
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 ) ;
}
29
Implementarea interfetei
1
2
3
4
5
6
8
9
10
11
12
13
14
15
16
17
18
19
20
package s e r v e r . impl ;
import i s e r v e r . IMyMServer ;
import j a v a . n e t . S e r v e r S o c k e t ;
import j a v a . i o . IOException ;
import j a v a . u t i l . c o n c u r r e n t . E x e c u t o r S e r v i c e ;
import j a v a . u t i l . c o n c u r r e n t . E x e c u t o r s ;
public c l a s s MyMServer implements 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 ( f i n a l 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 ;
}
public void myAction ( f i n a l S e r v e r S o c k e t s e r v e r S o c k e t ) {
int nthreads = 8192;
E x e c u t o r S e r v i c e e x e c = E x e c u t o r s . newFixedThreadPool ( n t h r e a d s ) ;
AppThread appThread = new AppThread ( ) ;
while ( true ) {
try {
e x e c . e x e c u t e ( appThread . a c t i o n . s e r v i c e ( s e r v e r S o c k e t . a c c e p t ( ) ) ) ;
} catch ( IOException e ) {
e . printStackTrace ( ) ;
}
}
}
22
23
24
25
26
27
28
29
30
31
32
33
34
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 ) {
int port = 7999;
i f ( args . length > 0)
port = Integer . parseInt ( args [ 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 ) ;
}
}
30
2.2.2
Streaming
Prin socluri se pot transmite fluxuri de date (streaming). Modul de programare depinde de natura datelor ce trebuie vehiculate (text, sunet, grafica).
Exemplul 2.2.2 Clientul solicita serverului transmisia unui fisier text, cerere
care va fi satisfacuta de server. Clientul cunoaste lista fisierelor pe care le poate
trimite serverul.
Structura aplicatiei este:
Client StreamClient.java
Server MyMServer.java
AppThread.java
Clasa StreamClient
1
2
3
4
5
6
7
8
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package s t r e a m i n g t e x t ;
import j a v a . i o . DataInputStream ;
import j a v a . i o . DataOutputStream ;
import j a v a . n e t . S o c k e t ;
import j a v a . i o . IOException ;
import j a v a . i o . EOFException ;
import j a v a . i o . UTFDataFormatException ;
import j a v a . u t i l . S c a n n e r ;
public c l a s s S t r e a m C l i e n t {
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 =7997;
System . out . p r i n t l n ( A l e g e t i f i s i e r u l : ) ;
System . out . p r i n t l n ( 1 : c a p i t o l . t x t ) ;
System . out . p r i n t l n ( 2 : j u n i t . t e x ) ;
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 ) ;
i n t n o F i l e=s c a n n e r . n e x t I n t ( ) ;
try ( S o c k e t c l i e n t S o c k e t = new S o c k e t ( hos t , p o r t ) ;
DataInputStream i n =
new DataInputStream ( c l i e n t S o c k e t . g e t I n p u t S t r e a m ( ) ) ;
DataOutputStream out=
new DataOutputStream ( c l i e n t S o c k e t . getOutputStream ( ) ) ) {
out . w r i t e I n t ( n o F i l e ) ;
System . out . p r i n t l n ( R e c e i v e d : ) ;
String s ;
while ( ! ( s=i n . readUTF ( ) ) . e q u a l s ( e n d O F f i l e ) ) System . out . p r i n t l n ( s ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( C l i e n t 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 ( ) ) ;
}
}
}
Clasa AppThread
1
2
package s t r e a m i n g t e x t ;
import j a v a . n e t . S o c k e t ;
31
3
4
5
6
7
8
10
11
import
import
import
import
import
import
io
io
io
io
io
io
. DataInputStream ;
. DataOutputStream ;
. File ;
. FileReader ;
. BufferedReader ;
. IOException ;
13
14
15
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
String s ;
while ( ( s=br . r e a d L i n e ( ) ) ! = n u l l ) out . writeUTF ( s ) ;
out . writeUTF ( e n d O F f i l e ) ;
out . f l u s h ( ) ;
br . c l o s e ( ) ;
fr . close ();
System . out . p r i n t l n ( A c t i v i t y F i n i s h e d ! ) ;
socket . close ( ) ;
33
34
35
36
37
38
39
40
}
catch ( IOException e ) {
e . printStackTrace ( ) ;
}
41
42
43
44
45
46
java .
java .
java .
java .
java .
java .
Exemplul 2.2.3 Clientul solicita serverului transmisia unui fisier grafic, cerere
care va fi satisfacuta de server. Clientul cunoaste lista fisierelor pe care le poate
trimite serverul.
Pe aceasi structura codurile claselor sunt
Clasa StreamClient
1
2
3
4
package s t r e a m i n g i m a g e ;
import j a v a . i o . DataOutputStream ;
import j a v a . i o . InputStream ;
import j a v a . awt . image . B u f f e r e d I m a g e ;
32
5
6
7
8
9
11
12
13
14
15
16
17
18
19
import
import
import
import
import
public c l a s s S t r e a m C l i e n t {
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 =7998;
System . out . p r i n t l n ( A l e g e t i f i s i e r u l : ) ;
System . out . p r i n t l n ( 1 : xmlp i c . j p g ) ;
System . out . p r i n t l n ( 2 : b r a s o v . j p g ) ;
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 ) ;
i n t n o F i l e=s c a n n e r . n e x t I n t ( ) ;
try ( S o c k e t c l i e n t S o c k e t = new S o c k e t ( hos t , p o r t ) ;
InputStream i n=c l i e n t S o c k e t . g e t I n p u t S t r e a m ( ) ;
DataOutputStream out=
new DataOutputStream ( c l i e n t S o c k e t . getOutputStream ( ) ) ) {
out . w r i t e I n t ( n o F i l e ) ;
B u f f e r e d I m a g e b i=ImageIO . r e a d ( i n ) ;
Image image=(Image ) b i ;
ShowImage s=new ShowImage ( image ) ;
s . show ( ) ;
}
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 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 ( ) ) ;
}
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package s t r e a m i n g i m a g e ;
import j a v a . n e t . S o c k e t ;
import j a v a . i o . InputStream ;
import j a v a . i o . OutputStream ;
import j a v a x . i m a g e i o . stream . FileImageOutputStream ;
import j a v a . i o . DataInputStream ;
import j a v a x . i m a g e i o . ImageIO ;
import j a v a . i o . IOException ;
import j a v a . i o . F i l e ;
import j a v a . awt . image . B u f f e r e d I m a g e ;
import j a v a . awt . Image ;
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 ( ) {
S t r i n g path= . . / r e s o u r c e s / images / ;
try ( OutputStream out=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 ( ) ) ) {
2.3. DATAGRAME
25
i n t n o F i l e=i n . r e a d I n t ( ) ;
27
S t r i n g f i l e N a m e= ;
i f ( n o F i l e ==1)
f i l e N a m e=xmlp i c . j p g ;
else
f i l e N a m e= b r a s o v . j p g ;
F i l e f i l e =new F i l e ( path+f i l e N a m e ) ;
B u f f e r e d I m a g e b i=ImageIO . r e a d ( f i l e ) ;
ImageIO . w r i t e ( bi , j p g , out ) ;
out . f l u s h ( ) ;
socket . close ( ) ;
28
29
30
31
32
33
34
35
36
}
catch ( E x c e p t i o n e ) {
e . printStackTrace ( ) ;
}
37
38
39
40
41
42
33
2.3
Datagrame
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 necesita crearea unui obiect DatagramPacket si
apoi acceptarea unui pachet UDP din retea. Dupa primire, se poate extrage
din obiectul DatagramPacket adresa sursa si continutul mesajului.
Constructori
Exista doi constructori pentru datagrame UDP. Primul constructor este
folosit pentru primirea de pachete si necesita doar furnizarea unei memorii
34
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
memoreaza n tamponul buffer avand lung octeti. Daca lungimea pachetului depaseste aceasta 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()
returneaza adresa IP a expeditorului.
int getPort()
returneaza portul expeditorului.
byte[] getData()
returneaza continutul pachetului.
int getLength()
returneaza lungimea pachetului.
void setAddress(InetAddress adresa)
fixeaza adresa IP a pachetului.
void setPort(int port)
fixeaza portul.
void setData(byte[] buffer )
fixeaza continutul pachetului.
2.3. DATAGRAME
35
Clasa java.net.DatagramSocket
Aceasta clasa 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
Creaza un obiect DatagramSocket cu un numar de port aleator;
DatagramSocket(int port) throws SocketException
Creaza un obiect DatagramSocket cu numarul de port 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 necunoscuta 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 sursa si lungimea mesajului. Executia metodei este blocata pana
cand se primeste cu succes un pachet sau se scurge timpul de asteptare.
InetAddress getLocalAddress()
Returneaza adresa locala catre care este legat acest DatagramSocket;
int getLocalPort()
Returneaza numarul de port unde asculta DatagramSocket.
36
void close()
Inchide DatagramSocket.
void setSoTimeout(int timpDeAsteptere) throws SocketException
Metoda fixeaza timpul de asteptare (n milisecunde) a soclului. Metoda
receive() se va bloca pentru timpul de asteptare specificat pentru primirea unui pachet UDP, dupa care va arunca o exceptie Interrupted
Exception. Daca valoarea parametrului este 0, atunci soclul este blocat.
int getSoTimeout() throws SocketException
Returneaza timpul de asteptare.
void setSendBufferSize(int lungime) throws SocketException
Fixeaza 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
Returneaza lungimea tamponului de trimitere a soclului.
void setReceiveBufferSize(int lungime) throws SocketException
Fixeaza 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
Returneaza lungimea tamponului de primire a soclului.
void disconnect()
Deconecteaza soclul conectat.
InetAddress getInetAddress()
Returneaza obiectul InetAddress catre care este conectat soclul sau
null daca acesta nu este conectat.
int getPort()
Returneaza portul la care este conectat soclul sau -1 daca acesta nu este
conectat.
2.3. DATAGRAME
37
Clasa java.net.InetAddress
Datele pot fi trimise prin retea indicand adresa IP corespunzatoare masinii
destinatie. Clasa InetAddress furnizeaza acces la adresele IP.
Nu exista constructori pentru aceasta clasa. Instantele trebuie create folosind
metodele statice:
InetAddress getLocalHost() throws UnknownHostException
Returneaza un obiect InetAddress corespunzator masinii locale.
InetAddress getByName(String host) throws UnknownHostException
Returneaza 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
Returneaza un sir de obiecte InetAddress corespunzator fiecarei adrese
IP a masinii host.
Metodele clasei InetAddress
byte [ ] getAddress()
Returneaza sirul de octeti corespunzator obiectului InetAddress de referinta.
String getHostName()
Returneaza numele masinii gazda.
String getHostAddress()
Returneaza adresa IP a masinii gazda.
boolean isMulticastAddress()
Returneaza true daca obiectul InetAddress reprezinta o adresa IP multicast (cuprins ntre 224.0.0.0 si 239.255.255.255).
Exemplul urmator afiseaza numele si adresa calculatorului gazda cat si
acela al calculatoarelor ale caror nume este transmis programului ca parametru.
Exemplul 2.3.1
38
1
2
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
37
import j a v a . n e t . I n e t A d d r e s s ;
import j a v a . n e t . UnknownHostException ;
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 ( ) ) ;
}
}
}
}
}
2.3.1
39
2.3. DATAGRAME
Object
Object
ObjectInputStream
ByteArrayInputStream
input - DatagramPacket
ObjectOutputStream
ByteArrayOutputStream
output - DatagramPacket
?
6
6
6
6
40
package s e r v e r ;
import j a v a . i o . S e r i a l i z a b l e ;
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 ;
}
}
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
1
2
3
4
5
6
7
8
9
10
11
13
14
15
16
18
19
20
21
22
package s e r v e r . impl ;
import s e r v e r . P r o t o c o l ;
import i s e r v e r . IMyMServer ;
import j a v a . n e t . DatagramSocket ;
import j a v a . n e t . DatagramPacket ;
import j a v a . n e t . I n e t A d d r e s s ;
import j a v a . i o . IOException ;
import j a v a . i o . ByteArrayInputStream ;
import j a v a . i o . ByteArrayOutputStream ;
import j a v a . i o . O b j e c t I n p u t S t r e a m ;
import j a v a . i o . ObjectOutputStream ;
public c l a s s MyMServer implements IMyMServer {
i n t e r f a c e ServerDatagramAct ion {
void s e r v i c e ( DatagramSocket s o c k e t ) ;
}
s t a t i c ServerDatagramActi on a c t i o n =
( DatagramSocket datagramSocket)>{
DatagramPacket p a c k e t=n u l l ;
P r o t o c o l p=n u l l ;
try {
41
2.3. DATAGRAME
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
}
catch ( E x c e p t i o n e ) {
e . printStackTrace ( ) ;
}
40
41
42
43
44
};
46
47
48
49
50
51
52
53
54
55
56
58
59
60
61
62
63
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 ) ;
}
42
16
Aplicatia client
1
2
3
4
5
6
7
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
39
40
41
42
43
44
45
46
47
48
49
package c l i e n t ;
import j a v a . n e t . DatagramSocket ;
import j a v a . n e t . DatagramPacket ;
import j a v a . n e t . I n e t A d d r e s s ;
import j a v a . i o . ByteArrayInputStream ;
import j a v a . i o . ByteArrayOutputStream ;
import j a v a . i o . O b j e c t I n p u t S t r e a m ;
import j a v a . i o . ObjectOutputStream ;
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 ;
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 ( ) ) ;
}
}
}
2.3. DATAGRAME
2.3.2
43
Clasa java.net.MulticastSocket
Prin intermediul unui soclu de tip MulticastSocket se pot receptiona
datagrame expediate de un server catre toti clientii cu un asemenea soclu.
Constructori
MulticastSocket(int port) throws SocketException
Metode
void joinGroup(InetAddress adresa ) 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 adresa ) throws SocketException
Soclul se deconecteaza la grupul definit de adresa IP.
void close()
Pregatirea 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 creaza
un soclu de tip MulticastSocket pentru portul la care emite serverul si care
se alatura 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 indica prin
44
DatagramSocket.setBroadcast(true)
Orice client care si creaza un soclu la portul la care emite serverul receptioneaza
datagramele trimise de server. Adresa utilizata de server la crearea datagramelor trebuie sa 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.3.3 Multicast
si Broadcast: programele server emit din cinci
n cinci secunde ora exacta. Un client va receptiona cate cinci datagrame.
Codurile sunt date n Fig. 2.1 si Fig. 2.2, respectiv pentru partea de server
si cea de client.
2.4
Canale de comunicatie
Odata 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.
2.4.1
Clasa java.nio.Buffer
Ierarhia claselor Buffer
abstract Buffer
ByteBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
CharBuffer
45
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);
}
Thread.sleep(FIVE_SECONDS);
}
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
46
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();
}
}
47
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 - implica modificarea indicelui tamponului;
absolut - fara modificarea indicelui.
Metode
Introducerea datelor n mod relativ:
ByteBuffer put(byte b)
48
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()
Daca 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.
public final byte[] array()
Transformarea inversa, obiectul ByteBuffer este convertit ntr-un sir de
octeti.
Un obiect de tip ByteBuffer se poate percepe ca un obiect de tip LongBuffer,
DoubleBuffer, etc prin
ByteBuffer bb=ByteBuffer.allocate(10);
LongBuffer lb=bb.asLongBuffer();
DoubleBuffer db=bb.asDoubleBuffer();
49
Clasa java.net.InetSocketAddress
Clasa InetSocketAddress extinde clasa SocketAddress si ncapsuleaza
adresa unui calculator din Internet mpreuna cu un port n vederea legarii 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().
50
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 sursa )
si se receptioneaza prin metoda
int read(ByteBuffer destinatie)
Valoarea returnata 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.4.1 Calculul celui mai mare divizor comun a doua numere naturale.
Aplicatie client-server bazat pe canale de comunicatie prin socluri se compune din:
Aplicatia server alcatuita din:
Interfata
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
Clasa MyMServer
1
2
3
4
5
6
7
8
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package s e r v e r . impl ;
import i s e r v e r . IMyMServer ;
import j a v a . n e t . I n e t S o c k e t A d d r e s s ;
import j a v a . n e t . S e r v e r S o c k e t ;
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 . E x e c u t o r S e r v i c e ;
import j a v a . u t i l . c o n c u r r e n t . E x e c u t o r s ;
import j a v a . i o . IOException ;
public c l a s s MyMServer implements 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 ) {
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 ) {
e . printStackTrace ( ) ;
}
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 ;
}
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 ) {
i n t NTHREADS=100;
AppThread appThread=new AppThread ( ) ;
E x e c u t o r S e r v i c e e x e c=E x e c u t o r s . newFixedThreadPool (NTHREADS) ;
while ( true ) {
try {
e x e c . e x e c u t e ( appThread .
action . s e r v i c e ( serverSocketChannel . accept ( ) ) ) ;
}
catch ( IOException e ) {
e . printStackTrace ( ) ;
}
}
}
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Clasa AppThread
1
2
3
4
6
7
8
9
11
12
13
14
15
package s e r v e r . impl ;
import j a v a . i o . IOException ;
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 . B y t e B u f f e r ;
public c l a s s AppThread{
interface ServerSocketChannelAction {
Thread s e r v i c e ( S o c k e t C h a n n e l s o c k e t ) ;
}
static ServerSocketChannelAction action =
( 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 )>{
return new Thread (()>{
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 ) ;
51
52
// 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 ) ;
App app=new App ( ) ;
long r=app . cmmdcService . 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 ) ;
s o c k e t C h a n n e l . w r i t e ( bb ) ;
socketChannel . c l o s e ( ) ;
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
}
catch ( IOException e ) {
e . printStackTrace ( ) ;
}
});
33
34
35
36
37
};
38
39
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
7
9
10
11
12
package c l i e n t ;
import j a v a . n e t . UnknownHostException ;
import j a v a . n e t . I n e t S o c k e t A d d r e s s ;
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 . B y t e B u f f e r ;
import j a v a . u t i l . S c a n n e r ;
import j a v a . i o . IOException ;
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 ( hos t , 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 ( ) ;
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
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 ( ) ) ;
}
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
53
. . .
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 0 2 4 ) ;
54
s o c k e t C h a n n e l . r e a d ( bb ) ;
byte [ ] b i n=bb . a r r a y ( ) ;
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 r o t o c o l p=( P r o t o c o l ) i n . r e a d O b j e c t ( ) ;
App app=new App ( ) ;
p . x=app . cmmdc( p . x , p . y ) ;
p . y =0;
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 ( ) ;
bb=B y t e B u f f e r . wrap ( bout ) ;
s o c k e t C h a n n e l . w r i t e ( bb ) ;
socketChannel . c l o s e ( ) ;
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
. . .
si, respectiv,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
. . .
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 ( 2 0 4 8 ) ;
P r o t o c o l p=new P r o t o c o l (m, n ) ;
try {
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 ( ) ;
bb=B y t e B u f f e r . wrap ( bout ) ;
s c . w r i t e ( bb ) ;
bb . c l e a r ( ) ;
s c . r e a d ( bb ) ;
byte [ ] b i n=bb . a r r a y ( ) ;
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 ) ;
sc . clos e ( ) ;
. . .
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);
}
catch(Exception e){. . .}
55
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
16
17
18
19
20
21
22
23
package s e r v e r . impl ;
import i s e r v e r . IMyMServer ;
import j a v a . n e t . DatagramSocket ;
import j a v a . n e t . I n e t S o c k e t A d d r e s s ;
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 . n i o . c h a n n e l s . DatagramChannel ;
import j a v a . n i o . B y t e B u f f e r ;
import j a v a . i o . IOException ;
public c l a s s MyMServer implements IMyMServer {
i n t e r f a c e ServerDatagramChannelAction {
void s e r v i c e ( DatagramChannel datagramChannel ) ;
}
s t a t i c ServerDatagramChannelAction a c t i o n =
( DatagramChannel datagramChannel)>{
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 ) ;
56
24
25
26
27
28
29
30
31
32
33
34
35
}
catch ( E x c e p t i o n e ) {
e . printStackTrace ( ) ;
}
36
37
38
39
40
};
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
58
59
60
61
62
63
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
7
8
9
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package c l i e n t ;
import j a v a . n e t . UnknownHostException ;
import j a v a . n e t . I n e t S o c k e t A d d r e s s ;
import j a v a . n e t . I n e t A d d r e s s ;
import j a v a . n e t . DatagramSocket ;
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 . B y t e B u f f e r ;
import j a v a . u t i l . S c a n n e r ;
import j a v a . i o . IOException ;
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
57
58
// r=l b . g e t ( 0 ) ;
System . out . p r i n t l n ( Cmmdc = +r ) ;
59
60
}
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 ( ) ;
}
61
62
63
64
65
66
67
68
69
2.4.2
Receptie cu Selector
Clasa java.nio.channel.Selector
Metode
public static Selector open() throws IOException
Instatiaza un obiect de tip Selector.
public Set<SelectionKey> selectedKeys()
Returneaza cheile inregistrate de selector.
public int select() throws IOException
Metoda blocanta pana la selectarea unui canal.
1
59
60
Exemplul 2.4.3 Aplicatia server pentru aplicatia de calcul a celui mai mare
divizor comun.
Aplicatia server va fi formata de clasele AppServer si App, cea utilizata n
acest capitol.
1
2
3
4
5
6
7
8
9
10
11
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
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 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 . c h a n n e l s . S e l e c t i o n K e y ;
import j a v a . n i o . c h a n n e l s . S e l e c t o r ;
import j a v a . n e t . I n e t S o c k e t A d d r e s s ;
import j a v a . n e t . S e r v e r S o c k e t ;
import j a v a . n i o . B y t e B u f f e r ;
import j a v a . u t i l . I t e r a t o r ;
import j a v a . u t i l . S e t ;
import j a v a . i o . IOException ;
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 ] ) ;
App app=new App ( ) ;
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 ) ;
serverSocketChannel . configureBlocking ( false ) ;
System . out . p r i n t l n ( S e r v e r r e a d y . . . ) ;
S e l e c t o r s e l e c t o r = S e l e c t o r . open ( ) ;
SelectionKey serverkey = serverSocketChannel . r e g i s t e r ( selec tor ,
S e l e c t i o n K e y .OP ACCEPT ) ;
ByteBuffer b u f f e r = ByteBuffer . a l l o c a t e ( 1 6 ) ;
while ( true ) {
selector . select ();
Set<S e l e c t i o n K e y > k e y s = s e l e c t o r . s e l e c t e d K e y s ( ) ;
f o r ( I t e r a t o r i = k e y s . i t e r a t o r ( ) ; i . hasNext ( ) ; ) {
S e l e c t i o n K e y key = ( S e l e c t i o n K e y ) i . n e x t ( ) ;
i . remove ( ) ;
i f ( key == s e r v e r k e y ) {
i f ( key . i s A c c e p t a b l e ( ) ) {
SocketChannel c l i e n t = serverSocketChannel . accept ( ) ;
c l i e n t . configureBlocking ( false ) ;
SelectionKey clientkey = c l i e n t . r e g i s t e r ( selector ,
S e l e c t i o n K e y .OP READ ) ;
}
}
else {
i f ( key . i s R e a d a b l e ( ) ) {
S o c k e t C h a n n e l c l i e n t = ( S o c k e t C h a n n e l ) key . c h a n n e l ( ) ;
int bytesread = c l i e n t . read ( b u f f e r ) ;
long m=b u f f e r . getLong ( 0 ) ;
long n=b u f f e r . getLong ( 8 ) ;
long r=app . cmmdcService . cmmdc(m, n ) ;
53
54
55
56
57
58
59
60
61
62
}
catch ( E x c e p t i o n e ) {
System . e r r . p r i n t l n ( B u f f e r O p E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}
finally {
try {
serverSocketChannel . c l o s e ( ) ;
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( C l o s e E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}
}
63
64
65
66
67
68
69
70
71
72
73
74
75
76
61
2.4.3
Interfata java.util.concurrent.Future<V>
Metode
V get()
boolean isDone()
Valoarea true rezulta daca s-a obtinut / generat obiectul de tip V.
62
Clasa AsynchronousServerSocketChannel
Un obiect de tip AsynchronousServerSocketChannel se obtine cu metoda
statica open().
Metode
static AsynchronousServerSocketChannel open() throws IOException
AsynchronousServerSocketChannel bind(SocketAddress addr )
Se precizeaza portul la care se leaga canalul asincron. Clasa InetSocketAddress
este extinde clasa SocketAddress.
public Future<AsynchronousSocketChannel> accept()
Metoda neblocanta genereaza un soclu prin care se realizeaza conexiunea
din partea serverului cu un client.
Clasa AsynchronousSocketChannel
Metodei
public static AsynchronousSocketChannel open() throws IOException
public abstract Future<Void> connect(SocketAddress remote)
public Future<Integer> read(ByteBuffer dst)
Metoda returneaza numarul octetilor ncarcati n dst.
public Future<Integer> write(ByteBuffer src)
Metoda returneaza numarul octetilor expediati din src.
Exemplul 2.4.4
Utilizam modelul aplicatiei dezvoltata pe baza clasei ServerSocketChannel:
1. IMyMServer.java
1
2
3
4
5
6
7
8
package i s e r v e r ;
import j a v a . n i o . c h a n n e l s . A s y n c h r o n o u 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 A s y n c h r o n o u s S e r v e r S o c k e t C h a n n e l
getAsynchronousServerSocketChannel ( int port ) ;
public void myAction ( A s y n c h r o n o u s S e r v e r S o c k e t C h a n n e l
asynchronousServerSocketChannel ) ;
}
2. MyMServer.java
1
2
3
4
5
6
7
8
9
11
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package s e r v e r . impl ;
import i s e r v e r . IMyMServer ;
import j a v a . n e t . I n e t S o c k e t A d d r e s s ;
import j a v a . n i o . c h a n n e l s . A s y n c h r o n o u 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 . n i o . c h a n n e l s . AsynchronousSocketChannel ;
import j a v a . u t i l . c o n c u r r e n t . E x e c u t o r S e r v i c e ;
import j a v a . u t i l . c o n c u r r e n t . E x e c u t o r s ;
import j a v a . i o . IOException ;
import j a v a . u t i l . c o n c u r r e n t . Future ;
public c l a s s MyMServer implements IMyMServer {
public A s y n c h r o n o u s S e r v e r S o c k e t C h a n n e l
getAsynchronousServerSocketChannel ( int port ){
AsynchronousServerSocketChannel asynchronousServerSocketChannel =
null ;
try {
asynchronousServerSocketChannel =
A s y n c h r o n o u s 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 ) ;
a s y n c h r o n o u s S e r v e r S o c k e t C h a n n e l . bind ( i s a ) ;
}
catch ( IOException e ) {
System . out . p r i n t l n ( A s y n c h r o n o u s 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 a s y n c h r o n o u s S e r v e r S o c k e t C h a n n e l ;
}
public void myAction ( A s y n c h r o n o u s S e r v e r S o c k e t C h a n n e l
asynchronousServerSocketChannel ){
i n t NTHREADS=100;
E x e c u t o r S e r v i c e e x e c=E x e c u t o r s . newFixedThreadPool (NTHREADS) ;
AppThread appThread=new AppThread ( ) ;
while ( true ) {
try {
Future<AsynchronousSocketChannel> f u t u r e =
asynchronousServerSocketChannel . accept ( ) ;
e x e c . e x e c u t e ( appThread . a c t i o n . s e r v i c e ( f u t u r e . g e t ( ) ) ) ;
}
catch ( E x c e p t i o n e ) {
System . e r r . p r i n t l n ( MyActionException : +e . g e t M e s s a g e ( ) ) ;
}
}
}
63
64
48
3. AppThread
1
2
3
4
5
7
8
9
10
package s e r v e r . impl ;
import j a v a . n i o . c h a n n e l s . AsynchronousSocketChannel ;
import j a v a . n i o . B y t e B u f f e r ;
import j a v a . u t i l . c o n c u r r e n t . Future ;
import j a v a . i o . IOException ;
public c l a s s AppThread{
interface ServerSocketAction {
Thread s e r v i c e ( AsynchronousSocketChannel a s c ) ;
}
s t a t i c S e r v e r S o c k e t A c t i o n a c t i o n =( AsynchronousSocketChannel a s c )>{
return new Thread (()>{
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 ( ) ;
Future<I n t e g e r > f r=a s c . r e a d ( bb ) ;
while ( ! f r . i s D o n e ( ) ) ;
// 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 ) ;
App app=new App ( ) ;
System . out . p r i n t l n (m+ <> +n ) ;
long r=app . cmmdcService . 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 ) ;
Future<I n t e g e r > fw=a s c . w r i t e ( bb ) ;
while ( ! fw . i s D o n e ( ) ) ;
asc . c l o s e ( ) ;
}
catch ( IOException e ) {
e . printStackTrace ( ) ;
}
});
};
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
4. AppServer.java
1
2
3
4
6
7
8
package s e r v e r ;
import j a v a . n i o . c h a n n e l s . A s y n c h r o n o u 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 ( ) ;
AsynchronousServerSocketChannel asynchronousServerSocketChannel =
myMServer . g e t A s y n c h r o n o u s 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 ( a s y n c h r o n o u s S e r v e r S o c k e t C h a n n e l ) ;
9
10
11
12
13
14
15
16
65
5. CmmdcClient.java
1
2
3
4
5
6
7
8
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
41
42
43
44
45
46
47
package c l i e n t ;
import j a v a . n e t . UnknownHostException ;
import j a v a . n e t . I n e t S o c k e t A d d r e s s ;
import j a v a . n i o . c h a n n e l s . AsynchronousSocketChannel ;
import j a v a . n i o . B y t e B u f f e r ;
import j a v a . u t i l . S c a n n e r ;
import j a v a . i o . IOException ;
import j a v a . u t i l . c o n c u r r e n t . Future ;
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 ] ) ;
AsynchronousSocketChannel a 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 ( hos t , p o r t ) ;
a s c=AsynchronousSocketChannel . open ( ) ;
asc . 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 ( ) ;
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 ) ;
bb . putLong ( 0 ,m) . putLong ( 8 , n ) ;
try {
Future<I n t e g e r > fw=a s c . w r i t e ( bb ) ;
while ( ! fw . i s D o n e ( ) ) ;
bb . c l e a r ( ) ;
Future<I n t e g e r > f r=a s c . r e a d ( bb ) ;
66
while ( ! f r . i s D o n e ( ) ) ;
r=bb . getLong ( 0 ) ;
System . out . p r i n t l n ( Cmmdc : +r ) ;
asc . c l o s e ( ) ;
48
49
50
51
}
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 ( ) ) ;
}
52
53
54
55
56
57
Comentarii
Tehnologiile prezentate sunt incluse n distributia Java standard, oferita de
Oracle.
S-au dezvoltat instrumente de programare cu scopul eficientizarii din diverse puncte de vedere a comunicatiilor bazate pe socluri:
apache-mina
netty
LMAX Disruptor
Comparare
Pe doua calculatoare
67
2
Rang Timp (ms)
4
2235
6
5735
3
2437
1
1812
2
1047
5
2344
Rang
3
6
5
2
1
4
Intreb
ari recapitulative
1. Precizati termenul socket (soclu).
2. Precizati clasele Java necesare unei aplicatii client-server cu socluri (socket).
3. Precizati diferenta de simetrie privind instantierea dintre un obiect de
tip Socket si unul de tip ServerSocket.
4. Care este rolul unui obiect de tip ServerSocket si cum se utilizeaza?
5. Precizati metodele unui obiect Socket, necesare n transmiterea si receptia
datelor.
6. Precizati termenul multicast.
7. In ce consta participarea serverului la transmisie multicast ?
8. In ce consta participarea unui client la receptia multicast ?
9. Precizati termenul broadcast.
10. In ce consta participarea serverului la transmisie broadcast ?
11. In ce consta participarea unui client la receptia broadcast ?
12. Care este rolul unui obiect de tip DatagramPacket ?
68
Probleme
1. Aplicatia cu AsyncronousSocketChannel nu functioneaza corect cu multi
clienti.
2. Rezolvarea solicitarii unui numa (foarte) mare de clienti (> 8192.)
Capitolul 3
Reg
asirea obiectelor prin
servicii de nume
Oricarui 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 cartii Referinta cartii din biblioteca Carte
2. Contactul telefonic cu o persoana:
Nume persoana Numar telefon Persoana
Un serviciu de nume contine asocieri dintre nume de obiecte si obiecte si
poate oferi facilitati de regasire a obiectelor.
3.1
70
CAPITOLUL 3. REGASIREA
OBIECTELOR PRIN SERVICII DE NUME
Interfata javax.naming.Context
Printr-un context se va ntelege o multime de asocieri nume - obiect. Corespunzator unui context, JNDI defineste interfata Context, cu metodele
void bind(String nume,Object object)
void rebind(String nume,Object object)
void unbind(String nume)
Object lookup(String nume)
NamingEnumeration list(String nume)
Returneaza lista cu nume obiectelor mpreuna cu tipul lor.
NamingEnumeration listBindings(String nume)
Returneaza lista cu nume obiectelor mpreuna cu tipul si locatia acestora.
Specificatiile JNDI prevad definirea unui context initial, implementat prin
clasa javax.naming.InitialContext, clasa ce implementeaza interfata Context.
Constructori.
71
72
CAPITOLUL 3. REGASIREA
OBIECTELOR PRIN SERVICII DE NUME
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
import
import
import
import
import
j a v a x . naming . Context ;
j a v a x . naming . I n i t i a l C o n t e x t ;
j a v a x . naming . B i n d i n g ;
j a v a x . naming . NamingEnumeration ;
j a v a x . naming . NamingException ;
j a v a x . naming . NameClassPair ;
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 ( ) ) ;
}
/
// 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 ( ) ) ;
}
41
42
43
44
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 ) ) ;
46
47
48
49
50
51
53
54
55
56
57
58
60
61
62
63
64
65
66
}
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 ( ) ) ;
}
67
68
69
70
71
72
73
sau
java
Lookup
3.1.1
LDAP
74
CAPITOLUL 3. REGASIREA
OBIECTELOR PRIN SERVICII DE NUME
1. o=organization,c=country
2. o=organization
3. dc=domain content 1,dc=domain content 2
De exemplu, dc=example,dc=com
4. uid=user id ,ou=organization unit
De exemplu, uid=admin,ou=system
Un utilizator este caracterizat prin atributul cn - common name si are
acces la LDAP prin precizarea simultana a atributelor DN si cn.
Vom utiliza ApacheDS (Apache Directory Service)1 . Produse pentru administrarea serverului prin intermediul unei interfete grafice sunt:
Apache Directory Studio;
jxplorer.
Instalarea consta din dezarhivarea fisierului descarcat din Internet.
Serverul utilizeaza portul 10389 si se instaleaza cu urmatoarele valori implicite:
Context.PROVIDER URL
ldap://localhost:10389/uid=admin,
ou=system
Context.SECURITY PRINCIPAL
uid=admin,ou=system
Context.SECURITY CREDENTIALS secret
Lansarea serverului se realizeaza prin apelarea fisierului apacheds.bat
din catalogul apacheds-*\bin.
Pentru oprire se tasteaza Ctrl+C.
Actiunile care pot fi ntreprinse de un client care interactioneaza cu serverul
constau n
autentificare: datele necesare sunt DN si parola;
conectare (bind) / deconectare (unbind) la un punct de intrare. Conectarea
implica crearea unui punct de intrare precizat prin cn;
cautarea / localizarea (lookup) unui punct de intrare precizat prin cn.
Exemplul 3.1.2 Program pentru nregistrarea si stergerea referintei unui obiect
de tip Cmmdc.
1
http://en.wikipedia.org/wiki/List_of_LDAP_software.
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
35
36
37
38
39
40
41
import
import
import
import
import
import
75
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 ) {
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 ) ;
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 ;
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 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 ( ) ;
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 ( ) ;
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 :
+e . g e t M e s s a g e ( ) ) ;
}
}
}
Exemplul 3.1.3 Utilizarea unui obiect de tip Cmmdc regasit pe baza referintei
din serverul LDAP.
1
2
3
4
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 ;
76
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
35
36
37
38
39
40
CAPITOLUL 3. REGASIREA
OBIECTELOR PRIN SERVICII DE NUME
import 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 ;
import j a v a . u t i l . S c a n n e r ;
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 ) {
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 ) ;
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 ) {
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 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 ) ) ;
ctx . c l o s e ( ) ;
}
}
catch ( NamingException e ) {
System . out . p r i n t l n ( LDAPClientCmmdc : +e . g e t M e s s a g e ( ) ) ;
}
}
}
Intreb
ari recapitulative
1. Care este rolul unui serviciu JNDI?
2. Ce nseamna abrevierea JNDI?
3. Care sunt tehnologiile care au utilizat servicii JNDI?
Capitolul 4
Invocarea procedurilor la
distant
a
Invocarea procedurilor la distanta (Remote Procedure Call RPC ) nseamna
apelarea unei metode a unui obiect aflat pe un alt calculator ca si cum acesta
s-ar afla pe calculatorul local.
Se vor prezenta doua cazuri:
Invocarea procedurilor la distanta n cazul mediului omogen Java. Denumirea tehnologiei n acest caz este Invocarea metodei la distanta Remote
Method Invocation (RMI). Prin mediu omogen se ntelege faptul ca atat
compontenta server cat si componenta client sunt programate n acelasi
limbaj de programare, Java n cazul de fata.
Invocarea procedurilor la distanta n cazul medii neomogene. Solutia
n acest caz este dat de Common Object Request Broker Arhitecture
(CORBA).
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 lanseaza n executie prin
start rmiregistry [port]
unde valoarea implicita a portului este 1099. Comanda start apartine sistemului de operare. rmiregistry este un serviciu de nume JNDI.
77
78
79
Server (IIS), apache-tomcat, respectiv ntr-un server ftp (apache-ftp). In momentul lansarii aplicatiei server, serverul http / ftp trebuie sa fie activ.
Daca se indica prin protocolul file calea catre cataloagele care contin
clasele interfetei si ale implementarii lor atunci ultimul caracter al caii este /.
Din punctul de vedere al executiei sunt implicate componentele:
Serviciul de nume rmiregistry;
Aplicatia server;
Aplicatia client.
Aplicatia server si rmiregistry trebuie s
a ruleze pe acelasi calculator.
Registrul rmiregistry implementeaza interfata java.rmi.registry.Registry1 .
Metodele oferite sunt:
void bind(String numeServiciu, Remote obj )throws
RemoteException, AlreadyBoundException, AccessException
Inregistreaza n registry obiectul obj ce implementeaza interfata Remote
sub numele numeServiciu.
void rebind(String numeServiciu, Remote obj )throws
RemoteException, AccessException
Renregistreaza n registry obiectul obj ce implementeaza interfata Remote
sub numele numeServiciu.
Aceasta metoda poate fi apelata doar daca programul care face nregistrarea
se afla pe aceasi masina ca registrul registry.
String[] list()throws RemoteException, AccessException
Returneaza o lista a tuturor serviciilor nregistrate n registry.
Remote lookup(String numeServiciu)throws
RemoteException, NotBoundException, AccessException
Returneaza stub-ul serviciului nregistrat sub numele numeServiciu.
void unbind(String numeServiciu)throws
RemoteException, NotBoundException, AccessException
Sterge din registru serviciul.
1
Varianta direct
a, f
ar
a a folosi facilit
atile JNDI pentru rmiregistry.
80
81
"com.sun.jndi.rmi.registry.RegistryContextFactory");
System.setProperty(Context.PROVIDER_URL,"rmi://"+host+":"+sPort);
Context ctx=new InitialContext();
ctx.bind("MyServiceName",stub);
Un client care doreste sa foloseasca trebuie sa cunoasca :
calculatorul pe care se gaseste obiectul registry si portul la care asculta
serviciul;
numele sub care serviciul s-a nregistrat n registry;
metodele puse la dispozitie de serviciu.
4.1.1
82
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
14
15
17
18
19
20
21
22
24
25
26
27
28
29
30
31
32
1
2
3
4
5
6
7
8
package s e r v e r ;
import cmmdc . ICmmdc ;
import j a v a . rmi . s e r v e r . UnicastRemoteObject ;
// V a r i a n t a cu a p e l r m i r e g i s t r y d i r e c t
import j a v a . rmi . r e g i s t r y . R e g i s t r y ;
import j a v a . rmi . r e g i s t r y . L o c a t e R e g i s t r y ;
// V a r i a n t a JNDI
import j a v a x . naming . Context ;
9
11
import j a v a x . naming . I n i t i a l C o n t e x t ;
public c l a s s CmmdcImpl
implements ICmmdc{
13
15
16
17
18
19
20
21
22
23
24
// 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 ) ;
/
26
27
28
29
30
// 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,
com . sun . j n d i . rmi . r e g i s t r y . R e g i s t r y C o n t e x t F a c t o r y ) ;
System . s e t P r o p e r t y ( Context . PROVIDER URL, rmi : / / +h o s t+ : +s 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 . bind ( CmmdcServer , s t u b ) ;
32
33
34
35
36
37
38
40
41
42
43
44
45
46
83
7
8
84
9
10
11
12
13
15
16
17
18
19
20
21
22
23
24
25
27
28
29
30
31
33
34
35
36
37
38
39
40
42
43
44
45
46
47
49
50
51
52
53
54
56
57
58
60
61
63
64
65
66
67
68
69
70
71
72
73
74
75
76
85
< !
<jvmarg v a l u e=
Djava . rmi . s e r v e r . c o d e b a s e=
f t p : //${ h o s t C o d e b a s e } : 2 1 2 1 / rmi /cmmdc . j a r />
>
<arg l i n e= ${ hostRMIRegistry } ${ p o r t } />
</ java>
</ target>
</ project>
Resursele / fisierele puse la dispozitie de serverul ftp sunt puse n catalogul FTP SERVER HOME\res\home.
Serverul RMI cu server ftp. Se creaza arhiva cmmdc.jar cu continutul
cmmdc
|
ICmmdc.class
server
|
CmmdcImpl.class
1
2
3
4
5
package c l i e n t ;
import cmmdc . ICmmdc ;
import j a v a . u t i l . S c a n n e r ;
// V a r i a n t a cu a p e l r m i r e g i s t r y d i r e c t
import j a v a . rmi . r e g i s t r y . R e g i s t r y ;
86
6
7
8
9
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
import j a v a . rmi . r e g i s t r y . L o c a t e R e g i s t r y ; ;
// V a r i a n t a JNDI
import j a v a x . naming . Context ;
import j a v a x . naming . I n i t i a l C o n t e x t ;
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 Lo ng ( 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 ) ;
ICmmdc o b j =(ICmmdc) r e g i s t r y . l o o k u p ( CmmdcServer ) ;
/
// 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,
com . sun . j n d i . rmi . r e g i s t r y . R e g i s t r y C o n t e x t F a c t o r y ) ;
System . s e t P r o p e r t y ( Context . PROVIDER URL, rmi : / / +h o s t+ : +s P o r t ) ;
Context c t x=new I n i t i a l C o n t e x t ( ) ;
ICmmdc o b j =(ICmmdc) c t x . l o o k u p ( CmmdcServer ) ;
x=o b j . cmmdc(m, n ) ;
System . out . p r i n t l n ( Cmmdc=+x ) ;
39
40
}
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 ( ) ) ;
}
41
42
43
44
45
46
7
8
9
10
11
12
14
15
16
17
18
19
20
22
23
24
25
26
27
28
30
31
32
33
34
35
37
38
39
40
41
42
43
44
45
46
47
87
4.1.2
Tipare de programare
Fabrica de obiecte
Tiparul fabrica de obiecte va permite crearea dinamica a unui server. Prin
aceea schema, se va crea o clasa - fabrica de obiecte - care implementeaza cate
o metoda get, ce returneaza o instanta de server. Aceste metode sunt declarate
ntr-o interfata la distanta.
Un client, apeland o asemenea metoda, va instantia serverul dorit si va
obtine stub-ul corespunzator.
In felul acesta se vor putea utiliza o multime de aplicatii distincte prin
intermediul unui singur rmiregistry. Fiecarei aplicatii i corespunde un server,
instantiat la apelul clientului de metoda get corespunzatoare.
88
package cmmdc0 ;
p u b l i c i n t e r f a c e ICmmdc0 e x t e n d s j a v a . rmi . Remote{
p u b l i c l o n g compute ( l o n g m, l o n g n ) throws j a v a . rmi . RemoteException ;
}
Aceasa interfata va fi implementata de clasa ServerCmmdc. Metoda compute este o metoda 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 clasa ce implementeaza interfata
1
2
3
4
package cmmdc0 ;
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 j a v a . rmi . Remote{
p u b l i c ICmmdc0 getCmmdc ( ) throws j a v a . rmi . RemoteException ;
}
package cmmdc0 ;
im po rt j a v a . rmi . RemoteException ;
im po rt j a v a . rmi . s e r v e r . UnicastRemoteObject ;
1
2
10
11
12
respectiv
package cmmdc0 ;
im po rt j a v a . rmi . RemoteException ;
im po rt j a v a . rmi . s e r v e r . UnicastRemoteObject ;
im po rt j a v a . rmi . r e g i s t r y . R e g i s t r y ;
im po rt j a v a . rmi . r e g i s t r y . L o c a t e 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
4
9
10
11
12
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 ] ;
try {
FabObiecte o b j=new FabObiecte ( ) ;
I F a b O b i e c t e s t u b =( I F a b O b i e c t e ) UnicastRemoteObject . e x p o r t O b j e c t ( obj , 0 ) ;
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 os t , p o r t ) ;
r e g i s t r y . bind ( O b j e c t F a c t o r y , s t u b ) ;
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 ( ) ) ;
}
}
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
89
package cmmdc0 ;
im po rt j a v a . rmi . RemoteException ;
im po rt j a v a . rmi . s e r v e r . UnicastRemoteObject ;
im po rt j a v a . rmi . r e g i s t r y . R e g i s t r y ;
im po rt j a v a . rmi . r e g i s t r y . L o c a t e 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
4
ICmmdc0 remote=n u l l ;
9
11
13
14
15
16
17
18
19
20
21
22
23
2. ClientCmmdc0
Apeleaza metoda compute a obiectului remote.
90
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 ) ;
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 ( ) ) ;
}
System . e x i t ( 0 ) ;
}
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1
2
3
4
5
package cmmdc0 ;
p u b l i c i n t e r f a c e ICmmdc0 e x t e n d s j a v a . rmi . Remote{
p u b l i c l o n g compute ( l o n g m, l o n g n ) throws j a v a . rmi . RemoteException ;
p u b l i c v o i d setMethod ( ICallbackCmmdc o b j ) throws j a v a . rmi . RemoteException ;
}
package cmmdc0 ;
p u b l i c i n t e r f a c e ICallbackCmmdc e x t e n d s j a v a . rmi . Remote{
p u b l i c S t r i n g getMethod ( ) throws j a v a . rmi . RemoteException ;
}
package cmmdc0 ;
im po rt j a v a . rmi . RemoteException ;
im po rt j a v a . rmi . s e r v e r . UnicastRemoteObject ;
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 ;
p u b l i c ServerCmmdc ( ) throws RemoteException {}
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 ;
}
p u b l i c v o i d setMethod ( ICallbackCmmdc o b j ) throws RemoteException {
method=o b j . getMethod ( ) ;
}
p r i v a t e long r e c u r s i v ( long a , long b){
i f ( a==b )
return a ;
else
i f ( a<b )
r e t u r n r e c u r s i v ( a , ba ) ;
else
r e t u r n r e c u r s i v ( ab , b ) ;
}
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);
91
92
return c ;
43
44
45
package cmmdc0 ;
im po rt j a v a . rmi . RemoteException ;
im po rt j a v a . rmi . s e r v e r . UnicastRemoteObject ;
im po rt j a v a . rmi . r e g i s t r y . R e g i s t r y ;
im po rt j a v a . rmi . r e g i s t r y . L o c a t e 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 ;
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 ;
12
14
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 ca 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 ;
}
15
16
17
18
19
20
21
22
23
24
25
26
28
29
30
31
32
33
34
35
36
37
38
si
1
2
4
5
6
7
8
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 ( ) ) ;
}
System . e x i t ( 0 ) ;
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
93
4.1.3
94
package acmmdc ;
im po rt j a v a . rmi . RemoteException ;
im po rt j a v a . rmi . M a r s h a l l e d O b j e c t ;
im po rt j a v a . rmi . a c t i v a t i o n . A c t i v a t a b l e ;
im po rt j a v a . rmi . a c t i v a t i o n . A c t i v a t i o n I D ;
im po rt cmmdc . ICmmdc ;
p u b l i c c l a s s CmmdcActivabil e x t e n d s A c t i v a t a b l e
implements ICmmdc{
p u b l i c CmmdcActivabil ( A c t i v a t i o n I D id , M a r s h a l l e d O b j e c t data )
throws RemoteException {
s u p e r ( id , 0 ) ;
}
11
12
13
14
p u b l i c l o n g cmmdc( l o n g m, l o n g n ) { . . . }
16
17
95
2. java.class.path=no.classpath
ceea ce previne grupul de activare sa ncarce o clasa din classpath-ul
local;
3. localizarea (URL) clasei ce implementeaza interfata
myactivation.impl.codebase;
4. localizarea unui fisier cu date de initializare a obiectului activabil
myactivation.file;
5. numele sub care nregistreaza serviciul n registry
myactivation.name.
Programul Setup realizeaza:
1. Construirea unui descriptor al grupului de activare, instanta a clasei
ActivationGroupDesc. Grupul de activare este un container ce gestioneaza obiectele activabile continute.
2. Inregistrarea descriptorului grupului de activare, instanta a clasei ActivationDesc si obtinerea unui identificator al grupului de activare, instanta
a clasei ActivationGroupID.
3. Construirea descriptorului de activare. Trebuie cunoscute
idendificatorul grupului de activare;
numele clasei ce implementeaza interfata la distanta;
localizarea (URL) clasei ce implementeaza interfata la distanta;
obiectul de tip MarshalledObject, cu datele de initializare a obiectului activabil.
4. Inregistrarea descriptorului de activare, n urma careia se obtine stub-ul
obiectului activabil.
5. Inregistrarea stub-ului mpreuna cu numele serviciului n registry.
Codul clasei setup este
96
1
2
3
4
5
7
8
10
11
12
13
14
15
16
17
18
19
20
package acmmdc ;
im po rt j a v a . rmi . ;
im po rt j a v a . rmi . a c t i v a t i o n . ;
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 . P r o p e r t i e s ;
p u b l i c c l a s s Setup {
p r i v a t e Setup ( ) {}
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 ) throws E x c e p t i o n {
// Argumentul l i n i e i de comanda
S t r i n g implClass = ;
i f ( args . length < 1) {
System . out . p r i n t l n ( u s a g e : ) ;
System . out . p r i n t l n ( j a v a [ o p t i o n s ] acmmdc . Setup <i m p l C l a s s > ) ;
System . e x i t ( 1 ) ;
}
else {
implClass = args [ 0 ] ;
}
// C o n s t r u i r e a d e s c r i p t o r u l u i g r u p u l u i de a c t i v a r e
S t r i n g p o l i c y=System . g e t P r o p e r t y ( m y a c t i v a t i o n . p o l i c y , group . p o l i c y ) ;
S t r i n g implCodebase=System . g e t P r o p e r t y ( m y a c t i v a t i o n . impl . c o d e b a s e ) ;
S t r i n g filename=System . g e t P r o p e r t y ( m y a c t i v a t i o n . f i l e , ) ;
P r o p e r t i e s p r o p s = new P r o p e r t i e s ( ) ;
p r o p s . put ( j a v a . s e c u r i t y . p o l i c y , p o l i c y ) ;
p r o p s . put ( j a v a . c l a s s . path , n o c l a s s p a t h ) ;
p r o p s . put ( m y a c t i v a t i o n . impl . c o d e b a s e , implCodebase ) ;
i f ( filename != n u l l && ! filename . equals ( ) ) {
p r o p s . put ( m y a c t i v a t i o n . f i l e , filename ) ;
}
A c t i v a t i o n G r o u p D e s c groupDesc = new A c t i v a t i o n G r o u p D e s c ( props , n u l l ) ;
22
23
24
25
26
27
28
29
30
31
32
33
// I n r e g i s t r a r e a g r u p u l u i de a c t i v a r e p e n t r u o b t i n e r e a
// i d e n t i f i c a t o r u l u i de a c t i v a r e
Ac tivat ionG roupI D groupID=
A c t i v a t i o n G r o u p . getSystem ( ) . r e g i s t e r G r o u p ( groupDesc ) ;
System . e r r . p r i n t l n ( A c t i v a t i o n group d e s c r i p t o r r e g i s t e r e d . ) ;
35
36
37
38
39
// C o n s t r u i r e a d e s c r i p t o r u l u i de a c t i v a r e
M a r s h a l l e d O b j e c t data = n u l l ;
i f ( filename != n u l l && ! filename . equals ( ) ) {
data = new M a r s h a l l e d O b j e c t ( filename ) ;
}
41
42
43
44
45
A c t i v a t i o n D e s c d e s c=
new A c t i v a t i o n D e s c ( groupID , i m p l C l a s s , implCodebase , data ) ;
47
48
// I n r e g i s t r a r e a d e s c r i p t o r u l u i de a c t i v a r e
Remote s t u b = A c t i v a t a b l e . r e g i s t e r ( d e s c ) ;
System . e r r . p r i n t l n ( A c t i v a t i o n d e s c r i p t o r r e g i s t e r e d . ) ;
50
51
52
// I n r e g i s t r a r e a s e r v i c i u l u i i n r e g i s t r y
S t r i n g name = System . g e t P r o p e r t y ( m y a c t i v a t i o n . name ) ;
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 ( ) . r e b i n d ( name , s t u b ) ;
System . e r r . p r i n t l n ( Stub bound i n r e g i s t r y . ) ;
54
55
56
57
58
59
97
98
4.2
CORBA
4.2.1
4.2. CORBA
99
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 . ICmmdc ;
im po rt j a v a . rmi . RemoteException ;
// 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
100
1
2
3
5
6
7
8
9
10
11
12
13
14
15
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 ) ;
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 . . . ) ;
17
18
19
20
21
22
23
24
25
}
catch ( Exception e ) {
System . out . p r i n t l n ( CmmdcServer: + e . g e t M e s s a g e ( ) ) ;
}
26
27
28
29
30
31
101
4.2. CORBA
1
2
7
8
9
10
11
12
13
14
16
17
18
19
20
21
22
23
24
25
26
28
29
30
31
32
33
34
36
37
38
39
40
41
42
43
44
45
46
47
49
50
51
52
53
55
56
57
58
/>
102
59
60
61
62
63
64
1
2
3
4
5
6
8
9
10
11
12
13
14
15
package cmmdciiop ;
import 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 ;
import j a v a x . naming . Context ;
import j a v a x . naming . I n i t i a l C o n t e x t ;
import j a v a . u t i l . S c a n n e r ;
import cmmdc . ICmmdc ;
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 ] ;
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 Lo ng ( 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 ( ) ;
17
18
19
20
21
22
23
24
25
26
27
29
30
31
32
34
35
36
37
38
}
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 ( ) ) ;
}
39
40
41
42
43
44
4.2. CORBA
103
7
8
9
10
11
12
13
14
15
16
17
19
20
21
22
23
24
25
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
45
46
47
48
49
50
52
53
104
54
55
56
57
58
59
60
61
<classpath>
<pathelement l oc a t io n= c l a s s e s /${ j a r f i l e } />
<pathelement path= c l a s s e s />
</ classpath>
<arg l i n e= ${ h o s t } ${ p o r t } />
</ java>
</ target>
</ project>
4.2.2
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
Legarea cererii unui client de codul serviciului care satisface cererea utilizeaza componenta CORBA Portable Object Adapter (POA).
105
4.2. CORBA
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 ) ;
};
};
im po rt CmmdcApp . ;
im po rt o r g . omg .CORBA.ORB;
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 ;
106
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
im po rt
im po rt
CmmdcApp . ;
o r g . omg . CosNaming . NameComponent ;
o r g . omg . CosNaming . NamingContextExtHelper ;
o r g . omg . CosNaming . NamingContextExt ;
o r g . omg .CORBA.ORB;
o r g . omg . P o r t a b l e S e r v e r .POA;
o r g . omg . P o r t a b l e S e r v e r . POAHelper ;
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 s e s i i n i t i a l i z a r e 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 POA s i
// a c t i v a r e a g e s t i o n a r u l u i POAManager
POA rootPOA =
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 ) ) ;
rootPOA . 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 p e n t r u s e r v a n t
o r g . omg .CORBA. O b j e c t r e f=rootPOA . 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 ) ;
NamingContextExt ncRef=NamingContextExtHelper . narrow ( o b j R e f ) ;
36
// L e g a r e a s e r v a n t u l u i i n 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 ) ;
38
40
// Gata p e n t r u s a t i s f a c e r e a
orb . run ( ) ;
33
34
35
41
42
43
44
45
46
clientilor
}
catch ( Exception e ) {
System . e r r . p r i n t l n ( ERROR: + e . g e t M e s s a g e ( ) ) ;
}
System . out . p r i n t l n ( CmmdcServer E x i t i n g . . . ) ;
. . . );
107
4.2. CORBA
47
48
im po rt
im po rt
im po rt
im po rt
im po rt
p u b l i c c l a s s CmmdcClient {
s t a t i c Cmmdc cmmdc ;
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 ) ;
10
11
12
13
// 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 ) ;
15
16
17
18
19
// 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 ;
cmmdc = CmmdcHelper . narrow ( ncRef . r e s o l v e s t r ( name ) ) ;
21
22
23
25
26
27
28
29
30
31
32
33
}
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 ) ;
}
34
35
36
37
38
39
40
CmmdcApp . ;
o r g . omg . CosNaming . NamingContextExtHelper ;
o r g . omg . CosNaming . NamingContextExt ;
o r g . omg .CORBA.ORB;
java . u t i l . Scanner ;
Din nou clasa client contine sablonul de accesare a unui serviciu CORBA.
Programele se compileaza
108
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
im po rt
im po rt
im po rt
im po rt
im po rt
im po rt
im po rt
im po rt
im po rt
java . u t i l . Properties ;
o r g . omg .CORBA.ORB;
o r g . omg .CORBA. P o l i c y ;
o r g . omg . CosNaming . NamingContextExtHelper ;
o r g . omg . CosNaming . NamingContextExt ;
o r g . omg . CosNaming . NameComponent ;
o r g . omg . P o r t a b l e S e r v e r .POA;
o r g . omg . P o r t a b l e S e r v e r . POAHelper ;
o r g . omg . P o r t a b l e S e r v e r . L i f e s p a n P o l i c y V a l u e ;
109
4.2. CORBA
18
20
// Pas 2 : C r e a r e a unui s e r v a n t
CmmdcImpl cmmdcImpl = new CmmdcImpl ( orb ) ;
21
// Pas 3 : O b t i n e r e a u n e i r e f e r i n t e POA s i
//
a c t i v a r e a g e s t i o n a r u l u i POAManager
//
// Pas 31 : O b t i n e r e a r a d a c i n i i rootPOA
POA rootPOA =
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 ) ) ;
// Pas 32 : C r e a t e s e c u r i t a t i i P e r s i s t e n t P o l i c y
P o l i c y [ ] p e r s i s t e n t P o l i c y = new P o l i c y [ 1 ] ;
p e r s i s t e n t P o l i c y [ 0 ] = rootPOA . c r e a t e l i f e s p a n p o l i c y (
L i f e s p a n P o l i c y V a l u e . PERSISTENT ) ;
// Pas 33 : C r e a r e a o b i e c t u l u i POA cu s e c u r i t a t e a t h e P e r s i s t e n t P o l i c y
POA p e r s i s t e n t P O A=rootPOA . create POA ( childPOA , n u l l , p e r s i s t e n t P o l i c y ) ;
// Pas 34 : A c t i v a r e a m a n a g e r u l u i PersistentPOA POAManager ,
p e r s i s t e n t P O A . the POAManager ( ) . a c t i v a t e ( ) ;
//
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// Pas 4 : A s o c i e r e a s e r v a n t u l u i cu PersistentPOA
p e r s i s t e n t P O A . a c t i v a t e o b j e c t ( cmmdcImpl ) ;
39
40
// Pas 5 :
//
// Numele
// Numele
42
43
44
45
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 r o o t C o n t e x t=NamingContextExtHelper . narrow ( o b j R e f ) ;
NameComponent [ ] nc = r o o t C o n t e x t . to name ( P e r s i s t e n t C m m d c S e r v e r ) ;
r o o t C o n t e x t . r e b i n d ( nc , p e r s i s t e n t P O A . s e r v a n t t o r e f e r e n c e ( cmmdcImpl ) ) ;
47
48
49
50
51
// Pas 6 : Gata p e n t r u s a t i s f a c e r e a
orb . run ( ) ;
53
54
clientilor
}
catch ( Exception e ) {
System . e r r . p r i n t l n ( E x c e p t i o n i n P e r s i s t e n t S e r v e r S t a r t u p +
e . getMessage ( ) ) ;
}
55
56
57
58
59
60
61
F i x a r e a c o n t e x t u l u i RootNaming s i
l e g a r e a de numele s e r v a n t u l u i
s e r v i c i u l u i de nume : NameService
s e r v a n t u l u i PersistentCmmdcServer
Programul client
1
2
3
5
6
7
8
9
10
11
12
im po rt CmmdcApp . ;
im po rt o r g . omg .CORBA.ORB;
im po rt j a v a . u t i l . S c a n n e r ;
public class PersistentClient {
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 ] ;
110
try {
// Pas 1 : I n i t i a l i z a r e ORB
ORB orb = ORB. i n i t ( a r g s , n u l l ) ;
13
14
15
// Pas 2 : R e z o l v a r e a p e r s i s t e n t e i
// S e r v i c i u l NameService r u l e a z a pe h o s t cu p o r t u l p o r t
// Numele s e r v i c i u l u i c e r u t l u i NameService e s t e
// P e r s i s t e n t C m m d c S e r v e r
o r g . omg .CORBA. O b j e c t o b j = orb . s t r i n g t o o b j e c t (
c o r b a n a m e : : +h o s t+ : +p o r t+#P e r s i s t e n t C m m d c S e r v e r ) ;
Cmmdc cmmdc=CmmdcHelper . narrow ( o b j ) ;
17
18
19
20
21
22
23
// Pas 3 : U t i l i z a r e a s e r v i c i u l u i
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 ( C a l l i n g P e r s i s t e n t S e r v e r . . ) ;
i n t m, n , r ;
System . out . p r i n t l n ( m= ) ;
m=s c a n n e r . n e x t I n t ( ) ;
System . out . p r i n t l n ( n= ) ;
n=s c a n n e r . n e x t I n t ( ) ;
System . out . p r i n t l n (cmmdc . cmmdc(m, n ) ) ;
25
26
27
28
29
30
31
32
33
}
catch ( Exception e ) {
System . e r r . p r i n t l n ( E x c e p t i o n i n P e r s i s t e n t C l i e n t . j a v a . . . +
e . getrMessage ( ) ) ;
}
34
35
36
37
38
39
40
Serverul trebuie sa fie pe acelasi calculator pe care ruleaza orbd. Executarea aplicatiei presupune:
1. Pornirea serviciului de intregistrare a numelor cu programul orbd.exe
din distributia jdk.
orbd -ORBInitialPort 1050 -serverPollingTime 200
2. Activarea serverului:
(a) Se lanseaza utilitarul servertool
servertool -ORBInitialPort 1050
(b) Se nregistreaza serverul mpreuna cu numele serviciului pe care l
ndeplineste:
servertool > register -server PersistentServer
-applicationName PersistentCmmdcServer
-classpath cale_catre_fisierele_server\
111
4.2. CORBA
Semnificatie
shutdown -serverid 257
Oprirea serviciului
unregister -serverid 257 Stergerea serviciului
Inchiderea utilitarului
quit
help
3. Executarea clientului
java PersistentClient [hostORB [portORB]]
Intreb
ari recapitulative
1. Precizati abrevierea RMI.
2. Care sunt componentele unei aplicatii client-server bazat pe RMI?
3. Cate si care sunt entitatile care participa la executia unei aplicatii clientserver bazat pe RMI?
4. Care este rolul ndeplinit de (rmi)registry?
5. Ce asigura sablonul de programare Fabrica de obiecte n RMI?
6. Ce asigura sablonul de programare Callback n RMI?
7. Explicati caracterul sincron al comunicarii n RMI.
112
Capitolul 5
Mesaje n Java
Comunicatia prin apelul la distanta - inclusiv RMI - este sincron: programul apelant se blocheaza si asteapta ca metoda apelata sa se termine si sa
furnizeze rezultatul cerut. Cu alte cuvinte apelul de procedura la distanta cere
atat clientului cat si serverului sa fie simultan disponibile.
Comunicatiile asincrone1 ntre programe permit realizarea unor sisteme de
programe cu un grad mult mai scazut de cuplare, n sensul ca lansarea unei
cereri si receptionarea rezultatului se pot executa n momente diferite de timp.
Asemenea aplicatii se pot realiza prin comunicatii de mesaje, mesaje care sunt
retinute de un intermediar (serviciu de mesagerie, server, broker, messaging
middleware).
5.1
113
114
apache ActiveMQ
apache qpid
Aceste produse implementeaza una sau mai multe protocoale privind reprezentarea datelor unui mesaj si detalii privind transmiterea lor. Advanced Message Queue Protocol (AMQP), Streaming Text Oriented Messaging Protocol
(STOMP) sunt exemple de asemenea protocoale. Scopul unui protocolul este
asigurarea interoperabilitatii ntre aplicatii de mesagerie realizate n diferite
limbaje de programare, produse sau platforme de calcul.
O aplicatie JMS este alcatuita din
un furnizor JMS (provider JMS) : un sistem de mesagerie ce implementeaza specificatiile JMS;
client JMS : aplicatie Java care trimite si receptioneaza mesaje;
mesaje : obiecte utilizate n schimbul de informatii de clienti JMS;
obiecte administrator - obiecte (resurse) create de administrator pentru
a fi utilizate de clientii JMS, precum
fabrica de conexiuni,
obiectele destinatie pentru retinerea mesajelor.
Aplicatiile dezvoltate pe baza JMS 1/JMS 1.1 functioneaza si n cazul utilizarii unui furnizor de servicii realizat pentru JMS-2. In esenta, JMS-2 simplifica programarea fata de JMS-1.
Modele de comunicatie:
Comunicatii punctuale : Un mesaj este generat de un producator (expeditor) si la care va avea acces un singur consumator (destinatar). Mesajul
este depus ntr-o coada, de unde este preluat de catre consumatorul care
s-a legat de coada. Daca de coada nu se leaga nici un consumator, atunci
mesajul este pastrat n coada.
Comunicatii axate pe subiect (topic) : Mesajele sunt depuse (publicate)
n destinatii specifice subiectului. Consumatorii ce au subscris la acel
subiect au acces la mesajele respective. Mai multi producatori pot genera
mesaje specifice unui subiect, mesaje care pot fi accesate de consumatorii
care au subscris subiectului.
Consumatorii abonati pe un subiect pot fi
115
abonat simplu - valabi, adica are acces la mesajele emise dupa momentul abonarii, pe durata conexiunii la furnizorul de servicii JMS;
abonat permanent - valabil si dupa o ntrerupere a conexiunii la
furnizorul de servicii JMS;
abonat partajat - mai multi abonati utilizeaza aceasi conexiune;
abonat partajat si permanent.
Structura unui mesaj Un mesaj este alcatuit din
Antet (header) : contine informatii pentru identificarea destinatiei cat si
pentru identificarea mesajului.
Proprietati : au caracter optional si sunt sub forma (nume, valoare).
Proprietatile ajuta consumatorii sa selecteze mesajele.
Corpul mesajului : optional. Potrivit specificatiilor JMS exista 6 tipuri
de mesaje.
javax.jms.Message : mesaj fara corp;
javax.jms.StreamMessage : corpul mesajului contine un flux Java
de date de tip predefinit;
javax.jms.ByteMessage :
javax.jms.MapMessage : corpul mesajului contine o familie de
perechi (nume, valoare);
javax.jms.TextMessage : corpul mesajului contine un string;
javax.jms.ObjectMessage : corpul mesajului contine un obiect
serializat.
Atasament (optional).
5.2
116
5.3
5.3.1
117
118
9
10
11
12
14
15
16
17
18
19
20
21
22
24
25
26
27
28
}
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 ) ;
29
30
31
32
33
34
35
5.3.2
119
Receptia sincron
a a unui mesaj
import
import
import
import
import
j a v a x . jms . TextMessage ;
j a v a x . jms . Message ;
j a v a x . jms . Queue ;
j a v a x . jms . JMSContext ;
j a v a x . jms . JMSConsumer ;
120
25
26
27
28
29
30
}
ctx . c l o s e ( ) ;
31
32
}
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 ) ;
33
34
35
36
37
38
39
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 ( ) ;
}
}
5.3.3
Receptia asincron
a a unui mesaj
1
2
3
4
6
7
import
import
import
import
9
10
11
13
14
15
16
17
18
19
20
21
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 ) ;
t e x t L i s t e n e r . run ( ) ;
ctx . c l o s e ( ) ;
23
24
25
26
}
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 ) ;
27
28
29
30
31
32
33
j a v a x . jms . MessageConsumer ;
j a v a x . jms . Queue ;
j a v a x . jms . JMSContext ;
j a v a x . jms . JMSConsumer ;
mpreuna cu ascultatorul
1
2
3
4
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
23
import
import
import
import
j a v a x . jms . M e s s a g e L i s t e n e r ;
j a v a x . jms . JMSException ;
j a v a x . jms . TextMessage ;
j a v a x . jms . Message ;
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 {
S t r i n g s=m. g e t T e x t ( ) ;
System . out . p r i n t l n ( s ) ;
}
catch ( JMSException e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}
}
else
s f a r s i t =true ;
}
public void run ( ) {
121
122
while ( ! s f a r s i t ) {
try {
Thread . s l e e p ( 1 ) ;
}
catch ( I n t e r r u p t e d E x c e p t i o n e ) { }
};
24
25
26
27
28
29
30
31
5.3.4
Publicarea mesajelor
9
10
11
12
13
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
5.3.5
123
import
import
import
import
import
j a v a x . jms . TextMessage ;
j a v a x . jms . Message ;
j a v a x . jms . Topic ;
j a v a x . jms . JMSContext ;
j a v a x . jms . JMSConsumer ;
124
else
break ;
35
36
}
ctx . c l o s e ( ) ;
37
38
}
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 ( S u b s c r i b e r f i n i s h e d ) ;
39
40
41
42
43
44
45
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 ( ) ;
}
}
}
5.3.6
Mai multi client JMS folosesc aceasi conexiune iar abonamentul se identifica
printr-un nume (String). Dintre acesi clienti doar unul receptioneaza mesajele
care sunt emise dupa momentul abonarii.
Exemplul 5.3.8
Fata de exemplul anterior se vor expedia mai multe mesaje de tip Message.
1
2
3
5
6
7
MsgPublisherT ( S t r i n g s u b i e c t , i n t n ) {
super ( ) ;
t h i s . n=n ;
t h i s . s u b i e c t=s u b i e c t ;
}
9
10
11
12
13
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
125
import
import
import
import
import
import
import
j a v a x . jms . TextMessage ;
j a v a x . jms . Message ;
j a v a x . jms . Topic ;
j a v a x . jms . JMSContext ;
j a v a x . jms . JMSConsumer ;
java . u t i l . concurrent . ExecutorService ;
java . u t i l . concurrent . Executors ;
public c l a s s
R e c e i v e r s T extends Thread {
String subiect ;
String sharedSubscriptionName ;
i n t noAbonati ;
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 ;
R e c e i v e r s T ( i n t noAbonati , S t r i n g s u b i e c t ,
String sharedSubscriptionName ){
t h i s . s u b i e c t=s u b i e c t ;
t h i s . noAbonati=noAbonati ;
t h i s . s h a r e d S u b s c r i p t i o n N a m e=s h a r e d S u b s c r i p t i o n N a m e ;
}
public void run ( ) {
E x e c u t o r S e r v i c e e x e c=E x e c u t o r s . newFixedThreadPool ( noAbonati ) ;
126
try {
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 ) ;
25
26
27
28
30
31
32
33
34
35
36
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( R e c e i v e r s : +e . g e t M e s s a g e ( ) ) ;
37
38
39
}
System . out . p r i n t l n ( R e c e i v e r s f i n i s h e d ) ;
41
42
43
44
import
import
import
import
import
j a v a x . jms . TextMessage ;
j a v a x . jms . Message ;
j a v a x . jms . Topic ;
j a v a x . jms . JMSContext ;
j a v a x . jms . JMSConsumer ;
}
else
break ;
35
36
37
}
ctx . c l o s e ( ) ;
38
39
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( M s g S u b s c r i b e r : +e . g e t M e s s a g e ( ) ) ;
}
System . out . p r i n t l n ( S u b s c r i b e r +c l i e n t N a m e+ f i n i s h e d ) ;
40
41
42
43
44
45
46
127
public 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 ;
S t r i n g s h a r e d S u b s c r i p t i o n N a m e= o u r S u b s c r i p t i o n ;
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 ) ;
R e c e i v e r s T a b o n a t i=new R e c e i v e r s T ( noAbonati , s u b i e c t ,
sharedSubscriptionName ) ;
abonati . s t a r t ( ) ;
publisher . start ( ) ;
}
}
5.3.7
Obiectele administrator, fabrica de conexiuni si obiectul destinatie, se precizeaza ntr-un fisier de proprietati - jndi.properties.
Pentru Open Message Queue acest fisier este
Varianta Oracle-Open Message Queue
1
2
3
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
j a v a . naming . p r o v i d e r . u r l= f i l e : /// d : /Temp
8
9
11
12
13
128
. RefFSContextFactory
. RefFSContextFactory
. RefFSContextFactory
. RefFSContextFactory
f s c o n t e x t . RefFSContextFactory
f s c o n t e x t . RefFSContextFactory
f s c o n t e x t . RefFSContextFactory
f s c o n t e x t . RefFSContextFactory
5.3.8
Aplicatia este alcatuita din clasele MsgHelloT, MsgSenderT, SyncMsgReceiverT, AsyncMsgReceiverT, TextListener. Fata de versiunea prezentata anterior se modifica doar clasele MsgSenderT, SyncMsgReceiverT, AsyncMsgReceiverT.
In clasa MsgHelloT campul queueName reprezinta numele JNDI al cozii.
Clasa MsgSenderT
1
2
3
4
5
6
7
8
10
11
12
13
14
16
17
18
19
21
22
23
24
25
26
27
import
import
import
import
import
import
129
j a v a x . jms . JMSContext ;
j a v a x . jms . JMSProducer ;
j a v a x . naming . I n i t i a l C o n t e x t ;
j a v a x . naming . NamingException ;
java . u t i l . Properties ;
j a v a . i o . IOException ;
29
30
31
32
33
34
35
}
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 ) ;
36
37
38
39
40
41
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
59
60
61
private void c l o s e J N D I ( ) {
try {
ctx . c l o s e ( ) ;
130
}
catch ( NamingException e ) {
System . e r r . p r i n t l n ( Unable t o c l o s e JNDI Context : + e ) ;
}
62
63
64
65
66
67
Clasa SyncMsgReceiverT
1
2
3
4
5
6
7
8
9
10
12
13
14
15
17
18
19
21
22
23
24
25
26
27
import
import
import
import
import
import
import
import
import
import
j a v a x . jms . QueueConnectionFactory ;
j a v a x . jms . Queue ;
j a v a x . jms . TextMessage ;
j a v a x . jms . Message ;
j a v a x . jms . JMSContext ;
j a v a x . jms . JMSConsumer ;
j a v a x . naming . I n i t i a l C o n t e x t ;
j a v a x . naming . NamingException ;
java . u t i l . Properties ;
j a v a . i o . IOException ;
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
48
50
private void c l o s e J N D I ( ) { . . . }
51
131
5.3.9
Comunicatia pe baz
a de subiect - topic
Aplicatia este alcatuita din clasele MsgPS, MsgPublisherT, MsgSubscriberT. Fata de versiunea prezentata anterior se modifica doar clasele MsgPublisherT si MsgSubscriberT.
In clasa MsgPS campul subiect reprezinta numele JNDI atasat topic-ului.
Clasa MsgPublisherT
1
2
3
4
5
6
7
8
10
11
12
13
14
16
17
18
19
21
22
23
24
25
26
27
import
import
import
import
import
import
import
import
j a v a x . jms . T o p i c C o n n e c t i o n F a c t o r y ;
j a v a x . jms . Topic ;
j a v a x . jms . JMSContext ;
j a v a x . jms . JMSProducer ;
j a v a x . naming . I n i t i a l C o n t e x t ;
j a v a x . naming . NamingException ;
java . u t i l . Properties ;
j a v a . i o . IOException ;
29
30
31
32
33
34
35
}
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 ) ;
36
37
38
39
40
41
43
45
private void c l o s e J N D I ( ) { . . . }
132
46
Clasa MsgSubscriberT
1
2
3
4
5
6
7
8
9
10
12
13
14
15
16
17
19
20
21
22
23
25
26
27
28
29
30
31
32
33
34
import
import
import
import
import
import
import
import
import
import
j a v a x . jms . T o p i c C o n n e c t i o n F a c t o r y ;
j a v a x . jms . Topic ;
j a v a x . jms . TextMessage ;
j a v a x . jms . Message ;
j a v a x . jms . JMSContext ;
j a v a x . jms . JMSConsumer ;
j a v a x . naming . I n i t i a l C o n t e x t ;
j a v a x . naming . NamingException ;
java . u t i l . Properties ;
j a v a . i o . IOException ;
36
37
38
39
40
41
42
43
44
45
}
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 ( S u b s c r i b e r f i n i s h e d ) ;
46
47
48
49
50
51
53
55
private void c l o s e J N D I ( ) { . . . }
56
133
5.3.10
Fisiere grafice (jpg, png), audio (mp3), video pot fi procesate prin mesaje
de tip StreamMessage
Exemplul 5.3.9 Aplicatie JMS cu clasa pentru publicarea si consumarea unui
mesaj care incorporeaza o imagine jpg.
Clasa MsgPublisherT
1
2
3
4
5
6
7
8
9
11
12
14
15
16
18
19
20
21
22
23
24
25
27
28
29
30
31
32
33
34
36
37
import
import
import
import
import
import
import
import
import
j a v a x . jms . Topic ;
j a v a x . jms . JMSContext ;
j a v a x . jms . StreamMessage ;
j a v a x . jms . BytesMessage ;
j a v a x . jms . JMSProducer ;
java . io . F i l e ;
j a v a . i o . ByteArrayOutputStream ;
j a v a . awt . image . B u f f e r e d I m a g e ;
j a v a x . i m a g e i o . ImageIO ;
40
JMSProducer p r o d u c e r=c t x . c r e a t e P r o d u c e r ( ) ;
p r o d u c e r . send ( t , msg ) ;
42
ctx . c l o s e ( ) ;
39
134
}
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 ) ;
43
44
45
46
47
48
49
Clasa MsgSubscriberT
1
2
3
4
5
6
7
8
9
10
12
13
14
15
17
18
19
20
21
23
24
25
26
27
28
29
30
31
32
import
import
import
import
import
import
import
import
import
import
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
j a v a x . jms . Message ;
j a v a x . jms . Topic ;
j a v a x . jms . JMSContext ;
j a v a x . jms . JMSConsumer ;
j a v a x . jms . StreamMessage ;
j a v a x . jms . BytesMessage ;
j a v a . awt . image . B u f f e r e d I m a g e ;
j a v a x . i m a g e i o . ImageIO ;
j a v a . i o . ByteArrayInputStream ;
j a v a . i o . InputStream ;
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 ( S u b s c r i b e r f i n i s h e d ) ;
50
51
52
53
54
55
import
import
import
import
import
j a v a . awt . Canvas ;
j a v a . awt . Image ;
j a v a . awt . G r a p h i c s ;
j a v a . awt . BorderLayout ;
j a v a x . swing . JFrame ;
10
11
12
public void p a i n t ( G r a p h i c s g ) {
g . drawImage ( image , 0 , 0 , t h i s ) ;
}
14
15
16
17
19
public c l a s s ShowImage{
MyCanvas mc=n u l l ;
20
22
23
24
26
27
28
29
30
31
32
33
34
35
36
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= s t r e a m i n g ;
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 ] ;
MsgSubscriberT abonat=new MsgSubscriberT ( s u b i e c t , myID , myName ) ;
MsgPublisherT p u b l i s h e r=new MsgPublisherT ( s u b i e c t ) ;
abonat . s t a r t ( ) ;
try {
Thread . s l e e p ( 1 0 0 0 ) ;
135
136
}
catch ( I n t e r r u p t e d E x c e p t i o n e ) { }
12
13
publisher . start ( ) ;
15
16
17
5.3.11
import
import
import
import
import
import
public c l a s s
1
2
3
4
5
10
11
12
13
15
16
17
18
19
j a v a x . jms . TextMessage ;
j a v a x . jms . Message ;
j a v a x . jms . Topic ;
j a v a x . jms . JMSContext ;
j a v a x . jms . JMSConsumer ;
j a v a x . jms . JMSProducer ;
MsgCmmdcServer{
// c f . s e t P r o p e r t y ( imqBrokerHostPort , 7 6 7 6 ) ;
Topic t=new com . sun . m e s s a g i n g . Topic ( Cmmdc ) ;
JMSContext c t x=c f . c r e a t e C o n t e x t ( ) ;
JMSConsumer consumer = c t x . c r e a t e S h a r e d C o n s u m e r ( t , Cmmdc ) ;
JMSProducer p r o d u c e r = c t x . c r e a t e P r o d u c e r ( ) ;
while ( true ) {
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 tm=(TextMessage ) msg ;
S t r i n g s=tm . g e t T e x t ( ) ;
S t r i n g [ ] s s=s . s p l i t ( ) ;
long m=Long . par se Lon g ( s s [ 0 ] ) ;
long n=Long . p ars eL ong ( s s [ 1 ] ) ;
S t r i n g t o p i c=s s [ 2 ] ;
long c=cmmdc(m, n ) ;
Topic t 1=new com . sun . m e s s a g i n g . Topic ( t o p i c ) ;
p r o d u c e r . send ( t1 , ( new Long ( c ) ) . t o S t r i n g ( ) ) ;
System . out . p r i n t l n ( S e r v e r s e n t +c+ t o +t o p i c ) ;
}
}
}
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
}
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 ( ) ) ;
}
43
44
45
46
47
49
50
Clasa MsgClientSender
1
2
3
4
5
7
8
import
import
import
import
import
j a v a x . jms . Topic ;
j a v a x . jms . JMSContext ;
j a v a x . jms . JMSProducer ;
j a v a x . jms . JMSConsumer ;
java . u t i l . Scanner ;
public c l a s s
MsgClientSender {
private S t r i n g msg , c l i e n t I D , clientName , t o p i c R e s u l t ;
23
MsgClientSender ( S t r i n g c l i e n t I D , S t r i n g clientName ){
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 ;
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 m : ) ;
long m=s c a n n e r . nextLong ( ) ;
S t r i n g sm=new Long (m) . t o S t r i n g ( ) ;
System . out . p r i n t l n ( I n t r o d u c e t i n : ) ;
long n=s c a n n e r . nextLong ( ) ;
S t r i n g sn=new Long ( n ) . t o S t r i n g ( ) ;
System . out . p r i n t l n ( I n t r o d u c e t i Topic u l r a s p u n s u l u i ) ;
t o p i c R e s u l t=s c a n n e r . n e x t ( ) ;
msg=sm+ +sn+ +t o p i c R e s u l t ;
}
25
private void s e r v i c e ( ) {
10
11
12
13
14
15
16
17
18
19
20
21
22
137
138
try {
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 ) ;
Topic t=new com . sun . m e s s a g i n g . Topic ( Cmmdc ) ;
JMSContext c t x=c f . c r e a t e C o n t e x t ( ) ;
26
27
28
29
30
31
32
34
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 ( JMSException : +e . g e t M e s s a g e ( ) ) ;
}
40
41
42
43
44
46
47
48
49
50
51
52
53
54
55
Clasa MsgClientReceiver
1
2
3
4
5
6
8
9
11
12
13
14
15
16
17
19
20
21
22
23
24
25
26
import
import
import
import
import
import
j a v a x . jms . TextMessage ;
j a v a x . jms . Message ;
j a v a x . jms . Topic ;
j a v a x . jms . JMSContext ;
j a v a x . jms . JMSConsumer ;
java . u t i l . Scanner ;
public c l a s s
MsgClientReceiver {
private S t r i n g t o p i c R e s u l t , c l i e n t I D , c l i e n t N a m e ;
MsgClientReceiver ( S t r i n g c l i e n t I D , S t r i n g clientName ){
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 ;
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 Topic u l r a s p u n s u l u i ) ;
t o p i c R e s u l t=s c a n n e r . n e x t ( ) ;
}
public void s e r v i c e ( ) {
try {
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 ) ;
Topic t=new com . sun . m e s s a g i n g . Topic ( t o p i c R e s u l t ) ;
JMSContext c t x=c f . c r e a t e C o n t e x t ( ) ;
ctx . setClientID ( c l i e n t I D ) ;
JMSConsumer consumer = c t x . c r e a t e D u r a b l e C o n s u m e r ( t , c l i e n t N a m e ) ;
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 ( Cmmdc : +m. g e t T e x t ( ) ) ;
break ;
}
}
ctx . c l o s e ( ) ;
27
28
29
30
31
32
33
34
35
36
37
}
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 ( ) ) ;
}
38
39
40
41
42
44
45
46
47
48
49
50
51
52
53
5.3.12
139
140
[-targetserver host:3700]
import
import
import
import
import
j a v a x . jms . QueueConnectionFactory ;
j a v a x . jms . Queue ;
j a v a x . jms . JMSContext ;
j a v a x . jms . JMSProducer ;
javax . annotation . Resource ;
public c l a s s MsgSender {
@Resource ( l o o k u p= myQueueConnectionFactory )
private s t a t i c QueueConnectionFactory c f ;
@Resource ( l o o k u p=myQueue )
private s t a t i c Queue q ;
private s t a t i c i n t n=3;
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
try {
JMSContext j m s c t x=c f . c r e a t e C o n t e x t ( ) ;
JMSProducer p r o d u c e r=j m s c t x . c r e a t e P r o d u c e r ( ) ;
f o r ( i n t i =0; i <n ; i ++){
p r o d u c e r . send ( q , H e l l o +i ) ;
}
p r o d u c e r . send ( q , j m s c t x . c r e a t e M e s s a g e ( ) ) ;
jmsctx . c l o s e ( ) ;
}
catch ( E x c e p t i o n e ) {
// System . o u t . p r i n t l n ( JMSException : +e . g e t M e s s a g e ( ) ) ;
e . printStackTrace ( ) ;
}
System . out . p r i n t l n ( Sen de r f i n i s h e d ) ;
23
24
25
26
27
28
29
30
import
import
import
import
import
import
import
public c l a s s SyncMsgReceiver {
@Resource ( l o o k u p= myQueueConnectionFactory )
private s t a t i c QueueConnectionFactory c f ;
@Resource ( l o o k u p=myQueue )
private s t a t i c Queue q ;
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
try {
JMSContext j m s c t x=c f . c r e a t e C o n t e x t ( ) ;
JMSConsumer consumer = j m s c t x . createConsumer ( q ) ;
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 ;
}
jmsctx . c l o s e ( ) ;
}
catch ( E x c e p t i o n e ) {
// System . o u t . p r i n t l n ( JMSException : +e . g e t M e s s a g e ( ) ) ;
e . printStackTrace ( ) ;
}
System . out . p r i n t l n ( Consumer f i n i s h e d ) ;
}
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
j a v a x . jms . QueueConnectionFactory ;
j a v a x . jms . Queue ;
j a v a x . jms . JMSContext ;
j a v a x . jms . JMSConsumer ;
j a v a x . jms . Message ;
j a v a x . jms . TextMessage ;
javax . annotation . Resource ;
Intreb
ari recapitulative
1. Explicati caracterul de cuplare slaba al unei aplicatii bazat pe JMS.
2. Care este rolul furnizorului (provider) JMS?
3. Precizati si explicati modelele de comunicatii cu mesaje n JMS.
141
142
Partea II
TEHNOLOGII CU
COMUNICAT
II PRIN
INTERNET
143
Capitolul 6
HyperText Transfer Protocol
Protocolul http- HyperText Transfer Protocol (http) este destinat schimburilor de informatii n Internet.
Protocolul http a ajuns la versiunea 2 (HTTP/2), versiunea anterioara fiind 1.1 (HTTP/1.1). Scopul lui HTTP/2 este reducerea latentei prin utilizarea
mai eficienta a retelei. Diferenta dintre HTTP/2 si HTTP/1.1 este la nivelul
de transport, adica a modului n care bitii sunt schimbati prin retea. HTTP/2
pastreaza structura mesajului din HTTP/1.1.
In vederea schimburilor dintre calculatoare prin Internet, reprezentarea
datelor se face utilizand n principal:
eXtensible Markup Language (XML) - subset al limbajului Standard
Generalized Markup Language (SGML);
JavaScript Object Notation (JSON).
HyperText Markup Language (HTML), XHTML, HTML 5 sunt principalele
limbaje pentru publicarea informatiilor pe Web. Aceste limbaje deriva de
asemenea din SGML.
6.1
Transactie http
146
6.1. TRANSACT
IE HTTP
147
Preambulul unui r
aspuns contine:
Indica
mesaj de informare
mesaj de succes
redirectare catre alt URL
eroare in mesajul clientului
eroare din partea serverului
Un antet (header ) este un atribut, adica o pereche (nume:valoare). Protocolul http defineste o paleta larga de atribute. Exemple de antete sunt date
n tabelul urmator:
148
Antet
Semnificatie
Exemplu
host
Gazda si portul serverului Web
localhost:8080
user-agent
Navigatorul care a lansat cererea
Mozilla/5.0 (Windows NT 6.1; WOW64)
AppleWebKit/535.2 (KHTML, like Gecko)
Chrome/15.0.874.106 Safari/535.2
referer
URL-ul cererii
http://localhost:8080/apphello/
accept-encoding Tipuri de arhive acceptate
gzip,deflate,sdch
accept-charset Tipuri de codificare acceptate
ISO-8859-1,utf-8;q=0.7,*;q=0.3
accept-language Cea mai potrivita limba pentru ntelegerea
continutului
en-US,en;q=0.8
content-type
Tipul MIME al corpului mesajului
http://application/x-www-form-urlencoded
content-length Lungimea corpului mesajului
22
Upgrade
Solicitare / Acord schimbare protocol
websocket
Corpul mesajului este reprezentat printr-un text. Daca continutul este
imagine, cod binar, etc., atunci acesta este codificat n text.
Codul Multipurpose Internet Mail Exchange (MIME) precizeaza natura
continutului unei resurse:
text/plain
text/html
text/xml
image/png
image/jpg
application/octet-stream
application/x-www-form-urlencoded
Ne propunem sa punem n evidenta mesajele http.
6.1. TRANSACT
IE HTTP
149
import
import
import
import
import
import
import
import
public c l a s s RequestHTTPMsg{
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
S o c k e t s o c k e t=n u l l ;
try {
S e r v e r S o c k e t 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 ( 8 0 8 0 ) ;
s o c k e t=s e r v e r S o c k e t . a c c e p t ( ) ;
}
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 ( ) ) ;
}
try (
InputStream i s=s o c k e t . g e t I n p u t S t r e a m ( ) ;
InputStreamReader i s r =new InputStreamReader ( i s ) ;
B u f f e r e d R e a d e r br=new B u f f e r e d R e a d e r ( i s r ) ;
F i l e W r i t e r fw=new F i l e W r i t e r ( ou tp ut . t x t , true ) ;
B u f f e r e d W r i t e r bw=new B u f f e r e d W r i t e r ( fw ) ) {
for ( ; ; ) {
S t r i n g s=br . r e a d L i n e ( ) ;
i f ( s==n u l l ) break ;
System . out . p r i n t l n ( s ) ;
bw . w r i t e ( s ) ;
bw . newLine ( ) ;
}
}
catch ( IOException e ) {
System . out . p r i n t l n ( I n p u t E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}
}
}
Rezultatul cererii depinde de metoda GET sau POST utilizata n formularul html folosit.
Pentru metoda GET cererea http este
GET /apphello/hello?name=mk&tip=text%2Fhtml HTTP/1.1
Host: localhost:8080
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64)
AppleWebKit/535.2 (KHTML, like Gecko)
Chrome/15.0.874.106 Safari/535.2
150
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
<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 t t p : / / l o c a l h o s t : 8 0 8 0 / a p p h e l l o / 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 value= A p e l e a z a >
<input type= h id de n name= t i p value= t e x t / html >
</form>
</ center>
</body>
</htm
Mesaj r
aspuns http
Un servlet (apphello) este activ ntr-un server Web. O clasa Java lanseaza
o cerere http catre acel servlet - chiar unul din mesajele obtinute mai sus dupa care receptioneaza raspunsul dat de servlet.
Codul clasei Java
1
2
3
4
5
import
import
import
import
import
6.1. TRANSACT
IE HTTP
6
7
8
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
38
39
40
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
151
import j a v a . i o . F i l e W r i t e r ;
import j a v a . i o . P r i n t W r i t e r ;
import j a v a . u t i l . S c a n n e r ;
public c l a s s ResponseHTTPMsg{
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 reqGET=GET / a p p h e l l o / h e l l o ?name=mk&t i p=t e x t%2Fhtml HTTP/ 1 . 1 \ r \n+
Host : l o c a l h o s t : 8 0 8 0 \ r \n+
C o n n e c t i o n : keepa l i v e \ r \n+
UserAgent : M o z i l l a / 5 . 0 ( Windows NT 6 . 1 ; WOW64) +
AppleWebKit / 5 3 5 . 2 (KHTML, l i k e Gecko ) +
Chrome / 1 5 . 0 . 8 7 4 . 1 0 6 S a f a r i / 5 3 5 . 2 \ r \n+
Accept : t e x t / html , a p p l i c a t i o n / xhtml+xml , a p p l i c a t i o n /xml ; +
q = 0 . 9 , / ; q =0.8\ r \n+
AcceptEncoding : g z i p , d e f l a t e , sdch \ r \n+
AcceptLanguage : enUS , en ; q =0.8\ r \n+
AcceptC h a r s e t : ISO88591, u t f 8; q = 0 . 7 , ; q =0.3\ r \n ;
S t r i n g reqPOST=POST / a p p h e l l o / h e l l o HTTP/ 1 . 1 \ r \n+
Host : l o c a l h o s t : 8 0 8 0 \ r \n+
C o n n e c t i o n : keepa l i v e \ r \n+
ContentLength : 23\ r \n+
CacheC o n t r o l : maxage =0\ r \n+
O r i g i n : n u l l \ r \n+
UserAgent : M o z i l l a / 5 . 0 ( Windows NT 6 . 1 ; WOW64) +
AppleWebKit / 5 3 5 . 2 (KHTML, l i k e Gecko ) +
Chrome / 1 5 . 0 . 8 7 4 . 1 0 6 S a f a r i / 5 3 5 . 2 \ r \n+
ContentType : a p p l i c a t i o n /xwwwformu r l e n c o d e d \ r \n+
Accept : t e x t / html , a p p l i c a t i o n / xhtml+xml , a p p l i c a t i o n /xml ; +
q = 0 . 9 , / ; q =0.8\ r \n+
AcceptEncoding : g z i p , d e f l a t e , sdch \ r \n+
AcceptLanguage : enUS , en ; q =0.8\ r \n+
AcceptC h a r s e t : ISO88591, u t f 8; q = 0 . 7 , ; q =0.3\ r \n+
\ r \n+
name=mk&t i p=t e x t%2Fhtml ;
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 ( P r e c i z a t i metoda HTTP : ) ;
System . out . p r i n t l n ( 1 : GET; 2 : POST ) ;
i n t metoda ;
do{
metoda=s c a n n e r . n e x t I n t ( ) ;
}
while ( ( metoda!=1)&&(metoda ! = 2 ) ) ;
try (
S o c k e t s o c k e t=new S o c k e t ( l o c a l h o s t , 8 0 8 0 ) ;
InputStreamReader i s r =new InputStreamReader ( s o c k e t . g e t I n p u t S t r e a m ( ) ) ;
B u f f e r e d R e a d e r br=new B u f f e r e d R e a d e r ( i s r ) ;
F i l e W r i t e r fw=new F i l e W r i t e r ( ou tp ut . t x t , true ) ;
B u f f e r e d W r i t e r bw=new B u f f e r e d W r i t e r ( fw ) ;
P r i n t W r i t e r pw=new P r i n t W r i t e r ( s o c k e t . getOutputStream ( ) , true )
){
switch ( metoda ) {
case 1 :
// Lansarea u n e i c e r e r i GET
pw . p r i n t l n ( reqGET ) ;
break ;
case 2 :
// Lansarea u n e i c e r e r i POST
152
pw . p r i n t l n ( reqPOST ) ;
}
for ( ; ; ) {
S t r i n g s=br . r e a d L i n e ( ) ;
i f ( s==n u l l ) break ;
System . out . p r i n t l n ( s ) ;
bw . w r i t e ( s ) ;
bw . newLine ( ) ;
bw . f l u s h ( ) ;
}
65
66
67
68
69
70
71
72
73
74
}
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 ( ) ) ;
}
75
76
77
78
79
80
6.2
In prezent sunt disponibile mai multe servere Web n care poate fi instalat
un servlet si un fisier JSP Java Server Pages. Despre un asemenea server Web
se spune ca este container de servlet si JSP. Dintre produsele gratuite amintim
apache-tomcat
jetty
glassfish
Acest server Web este utilizat n java ee sdk - o implementare JEE (Java
Enterprise Edition) de la Oracle.
apache-tomee este construit peste apache-tomcat si integreaza o serie de
tehnologii JEE
153
weblogic (Oracle)
jboss application server (RedHat)
Geronimo, o alta implementare JEE dezvoltata de fundatia apache, poate
utiliza containerul apache-tomcat sau jetty.
Serverul Apache HTTP Server si Windows Internet Information Server nu
sunt servere Web containere de servlet si JSP.
6.3
Numele si num
arul cataloagelor este dependent de distributia apache-tomcat.
154
155
6.4. GLASSFISH
6.4
Glassfish
156
Capitolul 7
Conexiune simpl
a prin clase din
java.net
Pachetul java.net ofera, prin intermediul claselor URL, URLConnection,
HttpURLConnection, HttpsURLConnection, JarURLConnection o posibilitate elementara de acces a unor resurse din Internet.
7.1
Clasa java.net.URL
157
158
Exemplul 7.1.1 Pe baza referintei catre un fisier html dintr-un catalog vizibil
al unui server Web, sa se afiseze continutul fisierului.
In codul reprodus mai jos, fisierul Hello.html se afla pe serverul apachetomcat, n catalogul webapps\url.
1
2
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
32
33
34
35
import
import
import
import
j a v a . n e t .URL;
j a v a . i o . InputStream ;
j a v a . i o . InputStreamReader ;
java . i o . BufferedReader ;
public c l a s s ReadHTTP{
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 adr= h t t p : / / l o c a l h o s t : 8 0 8 0 / u r l / H e l l o . html ;
// System . s e t P r o p e r t y ( h t t p . p r o x y H o s t , 1 0 . 3 . 5 . 1 3 3 ) ;
// System . s e t P r o p e r t y ( h t t p . p r o x y P o r t , 3 1 2 8 ) ;
URL u r l=n u l l ;
try {
u r l=new URL( adr ) ;
}
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 ( ) ) ;
}
try (
InputStream i n=u r l . openStream ( ) ;
InputStreamReader i s r =new InputStreamReader ( i n ) ;
B u f f e r e d R e a d e r br=new B u f f e r e d R e a d e r ( i s r ) ;
){
String s ;
do{
s=br . r e a d L i n e ( ) ;
i f ( s != n u l l )
System . out . p r i n t l n ( s ) ;
}
while ( s != n u l l ) ;
}
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 ( ) ) ;
}
}
}
Capitolul 8
Servlet
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 uzual de
o persoana utilizand un program navigator: Google Chrome, Mozilla
Firefox, Microsoft InternetExplorer, Opera, Apple Safari, etc.
Servicii Web: Cererea catre server se face de un program. Aplicatia
server si client se programeaza utilizand interfete de programare specifice.
Componenta server a unei aplicatii Web
contine o clasa Java care se excuta de un server Web, compatibil;
este gestionata de serverul Web;
este capabila sa receptioneze si sa rapunda cererilor formulate de clienti.
Structura minimala a unei aplicatii Web este
catalogAplicatiei
|--> WEB-INF
|
|--> classes
|
|
|
*.class
|
|--> lib
|
|
|
*.jar
|
index.html
159
160
CAPITOLUL 8. SERVLET
http://host:port/catalogAplicatieiWeb
Daca n loc de index fisierul html de apelare are alt nume, de exemplu xyz.html
atunci adresa de apelare va fi
http://host:port/catalogAplicatieiWeb/xyz.html
host este numele calculatorului pe care ruleaza serverul Web - gazda aplicatiei
Web. Portul implicit utilizat de un server Web container de servlet este 8080.
Catalogul aplicatiei este denumit context-ul aplicatiei Web.
Programarea si utilizarea unei aplicatii Web necesita:
Cunoasterea elementului (marcaj, tag) html <form> pentru realizarea
formularelor de introducere a datelor;
Utilizarea unui server Web, container de servleti. Dintre produsele gratuite amintim: apache-tomcat, jetty, glassfish.
8.1
Marcajul <form>
Intr-un document html introducerea datelor se poate obtine utilizand marcajul <form> ...</form> .
Atribute ale marcajului <form> . Reamintim ca atributele se prezinta
ca perechi (nume, valoare) si se scriu n antetul marcajului sub forma nume =
valoare.
161
Nume
action
Valoare
adresa tip URL
method
GET
POST
id
name
onSubmit
Semnificatia valorii
Resursa care prelucreaza formularul, cel putin
/context/numeApel
Mesajul trimis serverului Web contine dupa
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).
Valoare
Semnificatie
text
Se asteapta introducerea unui text
number
Se asteapta introducerea unui numar ntreg
date
Se asteapta introducerea unei date calendaristice
password
Se asteapta introducerea unei parole
submit
Se marcheaza sfarsitul completarii formularului
reset
Se reinitializeaza formularul
file
Permite selectarea unui fisier
hidden
Transmite mai departe un atribut fara vizualizarea lui
name
numele controlului
value
valoarea (initiala) a controlului
size
numarul caracterelor atasat controlului
162
CAPITOLUL 8. SERVLET
8.2
vert.x, Play sunt cadre de lucru care dezvolta n Java aplicatii distribuite fara sa se
bazeze pe servlet.
163
164
CAPITOLUL 8. SERVLET
cu precizarea fisierelor html sau jsp care apeleaza aplicatia Web. Declaratia
fisierului index.html este implicita.
Compilarea clasei servlet necesita completarea variabilei de mediu classpath
cu fisierul TOMCAT HOME\lib\servlet-api.jar.
Odata completata structura de cataloage si fisiere ale aplicatiei servlet
aceasta structura trebuie copiata 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 copiaza n catalogul TOMCAT HOME\webapps.
Serverul Web tomcat va dezarhiveaza arhiva. Astfel servlet-ul este instalat.
Aceasta instalare se numeste instalare dinamica - hot deployment.
Daca fisierul war este creat, atunci n locul copierii, instalarea se poate
face prin componenta manager a lui tomcat.
O aplicatie servlet arhivata war se poate instala de la distata prin produsele:
apache-tomcat-deployer
cargo
8.2.1
165
166
CAPITOLUL 8. SERVLET
167
168
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
CAPITOLUL 8. SERVLET
import
import
import
import
import
import
import
j a v a . i o . IOException ;
javax . s e r v l e t . ServletException ;
javax . s e r v l e t . http . HttpServlet ;
javax . s e r v l e t . http . HttpServletRequest ;
javax . s e r v l e t . http . HttpServletResponse ;
javax . s e r v l e t . ServletOutputStream ;
j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
@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 ( ) ;
}
28
29
30
31
32
169
|---> src
|
|
HelloServlet.java
|---> web
|
|---> WEB-INF
|
|
|---> classes
|
|
|---> lib
|
|
|
web.xml
|
|
index.html
build.xml
170
CAPITOLUL 8. SERVLET
i n c l u d e a n t r u n t i m e= f a l s e
s r c d i r= ${ b a s e d i r }/ s r c
d e s t d i r=web/WEBINF/ c l a s s e s />
22
23
24
25
27
28
29
30
</ t a r g e t>
<t a r g e t name= g e n e r a t e . war depends= c o m p i l e >
<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=web />
</ t a r g e t>
</ p r o j e c t>
import
import
import
import
import
import
import
j a v a . i o . IOException ;
java . io . PrintWriter ;
javax . s e r v l e t . ServletException ;
javax . s e r v l e t . http . HttpServlet ;
javax . s e r v l e t . http . HttpServletRequest ;
javax . s e r v l e t . http . HttpServletResponse ;
j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
@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 {
12
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
IN SERVLET
8.3. PROCESARE ASINCRONA
38
39
40
41
42
171
8.3
Procesare asincron
a n servlet
172
CAPITOLUL 8. SERVLET
package m y s e r v l e t ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
IN SERVLET
8.3. PROCESARE ASINCRONA
3
4
5
6
7
8
9
11
12
import
import
import
import
import
import
import
14
15
16
17
18
19
20
22
23
24
25
26
Clasa AsyncAction
package m y s e r v l e t ;
import j a v a x . s e r v l e t . AsyncContext ;
import j a v a . i o . P r i n t W r i t 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 ;
import j a v a x . s e r v l e t . S e r v l e t R e s p o n s e ;
import j a v a . i o . IOException ;
c l a s s AsyncAction {
1
2
3
4
5
12
i n t e r f a c e CmmdcService {
long cmmdc( long m, long n ) ;
}
14
16
interface IAsyncAction {
Thread s e r v i c e ( AsyncContext asyncCtx ) ;
}
10
11
17
18
20
21
22
23
24
25
26
27
28
29
30
31
I A s y n c A c t i o n f =(AsyncContext asyncCtx)>{
return new Thread (()>{
S e r v l e t R e q u e s t r e q=asyncCtx . g e 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=asyncCtx . g e t R e s p o n s e ( ) ;
S t r i n g sm=r e q . g e t P a r a m e t e r ( m ) ;
S t r i n g sn=r e q . g e t P a r a m e t e r ( n ) ;
long m=Long . par se Lo ng ( sm ) , n=Long . par se Lo ng ( sn ) ;
long x=cmmdcService . cmmdc(m, n ) ;
S t r i n g r e s u l t=new Long ( x ) . t o S t r i n g ( ) ;
System . out . p r i n t l n ( x ) ;
try {
P r i n t W r i t e r out=r e s . g e t W r i t e r ( ) ;
173
174
CAPITOLUL 8. SERVLET
S t r i n g t i t l e =Cmmdc S e r v l e t ;
r e s . setContentType ( t e x t / html ) ;
out . p r i n t l n ( <HTML><HEAD><TITLE> ) ;
out . p r i n t l n ( t i t l e ) ;
out . p r i n t l n ( </TITLE></HEAD><BODY> ) ;
out . p r i n t l n ( <H1>+ t i t l e +</H1> ) ;
out . p r i n t l n ( <P>Cmmdc i s +x ) ;
out . p r i n t l n ( </BODY></HTML> ) ;
out . c l o s e ( ) ;
32
33
34
35
36
37
38
39
40
}
catch ( IOException e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}
asyncCtx . c o m p l e t e ( ) ;
});
41
42
43
44
45
46
};
47
48
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
IN SERVLET
8.3. PROCESARE ASINCRONA
175
package m y s e r v l e t ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e q u e s t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e s p o n s e ;
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 x . s e r v l e t . AsyncContext ;
import j a v a . i o . IOException ;
import j a v a x . e n t e r p r i s e . c o n c u r r e n t . M a n a g e d E x e c u t o r S e r v i c e ;
import j a v a x . a n n o t a t i o n . R e s o u r c e ;
import j a v a . i o . P r i n t W r i t e r ;
@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 {
16
@Resource private M a n a g e d E x e c u t o r S e r v i c e e x e c u t o r S e r v i c e ;
18
19
20
21
22
23
24
25
26
27
176
CAPITOLUL 8. SERVLET
P r i n t W r i t e r out=r e s . g e t W r i t e r ( ) ;
i f ( t i p . e q u a l s ( t e x t / html ) ) {
S t r i n g t i t l e =Cmmdc S e r v l e t ;
r e s . setContentType ( t e x t / html ) ;
out . p r i n t l n ( <HTML><HEAD><TITLE> ) ;
out . p r i n t l n ( t i t l e ) ;
out . p r i n t l n ( </TITLE></HEAD><BODY> ) ;
out . p r i n t l n ( <H1>+ t i t l e +</H1> ) ;
out . p r i n t l n ( <P>Cmmdc i s +x ) ;
out . p r i n t l n ( </BODY></HTML> ) ;
}
else {
r e s . setContentType ( t e x t / p l a i n ) ;
out . p r i n t l n ( x ) ;
}
out . c l o s e ( ) ;
asyncCtx . c o m p l e t e ( ) ;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
}
catch ( IOException e ) { }
});
45
46
47
48
50
51
52
53
55
56
IN SERVLET-API 3.1
8.4. DEZVOLTARI
8.4
177
Dezvolt
ari n servlet-api 3.1
8.4.1
Procesare asincron
a neblocant
a
Diferenta majora consta n faptul ca solicitarea clientului este trimisa nemijlocit si ndeplinita de o clasa tip listener.
Clasa javax.servlet.ServletInputStream
Metode
public int readLine(byte[] b, int off, int len) throws IOException
public void setReadListener(ReadListenerreadListener )
Interfata javax.servlet.ReadListener declara metodele
void onDataAvailable() throws IOException
void onAllDataRead() throws IOException)
void onError(Throwable t)
Clasa care implementeaza aceasta interfata satisface cererea clientului.
Se va mai utiliza interfata javax.servlet.WriteListener care declara
metodele
void onWritePossible() throws java.io.IOException
void onError(java.lang.Throwable throwable)
Exemplul 8.4.1
11
import j a v a . i o . IOException ;
// i m p o r t j a v a . i o . P r i n t W r i t e r ;
import j a v a . n e t .URL;
import j a v a x . s e r v l e t . AsyncContext ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
import j a v a x . s e r v l e t . S e r v l e t I n p u t S t r e a m ;
import j a v a x . s e r v l e t . S e r v l e t O u t p u t S t r e a m ;
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 x . s e r v l e t . h t t p . H t t p S e r v l e t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e q u e s t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e s p o n s e ;
13
@WebServlet ( u r l P a t t e r n s = { / n o n b l o c k } , a s y n c S u p p o r t e d=true )
1
2
3
4
5
6
7
8
9
10
178
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public c l a s s N o n B l o c k i n g S e r v l e t extends H t t p S e r v l e t {
protected 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 ; c h a r s e t=UTF8 ) ;
ServletInputStream input = req . getInputStream ( ) ;
S e r v l e t O u t p u t S t r e a m o ut pu t = r e s . getOutputStream ( ) ;
ou tp ut . p r i n t l n ( <html> ) ;
ou tp ut . p r i n t l n ( <head> ) ;
ou tp ut . p r i n t l n ( < t i t l e >S e r v l e t R e a d T e s t S e r v l e t </ t i t l e > ) ;
ou tp ut . p r i n t l n ( </head> ) ;
ou tp ut . p r i n t l n ( <body> ) ;
ou tp ut . p r i n t l n ( <h1>S e r v l e t N o n B l o c k i n g S e r v l e t a t +
r e q . g e t C o n t e x t P a t h ( ) + </h1> ) ;
AsyncContext c o n t e x t = r e q . s t a r t A s y n c ( ) ;
CmmdcListener l i s t e n e r=new CmmdcListener ( i n p u t , c o n t e x t , ou tp ut ) ;
ou tp ut . p r i n t l n ( </body> ) ;
ou tp ut . p r i n t l n ( </html> ) ;
}
@Override
protected 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 ) ;
}
33
34
35
36
37
38
CAPITOLUL 8. SERVLET
import
import
import
import
import
import
import
1
2
3
4
5
6
11
12
13
14
15
16
18
19
20
21
22
23
24
25
27
28
29
30
31
j a v a . i o . IOException ;
j a v a x . s e r v l e t . AsyncContext ;
javax . s e r v l e t . ReadListener ;
javax . s e r v l e t . ServletOutputStream ;
javax . s e r v l e t . WriteListener ;
javax . s e r v l e t . ServletInputStream ;
j a v a . i o . IOException ;
private
private
private
private
private
private
public CmmdcListener ( S e r v l e t I n p u t S t r e a m in ,
AsyncContext ac , S e r v l e t O u t p u t S t r e a m o ut pu t ) {
input = in ;
c o n t e x t = ac ;
out = ou tp ut ;
in . setReadListener ( this ) ;
out . s e t W r i t e L i s t e n e r ( t h i s ) ;
}
@Override
public void o n D a t a A v a i l a b l e ( ) {
try {
int l e n = 0 ;
byte b [ ] = new byte [ 1 0 2 4 ] ;
IN SERVLET-API 3.1
8.4. DEZVOLTARI
32
33
34
35
36
}
catch ( IOException e ) {
System . out . p r i n t l n ( o n A v a i l a b l e E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}
37
38
39
40
41
43
@Override
public void onAllDataRead ( ) throws IOException {
System . out . p r i n t l n ( onAllDataRead ) ;
r e a d F i n i s h e d=true ;
System . out . p r i n t l n ( data ) ;
r e z=s o l v e r ( data ) ;
context . complete ( ) ;
onWritePossible ( ) ;
}
44
45
46
47
48
49
50
51
@Override
public void o n W r i t e P o s s i b l e ( ) throws IOException {
while ( ! r e a d F i n i s h e d ) ;
out . p r i n t l n ( <p> ) ;
out . p r i n t l n ( r e z ) ;
}
53
54
55
56
57
58
@Override
public void o n E r r o r ( Throwable t ) {
t . printStackTrace ( ) ;
context . complete ( ) ;
}
60
61
62
63
64
private S t r i n g s o l v e r ( S t r i n g data ) {
S t r i n g [ ] s=data . s p l i t ( & ) ;
S t r i n g [ ] s 0=s [ 0 ] . s p l i t ( = ) ;
long m=Long . par se Lon g ( s 0 [ 1 ] ) ;
S t r i n g [ ] s 1=s [ 1 ] . s p l i t ( = ) ;
long n=Long . p ars eL ong ( s 1 [ 1 ] ) ;
S t r i n g r =(new Long (cmmdc(m, n ) ) ) . t o S t r i n g ( ) ;
return Cmmdc : +r ;
}
66
67
68
69
70
71
72
73
74
76
77
179
8.4.2
180
CAPITOLUL 8. SERVLET
import
import
import
import
import
@WebServlet ( u r l P a t t e r n s = { / upgrade } )
public c l a s s U p g r a d e S e r v l e t extends H t t p S e r v l e t {
1
2
3
4
servlet
servlet
servlet
servlet
servlet
. ServletException ;
. http . HttpServlet ;
. http . HttpServletRequest ;
. http . HttpServletResponse ;
. a n n o t a t i o n . WebServlet ;
11
12
13
14
15
16
17
18
19
20
21
22
23
24
26
27
28
29
30
javax .
javax .
javax .
javax .
javax .
Pentru problema calculului celui mai mare divizor comun a doua numere
naturale clasa MyHttpUpgradeHandler este
IN SERVLET-API 3.1
8.4. DEZVOLTARI
1
2
3
4
6
7
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import
import
import
import
javax .
javax .
javax .
javax .
servlet
servlet
servlet
servlet
. ServletOutputStream ;
. ServletInputStream ;
. h t t p . WebConnection ;
. h t t p . HttpUpgradeHandler ;
181
182
private long cmmdc( long m, long n ) { . . . }
59
60
CAPITOLUL 8. SERVLET
Problema care ramane de rezolvat este inserarea antetului Update. Rezolvarea consta n generarea unui mesaj http care se va transmite printr-un
soclu TCP. Mesajul http foloseste metoda post, iar datele din corpul mesajului sunt preluate prin interfata HttpInputStream.
Lansarea aplicatiei se face dintr-un program client, n care se genereaza
mesajul http cu anterul Upgrade, mesaj expediat printr-un soclu TCP.
Client Java
1
2
3
4
5
6
7
9
10
11
12
13
14
15
16
17
18
19
20
21
23
24
25
26
27
28
29
30
31
32
33
34
36
37
38
39
40
41
42
43
44
45
import
import
import
import
import
import
import
public c l a s s J C l i e n t {
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 ( m= ) ;
long m=s c a n n e r . nextLong ( ) ;
S t r i n g sm=new Long (m) . t o S t r i n g ( ) ;
System . out . p r i n t l n ( n= ) ;
long n=s c a n n e r . nextLong ( ) ;
S t r i n g sn=new Long ( n ) . t o S t r i n g ( ) ;
S t r i n g data=sm+ +sn ;
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= 8080 ;
S t r i n g c o n t e x t R o o t= / upgrade ;
S t r i n g CRLF = \ r \n ;
S t r i n g r e q S t r = POST + c o n t e x t R o o t + / upgrade HTTP/ 1 . 1 + CRLF ;
r e q S t r += UserAgent : Java / 1 . 7 + CRLF ;
r e q S t r += Host : + h o s t + : + p o r t + CRLF ;
r e q S t r += Accept : t e x t / html , image / g i f , image / j p e g , ; q = . 2 , / ; q =.2 +
CRLF ;
r e q S t r += Upgrade : upgrade + CRLF ;
r e q S t r += C o n n e c t i o n : Upgrade + CRLF ;
r e q S t r += Contentt y p e : a p p l i c a t i o n /xwwwformu r l e n c o d e d + CRLF ;
r e q S t r += T r a n s f e r Encoding : chunked + CRLF ;
r e q S t r += CRLF ;
r e q S t r += data + CRLF ;
S o c k e t s o c k e t=n u l l ;
try {
s o c k e t=new S o c k e t ( hos t , I n t e g e r . p a r s e I n t ( p o r t ) ) ;
}
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 ( ) ) ;
}
try (
OutputStream out=s o c k e t . getOutputStream ( ) ;
InputStream i n=s o c k e t . g e t I n p u t S t r e a m ( ) ;
IN SERVLET-API 3.1
8.4. DEZVOLTARI
46
47
){
48
out . w r i t e ( r e q S t r . g e t B y t e s ( ) ) ;
out . f l u s h ( ) ;
String s ;
while ( ( s=br . r e a d L i n e ( ) ) ! = n u l l ) {
System . out . p r i n t l n ( s ) ;
};
socket . close ( ) ;
// System . e x i t ( 0 ) ;
49
50
51
52
53
54
55
56
}
catch ( IOException e ) {
System . out . p r i n t l n ( I n p u t E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}
57
58
59
60
61
62
Client servlet
1
2
3
4
5
6
7
9
10
11
12
13
15
16
18
19
20
21
23
24
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import
import
import
import
import
import
import
java . i o . BufferedReader ;
j a v a . i o . IOException ;
j a v a . i o . InputStream ;
j a v a . i o . InputStreamReader ;
j a v a . i o . OutputStream ;
java . io . PrintWriter ;
java . net . Socket ;
import
import
import
import
import
javax .
javax .
javax .
javax .
javax .
servlet
servlet
servlet
servlet
servlet
. ServletException ;
. a n n o t a t i o n . WebServlet ;
. http . HttpServlet ;
. http . HttpServletRequest ;
. http . HttpServletResponse ;
@WebServlet ( u r l P a t t e r n s = { / c l i e n t } )
public c l a s s C l i e n t S e r v l e t extends H t t p S e r v l e t {
protected 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 m=r e q . g e t P a r a m e t e r ( m ) ;
S t r i n g n=r e q . g e t P a r a m e t e r ( n ) ;
r e s . setContentType ( t e x t / html ; c h a r s e t=UTF8 ) ;
P r i n t W r i t e r out = r e s . g e t W r i t e r ( ) ;
f i n a l S t r i n g CRLF = \ r \n ;
f i n a l S t r i n g h o s t = r e q . getServerName ( ) ; // l o c a l h o s t ;
f i n a l i n t p o r t = r e q . g e t S e r v e r P o r t ( ) ; // 8 0 8 0 ;
f i n a l S t r i n g c o n t e x t R o o t = / upgrade ;
f i n a l S t r i n g data = m+ +n ;
InputStream i n p u t = n u l l ;
OutputStream o ut pu t = n u l l ;
BufferedReader r e a d e r = null ;
Socket s = null ;
try {
out . p r i n t l n ( <html> ) ;
out . p r i n t l n ( <head> ) ;
out . p r i n t l n ( < t i t l e >S e r v l e t C l i e n t T e s t </ t i t l e > ) ;
out . p r i n t l n ( </head> ) ;
183
184
40
41
43
44
45
46
47
48
49
50
51
52
53
54
56
57
58
59
60
62
63
64
CAPITOLUL 8. SERVLET
out . p r i n t l n ( <body> ) ;
out . p r i n t l n ( <h1>Http Upgrade P r o c e s s </h1> ) ;
// S e t t i n g t h e HTTP u p g r a d e r e q h e a d e r
S t r i n g r e q S t r = POST + c o n t e x t R o o t + / upgrade HTTP/ 1 . 1 + CRLF ;
r e q S t r += UserAgent : Java / 1 . 7 + CRLF ;
r e q S t r += Host : + h o s t + : + p o r t + CRLF ;
r e q S t r += Accept :
t e x t / html , image / g i f , image / j p e g , ; q = . 2 , / ; q =.2 + CRLF ;
r e q S t r += Upgrade : upgrade + CRLF ;
r e q S t r += C o n n e c t i o n : Upgrade + CRLF ;
r e q S t r += Contentt y p e : a p p l i c a t i o n /xwwwformu r l e n c o d e d + CRLF ;
r e q S t r += T r a n s f e r Encoding : chunked + CRLF ;
r e q S t r += CRLF ;
r e q S t r += data + CRLF ;
s = new S o c k e t ( hos t , p o r t ) ;
input = s . getInputStream ( ) ;
ou tp ut = s . getOutputStream ( ) ;
ou tp ut . w r i t e ( r e q S t r . g e t B y t e s ( ) ) ;
ou tp ut . f l u s h ( ) ;
out . p r i n t l n ( <h2>S e n d i n g upgrade r e q t o s e r v e r . . . . . . < / h2> ) ;
out . p r i n t l n ( <h3>Request h e a d e r with data : </h3> ) ;
out . p r i n t l n ( ) ;
69
S t r i n g r e q S t r D i s p l a y = r e q S t r . r e p l a c e A l l ( \ r \n , </br> ) ;
out . p r i n t l n ( r e q S t r D i s p l a y ) ;
out . p r i n t l n ( </br></br> ) ;
out . f l u s h ( ) ;
71
73
66
67
68
74
75
77
78
79
80
82
83
85
86
88
89
90
91
92
93
94
95
96
97
98
I DE PROGRAMARE CU SERVLET
8.5. FACILITAT
}
catch ( IOException e ) {
System . out . p r i n t l n ( C l i e n t S e r v l e t E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}
finally {
i f ( r e a d e r != n u l l ) {
reader . close ( ) ;
}
i f ( ou tp ut != n u l l ) {
o ut pu t . c l o s e ( ) ;
}
i f ( i n p u t != n u l l ) {
input . c l o s e ( ) ;
}
i f ( s != n u l l ) {
s . close ();
}
}
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
119
120
121
122
123
124
125
126
127
@Override
protected 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 ) ;
}
129
130
131
132
133
134
185
8.5
8.5.1
Facilit
ati de programare cu servlet
Program client al unui servlet
Apelarea unui servlet dintr-un program Java adica lansarea unei cereri si
receptionarea raspunsului furnizat de servlet se poate obtine
sincron cu produsul httpcomponents-client,
asincron cu unul din produsele
httpcomponents-client,
httpcomponents-asyncclient.
186
CAPITOLUL 8. SERVLET
I DE PROGRAMARE CU SERVLET
8.5. FACILITAT
187
}
catch(. . .){. . .}
POST
List<NameValuePair> qparams = new ArrayList<NameValuePair>();
qparams.add(new BasicNameValuePair("param_1", value_1));
qparams.add(new BasicNameValuePair("param_2", value_2));
. . .
try{
UrlEncodedFormEntity params=new UrlEncodedFormEntity(qparams,
"UTF-8");
HttpPost httppost=new HttpPost(uri);
httppost.setEntity(params);
. . .
}
catch(. . .){. . .}
cu uri=http://host:port/catalog/numeApel.
Clasele HttpGet, HttpPost apartin pachetului org.apache.http.client.
methods.
3. Lansarea cererii.
HttpResponse response=httpclient.execute(httpget);
respectiv
HttpResponse response=httpclient.execute(httppost);
4. Preluarea raspunsului.
HttpEntity entity=response.getEntity();
if(entity!=null){
InputStream is=entity.getContent();
int l;
byte[] tmp=new byte[2048];
while((l=is.read(tmp))!=-1){}
. . .
}
188
CAPITOLUL 8. SERVLET
import j a v a . u t i l . S c a n n e r ;
import o r g . apache . h t t p . H t t p E n t i t y ;
import
import
import
import
import
import
import
import
19
20
21
22
23
24
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
o r g . apache . h t t p . impl . c l i e n t . C l o s e a b l e H t t p C l i e n t ;
o r g . apache . h t t p . c l i e n t . methods . HttpPost ;
o r g . apache . h t t p . c l i e n t . methods . C l o s e a b l e H t t p R e s p o n s e ;
o r g . apache . h t t p . impl . c l i e n t . H t t p C l i e n t s ;
java . u t i l . List ;
java . u t i l . ArrayList ;
o r g . apache . h t t p . NameValuePair ;
o r g . apache . h t t p . message . BasicNameValuePair ;
Varianta fluenta
1
2
3
import j a v a . u t i l . S c a n n e r ;
import o r g . apache . h t t p . c l i e n t . f l u e n t . Form ;
import o r g . apache . h t t p . c l i e n t . f l u e n t . Request ;
I DE PROGRAMARE CU SERVLET
8.5. FACILITAT
5
6
public c l a s s ClientCmmdcServlet1 {
s t a t i c S t r i n g u r i= 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 ;
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 ( m= ) ;
S t r i n g m=s c a n n e r . n e x t L i n e ( ) . t r i m ( ) ;
System . out . p r i n t l n ( n= ) ;
S t r i n g n=s c a n n e r . n e x t L i n e ( ) . t r i m ( ) ;
8
9
10
11
12
13
15
16
17
18
19
20
21
22
23
24
25
26
27
28
30
31
32
33
34
35
36
37
38
39
40
41
189
import
import
import
import
import
import
j a v a . n e t .URL;
j a v a . n e t . HttpURLConnection ;
java . u t i l . Scanner ;
j a v a . i o . InputStreamReader ;
java . i o . BufferedReader ;
java . io . PrintWriter ;
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 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= ) ;
long m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
long n=s c a n n e r . nextLong ( ) ;
S t r i n g msg=m=+m+&n=+n+&t i p=t e x t / p l a i n ;
System . out . p r i n t l n ( HttpURLConnection cu metoda GET ) ;
try {
S t r i n g urlGET= 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? +msg ;
190
CAPITOLUL 8. SERVLET
19
20
21
22
23
24
25
26
27
28
29
30
31
}
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 ( HttpURLConnection cu metoda POST ) ;
try {
S t r i n g urlPOST= 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 ;
URL u r l=new URL( urlPOST ) ;
HttpURLConnection conn=(HttpURLConnection ) u r l . op enConne ction ( ) ;
conn . setRequestMethod ( POST ) ;
conn . s e t U s e C a c h e s ( f a l s e ) ;
conn . s e t D o I n p u t ( true ) ;
conn . setDoOutput ( true ) ;
conn . s e t R e q u e s t P r o p e r t y ( ContentType , a p p l i c a t i o n /xwwwformu r l e n c o d e d ) ;
P r i n t W r i t e r pw=new P r i n t W r i t e r ( conn . getOutputStream ( ) ) ;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
pw . p r i n t l n ( msg ) ;
pw . f l u s h ( ) ;
System . out . p r i n t l n ( conn . getResponseCode ( ) ) ;
System . out . p r i n t l n ( conn . g e t R e s p o n s e M e s s a g e ( ) ) ;
B u f f e r e d R e a d e r br=
new B u f f e r e d R e a d e r (new InputStreamReader ( conn . g e t I n p u t S t r e a m ( ) ) ) ;
String s ;
while ( ( s=br . r e a d L i n e ( ) ) ! = n u l l ) {
System . out . p r i n t l n ( s ) ;
}
br . c l o s e ( ) ;
pw . c l o s e ( ) ;
conn . d i s c o n n e c t ( ) ;
48
49
50
51
52
53
54
55
56
57
58
59
60
}
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 ( ) ) ;
}
61
62
63
64
65
66
Cazul asincron
1. httpcomponent-client
1
2
3
4
import
import
import
import
java . u t i l . Scanner ;
o r g . apache . h t t p . c l i e n t . f l u e n t . Form ;
o r g . apache . h t t p . c l i e n t . f l u e n t . Request ;
o r g . apache . h t t p . c l i e n t . f l u e n t . Async ;
I DE PROGRAMARE CU SERVLET
8.5. FACILITAT
5
6
7
8
9
11
12
import
import
import
import
import
public c l a s s AsyncClientCmmdcServlet {
s t a t i c S t r i n g u r i= 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 ;
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 ( m= ) ;
S t r i n g m=s c a n n e r . n e x t L i n e ( ) . t r i m ( ) ;
System . out . p r i n t l n ( n= ) ;
S t r i n g n=s c a n n e r . n e x t L i n e ( ) . t r i m ( ) ;
14
15
16
17
18
19
E x e c u t o r S e r v i c e t h r e a d p o o l = E x e c u t o r s . newFixedThreadPool ( 2 ) ;
Async a s y n c = Async . n e w I n s t a n c e ( ) . u s e ( t h r e a d p o o l ) ;
21
22
24
25
26
27
28
29
30
31
// V a r i a n t a 1
/
Future<Content> f u t u r e=async . e x e c u t e ( r e q u e s t ) ;
w h i l e ( ! f u t u r e . isDone ( ) ) { ; }
System . o u t . p r i n t l n (Cmmdc = + f u t u r e . g e t ( ) . a s S t r i n g ( ) ) ;
/
33
34
35
36
37
38
// V a r i a n t a 2
Future<Content> f u t u r e=a s y n c . e x e c u t e ( r e q u e s t ,
new F u t u r e C a l l b a c k <Content >(){
@Override
public void c o m p l e t e d ( f i n a l Content c o n t e n t ) {
System . out . p r i n t l n ( Cmmdc : +c o n t e n t . a s S t r i n g ( ) ) ;
}
@Override
public void f a i l e d ( f i n a l 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 ( ) + : + r e q u e s t ) ;
}
@Override
public void c a n c e l l e d ( ) {}
});
while ( ! f u t u r e . i s D o n e ( ) ) { ; }
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
t h r e a d p o o l . shutdown ( ) ;
}
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 ( ) ) ;
}
56
57
58
59
60
61
62
o r g . apache . h t t p . c l i e n t . f l u e n t . Content ;
java . u t i l . concurrent . ExecutorService ;
java . u t i l . concurrent . Executors ;
j a v a . u t i l . c o n c u r r e n t . Future ;
o r g . apache . h t t p . c o n c u r r e n t . F u t u r e C a l l b a c k ; // HttpCore
191
192
CAPITOLUL 8. SERVLET
2. httpcomponent-asyncclient
Variabila classpath contine referentele catre fiserele jar aflate n catalogul lib din httpcomponent-asyncclient.
Programarea consta din
(a) Crearea unei instante a clasei
org.apache.http.impl.nio.client.CloseableHttpAsyncClient
CloseableHttpAsyncClient httpclient =
HttpAsyncClients.createDefault();
httpclient.start();
(b) Lansarea unei cereri apeland o metoda execute:
<T> Future<T> execute(
org.apache.http.nio.protocol.HttpAsyncRequestProducer
requestProducer,
org.apache.http.nio.protocol.HttpAsyncResponseConsumer<T>
responseConsumer,
org.apache.http.concurrent.FutureCallback<T> callback )
O instanta de tip HttpAsyncRequestProducer se obtine prin
HttpAsyncMethods.createGet(uri)
Drept instanta a clasei HttpAsyncResponseConsumer poate fi o
clasa ce extinde clasa org.apache.http.nio.client.methods.AsyncChar
Consumer.
Exemplul 8.5.2
1
import j a v a . u t i l . S c a n n e r ;
import
import
import
import
import
import
import
4
5
6
7
8
9
11
12
13
15
16
o r g . apache . h t t p . HttpResponse ;
o r g . apache . h t t p . impl . n i o . c l i e n t . H t t p A s y n c C l i e n t s ;
o r g . apache . h t t p . n i o . IOControl ;
o r g . apache . h t t p . impl . n i o . c l i e n t . C l o s e a b l e H t t p A s y n c C l i e n t ;
o r g . apache . h t t p . n i o . c l i e n t . methods . AsyncCharConsumer ;
o r g . apache . h t t p . n i o . c l i e n t . methods . HttpAsyncMethods ;
o r g . apache . h t t p . p r o t o c o l . HttpContext ;
import j a v a . n i o . C h a r B u f f e r ;
import j a v a . i o . IOException ;
import j a v a . u t i l . c o n c u r r e n t . Future ;
public c l a s s AsyncClientCmmdcServlet {
s t a t i c S t r i n g u r i= 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 ;
I DE PROGRAMARE CU SERVLET
8.5. FACILITAT
193
18
19
20
21
22
23
24
25
26
CloseableHttpAsyncClient h t t p c l i e n t =
HttpAsyncClients . c r e a t e D e f a u l t ( ) ;
httpclient . start ();
try {
Future<Boolean> f u t u r e = h t t p c l i e n t . e x e c u t e (
HttpAsyncMethods . c r e a t e G e t ( u r i+r e q u e s t D a t a ) ,
new MyResponseConsumer ( ) , n u l l ) ;
Boolean r e s u l t = f u t u r e . g e t ( ) ;
i f ( r e s u l t != n u l l && r e s u l t . b o o l e a n V a l u e ( ) ) {
System . out . p r i n t l n ( Request s u c c e s s f u l l y e x e c u t e d ) ;
}
else {
System . out . p r i n t l n ( Request f a i l e d ) ;
}
System . out . p r i n t l n ( S h u t t i n g down ) ;
}
finally {
httpclient . close ();
}
System . out . p r i n t l n ( Done ) ;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
50
51
52
@Override
protected void onCharReceived ( f i n a l C h a r B u f f e r buf ,
f i n a l IOControl i o c t r l ) throws IOException {
System . out . p r i n t l n ( Cmmdc : ) ;
while ( b u f . hasRemaining ( ) ) {
System . out . p r i n t ( b u f . g e t ( ) ) ;
}
}
54
55
56
57
58
59
60
61
@Override
protected void r e l e a s e R e s o u r c e s ( ) {}
63
64
@Override
protected Boolean b u i l d R e s u l t ( f i n a l HttpContext c o n t e x t ) {
return Boolean .TRUE;
}
66
67
68
69
70
71
194
8.5.2
CAPITOLUL 8. SERVLET
Servlete nl
antuite
package cmmdc ;
import j a v a . i o . IOException ;
import j a v a . i o . P r i n t W r i t e r ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e q u e s t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e s p o n s e ;
import j a v a x . s e r v l e t . R e q u e s t D i s p a t c h e r ;
import j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
@WebServlet ( u r l P a t t e r n s = / v e r i f )
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 {
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 {
P r i n t W r i t e r out=r e s . g e t W r i t e r ( ) ;
r e s . setContentType ( t e x t / html ) ;
S t r i n g sm=r e q . g e t P a r a m e t e r ( m ) , sn=r e q . g e t P a r a m e t e r ( n ) ;
S t r i n g message= ;
long m, n ;
i f ( ( sm==n u l l ) | | ( sm . e q u a l s ( ) ) ) {
message=Numar a b s e n t ;
}
else {
try {
m=Long . par se Lo ng ( 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 ) ;
}
I DE PROGRAMARE CU SERVLET
8.5. FACILITAT
catch ( NumberFormatException e ) {
message=Nu e s t e numar ;
}
38
39
40
}
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 ( ) ;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
58
59
60
61
62
ComputeServlet.java
1
2
3
4
5
6
7
8
10
11
package cmmdc ;
import j a v a . i o . IOException ;
import j a v a . i o . P r i n t W r i t e r ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e q u e s t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e s p o n s e ;
import j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
@WebServlet ( u r l P a t t e r n s = / c a l c u l )
public c l a s s ComputeServlet extends H t t p S e r v l e t {
13
15
16
17
18
19
20
21
23
24
25
26
27
195
196
8.5.3
CAPITOLUL 8. SERVLET
Sesiune de lucru
import
import
import
import
import
import
import
import
j a v a . i o . IOException ;
java . io . PrintWriter ;
javax . s e r v l e t . ServletException ;
javax . s e r v l e t . http . HttpServlet ;
javax . s e r v l e t . http . HttpServletRequest ;
javax . s e r v l e t . http . HttpServletResponse ;
javax . s e r v l e t . http . HttpSession ;
j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
@WebServlet ( u r l P a t t e r n s = / s e s i u n e )
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 {
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 )
I DE PROGRAMARE CU SERVLET
8.5. FACILITAT
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 ( ) ;
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 ( ) ;
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
37
38
39
40
41
197
8.5.4
Cookie
198
CAPITOLUL 8. SERVLET
I DE PROGRAMARE CU SERVLET
8.5. FACILITAT
1
2
3
4
5
6
7
8
9
package c o o k i e ;
import j a v a . i o . IOException ;
import j a v a . i o . P r i n t W r i t e r ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e q u e s t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e s p o n s e ;
import j a v a x . s e r v l e t . h t t p . Cookie ;
import j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
11
@WebServlet ( u r l P a t t e r n s = / c o o k i e )
13
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 {
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
45
46
47
48
49
50
51
52
54
55
56
57
58
199
200
59
CAPITOLUL 8. SERVLET
8.5.5
Intr-o pagina html de apelare a unui servlet pot fi mai multe butoane
<input type="submit" value="text" name="numeBtn"/>
Ultimul atribut permite determinarea butonului accesat.
Sablonul de programare este
String button="";
for (Enumeration<String> e = req.getParameterNames(); e.hasMoreElements();){
button=e.nextElement();
switch(button){
case "numeBtn1":
. . .
break;
case "numeBtn2":
. . .
break;
. . .
}
}
I DE PROGRAMARE CU SERVLET
8.5. FACILITAT
1
2
3
4
5
6
7
8
9
package t i m e r ;
import j a v a . i o . IOException ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e q u e s t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e s p o n s e ;
import j a v a . i o . P r i n t W r i t e r ;
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 . Enumeration ;
11
@WebServlet ( u r l P a t t e r n s = / t i m e r )
13
public c l a s s T i m e r S e r v l e t extends H t t p S e r v l e t {
private s t a t i c MyTimer myTimer ;
14
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
49
50
51
52
53
package t i m e r ;
import j a v a . u t i l . Timer ;
import j a v a . u t i l . TimerTask ;
201
202
4
5
7
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
56
57
58
60
61
62
CAPITOLUL 8. SERVLET
import j a v a . i o . P r i n t W r i t e r ;
import j a v a . u t i l . C a l e n d a r ;
public c l a s s MyTimer{
private Timer t i m e r ;
private P r i n t W r i t e r out ;
private S t r i n g B u f f e r sb ;
public MyTimer ( i n t s e c o n d s , P r i n t W r i t e r out , S t r i n g B u f f e r sb ) {
t h i s . out=out ;
t h i s . sb=sb ;
t i m e r=new Timer ( ) ;
long ms=1000;
t i m e r . s c h e d u l e A t F i x e d R a t e (new MyTask ( ) , 0 ms , s e c o n d s ms ) ;
C a l e n d a r c a l e n d a r=C a l e n d a r . g e t I n s t a n c e ( ) ;
S t r i n g time = c a l e n d a r . g e t ( C a l e n d a r .HOUR OF DAY)+ : +
c a l e n d a r . g e t ( C a l e n d a r .MINUTE)+
: +c a l e n d a r . g e t ( C a l e n d a r .SECOND) ;
System . out . p r i n t l n ( Timer i s s t a r t e d : +time ) ;
sb . append ( <br/> ) ;
sb . append ( Timer i s s t a r t e d : +time ) ;
out . p r i n t l n ( <html> ) ;
out . p r i n t l n ( <body> ) ;
out . p r i n t l n ( <h1>T i m e r 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 ( sb . t o S t r i n g ( ) ) ;
out . p r i n t l n ( <p/> ) ;
out . p r i n t l n ( <a h r e f =\ i n d e x . html\> S t a r t Page</a> ) ;
out . p r i n t l n ( </body> ) ;
out . p r i n t l n ( </html> ) ;
}
public void t i m e r S t o p p e d ( ) {
timer . cancel ( ) ;
C a l e n d a r c a l e n d a r=C a l e n d a r . g e t I n s t a n c e ( ) ;
S t r i n g time = c a l e n d a r . g e t ( C a l e n d a r .HOUR OF DAY)+ : +
c a l e n d a r . g e t ( C a l e n d a r .MINUTE)+
: +c a l e n d a r . g e t ( C a l e n d a r .SECOND) ;
System . out . p r i n t l n ( Timer i s s t o p p e d : +time ) ;
sb . append ( <br/> ) ;
sb . append ( Timer i s s t o p p e d : +time ) ;
out . p r i n t l n ( <html> ) ;
out . p r i n t l n ( <body> ) ;
out . p r i n t l n ( <h1>T i m e r 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 ( sb . t o S t r i n g ( ) ) ;
out . p r i n t l n ( <p/> ) ;
out . p r i n t l n ( <a h r e f =\ i n d e x . html\> S t a r t Page</a> ) ;
out . p r i n t l n ( </body> ) ;
out . p r i n t l n ( </html> ) ;
}
public S t r i n g getSb ( ) {
return sb . t o S t r i n g ( ) ;
}
c l a s s MyTask extends TimerTask {
@Override
public void run ( ) {
I DE PROGRAMARE CU SERVLET
8.5. FACILITAT
C a l e n d a r c a l e n d a r=C a l e n d a r . g e t I n s t a n c e ( ) ;
S t r i n g time = c a l e n d a r . g e t ( C a l e n d a r .HOUR OF DAY)+ : +
c a l e n d a r . g e t ( C a l e n d a r .MINUTE)+
: +c a l e n d a r . g e t ( C a l e n d a r .SECOND) ;
sb . append ( <br/> ) ;
sb . append ( C u r r e n t time : +time ) ;
63
64
65
66
67
68
69
70
71
203
8.5.6
Autentificare
rolename="BASIC_ROLE"/>
rolename="DIGEST_ROLE"/>
username="basic" password="basic" roles="BASIC_ROLE"/>
username="digest" password="digest" roles="DIGEST_ROLE"/>
204
CAPITOLUL 8. SERVLET
<security-role>
<role-name>BASIC_ROLE</role-name>
</security-role>
<security-constraint>
<web-resource-collection>
<web-resource-name>Restricted Access - Members Only</web-resource-name>
<url-pattern>/cmmdc</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>BASIC_ROLE</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<!-<realm-name>My realm name</realm-name>
-->
</login-config>
org.apache.http.auth.AuthScope;
org.apache.http.auth.UsernamePasswordCredentials;
org.apache.http.impl.auth.BasicScheme;
org.apache.http.protocol.BasicHttpContext;
. . .
DefaultHttpClient httpclient = new DefaultHttpClient();
// Activitati pentru autentificare
httpclient.getCredentialsProvider().setCredentials(
new AuthScope(host,Integer.parseInt(port)),
// new AuthScope(host,Integer.parseInt(port),realm),
new UsernamePasswordCredentials(username,password)
);
BasicHttpContext context=new BasicHttpContext();
BasicScheme schema = new BasicScheme();
// DigestScheme schema = new DigestScheme();
context.setAttribute("preemptive-auth", schema);
. . .
HttpResponse response=httpclient.execute(httppost,context);
. . .
I DE PROGRAMARE CU SERVLET
8.5. FACILITAT
8.5.7
205
import
import
import
import
import
import
import
import
import
import
import
import
import
j a v a . i o . IOException ;
javax . s e r v l e t . ServletException ;
javax . s e r v l e t . ServletOutputStream ;
javax . s e r v l e t . ServletConfig ;
javax . s e r v l e t . http . HttpServlet ;
javax . s e r v l e t . http . HttpServletRequest ;
javax . s e r v l e t . http . HttpServletResponse ;
j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
j a v a . s q l . Statement ;
java . s q l . Connection ;
j a v a . s q l . DriverManager ;
j a v a . s q l . SQLException ;
java . s q l . ResultSet ;
@WebServlet ( u r l P a t t e r n s = / a d r e s e )
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 ;
C o n n e c t i o n con=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 ;
// SGBD Mysql
// S t r i n g j d b c D r i v e r =com . mysql . j d b c . D r i v e r ;
// S t r i n g URLBazaDate= j d b c : mysql : / / l o c a l h o s t : 3 3 0 6 / AgendaEMail ? u s e r=r o o t ;
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 ( ) ) ;
}
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
45
public void d e s t r o y ( ) {
try {
i f ( con != n u l l ) con . c l o s e ( ) ;
46
47
206
CAPITOLUL 8. SERVLET
}
catch ( SQLException e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}
48
49
50
51
52
54
55
56
57
58
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 ( ) ) ;
}
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
89
90
91
92
93
<html>
<body>
<h1> Cautare i n baza de d a t e AgendaEMail</h1>
<form method= g e t
action= / 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>
I DE PROGRAMARE CU SERVLET
8.5. FACILITAT
11
12
13
14
15
16
17
207
<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>
8.5.8
1
2
3
4
5
6
7
8
10
package g r a p h g i f ;
import j a v a . i o . IOException ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e q u e s t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e s p o n s e ;
import j a v a x . s e r v l e t . S e r v l e t O u t p u t S t r e a m ;
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 . n i o . f i l e . Path ;
208
CAPITOLUL 8. SERVLET
12
import j a v a . n i o . f i l e . Paths ;
import j a v a . n i o . f i l e . F i l e s ;
14
@WebServlet ( u r l P a t t e r n s = / g r a p h g i f )
16
11
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
1
2
3
4
5
6
7
8
package g r a p h j p g ;
import j a v a . i o . IOException ;
import j a v a . i o . P r i n t W r i t e r ;
import j a v a . i o . F i l e ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e q u e s t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e s p o n s e ;
15
import
import
import
import
import
import
17
@WebServlet ( u r l P a t t e r n s = / g r a p h j p g )
10
11
12
13
14
j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
j a v a x . i m a g e i o . ImageIO ;
j a v a . awt . Frame ;
j a v a . awt . Font ;
j a v a . awt . G r a p h i c s ;
j a v a . awt . image . B u f f e r e d I m a g e ;
I DE PROGRAMARE CU SERVLET
8.5. FACILITAT
19
21
22
23
24
25
26
27
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
46
// 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
48
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 , ext , f ) ;
49
// 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 ( ) ;
51
52
53
54
55
56
57
58
}
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 ( ) ;
}
59
60
61
62
63
64
65
66
209
8.5.9
Servlet cu RMI
210
CAPITOLUL 8. SERVLET
import java.rmi.Naming;
. . .
InterfataDistanta obj=(InterfataDistanta)
Naming.lookup("//"+host+":"+port+"/NumeServiciuRMI");
Exemplul 8.5.8 Client servlet pentru aplicatia RMI de calcul al celui mai
mare divizor comun a doua numere naturale.
1
2
3
4
5
6
7
8
9
11
12
14
15
16
17
import
import
import
import
import
import
import
import
import
j a v a . i o . IOException ;
java . io . PrintWriter ;
javax . s e r v l e t . ServletException ;
javax . s e r v l e t . http . HttpServlet ;
javax . s e r v l e t . http . HttpServletRequest ;
javax . s e r v l e t . http . HttpServletResponse ;
j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
j a v a . rmi . Naming ;
cmmdc . ICmmdc ;
@WebServlet ( u r l P a t t e r n s = / s e r v l e t r m i )
public c l a s s ServletRMI 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 sm=r e q . g e t P a r a m e t e r ( m ) , sn=r e q . g e t P a r a m e t e r ( n ) ;
long m=(new Long ( sm ) ) . l o n g V a l u e ( ) , n=(new Long ( sn ) ) . l o n g V a l u e ( ) ;
long x =0;
19
20
21
S t r i n g h o s t=r e q . g e t P a r a m e t e r ( h o s t ) . t r i m ( ) ;
S t r i n g s P o r t=r e q . g e t P a r a m e t e r ( p o r t ) ;
i n t p o r t=I n t e g e r . p a r s e I n t ( s P o r t ) ;
23
24
25
try {
ICmmdc o b j =(ICmmdc) Naming . l o o k u p ( // +h o s t+ : +p o r t+ /CmmdcServer ) ;
x=o b j . cmmdc(m, n ) ;
}
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 ( ) ) ;
}
S t r i n g t i t l e = CmmdcServlet ;
r e s . setContentType ( t e x t / html ) ;
out . p r i n t l n ( <HTML><HEAD><TITLE> ) ;
out . p r i n t l n ( t i t l e ) ;
out . p r i n t l n ( </TITLE></HEAD><BODY> ) ;
out . p r i n t l n ( <H1>+ t i t l e +</H1> ) ;
out . p r i n t l n ( <P>Cmmdc : +x ) ;
out . p r i n t l n ( </BODY></HTML> ) ;
out . c l o s e ( ) ;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
45
46
47
48
I DE PROGRAMARE CU SERVLET
8.5. FACILITAT
49
211
8.5.10
Servlet cu JMS
12
package jms ;
import j a v a x . jms . Topic ;
import j a v a x . jms . JMSContext ;
import j a v a x . jms . JMSProducer ;
import j a v a x . jms . JMSConsumer ;
import j a v a . i o . IOException ;
import j a v a x . s e r v l e t . S e r v l e t O u t p u t S t r e a m ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e q u e s t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e s p o n s e ;
import j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
14
@WebServlet ( u r l P a t t e r n s = / s e n d e r )
16
public c l a s s J M S S e n d e r S e r v l e t extends H t t p S e r v l e t {
1
2
3
4
5
6
7
8
9
10
11
18
19
20
21
22
23
24
25
26
27
28
29
30
212
CAPITOLUL 8. SERVLET
31
32
33
34
35
37
38
39
JMSProducer p r o d u c e r=c t x . c r e a t e P r o d u c e r ( ) ;
p r o d u c e r . send ( t , msg ) ;
41
42
ctx .
out .
out .
out .
out .
out .
44
45
46
47
48
49
close ();
p r i n t l n ( <html><body b g c o l o r=\#c c b b c c\>< c e n t e r > ) ;
p r i n t l n ( <h1> JSP Cmmdc </h1> ) ;
p r i n t l n ( <p> ) ;
p r i n t l n ( D a t e l e au f o s t e x p e d i a t e s e r v e r u l u i ) ;
p r i n t l n ( </ c e n t e r ></body></html> ) ;
}
catch ( E x c e p t i o n e ) {
out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}
out . c l o s 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 ) ;
50
51
52
53
54
55
56
58
59
60
61
62
12
package jms ;
import j a v a x . jms . Topic ;
import j a v a x . jms . JMSContext ;
import j a v a x . jms . JMSConsumer ;
import j a v a x . jms . TextMessage ;
import j a v a . i o . IOException ;
import j a v a x . s e r v l e t . S e r v l e t O u t p u t S t r e a m ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e q u e s t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e s p o n s e ;
import j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
14
@WebServlet ( u r l P a t t e r n s = / r e c e i v e r )
16
public c l a s s J M S R e c e i v e r S e r v l e t extends H t t p S e r v l e t {
1
2
3
4
5
6
7
8
9
10
11
18
19
20
21
22
23
24
I DE PROGRAMARE CU SERVLET
8.5. FACILITAT
// S t r i n g c l i e n t I D =JMSCmmdc ;
// S t r i n g c l i e n t N a m e=JMSCmmdc ;
try {
// V a r i a n t a OracleSun Message Topic
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 ) ;
Topic t=new com . sun . m e s s a g i n g . Topic ( t o p i c ) ;
JMSContext c t x=c f . c r e a t e C o n t e x t ( ) ;
ctx . setClientID ( c l i e n t I D ) ;
JMSConsumer consumer = c t x . c r e a t e D u r a b l e C o n s u m e r ( t , c l i e n t N a m e ) ;
TextMessage txtMsg=(TextMessage ) consumer . r e c e i v e ( ) ;
S t r i n g cmmdc=txtMsg . g e t T e x t ( ) ;
ctx . c l o s e ( ) ;
out . p r i n t l n ( <html><body b g c o l o r=\#c c b b c c\>< c e n t e r > ) ;
out . p r i n t l n ( <h1> JSP Cmmdc </h1> ) ;
out . p r i n t l n ( <p> ) ;
out . p r i n t l n ( R e z u l t a t u l o b t i n u t : +cmmdc ) ;
out . p r i n t l n ( </ c e n t e r ></body></html> ) ;
}
catch ( E x c e p t i o n e ) {
out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}
out . c l o s e ( ) ;
System . out . p r i n t l n ( S u b s c r i b e r f i n i s h e d ) ;
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
213
In catalogul lib al servlet-ului trebuie incluse fisierele jar ale serviciului JMS
folosit.
8.5.11
Servlet cu jurnalizare
11
package l o g t e s t ;
import j a v a . i o . IOException ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
import j a v a x . s e r v l e t . S e r v l e t C o n t e x t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e q u e s t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e s p o n s e ;
import j a v a x . s e r v l e t . S e r v l e t O u t p u t S t r e a m ;
import j a v a . u t i l . l o g g i n g . Logger ;
import j a v a . u t i l . l o g g i n g . F i l e H a n d l e r ;
import j a v a . u t i l . l o g g i n g . S i m p l e F o r m a t t e r ;
13
import 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
214
CAPITOLUL 8. SERVLET
15
@WebServlet ( u r l P a t t e r n s = / l o g g i n g )
17
public c l a s s L o g g e r S e r v l e t extends H t t p S e r v l e t {
private s t a t i c Logger l o g g e r=Logger . g e t L o g g e r ( l o g t e s t . L o g g e r S e r v l e t ) ;
18
public void i n i t ( ) {
try {
F i l e H a n d l e r l o g g i n g F i l e = new F i l e H a n d l e r ( webapps / l o g g e r / r e s u l t s . l o g ) ;
l o g g i n g F i l e . s e t F o r m a t t e r (new S i m p l e F o r m a t t e r ( ) ) ;
l o g g e r . addHandler ( l o g g i n g F i l e ) ;
}
catch ( IOException e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}
}
20
21
22
23
24
25
26
27
28
29
31
32
33
l o g g e r . i n f o ( INFO : H e l l o ) ;
l o g g e r . warning ( WARN : H e l l o ) ;
l o g g e r . s e v e r e ( ERROR : H e l l o ) ;
35
36
37
r e s . setContentType ( t e x t / html ) ;
j a v a . i o . P r i n t W r i t e r out = r e s . g e t W r i t e r ( ) ;
out . p r i n t l n ( <html><head><t i t l e >S e r v l e t l o g g i n g </ t i t l e ></head><body> ) ;
out . p r i n t l n ( <h2>H e l l o from L o g g e r S e r v l e t </h2> ) ;
out . p r i n t l n ( <br/> ) ;
out . p r i n t l n ( <a h r e f =\ h t t p : / / +
r e q . getServerName ()+ : +
r e q . g e t L o c a l P o r t ()+ f i l e S e p+
l o g g e r +f i l e S e p+ r e s u l t s . l o g \> V i z u a l i z a t i f i s i e r u l l o g </a> ) ;
out . p r i n t l n ( </body></html> ) ;
out . c l o s e ( ) ;
39
40
41
42
43
44
45
46
47
48
49
50
52
53
54
55
56
8.6
FileUpload
215
8.6. FILEUPLOAD
216
CAPITOLUL 8. SERVLET
8.6. FILEUPLOAD
217
package u pl oa d ;
import j a v a . i o . IOException ;
import j a v a . i o . InputStream ;
import j a v a . i o . InputStreamReader ;
import j a v a . i o . B u f f e r e d R e a d e r ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e q u e s t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e s p o n s e ;
import j a v a x . s e r v l e t . S e r v l e t O u t p u t S t r e a m ;
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 . L i s t ;
import j a v a . u t i l . I t e r a t o r ;
import j a v a . u t i l . V e c t o r ;
import o r g . apache . commons . f i l e u p l o a d . d i s k . D i s k F i l e I t e m F a c t o r y ;
import o r g . apache . commons . f i l e u p l o a d . s e r v l e t . S e r v l e t F i l e U p l o a d ;
import o r g . apache . commons . f i l e u p l o a d . F i l e I t e m F a c t o r y ;
import o r g . apache . commons . f i l e u p l o a d . F i l e I t e m ;
218
20
21
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
52
53
54
55
56
57
58
59
60
61
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
CAPITOLUL 8. SERVLET
@WebServlet ( u r l P a t t e r n s = / u pl o ad )
public c l a s s F i l e U p l o a d S e r v l e t extends H t t p S e r v l e t {
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 {
r e s . setContentType ( t e x t / p l a i n ) ;
S e r v l e t O u t p u t S t r e a m out = r e s . getOutputStream ( ) ;
try {
F i l e I t e m F a c t o r y f a c t o r y = new D i s k F i l e I t e m F a c t o r y ( ) ;
ServletFileUpload
up lo ad = new S e r v l e t F i l e U p l o a d ( f a c t o r y ) ;
L i s t i t e m s = up l oad . p a r s e R e q u e s t ( r e q ) ;
u pl oa d . s e t S i z e M a x ( 1 0 0 0 0 0 0 ) ;
I t e r a t o r i t e r=i t e m s . i t e r a t o r ( ) ;
while ( i t e r . hasNext ( ) ) {
F i l e I t e m item = ( F i l e I t e m ) i t e r . n e x t ( ) ;
i f ( ! item . i s F o r m F i e l d ( ) ) {
S t r i n g f i l e N a m e = item . getName ( ) ;
out . p r i n t l n ( f i l e N a m e ) ;
long s i z e I n B y t e s = item . g e t S i z e ( ) ;
out . p r i n t l n ( s i z e I n B y t e s ) ;
InputStream i n=item . g e t I n p u t S t r e a m ( ) ;
InputStreamReader i s r =new InputStreamReader ( i n ) ;
B u f f e r e d R e a d e r br=new B u f f e r e d R e a d e r ( i s r ) ;
double [ ] [ ] m a t r i x=g e t M a t r i x ( br ) ;
i n t m=m a t r i x . l e n g t h ;
i n t n=m a t r i x [ 0 ] . l e n g t h ;
f o r ( i n t i =0; i <m; i ++){
f o r ( i n t j =0; j <n ; j ++)
out . p r i n t ( m a t r i x [ i ] [ j ]+ ) ;
out . p r i n t l n ( ) ;
}
br . c l o s e ( ) ;
isr . close ();
in . close ( ) ;
out . c l o s e ( ) ;
}
}
}
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 ( ) ) ;
}
}
private double [ ] [ ] g e t M a t r i x ( B u f f e r e d R e a d e r br ) throws E x c e p t i o n {
Vector<Double> v=new Vector<Double > ( 1 0 ) ;
double [ ] [ ] m a t r i x=n u l l ;
try {
String line , s ;
i n t m=0 ,n , mn ;
do{
l i n e=br . r e a d L i n e ( ) ;
i f ( l i n e != n u l l ) {
m++;
S t r i n g [ ] s t=l i n e . s p l i t ( ) ;
for ( S t r i n g s : s t ){
v . addElement (new Double ( s ) ) ;
}
}
}
8.7. DESCARCAREA
UNUI FIS
IER
while ( l i n e != n u l l ) ;
i f ( v . s i z e () >0){
mn=v . s i z e ( ) ;
n=mn/m;
m a t r i x=new double [m ] [ n ] ;
f o r ( i n t i =0; i <m; i ++){
f o r ( i n t j =0; j <n ; j ++){
m a t r i x [ i ] [ j ] = ( ( Double ) v . elementAt ( i n+j ) ) . d o u b l e V a l u e ( ) ;
System . out . p r i n t ( m a t r i x [ i ] [ j ]+ ) ;
}
System . out . p r i n t l n ( ) ;
}
}
79
80
81
82
83
84
85
86
87
88
89
90
91
}
catch ( E x c e p t i o n e ) {
throw new E x c e p t i o n ( e . g e t M e s s a g e ( ) ) ;
}
return m a t r i x ;
92
93
94
95
96
97
98
219
8.7
Desc
arcarea unui fisier
Consideram cazul:
Exemplul 8.7.1 Fisierul ales de client dintr-o lista disponibila este descarcat
fiind transmis navigatorului.
1
2
import j a v a . i o . IOException ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
220
CAPITOLUL 8. SERVLET
10
import
import
import
import
import
import
import
import
12
@WebServlet ( u r l P a t t e r n s = / download )
14
public c l a s s D o w n l o a d 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 {
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 f i l e =r e q . g e t P a r a m e t e r ( f i l e ) ;
System . out . p r i n t l n ( f i l e ) ;
Path c a l e=Paths . g e t ( webapps / download / r e s o u r c e s / + f i l e ) ;
try {
System . out . p r i n t l n ( c a l e+ f i l e ) ;
r e s . setContentType ( A p p l i c a t i o n / Octetstream ) ;
r e s . addHeader ( ContentD i s p o s i t i o n , attachment ; f i l e n a m e=+ f i l e ) ;
F i l e s . copy ( c a l e , out ) ;
}
catch ( E x c e p t i o n e ) {
r e s . setContentType ( t e x t / p l a i n ) ;
out . p r i n t l n ( C e r e r e a dv o a s t r a nu p o a t e f i s a t i s f a c u t a ) ;
}
out . c l o s e ( ) ;
}
3
4
5
6
7
8
9
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
. http . HttpServlet ;
. http . HttpServletRequest ;
. http . HttpServletResponse ;
. ServletOutputStream ;
. a n n o t a t i o n . WebServlet ;
. Path ;
. Paths ;
. Files ;
34
35
36
37
38
javax . s e r v l e t
javax . s e r v l e t
javax . s e r v l e t
javax . s e r v l e t
javax . s e r v l e t
java . nio . f i l e
java . nio . f i l e
java . nio . f i l e
8.8
Filtru
8.8. FILTRU
221
<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>
Programat. Se utilizeaza adnotarea WebFilter
. . .
import javax.servlet.annotation.WebFilter;
@WebFilter(filterName="MyFilterDispatcher",urlPatterns={"/*"})
public class MyFilterDispatcher implements Filter {. . .}
Clasa filtrului implementeaza 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 8.8.1 Contextul filtrud contine doi servleti HelloServlet si CmmdcServlet, apelabili respectiv din hello.html, cmmdc.html. Sa se programeze un
filtru care
Redirecteaza solicitarea /filtrud/hello catre /cmmdc.html.
Daca se cere ca natura raspunsului sa fie text/xml atunci invalideaza
cererea.
Servletii HelloServlet si CmmdcServlet sunt cei dezvoltati la nceputul acestui capitol. Filtrul (n varianta descriptiva) are codul
222
1
2
3
4
5
6
7
8
9
10
12
13
import
import
import
import
import
import
import
import
import
import
j a v a . i o . IOException ;
javax . s e r v l e t . ServletRequest ;
javax . s e r v l e t . ServletResponse ;
javax . s e r v l e t . RequestDispatcher ;
javax . s e r v l e t . F i l t e r ;
javax . s e r v l e t . F i l t e r C o n f i g ;
javax . s e r v l e t . FilterChain ;
javax . s e r v l e t . ServletException ;
javax . s e r v l e t . http . HttpServletRequest ;
javax . s e r v l e t . http . HttpServletResponse ;
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 ;
}
15
16
17
public void d e s t r o y ( ) {
this . f i l t e r C o n f i g = null ;
}
19
20
21
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 ,
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 ( ) ;
System . out . p r i n t l n ( F i l t e r URI= +u r i ) ;
System . out . p r i n t l n ( u r i ) ;
23
24
25
26
27
28
29
i f ( u r i . equals ( / f i l t r u d ) | | u r i . equals ( / f i l t r u d / ) )
f i l t e r C h a i n . doFilter ( request , response ) ;
else {
i f ( u r i . equals ( / f i l t r u d / 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 f ( u r i . e q u a l s ( / f i l t r u d /cmmdc ) ) {
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 ) ;
}
}
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
CAPITOLUL 8. SERVLET
<webapp>
1
2
3
8.9. EVENIMENT S
I AUDITOR
7
8
9
10
12
13
14
15
16
223
< f i l t e r>
< f i l t e r name> f i l t e r D i s p a t c h e r</ f i l t e r name>
< f i l t e r c l a s s>M y F i l t e r D i s p a t c h e r</ f i l t e r c l a s s>
</ f i l t e r >
< f i l t e r mapping>
< f i l t e r name> f i l t e r D i s p a t c h e r</ f i l t e r name>
<u r l p a t t e r n>/</ u r l p a t t e r n>
</ f i l t e r mapping>
</webapp>
<html>
<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= / 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>
8.9
Eveniment si auditor
224
CAPITOLUL 8. SERVLET
import j a v a x . s e r v l e t . S e r v l e t C o n t e x t 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 C o n t e x t E v e n t ;
import j a v a x . s e r v l e t . S e r v l e t C o n t e x t ;
public c l a s s F i r s t C o n t e x t L i s t e n e r
implements S e r v l e t C o n t e x t L i s t e n e r {
public void c o n t e x t D e s t r o y e d ( S e r v l e t C o n t e x t E v e n t e v e n t ) {
System . out . p r i n t l n ( Web app was removed . ) ;
}
public void c o n t e x t I n i t i a l i z e d ( S e r v l e t C o n t e x t E v e n t e v e n t ) {
System . out . p r i n t l n ( Web app i s r e a d y . ) ;
S e r v l e t C o n t e x t s c=e v e n t . g e t S e r v l e t C o n t e x t ( ) ;
System . out . p r i n t l n ( s c . g e t C o n t e x t P a t h ( ) ) ;
System . out . p r i n t l n ( s c . g e t E f f e c t i v e M a j o r V e r s i o n ( ) ) ;
System . out . p r i n t l n ( s c . g e t E f f e c t i v e M i n o r V e r s i o n ( ) ) ;
}
}
Exemplul 8.9.2
1
2
4
5
import j a v a x . s e r v l e t . h t t p . H t t p S e s s i o n L i s t e n e r ;
import j a v a x . s e r v l e t . h t t p . H t t p S e s s i o n E v e n t ;
public c l a s s F i r s t S e s s i o n L i s t e n e r implements H t t p S e s s i o n L i s t e n e r {
static int u s e r s = 0 ;
public void s e s s i o n C r e a t e d ( H t t p S e s s i o n E v e n t e ) {
u s e r s ++;
}
public void s e s s i o n D e s t r o y e d ( H t t p S e s s i o n E v e n t e ) {
u s e r s ;
}
public s t a t i c i n t g e t C o n c u r r e n t U s e r s ( ) {
return u s e r s ;
}
7
8
9
10
11
12
13
14
15
16
225
8.10
Intr-o clasa Java se poate ncorpora un server tomcat n care pot fi instalate
una sau mai multi serveti. Resursele necesare sunt continute n apache-tomcat*-embedded, iar fisierele jar continute trebuie declarate n variabila de sistem
classpath.
Sablonul de programare este:
1
2
3
5
6
7
8
9
10
12
13
Tomcat . a d d S e r v l e t ( c t x t , n u m e S e r v l e t , new C l a s a S e r v l e t ( ) ) ;
c t x t . a d d S e r v l e t M a p p i n g ( /numeApel , n u m e S e r v l e t ) ;
15
16
tomcat . s t a r t ( ) ;
tomcat . g e t S e r v e r ( ) . a w a i t ( ) ;
18
19
}
catch ( E x c e p t i o n e ) {
e . printStackTrace ( ) ;
}
20
21
22
23
24
25
Probleme
226
CAPITOLUL 8. SERVLET
Intreb
ari recapitulative
1. Precizati sensurile si continutul cuvantului servlet.
2. Unde se instaleaza o aplicatie servlet n serverul Web apache-tomcat?
3. Cum se poate apela aplicatia servlet, dar servlet-ul propriu zis?
4. Extinzand clasa HttpServlet, ce trebuie sa faca programatorul?
5. Care sunt modurile de programare a unui servlet si precizati diferenta
dintre ele.
6. Care sunt sarcinile de indeplinit n metoda doGet?
7. Cum se rezolva solicitatarea clientului ntr-un servlet asincron conform
Servlet-API 3.0 ?
8. Cum se rezolva solicitatarea clientului ntr-un servlet asincron conform
Servlet-API 3.1 ?
9. Ce posibilitate de prelucrare ofera un filtru?
10. Ce posibilitate ofera clasa javax.servlet.http.Cookie?
11. Ce posibilitate ofera clasa javax.servlet.http.HttpSession?
12. Care sunt metodele de programare asincrona a unui servlet?
Capitolul 9
Java Server Page JSP
9.1
Tehnologia JSP
Tipul tehnologiei JSP este denumit procesare de sabloane (template engine). JSP este o tehnologie similara cu PHP, ASP.NET, apache-velocity, etc.
JSP permite includerea de cod Java ntr-un document html. Un asemenea
document se depoziteaza ntr-un server Web, container de servlet, cu extensia
jsp, eventual jspx.
Apelarea documentului JSP se realizeaza prin
meniul File/Open a unui navigator, cu
http://host:port/cale/doc.jsp
referinta 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" ...
>
228
|
|
|--> jsp
|
|
doc.jsp
<html>
<body>
Hello
</body>
</html>
n Hello.jsp si plasandu-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 consta 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.
Fisierul JSP poate fi construit pe un document xhtml, avand preambulul
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
sau document html 5. In acest caz preambulul este
<!doctype html>
Apelarea paginii / documentului JSP se face prin jsp/Hello.jsp
Exista doua moduri de a include elemente JSP ntr-un text html:
prin elemente specifice JSP.
Fisierul are extensia jsp si se numeste pagina JSP.
prin elemente xml apartinand spatiului de nume
http://java.sun.com/JSP/Page
Fisierul poate avea extensia jsp sau jspx si se numeste document JSP.
Comentariile JSP se scriu de forma
<%-- Comentariu --%>
229
<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>
Codul Java nglobat ntr-un text html se numeste scriptlet. Sintaxa utilizata este
Varianta paginii JSP
<% cod Java %>
230
Domeniu de valabilitate
pagina curenta
n pagina curenta,
n paginile incluse si
n paginile catre care se face o redirectare
session
n sesiunea curenta
application pe durata rularii aplicatiei
In orice pagina
Variabila
out
request
response
session
page
pageContext
application
exception
Astfel
String request.getParameter(String numeParametru)
furnizeaza valoarea parametrului numeParametru dintr-un formular html.
Exemplul 9.1.2 Pagina JSP Hello: Clientul transmite numele paginii care i
raspunde cu mesajul de salut Hi + nume + !.
Codul paginii JPS (hello.jsp) este
1
2
3
4
5
<html>
<head>
< t i t l e> j s p h e l l o </ t i t l e>
</head>
<body>
6
7
8
9
10
11
12
13
14
231
<center>
<h1> Pagina de r ă spuns </h1>
<p>
<%
out . p r i n t l n ( Hi +r e q u e s t . g e t P a r a m e t e r ( name)+ ! ) ;
%>
</ center>
</body>
</html>
<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= 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>
232
13
14
15
16
18
19
20
21
22
23
25
26
27
28
9.1.1
Declaratii JSP
<html>
<body>
<H1> CMMDC </H1>
<%!
l o n g cmmdc( l o n g m, l o n g n ) { . . . }
%>
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>
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
33
34
233
<html>
<head>
< t i t l e> I n i t </ t i t l e>
</head>
<body>
<%!
i n t numar ;
public void j s p I n i t (){
234
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
numar=0;
}
public void jspDestroy (){
System . out . p r i n t l n ( numar ) ;
}
%>
<center>
<h1> Pagina de r ă spuns </h1>
<p>
<%
String sn=r e q u e s t . g e t P a r a m e t e r ( numar ) ;
i n t n=I n t e g e r . p a r s e I n t ( sn ) ;
numar+=n ;
out . p r i n t l n ( Numarul e s t e : +numar ) ;
%>
</ center>
</body>
</html>
9.1.2
Directive JSP
Directiva include permite includerea unor fisiere .html sau .jsp n document
<%@ include file=fisier html, jsp %>
235
9.1.3
<jsp :
236
<jsp :
useBean id=numeComponentaJava
class=numeClasa
scope=domeniu />
setProperty name=numeComponentaJava
property=numeProp
value=valoare/>
getProperty name=numeComponentaJava
property=numeProp/>
9.1.4
Clasa componentei Java care se va utiliza ntr-o pagina JSP trebuie inclusa
ntr-un pachet.
Reluam exemplul 9.1.2 cu o componenta Java corespunzatoare numelui din
formularul index.html.
Exemplul 9.1.5
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 ;
}
}
237
Exemplul 9.1.6 Pagina JSP pentru calculul celui mai mare divizor comun
cu metoda de calcul definita ntr-o componenta Java.
Utilizand documentului html din Exemplul 9.1.3 se defineste componenta
Java
1
2
3
4
5
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 ;
238
7
8
9
10
11
12
13
14
15
16
17
18
24
public S t r i n g getCmmdc ( ) {
long a=Long . par se Lon g (m) ;
long b=Long . p ars eL ong ( n ) ;
return (new Long (cmmdc( a , b ) ) ) . t o S t r i n g ( ) ;
}
26
20
21
22
23
28
1
2
3
4
5
6
7
8
9
10
11
12
13
14
239
< !
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
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html>
<body>
<form method=p o s t
action= 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>
9.2
240
Descriere
Biblioteca de baza
Biblioteca de prelucrare
a documentelor xml
http://java.sun.com/jsp/jstl/fmt
Biblioteca de formatare a datelor
http://java.sun.com/jsp/jstl/sql
Biblioteca de lucru cu baze de date
http://java.sun.com/jsp/jstl/functions Biblioteca de functii ajutatoare
Instalarea bibliotecilor. Bibliotecile sunt livrate mpreuna cu apachetomcat-* n catalogul apache-tomcat-*\webapps\examples\WEB-INF\lib prin
fisierele taglibs-standard-spec-*.jar si taglibs-standard-impl-*.jar.
Utilizarea bibliotecilor. In vederea utilizarii, cele doua fisiere trebuie
copiate n catalogul lib al aplicatiei care utilizeaza bibliotecile.
In pagina / documentul JSP, o biblioteca utilizata trebuie declarata printro directiva taglib.
9.2.1
Biblioteca de baz
a
241
Fel
Descriere
obligatoriu Valoarea ce se evalueaza si se afiseaza.
optional
Cea ce se afiseaza n cazul n care
expresia nu poate fi evaluata.
escapeXml optional
true / false. Valoarea implicita este true.
Pe false interpreteaza caracterele din value
ca si cod html.
c:if Test, verificarea unei conditii.
Atribute ale marcajului:
Atribut Fel
Descriere
test
obligatoriu Conditia de test.
var
optional
Numele variabilei ce va stoca valoarea
testului.
scope
optional
Domeniul de valabilitate al variabilei
definita anterior.
In cazul n care conditia are valoarea true se prelucreaza corpul marcajului, n caz contrar, acesta este ignorat.
242
Exemplul 9.2.1 Preluarea datelor unui formular cu campurile de intrare nume, prenume si email se face prin pagina JSP
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
<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>
Fel
Descriere
optional Colectia care se parcurge.
optional Numele variabilei n care se stocheaza
valoarea elementului curent.
begin
optional Valoarea initiala a variabilei var.
end
optional Valoarea finala a variabilei var.
step
optional Valoarea pasului de iterare. Implicit este 1.
varStatus optional Informatii despre elementul curent.
243
244
Atribut
value
Fel
Descriere
obligatoriu Valoarea ce se evalueaza si se afiseaza.
expresiei.
default
optional
Cea ce se afiseaza n cazul n care
expresia nu poate fi evaluata.
escapeXml optional
true / false. Valoarea implicita este true.
Pe false interpreteaza caracterele din value
ca si cod html.
c:import Permite includerea altor pagini JSP n pagina curenta.
Atribute ale marcajului:
Atribut Fel
Descriere
url
obligatoriu Adresa documentului importat.
context optional
Context-ul paginii / documentului importat.
Simbolul /, urmat de numele unei aplicatii
de pe acelasi server.
var
optional
Numele variabilei n care va fi stocat
documentul importat.
scope
optional
Domeniul de valabilitate al variabilei var.
Unul din valorile:
page, request, session, application.
Cu marcajul c:param se pot fixa parametri pentru pagina importata.
Acest marcaj are doua atribute name si value. Acesti parametri se
transmit cu metoda get.
c:redirect Redirectarea activitatea catre o alta pagina.
Atribute ale marcajului:
Atribut Fel
Descriere
url
obligatoriu Adresa paginii catre care se face redirectarea.
context optional
Context-ul paginii catre care se face redirectarea.
Simbolul /, urmat de numele unei aplicatii
de pe acelasi server.
Prin redirectare, parametrii nu sunt retransmisi automat mai departe.
c:url Retine adrese URL.
Atribute ale marcajului:
245
Atribut Fel
Descriere
value
obligatoriu Adresa documentului de retinut.
context optional
Context-ul documentului.
Simbolul /, urmat de numele unei aplicatii
de pe acelasi server.
var
optional
Numele variabilei n care va fi stocata
adresa documentului.
scope
optional
Domeniul de valabilitate al variabilei var.
Unul din valorile:
page, request, session, application.
9.2.2
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.
Fel
obligatoriu
optional
optional
optional
obligatoriu
scope
optional
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.
246
<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 / AgendaEMail
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 a d r e s e />
<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>
</ c : i f>
</BODY>
</HTML>
9.3
9.3.1
247
Marcaje f
ar
a atribute si f
ar
a corp.
Pentru a crea unui asemenea marcaj JSP propriu este necesara definirea
urmatorelor componente:
1. O clasa de definitie a comportamentului marcajului JSP (tag handler
class).
2. Descriptorul bibliotecii de marcaje JSP, care leaga clasa de definitie a
marcajului cu identificatorul bibliotecii de marcaje. Acest descriptor
este un fisier cu extensia tld. Serverul Web va depista descriptorul
bibliotecii de marcaje n catalogul aplicatiei.
3. Fisierul JSP ce utilizeaza marcajul JSP (clientul).
Exemplificam acesta tehnologie prin
Exemplul 9.3.1 Sa se realizeze un marcaj dateTag, a carui efect sa fie afisarea
datei calendaristice.
1. Clasa de definitie a comportamentului marcajului. Programul consta
din:
(a) Importul pachetelor
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
Aceste pachete se gasesc n fisierul jsp-api.jar.
(b) Un marcaj fara atribute si fara corp trebuie sa extinda clasa TagSupport
si sa suprascrie metoda doStartTag, care defineste activitatea intreprinsa cand este ntalnit marcajul ntr-un document jsp. Metoda
trebuie sa returneze constanta SKIP BODY.
public class NumeClasa extends TagSupport{
public int doStartTag(){
. . .
return SKIP_BODY;
}
}
248
1
2
3
4
5
7
8
9
10
11
12
13
14
15
16
17
18
package j s p ;
import j a v a x . s e r v l e t . j s p . J s p W r i t e r ;
import j a v a x . s e r v l e t . j s p . t a g e x t . TagSupport ;
import j a v a . i o . IOException ;
import j a v a . u t i l . Date ;
public c l a s s DateTag extends TagSupport {
public i n t doStartTag ( ) {
try {
J s p W r i t e r out=pageContext . getOut ( ) ;
out . p r i n t l n (new Date ( ) ) ;
}
catch ( IOException e ) {
System . out . p r i n t l n ( DateTagException +e . g e t M e s s a g e ( ) ) ;
}
return SKIP BODY ;
}
}
2. Descriptorul bibliotecii de marcaje JSP este dependent de versiunea tomcat folosita. Acest fisier trebuie sa aiba extensia tld (Taglib Language
Definition).
1
2
3
4
5
6
7
9
10
11
12
13
15
16
17
18
19
20
21
249
1
2
3
4
5
6
7
8
<html>
<head>
< t i t l e>
Tag p e n t r u data c a l e n d a r i s t i c a c u r e n t a
</ t i t l e>
</head>
<body>
<%@ t a g l i b u r i= mytags
250
9
10
11
12
13
14
p r e f i x=mk %>
<p>
Data c u r e n t a e s t e :
<mk : dateTag />
</body>
</html>
apelat din
1
2
3
4
6
7
8
9
10
<html>
<body>
<form method= g e t
action= j s p / dateTag . j s p >
Data c a l e n d a r i s t i c ă:
<p><input type= submit value= A f i s e a z a >
</form>
</body>
</html>
9.3.2
Marcaje cu atribute si f
ar
a corp.
1
2
3
4
6
7
9
10
11
package j s p ;
import j a v a x . s e r v l e t . j s p . J s p W r i t e r ;
import j a v a x . s e r v l e t . j s p . t a g e x t . TagSupport ;
import j a v a . i o . IOException ;
public c l a s s ZiuaTag extends TagSupport {
String ziua ;
public void s e t Z i u a ( S t r i n g v a l u e ) {
z i u a=v a l u e ;
}
251
public i n t doStartTag ( ) {
try {
J s p W r i t e r out=pageContext . getOut ( ) ;
out . p r i n t l n ( z i u a ) ;
}
catch ( IOException e ) {
System . out . p r i n t l n ( ZiuaTagException +e . g e t M e s s a g e ( ) ) ;
}
return SKIP BODY ;
}
13
14
15
16
17
18
19
20
21
22
23
Fel
obligatoriu
obligatoriu
optional
1
2
3
4
5
6
7
8
9
<html>
<body>
<form method= g e t
action= j s p / ziuaTag . j s p >
<p>A s t a z i , e s t e
<s e l e c t name= z i u a >
<option value= l u n i > Luni
<option value= m a r t i > Marti
<option value= m i e r c u r i > M i e r c u r i
252
10
11
12
13
14
15
16
17
18
<html>
<head>
< t i t l e> Tag cu marcaj </ t i t l e>
</head>
<body>
<%@ t a g l i b u r i= mytags
p r e f i x=mk %>
<p>
<%
String z i=r e q u e s t . g e t P a r a m e t e r ( z i u a ) ;
%>
Ziua e s t e :
<mk : ziuaTag z i u a=<%= z i %> />
</body>
</html>
9.3.3
Marcaje cu corp.
1
2
3
4
6
7
8
package j s p ;
import j a v a x . s e r v l e t . j s p . J s p W r i t e r ;
import j a v a x . s e r v l e t . j s p . t a g e x t . TagSupport ;
import j a v a . i o . IOException ;
public c l a s s ModTag extends TagSupport {
String text ;
boolean toUpperCase ;
public void s e t T e x t ( S t r i n g v a l u e ) {
t e x t=v a l u e ;
}
10
11
12
public void s e t T r a n s ( S t r i n g v a l u e ) {
toUpperCase=(new Boolean ( v a l u e ) ) . b o o l e a n V a l u e ( ) ;
}
14
15
16
public i n t doStartTag ( ) {
try {
J s p W r i t e r out=pageContext . getOut ( ) ;
i f ( toUpperCase )
out . p r i n t l n ( t e x t . toUpperCase ( ) ) ;
else
out . p r i n t l n ( t e x t . toLowerCase ( ) ) ;
}
catch ( IOException e ) {
System . out . p r i n t l n ( ModTagException +e . g e t M e s s a g e ( ) ) ;
}
return EVAL BODY INCLUDE ;
}
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<html>
<body>
<form method= g e t
253
254
4
5
6
7
8
9
10
11
12
13
14
15
16
mpreuna cu modtextTag.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<html>
<body>
<%@ t a g l i b u r i= mytags p r e f i x=mk %>
<%
String text=r e q u e s t . g e t P a r a m e t e r ( t e x t ) ;
String t r a n s=r e q u e s t . g e t P a r a m e t e r ( t r a n s ) ;
String t ;
i f ( t r a n s . e q u a l s ( upperCase ) )
t= t r u e ;
else
t= f a l s e ;
%>
<p>
<mk : modTag text=<%= t e x t %> t r a n s=<%=t%>>
<mk : dateTag />
</mk : modTag>
</body>
</html>
9.4
9.4. AUTENTIFICARE S
I AUTORIZARE CU APACHE-SHIRO
255
Termeni
Credential informatie pe baza careia se realizeaza autentificarea unui
utilizator / subiect (de exemplu: o parola);
Principal Autentificarea se asigura printr-una sau mai multe credentials
printre care se afla principal, (de exemplu: username);
Realm (taram/domeniu) entitatea care retine datele de identificare a unui
utilizator;
Subject termen utilizat pentru un utilizator (om sau program).
Fisierul de configurare shiro.ini pentru aplicatie Web contine:
1. [main] shiro.loginUrl = /login.jsp
Se indica pagina de autentificare.
2. [users]
Declararea utilizatorilor mpreuna cu parola de autentificare si rolul /
rolurile. Un rol fixeaza activitatile (permissions) de care dispune utilizatorul.
Sintaxa utilizata este
numeUtilizator = parola, rol 1,rol 2,. . .
3. [roles]
Se declara activitatile permise de rol, mai precis pentru care se asigura
autorizarea.
Sintaxa utilizata este
rol = activitatea 1,activitatea 2,. . .
* desemneaza orice activitate.
4. [urls]
Se declara referintele din serverul Web la care se asigura accesul doar n
urma autentificarii, care sunt filtrate de apache-shiro.
Sintaxa utilizata este
/fisier.jsp sau catalog/** = authc
Deconectarea se indica prin
/logout = logout
256
Exemplul 9.4.1
1
2
4
5
6
7
8
9
11
12
13
14
15
17
18
19
20
[ main ]
shiro . loginUrl = / login . jsp
[ users ]
# f o r m a t : username = password , r o l e 1 , r o l e 2 ,
admin = admin , admin
guest = guest , guest
cmmdc=cmmdc , rolCmmdc
h e l l o=h e l l o , r o l H e l l o
. . . , roleN
[ roles ]
# f o r m a t : roleName = p e r m i s s i o n 1 , p e r m i s s i o n 2 ,
admin = a l l
rolCmmdc=cmmdc
r o l H e l l o=h e l l o
. . . , permissionN
[ urls ]
/ l o g i n . j s p = authc
/ logout = logout
/ a c c e s A u t o r i z a t / = authc
9.4. AUTENTIFICARE S
I AUTORIZARE CU APACHE-SHIRO
7
8
9
10
11
13
14
15
16
17
18
20
21
22
23
24
257
< l i s t e n e r>
< l i s t e n e r c l a s s>
o r g . apache . s h i r o . web . env . E n v i r o n m e n t L o a d e r L i s t e n e r
</ l i s t e n e r c l a s s>
</ l i s t e n e r>
< f i l t e r>
< f i l t e r name> S h i r o F i l t e r</ f i l t e r name>
< f i l t e r c l a s s>
o r g . apache . s h i r o . web . s e r v l e t . S h i r o F i l t e r
</ f i l t e r c l a s s>
</ f i l t e r >
< f i l t e r mapping>
< f i l t e r name> S h i r o F i l t e r</ f i l t e r name>
<u r l p a t t e r n>/</ u r l p a t t e r n>
</ f i l t e r mapping>
</webapp>
<html>
<head>
<META HTTPEQUIV= R e f r e s h CONTENT= 0 ;URL=home . j s p >
</head>
<body>
<p>A p e l a r e a a p l i c a t i e i . . . </p>
</body>
</html>
258
<shiro:user>
Executa marcajul interior daca utilizatorul (Subject) este autentificat.
<shiro:hasRole name=rol>
Executa marcajul interior daca utilizatorul are rolul rol.
<shiro:lacksRole name=rol>
Executa marcajul interior daca utilizatorul nu are rolul rol.
<hasAnyRole name=rol1,rol2,. . . >
Executa marcajul interior daca utilizatorul are unul din rolurile din lista.
<shiro:hasPermission name=actiune>
Executa marcajul interior daca rolului i este atribuit activitatea actiune.
<shiro:hasPermission name=actiune>
Executa marcajul interior daca rolului nu i este atribuit activitatea
actiune.
Exemplul 9.4.2 Aplicatie Web utilizand fisierul shiro.ini cu acces catre
aplicatiile cmmdc1pagina.jsp si hello1pagina.jsp.
Se definesc trei clienti admin, cmmdc si hello. Administratorul va avea
acces la ambele aplicatii dar clientul cmmdc / hello va avea acces doar la
aplicatia cmmdc1pagina / hello1pagina.
Structura aplicatiei si fisierul shiro.ini sunt cele date mai sus.
Fisierul home.jsp este
1
2
4
5
6
8
9
10
12
13
14
15
16
17
18
9.4. AUTENTIFICARE S
I AUTORIZARE CU APACHE-SHIRO
19
20
21
22
23
24
25
26
27
29
30
31
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
50
51
52
53
54
55
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
76
77
</td>
</ tr>
<tr>
<td>
<a href=<c : u r l v a l u e= / l o g o u t />>Log out</a>
</td>
</ tr>
</ table>
</ s h i r o : u s e r>
<s h i r o : g u e s t>
<a href=<c : u r l v a l u e= / l o g i n . j s p />>Log i n</a>
</ s h i r o : g u e s t>
<p/>
<s h i r o : h a s R o l e name= admin >admin<br/>
<%
s e s s i o n . s e t A t t r i b u t e ( r o l , admin ) ;
%>
</ s h i r o : h a s R o l e>
<s h i r o : h a s R o l e name=rolCmmdc>rolCmmdc<br/>
<%
s e s s i o n . s e t A t t r i b u t e ( r o l , rolCmmdc ) ;
%>
</ s h i r o : h a s R o l e>
<s h i r o : h a s R o l e name= r o l H e l l o > r o l H e l l o<br/>
<%
session . setAttribute ( rol , rolHello );
%>
</ s h i r o : h a s R o l e>
<p/>
<h3>R o l u r i pe c a r e
<p/>
<s h i r o : l a c k s R o l e
<s h i r o : l a c k s R o l e
<s h i r o : l a c k s R o l e
<p/>
<h3>A c t i v i t ăţ i l e dv o a s t r ă</h3>
<p>
<s h i r o : h a s P e r m i s s i o n name= a l l > a l l<br/>
<%
s e s s i o n . setAttribute ( act , a l l ) ;
%>
</ s h i r o : h a s P e r m i s s i o n>
<s h i r o : h a s P e r m i s s i o n name=cmmdc>cmmdc<br/>
<%
s e s s i o n . s e t A t t r i b u t e ( a c t , cmmdc ) ;
%>
</ s h i r o : h a s P e r m i s s i o n>
<s h i r o : h a s P e r m i s s i o n name= h e l l o > h e l l o<br/>
<%
s e s s i o n . setAttribute ( act , h e l l o ) ;
%>
</ s h i r o : h a s P e r m i s s i o n>
<p/>
<h3>A c t i v i t ăţ i de c a r e nu d i s p u n e ţ i</h3>
259
260
78
79
80
81
82
<p/>
<s h i r o : l a c k s P e r m i s s i o n name=cmmdc>cmmdc<br/></ s h i r o : l a c k s P e r m i s s i o n>
<s h i r o : l a c k s P e r m i s s i o n name= h e l l o > h e l l o<br/></ s h i r o : l a c k s P e r m i s s i o n>
</body>
</html>
<html>
<body>
<h2>Pagina de c o n e c t a r e</h2>
<form method= p o s t >
<table a l i g n= l e f t border= 0 c e l l s p a c i n g= 0 cellpadding= 3 >
<tr>
<td> U t i l i z a t o r :</td>
<td>
<input type= t e x t name= username maxlength= 30 >
</td>
</ tr>
<tr>
<td>P a r o l a :</td>
<td>
<input type= password name= password maxlength= 30 >
</td>
</ tr>
<tr>
<td colspan= 2 a l i g n= r i g h t >
<input type= submit name= submit value= Login >
</td>
</ tr>
</ table>
</form>
</body>
</html>
<html>
<body bgcolor=#a a e e a a >
<table>
<%
String a c t =(String ) s e s s i o n . g e t A t t r i b u t e ( a c t ) ;
i f ( a c t== a l l ) {
%>
<tr>
<td>
<a href= a l e g e . html >A c t i u n i a d m i n i s t r a t o r</a>
</td>
</ tr>
<%
}
i f ( a c t==cmmdc ) {
%>
<tr>
<td>
<a href=cmmdc . html >C a l c u l cmmdc</a>
</td>
</ tr>
<%
9.4. AUTENTIFICARE S
I AUTORIZARE CU APACHE-SHIRO
23
24
25
26
27
28
29
30
31
32
33
34
35
36
}
i f ( a c t== h e l l o ) {
%>
<tr>
<td>
<a href= h e l l o . html >A p l i c a t i a H e l l o Name</a>
</td>
</ tr>
<%
}
%>
</ table>
</body
</html>
Intreb
ari recapitulative
1. Care este tipul tehnologiei JSP ?
2. Precizati diferenta dintre o pagina JSP si un document JSP.
3. Unde se instaleaza o pagina JSP?
4. Care este rolul unei declaratii JSP ?
5. Care este rolul unei directive JSP ?
6. Cum apeleaza o pagina JSP ?
7. Cum prelucreaza un server Web o pagina / document JSP ?
8. Care sunt trasaturile unei componente Java (bean) ?
9. Care este rolul unui element <jsp:useBean> ?
261
262
Capitolul 10
Desf
asurarea n nor
Dezvoltarea Internetului, nevoia de a reduce costurile legate de realizarea
si ntretinerea infrastructurii care ofera servicii pe Internet, concomitent cu
nevoia de crestere a calitatii serviciilor a condus la servicii n nor (Cloud
Computing).
Avantajele oferite de serviciile serviciile n nor sunt:
Reducerea costurilor
Agilitate (Agility)
Reducerea duratei:
de asteptare n cazul aparitiei unei disfunctionalitati din partea
furnizorului serviciului n nor;
de actualizare si ntretinere din partea realizatorului serviciului n
nor.
Elasticitate (Elasticity)
Posibilitatea de crestere / descrestere a resurselor (n principal hard)
alocate pentru a satisface cerintele clientilor ntr-un interval de timp.
Se face distinctie de scalabilitate, termen care desemneaza nevoia de
cresere / descrestere a resurselor alocate legata de dezvoltarea aplicatiilor
care compun serviciul.
Tipuri de servicii n nor:
Aplicatii ca serviciu (Software as a Service - SaaS )
Skype, Googles Docs, Gmail, Yahoo Messenger, Microsoft Office 365,
etc.
263
264
URAREA IN NOR
CAPITOLUL 10. DESFAS
10.1
WEB-INF
|--> classes
|
| *.class
|--> lib
|
| *.jar
|
web.xml
|
appengine-web.xml
index.html
10.1. SERVLET S
I JSP IN GOOGLE APP ENGINE
265
Singurul fisier specific GAE este appengine-web.xml. Codul acestui fiser este
1
2
3
4
6
8
266
URAREA IN NOR
CAPITOLUL 10. DESFAS
Se executa cu ant obiectivul implicit din build.xml, urmat de lansarea simulatorului din interiorul catalogului appcmmdc. Deoarece numele fisierului html
difera de index, aplicatia se apeleaza prin
http://localhost:8080/cmmdc.html.
Alternativ, aplicatia se poate construi cu Eclipse folosind o componenta
(plug-in) specifica.
GAE contine n plus un serviciu de autentificare si autorizare UserService,
un sistem de persistenta a datelor Datastore, Task-Queue.
Desf
asurarea n GAE
Acest pas necesita din partea dezvoltatorului cont Google.
Desfasurarea gratuita (cel mult 10 aplicatii) n GAE presupune:
1. Inregistrarea aplicatiei:
(a) Se acceseaza pagina Web https://appengine.google.com/.
(b) Inregistrarea propriu-zisa:
i. Application Identifier
Se fixeaza identificatorul aplicatiei app id, care se trece si n
elementul <application> din appengine-web.xml;
ii. Check Availibility
Verificarea disponibilitatii identificatorului;
iii. Application title
Fixarea titlului aplicatiei;
iv. Create Application
2. Incarcarea n nor (upload)
%GAE_HOME%\bin\appcfg.cmd --oauth2 update locatia_aplicatiei_web
10.2
Heroku
Heroku este o PaaS care ofera suport pentru mai aplicatii dezvoltate n mai
multe limbaje de programare, printre care si Java.
10.2. HEROKU
267
Instalarea resurselor
1. Punctul de pornire este crearea unui cont Heroku la https://devcenter.
heroku.com prin Getting Started. Parametrii contului sunt (adresa de
email, parola).
2. Se va instala Heroku Toolbeit. Cu acest prilej se instaleaza Ruby si Git
n c:\Program Files (x86).1 Ruby se instaleaza n Heroku. Variabila de sistem PATH se actualizeaza cu caile la Heroku si Git (dar nu la
Git\bin\ssh-keygen.exe).
3. Login pentru generarea cheii de identificare.
heroku login
La conectari ulterioare nu se mai genereaza aceasta cheie.
Utilizarea.
Gestionarea aplicatiilor se realizeaza la https://dashboard.heroku.com/
apps.
Dezvoltarea aplicatiilor se bazeaza pe maven iar desfasurarea pe Git.
10.2.1
JSP n Heroku
1. Generarea aplicatiei:
set GroupID=myGroupId
set ArtifactID=myArtifactId
set Version=1.0
mvn archetype:generate -DgroupId=%GroupID%
-DartifactId=%ArtifactID%
-Dversion=%Version%
-DarchetypeArtifactId=maven-archetype-webapp
-DinteractiveMode=false
2. Completarea fisierului pom.xml:
1
2
3
4
5
268
URAREA IN NOR
CAPITOLUL 10. DESFAS
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
269
10.2. HEROKU
1
2
system.properties
1
j a v a . r u n t i m e . v e r s i o n =1.7
.gitignore
1
target
6. Pregatirea Git
git init
git add .
git commit -m "myapp"
7. Generarea si desfasurarea aplicatiei
heroku create
git push heroku master
Heroku atribuie un nume aplicatiei. Dintr-un navigator aplicatia se va
apela prin acest nume:
http://numeDatDeHeroku.herokuapp.com/
8. Calibrare
270
URAREA IN NOR
CAPITOLUL 10. DESFAS
10.2.2
Servlet n Heroku
package h e l l o . heroku ;
import j a v a . i o . IOException ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e q u e s t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e s p o n s e ;
import j a v a x . s e r v l e t . S e r v l e t O u t p u t S t r e a m ;
import o r g . e c l i p s e . j e t t y . s e r v e r . S e r v e r ;
import o r g . e c l i p s e . j e t t y . s e r v l e t . S e r v l e t C o n t e x t H a n d l e r ;
import o r g . e c l i p s e . j e t t y . s e r v l e t . S e r v l e t H o l d e r ;
public c l a s s HelloWorld extends H t t p S e r v l e t {
@Override
protected 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 p )
throws S e r v l e t E x c e p t i o n , IOException {
r e s p . g e t W r i t e r ( ) . p r i n t ( H e l l o from Java ! \ n ) ;
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) throws E x c e p t i o n {
S e r v e r s e r v e r = new S e r v e r ( I n t e g e r . v a l u e O f ( System . g e t e n v ( PORT ) ) ) ;
ServletContextHandler context =
new S e r v l e t C o n t e x t H a n d l e r ( S e r v l e t C o n t e x t H a n d l e r . SESSIONS ) ;
context . setContextPath ( / ) ;
server . setHandler ( context ) ;
c o n t e x t . a d d S e r v l e t (new S e r v l e t H o l d e r (new HelloWorld ( ) ) , / ) ;
server . start ();
server . join ();
}
19
20
21
22
23
24
25
26
27
28
29
10.2. HEROKU
271
Fisierele html, css care asigura interfata grafica a aplicatiei servlet nu fac
parte din ce se ncarca n nor.
Servletul se apeleaza prin
http://numeDatDeHeroku.herokuapp.com/numeApel
Desfasurarea si apelarea consta din
1. Generarea aplicatiei.
2. Completarea fisierului pom.xml:
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
33
34
35
36
37
38
39
40
41
42
43
44
45
272
46
47
48
49
50
51
52
53
54
55
URAREA IN NOR
CAPITOLUL 10. DESFAS
</ e x e c u t i o n s>
</ p l u g i n>
<p l u g i n>
<g r o u p I d>o r g . e c l i p s e . j e t t y</ g r o u p I d>
< a r t i f a c t I d>j e t t y mavenp l u g i n</ a r t i f a c t I d>
<version> 9 . 1 . 0 . v20131115</ version>
</ p l u g i n>
</ p l u g i n s>
</ b u i l d>
</ p r o j e c t>
5. Completarea cu fisierele
Procfile
1
2
system.properties
.gitignore
Structura aplicatiei devine
myapp
|--> src
|
|--> main
|
|
|--> java
|
|
|
*.java
|
|
|--> resources
|
|
|--> webapp
|
|
|
|--> WEB-INF
|
|
|
|
|
web.xml
|--> target
|
|
*
|
.gitignore
|
Procfile
|
system.properties
|
pom.xml
6. Pregatirea Git
10.3. OPENSHIFT
273
git init
git add .
git commit -m "myapp"
7. Generarea si desfasurarea aplicatiei
heroku create
git push heroku master
Heroku atribuie un nume aplicatiei. Dintr-un navigator aplicatia se va
apela prin acest nume.
8. Calibrare
heroku ps:scale web=1
cu verificarea calibrarii
heroku ps
Aceasta setare fixeaza resursele atribuite aplicatiei la 1 dynos. Un numar
mai mare de resurse presupune un cost.
9. Daca se transmit date aplicatiei printr-un fisier html atunci lansarea
aplicatiei se face din navigator completand atributul action cu adresa
furnizata de heroku iar n caz contrar din linie de comanda se apeleaza
heroku open
10. Optional se poate consulta fisierul de jurnalizare
heroku logs
10.3
OpenShift
274
URAREA IN NOR
CAPITOLUL 10. DESFAS
Comunicatiile unei aplicatii se fac exclusiv potrivit protocoalelor si porturilor din tabelul urmator:
Protocolul
HTTP
HTTPS
SSH-SecureSHell
WebSocket HTTP
WebSocket HTTPS
Portul
80
443
22
8000
8443
O aplicatie apartine unui cartus - cartridge - dar care poate contine si alte
componente ale aplicatiei (de exemplu un SGBD). Unui cartus i se asociaza
un angrenaj - gear - ce trebuie privit ca un container al aplicatiei. Angrenajul
poate fi mic (512 MB), mediu (1 GB) sau mare (2 GB).
Cartusul defineste natura aplicatiei (servlet sau JSP n tomcat 6 sau 7,
aplicatie JEE, etc).
Un utilizator trebuie sa se nregistreze (gratuit) la www.openshift.com,
moment n care se fixeaza codul de identificare - o adresa de e-mail - si o
parola.
Unui dezvoltator i se asociaza un domeniu - namespace - indicat printr-un
cuvant. Apelarea unei aplicatii se face dupa schema
http://numeApp-domeniu.rhcloud.com
Gratuit un dezvoltator poate instala pana la 3 aplicatii ntr-un angrenaj
mic.
O aplicatie se poate dezvolta:
n linie de comanda prin clientul OpenShift rhc;
ntr-o consola Web;
n Eclipse cu o componenta (plug-in) specifica.
In continuare consideram doar dezvoltarea n linie de comanda.
10.3. OPENSHIFT
Verificarea instalarii:
ruby -e puts "Welcome to Ruby"
2. Se instaleaza Git (http://git-scm.com/download/win).
Verificarea instalarii:
git --version
3. Descarcarea clientului OpenShift
gem install rhc
Locatia este RUBY HOME\include.
4. Instalarea clientului OpenShift
rhc setup
275
276
|
|
|
|-->
|
|
URAREA IN NOR
CAPITOLUL 10. DESFAS
|
|
|
|
|
|
|
|
|
webapps
README.md
pom.xml
|
web.xml
index.html
snoop.jsp
Inc
arcarea n nor
git add .
git commit -m "text"
git push
Operatii rhc
rhc --help
rhc --help comanda rhc
rhc cartridge list
Lista cartuselor disponibile.
rhc app delete numeApp
Stergerea aplicatiei.
rhc apps
Lista aplicatiilor.
Intreb
ari recapitulative
1. Precizati tipurile principale de servicii n nor.
2. Enumerati servicii n nor de tip PaaS cu suport pentru Java.
Capitolul 11
Java Web Start
11.1
all-permissions
278
private void i n i t C o m p o n e n t s ( ) {
// cod g e n e r a t de Netbeans
}
9
10
12
13
14
15
16
17
18
19
20
21
22
23
24
25
27
28
29
31
32
33
private
private
private
private
private
private
35
36
37
38
39
40
41
279
all-permissions
(b)
(c)
280
<html>
<body bgcolor=#AAEEAA>
<center>
<h3>V i s u a l Cmmdc A p p l i c a t i o n </h3>
<a href= h t t p : / / h o s t : 8 0 8 0 / cmmdc/ l a u n c h . j n l p >
Launch t h e a p p l i c a t i o n </a>
</ center>
</body>
</html>
5. Ansamblul
cmmdc
|
cmmdc.jar
|
cmmdc.html
|
launch.jnlp
281
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
? xml v e r s i o n= 1 . 0 e n c o d i n g= i s o 88591?>
< !DOCTYPE webapp
PUBLIC //Sun Microsystems , I n c . / /DTD Web A p p l i c a t i o n 2 . 3 / /EN
h t t p : // j a v a . sun . com/ dtd /weba p p 2 3 . dtd >
<webapp>
< ! Standard Ac ti o n S e r v l e t C o n f i g u r a t i o n ( w i t h d e b u g g i n g ) >
<webapp>
< s e r v l e t>
<s e r v l e t name>J n l p D o w n l o a d S e r v l e t</ s e r v l e t name>
<s e r v l e t c l a s s>
j n l p . sample . s e r v l e t . J n l p D o w n l o a d S e r v l e t
</ 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>J n l p D o w n l o a d S e r v l e t</ s e r v l e t name>
<u r l p a t t e r n> . j n l p</ u r l p a t t e r n>
</ s e r v l e t mapping>
</webapp>
</webapp>
1. Daca aplicatia Java utilizeaza alte resurse date prin fisiere jar
atunci toate fisierele jar trebuie sa poarte aceasi certificare.
2. Fisierele jar certificate se depun n catalogul app\lib.
3. In fisierul jnlp, n elementul resources, pentru fiecare fisier jar
utilizat se introduce declaratia
<jar href=lib/resource.jar/>
282
Daca arhiva jar a aplicatiei Java este executabila atunci, n fisierul jnlp,
elementul application-desc poate lipsi.
Intr-o arhiva jar executabila, fisierul MANIFEST.MF indica clasa cu metoda
main si eventualele resurse externe utilizate (fisiere jar) prin proprietatile
Main-class: numeClasa
Class-path: lib/resursa1.jar lib/resursa2.jar . . .
Intreb
ari recapitulative
1. Ce posibilitate ofera tehnologia Java Web Start ?
2. O aplicatie Java urmeaza sa fie valorificat pe Internet prin Java Web
Start. Daca aplicatia necesita date ale clientului ce restrictie exista si
cum se satisface restrictia ?
3. Ce nseamna abrevierea JNLP?
4. Unde se utilizeaza JNLP?
5. In ce consta utilizarea protocolului JNLP?
6. Care este programul executabil care preceseaza un fisier jnlp?
Capitolul 12
WebSocket
HTML5 introduce protocolul WebSocket pentru comunicatii bidirectionale
ntre un client HTML5 dintr-un navigator si un server Web. Utilizarea protocolului WebSocket conduce la reducerea semnificativa a traficului n retea.
Toate navigatoarele importante suporta protocolul WebSocket.
12.1
Protocolul WebSocket
Daca ntre cei doi parteneri se stabileste acordul (handshake) atunci restul
comunicatiilor au loc prin intermediul unui soclu TCP pe portul 80.
Astfel ciclul de viata al procesului de comunicatie este:
283
284
1. Un client solicita printr-un mesaj http acordul pentru trecerea la protocolul WebSocket.
2. Serverul raspunde acceptand acordul.
3. Odata stabilita conexiunea, acesta devine bidirectionala (simetrica), clientul si serverul transmit si receptioneaza mesaje.
4. Una din parti nchide conexiunea.
12.2
Semnificatia
Nu s-a stabilit conexiunea
Conexiune pregatita pentru comunicatii
Conexiune n pragul confirmarii (handshake)
Conexiune nchisa si nu mai poate fi redeschisa
285
bufferedAmount
Numarul octetilor trimisi de functia send. Datele sunt codificate UTF-8.
Un sablon de utilizare poate fi
<script language="javascript" type="text/javascript">
var wsUri = "ws://host:8080/context/numeApel";
var websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) { . . . };
websocket.onmessage = function(evt) { . . . };
websocket.onerror = function(evt) { . . . };
websocket.onclose = function(evt) { . . . };
. . .
</script>
Expedierea datelor.
Consideram formularul HTML
<form name="myform">
<input type="text" name="xyz" . . ./>
. . .
<input type="button" onclick="send"/>
</form>
Receptia unui rezultat furnizat de server. Functia onmessage permite recuperarea rezultatului din evt.data.
12.3
WebSocket n Java
286
12.3.1
287
Interfata javax.websocket.RemoteEndpoint.Basic
Metode
void sendObject(Object data) throws IOException,EncodeException
void sendText(String data) throws IOException
void sendBinary(ByteBuffer data) throws IOException
OutputStream getSendStream() throws IOException
Structura aplicatiei Web cu desfasurare n glassfish este
AppSerser
|--> WEB-INF
|
|--> classes
|
|
|
*.class
|
index.html
Exemplul 12.3.1 Calculul celui mai mare divizor comun a doua numere naturale.
Aplicatia server are codul
1
2
3
4
5
6
7
8
9
10
11
12
14
15
16
17
19
20
21
22
23
24
25
26
27
package w e b s o c k e t . cmmdc ;
import j a v a x . w e b s o c k e t . OnMessage ;
import j a v a x . w e b s o c k e t . s e r v e r . S e r v e r E n d p o i n t ;
import j a v a x . w e b s o c k e t . RemoteEndpoint ;
import j a v a x . w e b s o c k e t . S e s s i o n ;
import j a v a x . w e b s o c k e t . OnOpen ;
import j a v a x . w e b s o c k e t . OnClose ;
import j a v a x . w e b s o c k e t . EncodeException ;
import j a v a . i o . IOException ;
import j a v a . u t i l . S e t ;
import j a v a . u t i l . C o l l e c t i o n s ;
import j a v a . u t i l . HashSet ;
@ServerEndpoint ( v a l u e= /cmmdc )
public c l a s s CmmdcWebSocketServer {
private s t a t i c Set<S e s s i o n > s e s s i o n s =
C o l l e c t i o n s . s y n c h r o n i z e d S e t (new HashSet<S e s s i o n > ( ) ) ;
@OnMessage
public void myTask ( S t r i n g msg , S e s s i o n s e s s i o n )
throws IOException , EncodeException {
S t r i n g [ ] elem=msg . s p l i t ( : ) ;
long m=Long . par se Lon g ( elem [ 0 ] ) ;
long n=Long . p ars eL ong ( elem [ 1 ] ) ;
long r=cmmdc(m, n ) ;
for ( S e s s i o n peer : s e s s i o n s ) {
i f ( peer . equals ( s e s s i o n )){
288
28
29
30
31
33
35
@OnOpen
public void onOpen ( S e s s i o n s e s s i o n ) {
s e s s i o n s . add ( s e s s i o n ) ;
}
36
37
38
@OnClose
public void o n C l o s e ( S e s s i o n s e s s i o n ) {
s e s s i o n s . remove ( s e s s i o n ) ;
}
40
41
42
43
44
package w e b s o c k e t . cmmdc ;
im po rt j a v a x . w e b s o c k e t . OnMessage ;
im po rt j a v a x . w e b s o c k e t . s e r v e r . S e r v e r E n d p o i n t ;
im po rt j a v a x . w e b s o c k e t . S e s s i o n ;
im po rt j a v a x . w e b s o c k e t . OnOpen ;
im po rt j a v a x . w e b s o c k e t . OnClose ;
im po rt j a v a x . w e b s o c k e t . EncodeException ;
im po rt j a v a . i o . IOException ;
im po rt j a v a . u t i l . S e t ;
im po rt j a v a . u t i l . C o l l e c t i o n s ;
im po rt j a v a . u t i l . HashSet ;
im po rt j a v a . u t i l . stream . Stream ;
im po rt j a v a x . w e b s o c k e t . RemoteEndpoint ;
@ServerEndpoint ( v a l u e= /cmmdc )
p u b l i c c l a s s CmmdcWebSocketServer {
i n t e r f a c e CmmdcService {
l o n g cmmdc( l o n g m, l o n g n ) ;
}
s t a t i c CmmdcService cmmdcService=( 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 ;
};
p r i v a t e s t a t i c S e t<S e s s i o n> s e s s i o n s =
C o l l e c t i o n s . s y n c h r o n i z e d S e t ( new HashSet<S e s s i o n> ( ) ) ;
@OnMessage
p u b l i c v o i d myTask ( S t r i n g msg , S e s s i o n s e s s i o n )
throws IOException , EncodeException {
S t r i n g [ ] elem=msg . s p l i t ( : ) ;
l o n g m=Long . pa rse Lo ng ( elem [ 0 ] ) ;
l o n g n=Long . pa rse Lo ng ( elem [ 1 ] ) ;
System . out . p r i n t l n (m+ : +n ) ;
l o n g r=cmmdcService . cmmdc(m, n ) ;
S t r i n g r e z=new Long ( r ) . t o S t r i n g ( ) ;
Stream<S e s s i o n> stream=s e s s i o n s . stream ( ) ;
stream
. f i l t e r ( s>s . e q u a l s ( s e s s i o n ) )
. f o r E a c h ( s>{
RemoteEndpoint . B a s i c e n d p o i n t=s . getBasicRemote ( ) ;
try {
e n d p o i n t . sendText ( r e z ) ;
}
c a t c h ( IOException e ) { } ;
});
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
58
@OnOpen
p u b l i c v o i d onOpen ( S e s s i o n s e s s i o n ) {
s e s s i o n s . add ( s e s s i o n ) ;
}
59
60
61
@OnClose
p u b l i c void onClose ( S e s s i o n s e s s i o n ){
s e s s i o n s . remove ( s e s s i o n ) ;
}
63
64
65
66
67
289
290
29
31
f u n c t i o n onMessage ( e v t ) {
w r i t e T o S c r e e n ( RECEIVED : + e v t . data ) ;
}
32
33
35
36
37
38
40
41
42
44
45
46
48
49
50
51
52
53
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
f u n c t i o n onError ( evt ) {
w r i t e T o S c r e e n ( <span s t y l e= c o l o r : r e d ; >ERROR:</span> +
e v t . data ) ;
}
f u n c t i o n onClose ( evt ) {
w r i t e T o S c r e e n ( CLOSED ) ;
}
f u n c t i o n myclose ( ) {
websocket . c l o s e ( ) ;
}
f u n c t i o n w r i t e T o S c r e e n ( message ) {
v a r p r e = document . c r e a t e E l e m e n t ( p ) ;
p r e . s t y l e . wordWrap = breakword ;
p r e . innerHTML = message ;
o ut pu t . appendChild ( p r e ) ;
}
window . a d d E v e n t L i s t e n e r ( l o a d , i n i t , f a l s e ) ;
</ s c r i p t>
</head>
<body>
<h1>CMMDC with WebSocket ! ! </h1>
<div s t y l e= t e x t a l i g n : c e n t e r ; >
<form name=cmmdc>
<table border= 1 >
<tr>
<td> Primul numă r </td>
<td> <input type=number name=m value= 1
r e q u i r e d min= 1 /> </td>
</ tr>
<tr>
<td> Al d o i l e a numă r </td>
<td> <input type=number name=n value= 1
r e q u i r e d min= 1 /> </td>
</ tr>
<tr>
<td>
<input type= b ut to n value= C a l c u l e a z a onclick= send ( ) />
</td>
<td></td>
</ tr>
<tr>
<td>
<input type= b ut to n value= I n c h i d e onclick= m y c l o s e ( ) />
</td>
<td></td>
</ tr>
</ table>
</form>
</ div>
88
89
90
291
12.3.2
Programare f
ar
a adnot
ari
Clasa javax.websocket.Endpoint
Metode
void onClose(Session session, CloseReason closeReason)
void onError(Session session, Throwable th)
abstract void onOpen(Session session, EndpointConfig config)
Interfata javax.websocket.MessageHandler.Whole<T>
Metode
void onMessage(T message)
In functie de
Mesaj text
String
Reader
292
Codurile sunt:
import
import
import
import
public c l a s s M y A p p l i c a t i o n C o n f i g implements S e r v e r A p p l i c a t i o n C o n f i g {
1
2
3
@Override
public Set<S e r v e r E n d p o i n t C o n f i g > g e t E n d p o i n t C o n f i g s (
Set<C l a s s <? extends Endpoint>> s e t ) {
return new HashSet<S e r v e r E n d p o i n t C o n f i g >() {
{
add ( S e r v e r E n d p o i n t C o n f i g . B u i l d e r
. c r e a t e ( CmmdcWebSocketEndpoint . c l a s s , /cmmdc )
. build ( ) ) ;
}
};
}
8
9
10
11
12
13
14
15
16
17
18
@Override
public Set<C l a s s <?>> g e t A n n o t a t e d E n d p o i n t C l a s s e s ( Set<C l a s s <?>> s e t ) {
return C o l l e c t i o n s . emptySet ( ) ;
}
20
21
22
23
24
java . u t i l . Set ;
j a v a x . w e b s o c k e t . Endpoint ;
javax . websocket . s e r v e r . S e r v e r A p p l i c a t i o n C o n f i g ;
javax . websocket . s e r v e r . ServerEndpointConfig ;
si
1
2
3
4
5
6
7
8
9
11
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
30
31
package w e b s o c k e t . cmmdc ;
import j a v a x . w e b s o c k e t . C l os e R e a s o n ;
import j a v a x . w e b s o c k e t . RemoteEndpoint ;
import j a v a x . w e b s o c k e t . S e s s i o n ;
import j a v a x . w e b s o c k e t . Endpoint ;
import j a v a x . w e b s o c k e t . E n d p o i n t C o n f i g ;
import j a v a x . w e b s o c k e t . MessageHandler ;
import j a v a x . w e b s o c k e t . EncodeException ;
import j a v a . i o . IOException ;
public c l a s s CmmdcWebSocketEndpoint extends Endpoint {
public void onOpen ( S e s s i o n s e s s i o n , E n d p o i n t C o n f i g c o n f i g ) {
f i n a l RemoteEndpoint . B a s i c remote = s e s s i o n . getBasicRemote ( ) ;
s e s s i o n . addMessageHandler (new MessageHandler . Whole<S t r i n g >() {
public void onMessage ( S t r i n g msg ) {
try {
S t r i n g [ ] elem=msg . s p l i t ( : ) ;
long m=Long . par se Lon g ( elem [ 0 ] ) ;
long n=Long . p ars eL ong ( elem [ 1 ] ) ;
System . out . p r i n t l n (m+ : +n ) ;
long r=cmmdc(m, n ) ;
remote . sendText (new Long ( r ) . t o S t r i n g ( ) ) ;
}
catch ( E x c e p t i o n i o e ) { }
}
});
}
public void o n C l o s e ( S e s s i o n s e s s i o n , C l o s e R e a s o n c l o s e R e a s o n ) {
System . out . p r i n t l n ( C l o s i n g : + c l o s e R e a s o n . g e t R e a s o n P h r a s e ( ) ) ;
32
34
35
36
38
39
12.3.3
import
import
import
import
import
import
import
import
import
import
import
j a v a . i o . IOException ;
j a v a . n e t . URI ;
java . u t i l . Scanner ;
j a v a . n e t . URISyntaxException ;
javax . websocket . ContainerProvider ;
j a v a x . w e b s o c k e t . DeploymentException ;
j a v a x . w e b s o c k e t . WebSocketContainer ;
javax . websocket . S e s s i o n ;
j a v a x . w e b s o c k e t . Endpoint ;
javax . websocket . EndpointConfig ;
j a v a x . w e b s o c k e t . MessageHandler ;
293
294
16
ws : / / l o c a l h o s t : 8 0 8 0 / CmmdcWebSocketAD/cmmdc ;
18
19
20
21
22
23
24
25
26
27
28
try {
Session s e s s i o n = container . connectToServer (
WebSocketClient . c l a s s , null , new URI (SERVER ) ) ;
s e s s i o n . getBasicRemote ( ) . sendText ( data ) ;
while ( ! s f a r s i t ) { System . out . p r i n t l n ( ) ; } ;
session . close ();
}
catch ( E x c e p t i o n ex ) {
System . out . p r i n t l n ( LocalEndPoint E x c e p t i o n : +ex . g e t M e s s a g e ( ) ) ;
}
30
31
32
33
34
35
36
37
38
39
40
42
43
44
45
46
47
48
49
50
12.3.4
295
1
2
3
4
5
6
7
8
9
10
11
12
13
14
16
17
18
19
package w e b s o c k e t . cmmdc ;
import j a v a x . w e b s o c k e t . OnMessage ;
import j a v a x . w e b s o c k e t . s e r v e r . S e r v e r E n d p o i n t ;
import j a v a x . w e b s o c k e t . S e s s i o n ;
import j a v a x . w e b s o c k e t . OnOpen ;
import j a v a x . w e b s o c k e t . OnClose ;
import j a v a x . w e b s o c k e t . OnError ;
import j a v a x . w e b s o c k e t . RemoteEndpoint ;
import j a v a x . w e b s o c k e t . EncodeException ;
import j a v a x . w e b s o c k e t . s e r v e r . PathParam ;
import j a v a . i o . IOException ;
import j a v a . u t i l . S e t ;
import j a v a . u t i l . C o l l e c t i o n s ;
import j a v a . u t i l . HashSet ;
@ServerEndpoint ( v a l u e= /cmmdc/{msg} )
public c l a s s CmmdcWebSocketServer {
private s t a t i c Set<S e s s i o n > s e s s i o n s =
C o l l e c t i o n s . s y n c h r o n i z e d S e t (new HashSet<S e s s i o n > ( ) ) ;
23
i n t e r f a c e CmmdcService {
long cmmdc( long m, long n ) ;
}
25
27
@OnMessage
public void onMessage ( S t r i n g message , S e s s i o n s e s s i o n ) { }
21
22
28
@OnOpen
public void onOpen ( S e s s i o n s e s s i o n , @PathParam ( msg ) S t r i n g msg )
throws IOException , EncodeException {
s e s s i o n s . add ( s e s s i o n ) ;
S t r i n g [ ] elem=msg . s p l i t ( : ) ;
long m=Long . par se Lon g ( elem [ 0 ] ) ;
long n=Long . p ars eL ong ( elem [ 1 ] ) ;
long r=cmmdcService . cmmdc(m, n ) ;
S t r i n g r e z=new Long ( r ) . t o S t r i n g ( ) ;
s e s s i o n s . stream ( )
. f i l t e r ( s>s . e q u a l s ( s e s s i o n ) )
. f o r E a c h ( s>{
RemoteEndpoint . B a s i c e n d p o i n t=s . getBasicRemote ( ) ;
try {
e n d p o i n t . sendText ( r e z ) ;
}
catch ( IOException e ) { } ;
});
}
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@OnClose
public void o n C l o s e ( S e s s i o n s e s s i o n ) {
s e s s i o n s . remove ( s e s s i o n ) ;
}
50
51
52
53
54
cu apelarea din
1
2
.};
296
3
4
5
7
8
10
11
12
14
15
16
17
18
19
20
21
22
23
24
26
27
28
30
31
32
34
35
36
38
39
40
41
43
44
45
47
48
49
50
51
52
54
55
56
57
58
59
60
61
<head>
<meta httpe q u i v= ContentType content= t e x t / html ; c h a r s e t=UTF8>
< t i t l e>Cmmdc WebSocket</ t i t l e>
<s c r i p t l a n g u a g e= j a v a s c r i p t type= t e x t / j a v a s c r i p t >
var websocket ;
function i n i t () {
o ut pu t = document . getElementById ( r e s u l t ) ;
}
f u n c t i o n send ( ) {
v a r sm=document . cmmdc .m. v a l u e ;
v a r sn=document . cmmdc . n . v a l u e ;
v a r msg=sm+ : +sn ;
v a r wsUri = ws : / / l o c a l h o s t : 8 0 8 0 / CmmdcWebSocketAD/cmmdc/ +msg ;
w e b s o c k e t = new WebSocket ( wsUri ) ;
w e b s o c k e t . onopen = f u n c t i o n ( e v t ) { onOpen ( e v t ) } ;
w e b s o c k e t . onmessage = f u n c t i o n ( e v t ) { onMessage ( e v t ) } ;
websocket . o n e r r o r = f u n c t i o n ( evt ) { onError ( evt ) } ;
websocket . o n c l o s e = f u n c t i o n ( evt ) { onClose ( evt ) } ;
}
f u n c t i o n myclose ( ) {
websocket . c l o s e ( ) ;
}
f u n c t i o n onOpen ( e v t ) {
w r i t e T o S c r e e n ( CONNECTED ) ;
}
f u n c t i o n onMessage ( e v t ) {
w r i t e T o S c r e e n ( RECEIVED : + e v t . data ) ;
}
f u n c t i o n onError ( evt ) {
w r i t e T o S c r e e n ( <span s t y l e= c o l o r : r e d ; >ERROR:</span> +
e v t . data ) ;
}
f u n c t i o n onClose ( evt ) {
w r i t e T o S c r e e n ( CLOSED ) ;
}
f u n c t i o n w r i t e T o S c r e e n ( message ) {
v a r p r e = document . c r e a t e E l e m e n t ( p ) ;
p r e . s t y l e . wordWrap = breakword ;
p r e . innerHTML = message ;
o ut pu t . appendChild ( p r e ) ;
}
window . a d d E v e n t L i s t e n e r ( l o a d , i n i t , f a l s e ) ;
</ s c r i p t>
</head>
<body>
<h1>CMMDC with WebSocket ! ! </h1>
<div s t y l e= t e x t a l i g n : c e n t e r ; >
<form name=cmmdc>
<table border= 1 >
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
297
<tr>
<td> Primul numă r </td>
<td> <input type=number name=m value= 1
r e q u i r e d min= 1 /> </td>
</ tr>
<tr>
<td> Al d o i l e a numă r </td>
<td> <input type=number name=n value= 1
r e q u i r e d min= 1 /> </td>
</ tr>
<tr>
<td>
<input type= b ut to n value= C a l c u l e a z a onclick= send ( ) />
</td>
<td></td>
</ tr>
<tr>
<td>
<input type= b ut to n value= I n c h i d e onclick= m y c l o s e ( ) />
</td>
<td></td>
</ tr>
</ table>
</form>
</ div>
<div id= r e s u l t ></ div>
</body>
</html>
12.3.5
298
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;
import javax.websocket.EncodeException;
public class MyEncoder implements Encoder.Text<T> {
@Override
public void init(EndpointConfig ec) { }
@Override
public void destroy() { }
@Override
public String encode(T obj) throws EncodeException{
// Cod de conversie al campurilor obiectului obj in JSON
return objJsonString;
}
}
Exemplul 12.3.3
Fie componenta Java
1
@XmlRootElement ( name= d a t e )
public c l a s s CmmdcBean{
private long m;
private long n ;
public void setM ( long m) {
t h i s .m=m;
}
4
5
6
7
8
9
11
12
13
15
16
17
19
20
21
22
299
package w e b s o c k e t . cmmdc ;
import j a v a x . w e b s o c k e t . OnMessage ;
import j a v a x . w e b s o c k e t . s e r v e r . S e r v e r E n d p o i n t ;
import j a v a x . w e b s o c k e t . S e s s i o n ;
import j a v a x . w e b s o c k e t . OnOpen ;
import j a v a x . w e b s o c k e t . OnClose ;
import j a v a x . w e b s o c k e t . EncodeException ;
import j a v a . i o . IOException ;
import j a v a . u t i l . S e t ;
import j a v a . u t i l . C o l l e c t i o n s ;
import j a v a . u t i l . HashSet ;
@ServerEndpoint ( v a l u e= /cmmdc ,
d e c o d e r s={CmmdcBeanXMLDecoder . c l a s s , CmmdcBeanJSONDecoder . c l a s s } )
public c l a s s CmmdcWebSocketServer {
private s t a t i c Set<S e s s i o n > s e s s i o n s =
C o l l e c t i o n s . s y n c h r o n i z e d S e t (new HashSet<S e s s i o n > ( ) ) ;
@OnMessage
public void myTask ( S e s s i o n s e s s i o n , CmmdcBean o b j )
throws IOException , EncodeException {
long m=o b j . getM ( ) ;
long n=o b j . getN ( ) ;
long r=cmmdc(m, n ) ;
for ( S e s s i o n peer : s e s s i o n s ) {
i f ( peer . equals ( s e s s i o n )){
p e e r . getBasicRemote ( ) . sendText (new Long ( r ) . t o S t r i n g ( ) ) ;
}
}
}
19
20
21
22
23
24
25
26
27
28
29
30
@OnOpen
public void onOpen ( S e s s i o n s e s s i o n ) {
s e s s i o n s . add ( s e s s i o n ) ;
}
32
33
34
35
@OnClose
public void o n C l o s e ( S e s s i o n s e s s i o n ) {
s e s s i o n s . remove ( s e s s i o n ) ;
}
37
38
39
40
42
43
300
package w e b s o c k e t . cmmdc ;
import j a v a x . w e b s o c k e t . Decoder ;
import j a v a x . w e b s o c k e t . E n d p o i n t C o n f i g ;
import j a v a x . w e b s o c k e t . DecodeException ;
import j a v a x . j s o n . Json ;
import j a v a x . j s o n . JsonArray ;
import j a v a x . j s o n . J s o n O b j e c t ;
import j a v a x . j s o n . JsonReader ;
import j a v a . i o . S t r i n g R e a d e r ;
public c l a s s CmmdcBeanJSONDecoder implements Decoder . Text<CmmdcBean>{
@Override
public void i n i t ( E n d p o i n t C o n f i g e c ) { }
@Override
public void d e s t r o y ( ) { }
15
16
@Override
public CmmdcBean de co de ( S t r i n g s t r i n g ) throws DecodeException {
S t r i n g R e a d e r s r=new S t r i n g R e a d e r ( s t r i n g ) ;
JsonReader j s o n R e a d e r = Json . c r e a t e R e a d e r ( s r ) ;
J s o n O b j e c t o b j=j s o n R e a d e r . r e a d O b j e c t ( ) ;
jsonReader . c l o s e ( ) ;
long m=0 ,n=0;
S t r i n g sm=o b j . g e t S t r i n g ( m ) ;
m=Long . par se Lon g ( sm ) ;
S t r i n g sn=o b j . g e t S t r i n g ( n ) ;
n=Long . p ars eL ong ( sn ) ;
CmmdcBean bean=new CmmdcBean ( ) ;
bean . setM (m) ;
bean . setN ( n ) ;
return bean ;
}
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Override
public boolean w i l l D e c o d e ( S t r i n g s t r i n g ) {
return true ;
}
35
36
37
38
39
package w e b s o c k e t . cmmdc ;
import j a v a x . w e b s o c k e t . Decoder ;
import j a v a x . w e b s o c k e t . E n d p o i n t C o n f i g ;
import j a v a x . w e b s o c k e t . DecodeException ;
import j a v a x . xml . bind . JAXBContext ;
import j a v a x . xml . bind . U n m a r s h a l l e r ;
import j a v a . i o . S t r i n g R e a d e r ;
public c l a s s CmmdcBeanXMLDecoder implements Decoder . Text<CmmdcBean>{
@Override
public void i n i t ( E n d p o i n t C o n f i g e c ) { }
14
@Override
public void d e s t r o y ( ) { }
16
@Override
13
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Override
public boolean w i l l D e c o d e ( S t r i n g s t r i n g ) {
return ( s t r i n g != n u l l ) ;
}
32
33
34
35
36
301
Clasa clientului utilizeaza doar conversia datelor n obiect JSON sau XML.
Codorul n JSON este
1
2
3
4
5
7
8
9
import
import
import
import
import
11
12
@Override
public S t r i n g e nc od e (CmmdcBean o b j ) throws EncodeException {
long m=o b j . getM ( ) ;
long n=o b j . getN ( ) ;
J s o n O b j e c t j s o n O b j e c t=Json . c r e a t e O b j e c t B u i l d e r ( )
. add ( m ,new Long (m) . t o S t r i n g ( ) )
. add ( n ,new Long ( n ) . t o S t r i n g ( ) )
. build ( ) ;
S t r i n g o b j J s o n S t r i n g=j s o n O b j e c t . t o S t r i n g ( ) ;
return o b j J s o n S t r i n g ;
}
14
15
16
17
18
19
20
21
22
23
24
25
j a v a x . w e b s o c k e t . Encoder ;
javax . websocket . EndpointConfig ;
j a v a x . w e b s o c k e t . EncodeException ;
j a v a x . j s o n . Json ;
javax . json . JsonObject ;
import
import
import
import
import
import
j a v a x . w e b s o c k e t . Encoder ;
javax . websocket . EndpointConfig ;
j a v a x . w e b s o c k e t . EncodeException ;
j a v a x . xml . bind . JAXBContext ;
j a v a x . xml . bind . M a r s h a l l e r ;
java . io . StringWriter ;
302
8
9
10
12
13
@Override
public S t r i n g e nc od e (CmmdcBean o b j ) throws EncodeException {
JAXBContext j a x b C o n t e x t=n u l l ;
S t r i n g W r i t e r s t=n u l l ;
try {
j a x b C o n t e x t=JAXBContext . n e w I n s t a n c e (CmmdcBean . c l a s s ) ;
M a r s h a l l e r m a r s h a l l e r=j a x b C o n t e x t . c r e a t e M a r s h a l l e r ( ) ;
s t=new S t r i n g W r i t e r ( ) ;
m a r s h a l l e r . m ar sh al ( obj , s t ) ;
System . out . p r i n t l n ( R e s u l t s : +s t . t o S t r i n g ( ) ) ;
}
catch ( E x c e p t i o n e ) {
e . printStackTrace ( ) ;
}
return s t . t o S t r i n g ( ) ;
}
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import
import
import
import
import
import
import
import
j a v a . n e t . URI ;
javax . websocket . ContainerProvider ;
j a v a x . w e b s o c k e t . WebSocketContainer ;
javax . websocket . S e s s i o n ;
java . u t i l . Scanner ;
j a v a x . w e b s o c k e t . Endpoint ;
javax . websocket . EndpointConfig ;
j a v a x . w e b s o c k e t . MessageHandler ;
C o n t a i n e r P r o v i d e r . getWebSocketContainer ( ) ;
S t r i n g r e q u e s t=n u l l ;
try {
i f ( t i p ==1){
s e r v e r=ws : / / l o c a l h o s t : 8 0 8 0 / JsonCmmdcWebSocket/cmmdc ;
CmmdcBeanJSONEncoder encoderJSON=new CmmdcBeanJSONEncoder ( ) ;
r e q u e s t=encoderJSON . en co de ( o b j ) ;
}
else {
s e r v e r=ws : / / l o c a l h o s t : 8 0 8 0 / XmlCmmdcWebSocket/cmmdc ;
CmmdcBeanXMLEncoder encoderXML=new CmmdcBeanXMLEncoder ( ) ;
r e q u e s t=encoderXML . en co de ( o b j ) ;
}
System . out . p r i n t l n ( r e q u e s t ) ;
S e s s i o n s e s s i o n=
c o n t a i n e r . c o n n e c t T o S e r v e r ( WebSocketClient . c l a s s , null ,
new URI ( s e r v e r ) ) ;
s e s s i o n . getBasicRemote ( ) . sendText ( r e q u e s t ) ;
while ( ! s f a r s i t ) { ; } ;
}
catch ( E x c e p t i o n ex ) {
System . out . p r i n t l n ( LocalEndPoint E x c e p t i o n : +ex . g e t M e s s a g e ( ) ) ;
}
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
58
59
60
61
62
63
64
65
66
67
303
304
12.3.6
Streaming
Prin socluri se pot transmite fluxuri de date (streaming). Detalii de programare depind de natura datelor ce trebuie vehiculate (text, sunet, grafica).
Expedierea datelor de catre server se realizeaza prin intermediul unui flux
dat de metoda
OutputStream getSendStream()
a clasei javax.websocket.RemoteEndpoint.Basic.
Exemplul 12.3.4 Clientul solicita serverului transmisia unui fisier text, cerere
care va fi satisfacuta de server. Clientul cunoaste lista fisierelor pe care le poate
trimite serverul.
Atat pentru programul server cat si pentru programul client indicam doua
solutii care se corespund.
Clasa server TextStreaming
1
2
3
4
5
6
7
8
9
10
11
12
14
15
16
17
18
19
20
21
22
23
25
26
27
28
30
31
32
33
34
import
import
import
import
import
import
import
import
import
import
import
import
j a v a x . w e b s o c k e t . OnMessage ;
javax . websocket . s e r v e r . ServerEndpoint ;
javax . websocket . S e s s i o n ;
j a v a x . w e b s o c k e t . OnOpen ;
j a v a x . w e b s o c k e t . OnClose ;
j a v a x . w e b s o c k e t . EncodeException ;
j a v a . i o . IOException ;
j a v a . i o . OutputStream ;
java . u t i l . Set ;
java . u t i l . C o l l e c t i o n s ;
j a v a . u t i l . HashSet ;
j a v a . n i o . f i l e . Paths ;
// V a r i a n t a 1
/
import java . i o . F i l e ;
import java . i o . FileReader ;
import java . i o . BufferedReader ;
i m p o r t j a v a . i o . DataOutputStream ;
/
// V a r i a n t a 2
import j a v a . n i o . f i l e . Path ;
import j a v a . n i o . f i l e . F i l e s ;
@ServerEndpoint ( v a l u e= / t e x t )
public c l a s s TextStreaming {
private s t a t i c Set<S e s s i o n > s e s s i o n s =
C o l l e c t i o n s . s y n c h r o n i z e d S e t (new HashSet<S e s s i o n > ( ) ) ;
@OnMessage
public void myTask ( S t r i n g msg , S e s s i o n s e s s i o n )
throws IOException , EncodeException {
S t r i n g f s=System . g e t P r o p e r t y ( f i l e . s e p a r a t o r ) ;
S t r i n g p a t h S e r v e r=new j a v a . i o . F i l e ( . ) . g e t C a n o n i c a l P a t h ( ) ;
i n t x=p a t h S e r v e r . i n d e x O f ( g l a s s f i s h ) ;
S t r i n g path= ;
S t r i n g path0=f s+ TextStreaming +
f s+WEBINF+f s+ t e x t +f s ;
i f ( x==1){
// apachetomcat
path=Paths . g e t ( p a t h S e r v e r ) . t o S t r i n g ()+
f s+ webapps +path0 ;
}
else {
// g l a s s f i s h
x=p a t h S e r v e r . l a s t I n d e x O f ( f s ) ;
S t r i n g p a t h G l a s s f i s h=p a t h S e r v e r . s u b s t r i n g ( 0 , x ) ;
path=Paths . g e t ( p a t h G l a s s f i s h ) . t o S t r i n g ()+
f s+ a p p l i c a t i o n s +path0 ;
}
i n t n o F i l e=I n t e g e r . p a r s e I n t ( msg ) ;
S t r i n g f i l e N a m e= ;
switch ( n o F i l e ) {
case 1 :
f i l e N a m e= c a p i t o l . t x t ;
break ;
case 2 :
f i l e N a m e= j u n i t . t e x ;
break ;
}
System . out . p r i n t l n ( path+f i l e N a m e ) ;
// V a r i a n t a 1
/
F i l e i n p u t F i l e=new F i l e ( p a t h+f i l e N a m e ) ;
F i l e R e a d e r f r=new F i l e R e a d e r ( i n p u t F i l e ) ;
B u f f e r e d R e a d e r b r= new B u f f e r e d R e a d e r ( f r ) ;
fo r ( Session peer : s e s s i o n s ) {
i f ( peer . equals ( s e s s i o n )){
OutputStream o u t=p e e r . getBasicRemote ( ) . getSendStream ( ) ;
DataOutputStream dos=new DataOutputStream ( o u t ) ;
String s ;
w h i l e ( ( s=b r . r e a d L i n e ( ) ) ! = n u l l ) dos . writeUTF ( s ) ;
dos . writeUTF ( e n d O F f i l e ) ;
dos . f l u s h ( ) ;
br . c l o s e ( ) ;
fr . close ();
dos . c l o s e ( ) ;
}
}
/
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// V a r i a n t a 2
Path c a l e=Paths . g e t ( path+f i l e N a m e ) ;
for ( S e s s i o n peer : s e s s i o n s ) {
i f ( peer . equals ( s e s s i o n )){
OutputStream out=p e e r . getBasicRemote ( ) . getSendStream ( ) ;
F i l e s . copy ( c a l e , out ) ;
out . c l o s e ( ) ;
}
}
82
83
84
85
86
87
88
89
90
91
93
@OnOpen
305
306
public void onOpen ( S e s s i o n s e s s i o n ) {
s e s s i o n s . add ( s e s s i o n ) ;
}
94
95
96
@OnClose
public void o n C l o s e ( S e s s i o n s e s s i o n ) {
s e s s i o n s . remove ( s e s s i o n ) ;
}
98
99
100
101
102
import
import
import
import
import
import
import
import
import
import
import
import
import
j a v a . i o . IOException ;
j a v a . n e t . URI ;
javax . websocket . ContainerProvider ;
j a v a x . w e b s o c k e t . DeploymentException ;
j a v a x . w e b s o c k e t . WebSocketContainer ;
javax . websocket . S e s s i o n ;
java . u t i l . Scanner ;
j a v a x . w e b s o c k e t . Endpoint ;
javax . websocket . EndpointConfig ;
j a v a x . w e b s o c k e t . MessageHandler ;
j a v a . i o . DataInputStream ;
j a v a . i o . InputStream ;
j a v a . i o . ByteArrayInputStream ;
w h i l e ( ! ( s=i n . readUTF ( ) ) . e q u a l s ( e n d O F f i l e ) )
System . o u t . p r i n t l n ( s ) ;
48
49
}
c a t c h ( IOException e ) {
e . printStackTrace ( ) ;
}
s f a r s i t =t r u e ;
50
51
52
53
54
55
});
56
}
/
57
58
// Variana 2
public void onOpen ( S e s s i o n s e s s i o n , E n d p o i n t C o n f i g c o n f i g ) {
s e s s i o n . addMessageHandler (new MessageHandler . Whole<byte [ ] > ( ) {
public void onMessage ( byte [ ] msg ) {
System . out . p r i n t l n (new S t r i n g ( msg ) ) ;
s f a r s i t =true ;
}
});
}
60
61
62
63
64
65
66
67
68
69
307
import
import
import
import
import
import
import
import
import
import
import
import
import
import
j a v a x . w e b s o c k e t . OnMessage ;
javax . websocket . s e r v e r . ServerEndpoint ;
javax . websocket . S e s s i o n ;
j a v a x . w e b s o c k e t . OnOpen ;
j a v a x . w e b s o c k e t . OnClose ;
j a v a x . w e b s o c k e t . EncodeException ;
j a v a . i o . IOException ;
j a v a . i o . OutputStream ;
java . u t i l . Set ;
java . u t i l . C o l l e c t i o n s ;
j a v a . u t i l . HashSet ;
j a v a . n i o . f i l e . Paths ;
j a v a . n i o . f i l e . Path ;
java . nio . f i l e . F i l e s ;
@ServerEndpoint ( v a l u e= / image )
public c l a s s ImageStreaming {
private s t a t i c Set<S e s s i o n > s e s s i o n s =
C o l l e c t i o n s . s y n c h r o n i z e d S e t (new HashSet<S e s s i o n > ( ) ) ;
@OnMessage
public void myTask ( S t r i n g msg , S e s s i o n s e s s i o n )
throws IOException , EncodeException {
S t r i n g f s=System . g e t P r o p e r t y ( f i l e . s e p a r a t o r ) ;
S t r i n g p a t h S e r v e r=new j a v a . i o . F i l e ( . ) . g e t C a n o n i c a l P a t h ( ) ;
i n t x=p a t h S e r v e r . i n d e x O f ( g l a s s f i s h ) ;
S t r i n g path= ;
308
S t r i n g path0=f s+ ImageStreaming +
f s+WEBINF+f s+ images +f s ;
i f ( x==1){
// apachetomcat
path=Paths . g e t ( p a t h S e r v e r ) . t o S t r i n g ()+
f s+ webapps +path0 ;
}
else {
// g l a s s f i s h
x=p a t h S e r v e r . l a s t I n d e x O f ( f s ) ;
S t r i n g p a t h G l a s s f i s h=p a t h S e r v e r . s u b s t r i n g ( 0 , x ) ;
path=Paths . g e t ( p a t h G l a s s f i s h ) . t o S t r i n g ()+
f s+ a p p l i c a t i o n s +path0 ;
}
i n t n o F i l e=I n t e g e r . p a r s e I n t ( msg ) ;
S t r i n g f i l e N a m e= ;
switch ( n o F i l e ) {
case 1 :
f i l e N a m e= b r a s o v . j p g ;
break ;
case 2 :
f i l e N a m e=xmlp i c . j p g ;
break ;
}
Path c a l e=Paths . g e t ( path+f i l e N a m e ) ;
for ( S e s s i o n peer : s e s s i o n s ) {
i f ( peer . equals ( s e s s i o n )){
OutputStream out=p e e r . getBasicRemote ( ) . getSendStream ( ) ;
F i l e s . copy ( c a l e , out ) ;
out . c l o s e ( ) ;
}
}
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
60
62
@OnOpen
public void onOpen ( S e s s i o n s e s s i o n ) {
s e s s i o n s . add ( s e s s i o n ) ;
}
63
64
65
@OnClose
public void o n C l o s e ( S e s s i o n s e s s i o n ) {
s e s s i o n s . remove ( s e s s i o n ) ;
}
67
68
69
70
71
import
import
import
import
import
import
import
j a v a . i o . IOException ;
j a v a . n e t . URI ;
javax . websocket . ContainerProvider ;
j a v a x . w e b s o c k e t . DeploymentException ;
j a v a x . w e b s o c k e t . WebSocketContainer ;
javax . websocket . S e s s i o n ;
java . u t i l . Scanner ;
import j a v a x . w e b s o c k e t . Endpoint ;
import j a v a x . w e b s o c k e t . E n d p o i n t C o n f i g ;
import j a v a x . w e b s o c k e t . MessageHandler ;
13
14
15
16
17
19
20
21
22
import
import
import
import
import
j a v a . awt . image . B u f f e r e d I m a g e ;
j a v a x . i m a g e i o . ImageIO ;
j a v a . i o . InputStream ;
j a v a . i o . ByteArrayInputStream ;
j a v a . awt . Image ;
24
25
26
27
28
29
30
31
32
try {
S e s s i o n s e s s i o n=
c o n t a i n e r . c o n n e c t T o S e r v e r ( WebSocketClient . c l a s s , null ,
new URI (SERVER ) ) ;
s e s s i o n . getBasicRemote ( ) . sendText ( data ) ;
while ( ! s f a r s i t ) { ; } ;
}
catch ( E x c e p t i o n ex ) {
System . out . p r i n t l n ( LocalEndPoint E x c e p t i o n : +ex . g e t M e s s a g e ( ) ) ;
}
34
35
36
37
38
39
40
41
42
43
44
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
309
310
Capitolul 13
Enterprise Java Beans
In prezent se evidentiaza doua abordari privind realizarea aplicatiilor de
complexitate mai mare (aplicatiilor de ntreprindere):
Java Enterprise Edition - JEE este o extensie a interfetei de programare
(API ) Java, pentru care exista mai multe implementari. Principalul
promotor este al modelului este Oracle , dar este sustinut si de RedHat
- JBoss.;
Spring a carei dezvoltare tine de firma VMware. Spring este alcatuit din
mai multe cadre de lucru. Acest model de dezvoltare este sustinut de
Google.
Java Enterprise Edition este un cadru de lucru care nglobeaza pe o serie
implementari ale interfetelor de programare (JDBC, JMS, JNDI, JSF, RMIIIOP, JPA, JTA, JAAS, etc), resurse care pot utiliza componente Enterprise
Java Bean- EJB.
O componenta EJB este o clasa Java - de obicei de tip POJO - care face
parte din aplicatia server, contine metodele care rezolva o problema (business logic) si este continut ntr-un server de aplicatii. Serverul de aplicatii
asigura o serie de functionalitati ca instantierea componentelor EJB, injectarea
dependintelor, conexiunea cu bazele de date, gestiunea tranzactiilor, etc. Serverul
de aplicatii poate fi interpretat si ca un container de componente EJB.
Se spune ca serverul de aplicatie JEE asigura accesul la contextul n care
ruleaza aplicatia, adica la resursele serverului, si la injectarea dependintelor
(Context and Dependency Injection -CDI ).
Servere de aplicatii gratuite:
glassfish - Oracle.
311
312
13.1
Session EJB
Starea unui obiect Java este data de valorile campurilor sale. Din punctul
de vedere al retinerii starii, exista urmatoarele tipuri de componente sesiune
EJB:
stateless - fara retinerea starii;
stateful - cu retinerea starii pe parcursul sesiunii serverului;
singleton - exista o singura instanta a componentei EJB. Durata de viata
a componentei coincide cu intervalul de timp n care componenta EJB
este activa n serverul de aplicatii.
Aplicatiile cu componenta EJB constau din:
componenta EJB - desfasurata n serverul de aplicatii. Aceasta componenta poate fi totodata si un serviciu Web de tip JAX-WS;
aplicatie client care poate fi
client Web - servlet sau client al serviciului Web de tip JAX-WS;
client RMI-IIOP (Internet Inter ORB Protocol).
313
13.1.1
Component
a EJB sesiune stateless
Sablonul pentru crearea unei componente EJB de tip stateless session este
import javax.ejb.Stateless;
@Stateless
public class Componenta{
public tip metoda(. . .){. . .}
. . .
}
Exemplul 13.1.1 Cel mai mare divizor comun a doua numere naturale.
Componentei EJB are codul
1
2
4
5
6
7
package cmmdc . e j b ;
import j a v a x . e j b . S t a t e l e s s ;
@Stateless
public c l a s s CmmdcBean{
public long cmmdc( long m, long n ) { . . . }
}
Aplicatia client va fi un servlet gazduit de acelasi server de aplicatie. Accesul la componenta EJB se poate programa:
prin injectare, utilizand adnotari;
prin JNDI.
In ambele cazuri serverul Web este responsabil de instantierea componentei
EJB.
314
Injectare cu adnotare
Serverul de aplicatie injecteaza n servlet o instanta a componentei EJB
sau altfel explicat
@EJB
Tip var;
@EJB(name="xyz")
Tip var;
injecteaza (realizeaza o referinta) pentru var catre un obiect de tipul Tip specificat. Actiunea este declansata de adnotarea EJB.
Codul servlet-ului este
1
2
3
4
5
6
7
8
9
10
12
13
14
15
17
18
19
20
21
22
S t r i n g t i t l e =Cmmdc S e r v l e t ;
r e s . setContentType ( t e x t / html ) ;
out . p r i n t l n ( <HTML><HEAD><TITLE> ) ;
out . p r i n t l n ( t i t l e ) ;
out . p r i n t l n ( </TITLE></HEAD><BODY> ) ;
out . p r i n t l n ( <H1>+ t i t l e +</H1> ) ;
out . p r i n t l n ( <P>Cmmdc : +x ) ;
out . p r i n t l n ( </BODY></HTML> ) ;
24
25
26
27
28
29
30
31
out . c l o s e ( ) ;
33
34
36
37
38
39
40
Desfasurarea aplicatiei
ejbcmmdc
|--> WEB-INF
|
|--> classes
|
|
|--> cmmdc
315
|
|
|
|
|
|
|
|-->
|
|
|
|
|
|-->
|
|
|
index.html
ejb
|
CmmdcBean.class
web
|
CmmdcServlet.class
316
30
31
33
34
35
36
13.1.2
Component
a cu metode asincrone
In cazul apelarii unei metode a unei componente EJB, clientul este blocat
pana la furnizarea rezultatului de catre serverul de aplicatie. Programand
metode asincrone, programul client va detine controlul imediat dupa apelare
sau altfel explicat apelarea nu mai este blocanta.
Definirea unei metode asincrone
Se ndeplinesc doua conditii:
1. Metoda asincrona este adnotata @Asynchronous (javax.ejb.Asynchronous);
2. Rezultatul metodei va fi de tip java.util.concurrent.Future<V>.
Exemplul 13.1.2
In cazul exemplului tratat anterior, codul componentei EJB sesiune stateless devine
1
2
3
4
5
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package cmmdc . e j b ;
import j a v a x . e j b . S t a t e l e s s ;
import j a v a x . e j b . Asynchronous ;
import j a v a x . e j b . A s y n c R e s u l t ;
import j a v a . u t i l . c o n c u r r e n t . Future ;
@Stateless
public c l a s s CmmdcBean{
@Asynchronous
public Future<Long> cmmdc( long m, long n ) {
long r , c ;
do{
c=n ;
r=m%n ;
m=n ;
n=r ;
} while ( r ! = 0 ) ;
Long r e s u l t=new Long ( c ) ;
return new AsyncResult<Long>( r e s u l t ) ;
}
}
317
13.1.3
Desfasurarea aplicatiei va fi
|-->
|
|
|
META-INF
|
application.xml
modul-ejb.jar
modul-Web.war
Instalarea aplicatie, adica a ansamblului alcatuit din cele 2 module se face prin
intermediul administratorului.
Fisierul application.xml precizeaza structura aplicatiei
318
package cmmdc . e j b ;
import j a v a x . e j b . Remote ;
@Remote
public i n t e r f a c e Cmmdc{
public long cmmdc( long m, long n ) ;
}
si
1
2
4
5
6
7
package cmmdc . e j b ;
import j a v a x . e j b . S t a t e l e s s ;
@Stateless
public c l a s s CmmdcBean implements Cmmdc{
public long cmmdc( long m, long n ) { . . . }
}
319
cmmdc-iiop
|--> cmmdc
|
|--> client
|
|
|
|
|--> ejb
|
|
|
CmmdcClient.class
Cmmdc.class
package cmmdc . c l i e n t ;
import j a v a x . e j b . EJB ;
import cmmdc . e j b . Cmmdc ;
import j a v a . u t i l . S c a n n e r ;
public c l a s s CmmdcClient {
@EJB
private s t a t i c Cmmdc cb ;
public s t a t i c void main ( S t r i n g [ ] a r g s ) throws E x c e p t i o n {
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= ) ;
long m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
long n=s c a n n e r . nextLong ( ) ;
long x=cb . cmmdc(m, n ) ;
System . out . p r i n t l n ( Cmmdc : +x ) ;
}
10
11
12
13
14
15
16
17
18
19
13.1.4
Component
a EJB sesiune singleton
320
1
2
4
5
6
7
8
9
10
package s i n g l e . e j b ;
import j a v a x . e j b . Remote ;
@Remote
public i n t e r f a c e S i n g l e {
public i n t g e t I n d e x ( ) ;
}
package s i n g l e . e j b ;
import j a v a x . e j b . S i n g l e t o n ;
@Singleton
public c l a s s S i n g l e B e a n implements S i n g l e {
private i n t i n d e x =0;
public i n t g e t I n d e x ( ) {
return ++i n d e x ;
}
}
package s i n g l e . web ;
import j a v a . i o . IOException ;
import j a v a . i o . P r i n t W r i t e r ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e q u e s t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e s p o n s e ;
import s i n g l e . e j b . S i n g l e ;
import j a v a x . e j b . EJB ;
import j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
@WebServlet ( u r l P a t t e r n s = / s i n g l e )
public c l a s s S i n g l e S e r v l e t extends H t t p S e r v l e t {
@EJB
S i n g l e sb ;
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 {
i n t x=sb . g e t I n d e x ( ) ;
P r i n t W r i t e r out=r e s . g e t W r i t e r ( ) ;
r e s . setContentType ( t e x t / html ) ;
S t r i n g t i t l e = S i n g l e S e r v l e t ;
out . p r i n t l n ( <HTML><HEAD><TITLE> ) ;
out . p r i n t l n ( t i t l e ) ;
out . p r i n t l n ( </TITLE></HEAD><BODY> ) ;
out . p r i n t l n ( <H1>+ t i t l e +</H1> ) ;
out . p r i n t l n ( <p>V a l o a r e a i n d e x : +x ) ;
out . p r i n t l n ( </BODY></HTML> ) ;
out . c l o s e ( ) ;
}
17
18
19
20
21
22
23
24
25
26
27
28
29
30
32
33
34
35
36
321
<html>
<body bgcolor=#c c b b c c >
<center>
<h1> EJB S i n g l e S e r v l e t </h1>
<form method= g e t
action= s i n g l e >
<p><input type= submit value= A p e l e a z a >
</form>
</ center>
</body>
</html
package s i n g l e . c l i e n t ;
import j a v a x . e j b . EJB ;
import s i n g l e . e j b . S i n g l e ;
import j a v a . u t i l . S c a n n e r ;
public c l a s s S i n g l e C l i e n t {
@EJB
private s t a t i c S i n g l e nb ;
public s t a t i c void main ( S t r i n g [ ] a r g s ) throws E x c e p t i o n {
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 ) ;
S t r i n g ch=Y ;
i n t i n d e x =0;
10
11
12
13
while ( ch . e q u a l s ( Y ) ) {
i n d e x=nb . g e t I n d e x ( ) ;
System . out . p r i n t l n ( Numarul de a p e l a r i : +i n d e x ) ;
System . out . p r i n t l n ( C o n t i n u a t i ? (Y/N) ) ;
do{
ch=s c a n n e r . n e x t ( ) . t r i m ( ) . toUpperCase ( ) ;
}
while ( ( ! ch . s t a r t s W i t h ( Y ))&&(! ch . s t a r t s W i t h ( N ) ) ) ;
}
15
16
17
18
19
20
21
22
23
24
25
13.1.5
Component
a EJB sesiune stateful
322
1
2
4
5
6
7
8
package numara . e j b ;
import j a v a x . e j b . Remote ;
@Remote
public i n t e r f a c e Numara{
public i n t g e t I n d e x ( ) ;
public void remove ( ) ;
}
si implementarea
1
2
3
5
6
7
8
9
10
package numara . e j b ;
import j a v a x . e j b . S t a t e f u l ;
import j a v a x . e j b . Remove ;
@Stateful
public c l a s s NumaraBean implements Numara{
private i n t i n d e x =0;
public i n t g e t I n d e x ( ) {
return ++i n d e x ;
}
@Remove
public void remove ( ) {}
12
13
14
S t r i n g t i t l e =Numara S e r v l e t ;
out . p r i n t l n ( <HTML><HEAD><TITLE> ) ;
out . p r i n t l n ( t i t l e ) ;
out . p r i n t l n ( </TITLE></HEAD><BODY> ) ;
out . p r i n t l n ( <H1>+ t i t l e +</H1> ) ;
switch ( o p e r ) {
case i n d e x :
i n t x=nb . g e t I n d e x ( ) ;
out . p r i n t l n ( <p>V a l o a r e a i n d e x : +x ) ;
break ;
case e x i t :
out . p r i n t l n ( <p>OK: Pe r a s p u n d e r e a dv o a s t r a ) ;
nb . remove ( ) ;
break ;
}
out . p r i n t l n ( </BODY></HTML> ) ;
out . c l o s e ( ) ;
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
39
40
41
42
43
apelat din
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
<html>
<body bgcolor=#c c b b c c >
<center>
<h1> EJB Numară S e r v l e t </h1>
<form method= g e t
action=numara>
<table>
<tr>
<td>S e l e c t a ţ i o p e r a ţ i a</td>
<td>
<s e l e c t name= o p e r >
<option value= i n d e x > Numă r de a p e l ă r i
<option value= e x i t > S t e r g e componenta EJB
</ s e l e c t>
</td>
</ tr>
<tr>
<td> <input type= submit value= A p e l e a z a ></td>
<td/>
</ tr>
</ table>
</form>
</ center>
</body>
</html>
package numara . c l i e n t ;
import j a v a x . e j b . EJB ;
import numara . e j b . Numara ;
323
324
import j a v a . u t i l . S c a n n e r ;
public c l a s s NumaraClient {
@EJB
private s t a t i c Numara nb ;
7
8
10
11
12
13
while ( ch . e q u a l s ( Y ) ) {
System . out . p r i n t l n ( O p e r a t i i : 1 . Numara 2 . S t e r g e componenta EJB ) ;
System . out . p r i n t l n ( O p e r a t i a : ) ;
op=s c a n n e r . n e x t I n t ( ) ;
switch ( op ) {
case 1 :
i n d e x=nb . g e t I n d e x ( ) ;
msg=Numarul de a p e l a r i : +(new I n t e g e r ( i n d e x ) ) . t o S t r i n g ( ) ;
break ;
case 2 :
nb . remove ( ) ;
msg=Sa s t e r s componenta EJB ;
break ;
default :
msg=Cod o p e r a t i e e r o n a t ;
break ;
}
System . out . p r i n t l n ( msg ) ;
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
13.2
Component
a EJB MessageDriven
EJB MESSAGEDRIVEN
13.2. COMPONENTA
325
Din
1. Destination Resources
myQueue
JNDI Name :
myQueue
Physical Destination Name :
javax.jms.Queue
myTopic
JNDI Name :
myTopic
Physical Destination Name :
javax.jms.Topic
2. Connection Factories
myQueueConnectionFactory
JNDI Name :
myQueueConnectionFactory
Resource Type : javax.jms.QueueConnectionFactory
myTopicConnectionFactory
JNDI Name :
myTopicConnectionFactory
Resource Type : javax.jms.TopicConnectionFactory
Exemplul 13.2.1 O aplicatie client trimite un numar de mesaje catre o componenta MDB.
Codul componentei EJB
1
2
3
4
5
6
8
9
10
11
13
14
15
16
17
package mdb ;
import j a v a x . e j b . MessageDriven ;
import j a v a x . jms . Message ;
import j a v a x . jms . TextMessage ;
import j a v a x . jms . M e s s a g e L i s t e n e r ;
import j a v a . u t i l . l o g g i n g . Logger ;
@MessageDriven ( mappedName=myQueue )
public c l a s s MessageBean implements M e s s a g e L i s t e n e r {
private s t a t i c f i n a l Logger l o g g e r =
Logger . g e t L o g g e r ( MessageBean . c l a s s . getName ( ) ) ;
public void onMessage ( Message msg ) {
TextMessage txtMsg = n u l l ;
try {
i f ( msg instanceof TextMessage ) {
txtMsg = ( TextMessage ) msg ;
326
18
19
}
}
catch ( Throwable th ) {
th . p r i n t S t a c k T r a c e ( ) ;
}
20
21
22
23
24
25
26
package mdb ;
import j a v a x . jms . QueueConnectionFactory ;
import j a v a x . jms . D e s t i n a t i o n ;
import j a v a x . a n n o t a t i o n . R e s o u r c e ;
import j a v a x . jms . JMSContext ;
import j a v a x . jms . JMSProducer ;
public c l a s s
MessageClient {
@Resource ( l o o k u p= myQueueConnectionFactory )
private s t a t i c QueueConnectionFactory c f ;
@Resource ( l o o k u p=myQueue )
private s t a t i c D e s t i n a t i o n q ;
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
try {
JMSContext c t x=c f . c r e a t e C o n t e x t ( ) ;
JMSProducer p r o d u c e r=c t x . c r e a t e P r o d u c e r ( ) ;
f o r ( i n t i =0; i <5; i ++){
p r o d u c e r . send ( q , H e l l o +i ) ;
}
p r o d u c e r . send ( q , c t x . c r e a t e M e s s a g e ( ) ) ;
ctx . c l o s e ( ) ;
}
catch ( E x c e p t i o n e ) {
e . printStackTrace ( ) ;
}
}
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
si prin JNDI
1
2
3
4
5
6
package mdb ;
import j a v a x . jms . QueueConnectionFactory ;
import j a v a x . jms . D e s t i n a t i o n ;
import j a v a x . naming . Context ;
import j a v a x . naming . I n i t i a l C o n t e x t ;
import j a v a x . jms . JMSContext ;
EJB ENTITY
13.3. COMPONENTA
public c l a s s
MessageClient {
private s t a t i c QueueConnectionFactory c f ;
private s t a t i c D e s t i n a t i o n q ;
10
11
13
14
15
16
17
18
19
20
21
22
23
try {
JMSContext jmsCtx=c f . c r e a t e C o n t e x t ( ) ;
JMSProducer p r o d u c e r=jmsCtx . c r e a t e P r o d u c e r ( ) ;
f o r ( i n t i =0; i <5; i ++){
p r o d u c e r . send ( q , H e l l o +i ) ;
}
p r o d u c e r . send ( q , jmsCtx . c r e a t e M e s s a g e ( ) ) ;
jmsCtx . c l o s e ( ) ;
}
catch ( E x c e p t i o n e ) {
e . printStackTrace ( ) ;
}
25
26
27
28
29
30
31
32
33
34
35
36
37
38
327
13.3
Component
a EJB Entity
Din
328
2. JDBC Resources
leg
atura dintre numele JNDI asociat bazei de date cu cuva de conexiuni creat
a anterior.
Creare JDBC Connection Pool
1. Pool Name adresePool un nume simbolic atasat cuvei
2. Resource Type Se selecteaza java.sql.Driver
3. Database Driver Vendor Se selecteaz
a Derby
4. Introspect Se bifeaz
a Enabled
5. Next
6. Driver Classname Se selecteaz
a org.apache.derby.jdbc.ClientDriver
7. Additional Properties Se bifeaz
a URL si se completeaz
a coloana Value cu
jdbc:derby:\. . . calea c
atre locatia bazei de date. . .\AgendaEMail
8. Finish
Creare JDBC Resources
1. JNDI Name jdbc/Adrese, un nume simbolic atasat resursei
2. Pool Name Se selecteaz
a adresePool, numele cuvei de conexiuni
3. OK
Aplicatie cu component
a Entity
O componenta Entity va fi adnotata @Entity si corespunde unui tabel al
bazei de date relationale.
Exemplul 13.3.1 Aplicatie de consultarea a bazei de date AgendaEMail.
Desfasurarea aplicatiei este
agendae-ear
|--> META-INF
|
|
persistence.xml
|
agenda-ejb.jar
EJB ENTITY
13.3. COMPONENTA
329
package e n t i t y ;
import j a v a . i o . S e r i a l i z a b l e ;
import j a v a x . p e r s i s t e n c e . E n t i t y ;
import j a v a x . p e r s i s t e n c e . I d ;
import j a v a x . p e r s i s t e n c e . GeneratedValue ;
import j a v a x . p e r s i s t e n c e . GenerationType ;
import j a v a . i o . S e r i a l i z a b l e ;
@Entity
public c l a s s Adrese implements S e r i a l i z a b l e {
@Id
@GeneratedValue ( s t r a t e g y=GenerationType . IDENTITY)
private i n t i d ;
private S t r i n g nume ;
private S t r i n g e m a i l ;
public S t r i n g getNume ( ) {
return nume ;
}
public void setNume ( S t r i n g nume ) {
t h i s . nume = nume ;
}
public S t r i n g g e t E m a i l ( ) {
return e m a i l ;
}
public void s e t E m a i l ( S t r i n g e m a i l ) {
this . email = email ;
}
public i n t g e t I d ( ) {
return i d ;
}
public void s e t I d ( i n t i d ) {
this . id = id ;
}
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package e j b ;
import j a v a x . e j b . Remote ;
import e n t i t y . Adrese ;
import j a v a . u t i l . L i s t ;
@Remote
public i n t e r f a c e AgendaEMail {
public L i s t <Adrese> g e t E m a i l ( S t r i n g nume ) ;
public L i s t <Adrese> getNume ( S t r i n g e m a i l ) ;
}
package e j b ;
import j a v a x .
import j a v a x .
import j a v a x .
import j a v a x .
ejb . S t a t e l e s s ;
persistence . PersistenceContext ;
p e r s i s t e n c e . EntityManager ;
p e r s i s t e n c e . Query ;
330
6
7
9
10
11
12
import e n t i t y . Adrese ;
import j a v a . u t i l . L i s t ;
@Stateless
public c l a s s AgendaEMailBean implements AgendaEMail {
@ P e r s i s t e n c e C o n t e x t ( unitName= a g e n d a e p e r s i s t e n c e c t x )
EntityManager em ;
public L i s t <Adrese> g e t E m a i l ( S t r i n g nume ) {
S t r i n g nm= \ +nume+ \ ;
S t r i n g s q l=SELECT e n t i t y FROM Adrese e n t i t y WHERE e n t i t y . nume=+nm ;
System . out . p r i n t l n ( s q l ) ;
Query query=em . c r e a t e Q u e r y ( s q l ) ;
L i s t <Adrese> l i s t =( L i s t <Adrese >) query . g e t R e s u l t L i s t ( ) ;
return l i s t ;
}
14
15
16
17
18
19
20
21
23
24
25
26
27
28
29
30
31
EJB ENTITY
13.3. COMPONENTA
agendae-client
|--> ejb
|
|
AgendaEMail.class
|--> entity
|
|
Adrese.class
|--> META-INF
|
|
MANIFEST.MF
|
Client.class
import
import
import
import
import
import
import
e j b . AgendaEMail ;
j a v a x . e j b . EJB ;
java . u t i l . List ;
java . u t i l . I t e r a t o r ;
java . u t i l . Scanner ;
j a v a . u t i l . InputMismatchException ;
e n t i t y . Adrese ;
public c l a s s C l i e n t {
@EJB
private s t a t i c AgendaEMail bean ;
private s t a t i c L i s t <Adrese> l i s t =n u l l ;
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
i n t p r e l , no ;
S t r i n g ch=Y , nume= , e m a i l= ;
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 ) ;
I t e r a t o r <Adrese> i t e r=n u l l ;
Adrese i n r e g=n u l l ;
try {
while ( ch . s t a r t s W i t h ( Y ) ) {
do{
System . out . p r i n t l n ( Continue ? (Y/N) ) ;
ch=s c a n n e r . n e x t ( ) . toUpperCase ( ) ;
}
while ( ( ! ch . s t a r t s W i t h ( Y ))&&(! ch . s t a r t s W i t h ( N ) ) ) ;
i f ( ch . s t a r t s W i t h ( Y ) ) {
System . out . p r i n t l n ( Natura i n t e r o g a r i i ? ) ;
System . out . p r i n t l n ( ( Dupa nume : 1 , Dupa e m a i l : 2 ) ) ;
do{
p r e l =0;
try {
p r e l=s c a n n e r . n e x t I n t ( ) ;
}
catch ( InputMismatchException e ) { }
}
while ( ( p r e l <1)&&( p r e l > 2 ) ) ;
switch ( p r e l ) {
case 1 :
System . out . p r i n t l n ( Numele ) ;
nume=s c a n n e r . n e x t ( ) . t r i m ( ) ;
l i s t =bean . g e t E m a i l ( nume ) ;
i t e r= l i s t . i t e r a t o r ( ) ;
331
332
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
}
}
catch ( E x c e p t i o n e ) {
e . printStackTrace ( ) ;
}
65
66
67
68
69
70
71
Intreb
ari recapitulative
1. Care sunt tipurile de componente EJB studiate?
2. Care sunt posibilitatile de apelare / utilizare al unei componente EJB?
3. Care este tehnologia de comunicatie utilizata pentru apelerea unei componente EJB de un client program?
4. Cum se apeleaza un client - program al unei componente EJB?
5. Care sunt tiputile de componente sesiune EJB din JEE?
Capitolul 14
Aplicatie pe nivele
Ne propunem sa aratam locul unde instrumentele de programare dezvoltate
n cadrul cursului apar n activitatea uzuala de programare pentru o ntreprindere
economica.
Pe langa faptul ca trebuie sa asigure o functionalitate specifica, definirea /
implementarea unui nivel presupune alegerea unei tehnologii informatice sau
a unui produs informatic.
Una din aplicatiile uzuale este ntretinerea unei baze de date. Consideram
cazul unei baze de date gestionata de un sistem de gestiune a bazelor de date
(SGBD) relational. Problema ntretinerii consta n asigurarea urmatoarelor
operatii (denumite generic CRUD):
adaugarea unei nregistrari noi (Create);
consultarea bazei de date, extragerea de date (Read);
modificarea unei nregistrari (Update);
stergerea unei nregistrari (Delete).
In cele ce urmeaza luam n considerare platforma Java.
Punem n evidenta nivele (tiers) (se mai utilizeaza si terminologia staturi
- layers) ca obiective ale unei metode pentru rezolvarea problemei enuntata
anterior.
333
334
14.1
1
2
3
4
5
6
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
335
<?xml v e r s i o n= 1 . 0 e n c o d i n g=UTF8?>
< p e r s i s t e n c e v e r s i o n= 2 . 1
xmlns= h t t p : / / xmlns . j c p . o r g /xml/ ns / p e r s i s t e n c e
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 : / / xmlns . j c p . o r g /xml/ ns / p e r s i s t e n c e
h t t p : / / xmlns . j c p . o r g /xml/ ns / p e r s i s t e n c e / p e r s i s t e n c e 2 1 . xsd >
<p e r s i s t e n c e u n i t name= n u m e l e u n i t a t i i d e p e r s i s t e n t a
t r a n s a c t i o n t y p e=RESOURCE LOCAL>
<c l a s s >c l a s a e n t i t y a t a b e l u l u i </c l a s s >
<p r o p e r t i e s >
<p r o p e r t y name= j a v a x . p e r s i s t e n c e . j d b c . d r i v e r
v a l u e= d r i v e r u l b a z e i d e d a t e />
<p r o p e r t y name= j a v a x . p e r s i s t e n c e . j d b c . u r l
v a l u e= a d r e s a u r l a b a z e i d e d a t e />
<p r o p e r t y name= j a v a x . p e r s i s t e n c e . j d b c . u s e r
v a l u e= user name />
<p r o p e r t y name= j a v a x . p e r s i s t e n c e . j d b c . password
v a l u e= password />
</ p r o p e r t i e s >
</ p e r s i s t e n c e u n i t >
</ p e r s i s t e n c e >
<?xml v e r s i o n= 1 . 0 e n c o d i n g=UTF8?>
< p e r s i s t e n c e v e r s i o n= 2 . 1
xmlns= h t t p : / / xmlns . j c p . o r g /xml/ ns / p e r s i s t e n c e
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 : / / xmlns . j c p . o r g /xml/ ns / p e r s i s t e n c e
h t t p : / / xmlns . j c p . o r g /xml/ ns / p e r s i s t e n c e / p e r s i s t e n c e 2 1 . xsd >
<p e r s i s t e n c e u n i t name= n u m e l e u n i t a t i i d e p e r s i s t e n t a >
<p r o v i d e r >
org . e c l i p s e . p e r s i s t e n c e . jpa . P e r s i s t e n c e P r o v i d e r
</ p r o v i d e r >
<j t a datas o u r c e >n u m e l e j n d i a l b a z e i d e d a t e </ j t a datas o u r c e >
<p r o p e r t i e s >
<p r o p e r t y name= e c l i p s e . j d b c . d r i v e r
v a l u e= d r i v e r u l b a z e i d e d a t e />
</ p r o p e r t i e s >
</ p e r s i s t e n c e u n i t >
</ p e r s i s t e n c e >
336
Nivelul prelucr
arii unui tabel al bazei de date
Modelul prezentat n acest nivel este Data Access Object (DAO). O varianta
de programare a acestui nivel consta din:
O interfata cu operatiile asupra datelor din tabel;
Implementarea interfetei;
O clasa care mijloceste apelarea operatiile interfetei aparand ca un serviciu. Rolul acestei clase este simplificarea aplicatiei client.
Aceasta arhitectura permite utilizarea ei pentru diferite tipuri de client sau
moduri de acces la SGBD. Functie de modul de acces la SGBD utilizat sau de
tipul de client detaliile de programare pot diferi.
337
Exemple
inerea bazei de date Agenda de adrese email.
Exemplul 14.1.1 Intret
Nivelul SGBD : *
Nivelul de acces la SGBD : nemijlocit
Nivelul aplicatiei client : desktop, servlet, rest (jersey), websocket
Nivelul autentificare si autorizare : desktop, servlet, rest (jersey,
inclusiv client jersey)
338
Probleme
1. glassfish cu Mysql
2. glassfish cu client websocket (cu injectii)
3. openjpa cu client servlet, restful, websocket
4. empire sau alt produs ORM
Partea III
ANEXE
339
Anexa A
Unelte de dezvoltare
Incepem aceasta sectiune prin a introduce cateva elemente privind sintaxa
unui document xml.
A.1
XML
342
A.1. XML
20
21
22
23
24
25
26
27
343
344
A.2
apache-ant
A.2. APACHE-ANT
345
Asem
an
ator cu maven, un alt produs de dezvoltare.
346
A.3
apache-maven
A.3. APACHE-MAVEN
347
publice de resurse soft necesare dezvoltarii de aplicatii cu maven 3 iar dezvoltatorii de instrumente soft au posibilitatea de a-si promova produsele prin
depunerea ntr-un depozit maven. Dintr-un asemenea depozit public resursele
necesare sunt descarcate n depozitul local.
De exemplu repo1.maven.org/maven2.
348
Comanda maven
mvn -version
Semnificatia
afiseaza versiunea maven
(utila pentru verificarea functionarii lui maven)
mvn clean
sterge fisierele maven generate
mvn compile
compilarea sursele Java
mvn test-compile compileaza sursele Java care
realizeaza testele junit
mvn test
executa testul junit
mvn package
creaza o arhiva jar sau war
mvn install
depune arhiva jar sau war n depozitul local
A.3. APACHE-MAVEN
Comanda maven
mvn -B archetype:generate
349
Semnificatia
genereaza structura de cataloage a
proiectului. Optiunea -B are ca efect
generarea neinteractiva.
mvn -B archetype:generate \
-DgroupId=numelePachetuluiAplicatiei \
-DartifactId=numeleProiectului \
-DarchetypeArtifactId=numeS
ablon\
-Dversion=versiuneaProiectului
mvn archetype:generate
mvn clean:clean
mvn
mvn
mvn
mvn
compiler:compile
surefire:test
jar:jar
install:install-file
mvn exec:java
mvn dependency:copy-dependencies
Astfel comanda
set GroupID=simple.app.helloworld
set ArtifactID=helloworld
set Version=1.0
mvn -B archetype:generate -DgroupId=%GroupID%
-DartifactId=%ArtifactID%
-Dversion=%Version%
-DarchetypeArtifactId=maven-archetype-quickstart
-DinteractiveMode=false
genereaza arborescenta
clasaMetodeiMain
-Dexec.args=lista argumente
descarca n catalogul target resursele
declarate n dependencies.
350
hello
|--> src
|
|--> main
|
|
|-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|--> test
|
|
|-->
|
|
|
|
|
|
|
|
|
|
|
|
|
pom.xml
java
|-->
|
|
|
unitbv
|--> cs
|
|--> calcul
|
|
| App.java
java
|-->
|
|
|
unitbv
|--> cs
|
|--> calcul
|
|
| AppTest.java
App.java este programul Java HelloWorld iar AppTest.java este un program de verificare bazat pe junit.
Pentru testarea aplicatiei, din catalogul hello se executa comenzile
mvn compile
mvn exec:java -Dexec.mainClass="simple.app.helloworld.App"
mvn test
A.3. APACHE-MAVEN
351
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<mainClass>${target.main.class}</mainClass>
<includePluginDependencies>false</includePluginDependencies>
</configuration>
</plugin>
</plugins>
</build>
Aceasta varianta este avantajoasa n cazul n care proiectul include mai multe
clase cu metoda main.
Sarcina programatorul este acela de a nlocui aceste programe cu cele care
rezolva sarcinile proiectului. Pentru orice prelucrare toate dependintele trebuie
sa se gaseasca n depozitul local maven. Daca o dependinta (resursa jar)
nu se gaseste n depozitul local atunci resursa este cautata ntr-un depozit
global si este descarcata n depozitul global. Este sarcina programatorului sa
declare toate dependintele necesare unei aplicatii. Declararea se face ntr-un
element <dependency>. Daca resursa este inaccesibila atunci maven termina
prelucrarea.
Programatorul are posibilitatea sa specifice depozite globale unde sa se
gaseasca resursele necesare, de exemplu
<repositories>
<repository>
<id>java.net-promoted</id>
<url>https://maven.java.net/content/groups/promoted/</url>
</repository>
</repositories>
352
1.
1
2
4
5
6
7
8
9
10
11
12
14
15
2.
1
2
3
4
5
7
9
9
10
11
12
@Test
public void testCmmdc1 ( ) {
r e z=o b j . cmmdcService . cmmdc ( 5 6 , 4 2 ) ;
a s s e r t E q u a l s (14 l , rez ) ;
}
14
15
16
17
18
20
21
22
23
A.3. APACHE-MAVEN
353
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
2. Intrucat dorim sa folosim cea mai recenta versiune a produsului junit
modificam numarul versiunii.
Fisierul pom.xml devine
1
2
3
4
5
7
8
9
10
12
13
15
16
17
19
20
21
22
23
24
25
26
28
29
30
31
32
354
33
34
35
36
37
38
39
40
41
<c o n f i g u r a t i o n>
< ! or w h a t e v e r version you u s e >
<s o u r c e>1 . 8</ s o u r c e>
<t a r g e t>1 . 8</ t a r g e t>
</ c o n f i g u r a t i o n>
</ p l u g i n>
</ p l u g i n s>
</ b u i l d>
</ p r o j e c t>
maven cu ant
In maven se pot integra sarcini apache-ant pentru orice etapa al evolutiei
unei aplicatii. Utilizarea consta n completarea fisierului pom.xml cu
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>
<!-- etapa de viata : compile, package, install, test -->
</phase>
<configuration>
<tasks>
<!-- Exemplu
<property name="compile_classpath" refid="maven.compile.classpath"/>
<property name="runtime_classpath" refid="maven.runtime.classpath"/>
<property name="test_classpath" refid="maven.test.classpath"/>
<property name="plugin_classpath" refid="maven.plugin.classpath"/>
<echo message="compile classpath:
<echo message="runtime classpath:
<echo message="test classpath:
<echo message="plugin classpath:
-->
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
${compile_classpath}"/>
${runtime_classpath}"/>
${test_classpath}"/>
${plugin_classpath}"/>
A.3. APACHE-MAVEN
355
resources
webapp
|--> WEB-INF
|
|
web.xml
|
index.jsp
356
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2. Completarea aplicatiei.
Se completeaza structura creata anterior cu
helloname
|--> src
|
|--> main
|
|
|-->
|
|
|
|
|
|
|
|
|-->
|
|
|-->
|
|
|
|
|
|
|
|
|
|
pom.xml
java
|--> hello
|
|
HelloServlet.java
resources
webapp
|--> WEB-INF
|
|
web.xml
|
index.html
A.3. APACHE-MAVEN
357
358
32
33
34
35
36
Clauza provided din elementul <scope> implica neincluderea resursei n arhiva war.
3. Prelucrarea revine la
(a) mvn clean package
(b) lansarea serverului Web jetty: mvn jetty:run
Serverul se opreste cu Ctrl+C.
(c) testarea servlet-ului: ntr-un navigator se deschide pagina
http://localhost:8080/index.html.
2. Se completeaza aplicatia cu fisierele CmmdcBean.java, cmmdc.jsp si index.html din cursul Programare distribuita, desfasurarea fiind
cmmdcjsp
|--> src
|
|--> main
|
|
|-->
|
|
|
|
|
|-->
|
|
|-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pom.xml
java
|
CmmdcBean.java
resources
webapp
|--> jsp
|
|
cmmdc.jsp
|--> WEB-INF
|
|
web.xml
index.html
359
A.4
360
In cataloagele java sunt prezente fisierele Library.java si respectiv LibraryTest.java. Testarea este bazata pe junit. Dezvoltarea se face nlocuind aceste
fisiere cu cele ale aplicatiei.
Intr-un proict, optional pot fi prezente fisierele gradle.properties si
gradle.settings.
Fisierul build.gradle precizeaza prelucrarile solicitate. Compilarea se
obtine cu
1
apply pl ugin :
java
apply pl ugin :
apply pl ugin :
java
application
iar lansarea va fi
1
g r a d l e c l e a n a s s e m b l e run
include
In acest caz se vor executa sarcinile cerute pentru fiecare din proiectele Gradle
specificate (clean, assemble).
361
Sarcina
clean
compileJava
compileTest
assemble
run
test
Actiune
Sterge catalogul build
Compilare
Compilare claselor test
Compilare si arhivare
Executa aplicatia
Executa testele
Table A.1: Sarcini Gradle
ant.importBuild build.xml
prin
gradle obiectiv_Ant_din_build.xml
Detalii de configurare
Introducerea de date se poate face doar prin intermediul unei interfete
grafice.
Comentariile n build.gradle se indica prin
// linie de comentariu
(* text comentariu *)
Preluarea argumentelor din linia de comand
a se indica n build.gradle
prin
1. Varianta 1
2
apply pl ugin :
apply pl ugin :
run {
a r g s System . g e t P r o p e r t y ( e x e c . a r g s ) . s p l i t ( )
}
7
8
java
application
cu
1
2. Varianta 2
362
apply pl ugin :
apply pl ugin :
run {
i f ( p r o j e c t . hasProperty ( args )){
a r g s p r o j e c t . a r g s . s p l i t ( \\ s )
}
}
7
8
9
10
java
application
cu
1
Propriet
atile de sistem se declara n fisierul build.gradle
run {
classpath = sourceSets.main.runtimeClasspath
//classpath.each { println it }
/* Can pass all the properties: */
//systemProperties System.getProperties()
/* Or just each by name: */
systemProperty "java.rmi.server.codebase", System.getProperty("java.rmi.server.codebase")
}
363
urmat de comanda
gradle clean assemble jettyRunWar
364
Servlet 3.0
Structura aplicatiei
Catalogul_aplicatiei
|--> lib
|
|
servlet-api.jar
|--> src
|
|--> main
|
|
|--> java
|
|
|--> webapp
|
|
|
|--> WEB-INF
|
|
|
|
|--> lib
(optional)
|
|
|
|
index.html
|
build.gradle
Fisierul build.gradle se completeaza cu
apply plugin: java
apply plugin: war
repositories{
flatDir{
dirs lib,src/main/webapp/WEB-INF/lib
}
}
dependencies{
providedCompile javax.servlet:servlet-api:3.0
}
Prelucrarea este
gradle.bat clean assemble
Arhiva war din catalogul build\libs se va desfasura ntr-un server Web compatibil.
Anexa B
Fir de executie prin -expresie
Java introduce firele de executie prin interfetele
java.lang.Runnable
Interfata declara metoda public void run().
Clasa java.lang.Thread implementeaza interfata Runnable.
java.util.concurrent.Callable<V>
Interfata declara metoda public V call().
Sablon pentru definirea unui fir de executie de tip Thread printr-o lambda
expresie
interface MyThread{
Thread service(semnatura datelor de intrare);
}
static MyThread action=(semnatura datelor de intrare)->{
return new Thread(()->{
codul metodei run
});
};
Exemplul B.0.1
interface MyThread{
Thread scrie(String txt);
}
static MyThread f=(String txt)->{
365
366
367
}
static MyCallable f=(int index)->{
Callable<Integer> c=()->{
System.out.println("I am "+index);
return index;
};
return c;
};
368
Anexa C
Testare cu junit
Verificarea / testarea automata a programelor Java se poate face cu produsul informatic junit. Deseori se formuleaza probleme de test ale caror rezultate sunt cunoscute, cu rolul de a verifica functionarea unui program de rezolvare, pentru depistarea unor greseli.
S-a dezvoltat si o metodologie de lucru Test Driven Development - (TDD)
care presupune pentru orice clasa elaborata realizarea unui program de testare,
chiar a priori.
Un alt produs care are acelasi scop de verificare a rezultatelor este TestNG.
junit permite verificarea automata a rezultatelor furnizate de un program,
pentru o multime de date de test.
Instalarea produsului consta din dezarhivarea fisierului descarcat ntr-un
catalog JUNIT HOME. Pentru compilare si executie, variabila de sistem classpath
trebuie sa contina referinta JUNIT HOME\junit-*.jar.
Utilizarea produsului ntr-un program Java consta din:
1. Declararea resurselor pachetului junit prin
import org.junit.*;
import static org.junit.Assert.*;
2. Declararea clasei cu testele junit - uzual n metoda main.
org.junit.runner.JUnitCore.main("AppClass");
3. Eventuale operatii necesare nainte sau dupa efectuarea testelor se precizeaza respectiv, n cate o metoda care a fost declarata cu adnotarea
@org.junit.Before si respectiv, @org.junit.After.
4. Testele se definesc n metode declarate cu adnotarea @org.junit.Test.
Clasa Assert poseda metodele de verificare ale unui rezultat:
369
370
import o r g . j u n i t . ;
import s t a t i c o r g . j u n i t . A s s e r t . ;
public c l a s s Exemplu{
public double r e z u l t a t = 1 . 0 ;
public double e p s=1e 6;
double g e t V a l u e ( ) {
return 1 . 0 0 0 0 0 0 1 ;
}
8
9
10
@Test
public void t e s t ( ) {
a s s e r t E q u a l s ( r e z u l t a t , getValue ( ) , eps ) ;
}
12
13
14
15
17
18
19
20
se obtine
JUnit version 4.5
.
Time: 0.03
OK (1 test)
371
1
2
3
5
6
package s e r v e r ;
import o r g . j u n i t . ;
import s t a t i c o r g . j u n i t . A s s e r t . ;
public c l a s s TestApp {
private App app ;
@Before
public void i n i t i a l i z a r e ( ) {
app=new App ( ) ;
}
8
9
10
11
@Test
public void t e s t ( ) {
a s s e r t E q u a l s ( 8 , app . cmmdc ( 5 6 , 2 4 ) ) ;
}
13
14
15
16
19
20
21
22
package s e r v e r . impl ;
import s e r v e r . impl . MyMServer ;
import o r g . j u n i t . B e f o r e ;
import o r g . j u n i t . Test ;
import s t a t i c o r g . j u n i t . A s s e r t . ;
import j a v a . n e t . S e r v e r S o c k e t ;
import i s e r v e r . IMyMServer ;
import j a v a . n e t . S o c k e t ;
import j a v a . i o . DataInputStream ;
import j a v a . i o . DataOutputStream ;
372
12
13
14
15
16
17
public c l a s s TestMyMServer {
private IMyMServer o b j ;
private s t a t i c i n t p o r t =7999;
public s t a t i c f i n a l long M=12;
public s t a t i c f i n a l long N=15;
public s t a t i c f i n a l long RESULT=3;
@Before
public void i n i t i a l i z a r e ( ) {
o b j=new MyMServer ( ) ;
}
19
20
21
22
@Test
public void t e s t ( ) {
i n t p o r t =8999;
O b j e c t r e s u l t=o b j . g e t S e r v e r S o c k e t ( p o r t ) ;
a s s e r t N o t N u l l ( Must not r e t u r n a n u l l r e s p o n s e , r e s u l t ) ;
a s s e r t E q u a l s ( ServerSocket . class , r e s u l t . g e t C l a s s ( ) ) ;
}
24
25
26
27
28
29
30
@Test
public void t e s t M y A c t i o n ( ) {
long r =0;
S e r v e r S o c k e t s s=o b j . g e t S e r v e r S o c k e t ( p o r t ) ;
EmbeddedThread t h r e a d=new EmbeddedThread ( s s ) ;
thread . s t a r t ( ) ;
try ( S o c k e t cmmdcSocket = new S o c k e t ( l o c a l h o s t , p o r t ) ;
DataInputStream i n=new DataInputStream ( cmmdcSocket . g e t I n p u t S t r e a m ( ) ) ;
DataOutputStream out=
new DataOutputStream ( cmmdcSocket . getOutputStream ( ) ) ) {
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 ( ) ;
}
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 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 ( ) ) ;
}
a s s e r t E q u a l s ( r , RESULT ) ;
}
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
52
53
54
56
57
EmbeddedThread ( S e r v e r S o c k e t s s ) {
t h i s . s s=s s ;
}
59
60
61
63
64
65
66
67
Anexa D
Jurnalizare
Jurnalizarea adica afisarea / retinerea rezultatelor sau evenimentelor ntrun fisier. Deseori prezinta interes evolutia procesului de calcul prin prisma
unor rezultate intermediare. In acest sens se pot utiliza:
pachetul java.util.logging din jdk.
apache-log4j-2.
slf4j (Simple Logging Facade for Java), (www.QOS.ch, Quality of Open
Software).
logback (logback.qos.ch).
import j a v a . u t i l . l o g g i n g . Logger ;
public c l a s s Exemplu{
s t a t i c Logger l o g g e r = Logger . g e t L o g g e r ( Exemplu . c l a s s . getName ( ) ) ;
6
7
8
9
10
11
Programul afiseaza
Jan 23, 2013 2:34:40 PM Exemplu main
SEVERE: SEVERE : Hello
Jan 23, 2013 2:34:40 PM Exemplu main
373
374
ANEXA D. JURNALIZARE
import
import
import
import
u t i l . l o g g i n g . Logger ;
u t i l . logging . FileHandler ;
u t i l . l o g g i n g . SimpleFormatter ;
i o . IOException ;
public c l a s s Exemplu{
s t a t i c Logger l o g g e r = Logger . g e t L o g g e r ( Exemplu . c l a s s . getName ( ) ) ;
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
try {
F i l e H a n d l e r l o g g i n g F i l e = new F i l e H a n d l e r ( l o g g i n g . t x t ) ;
l o g g i n g F i l e . s e t F o r m a t t e r (new S i m p l e F o r m a t t e r ( ) ) ;
l o g g e r . addHandler ( l o g g i n g F i l e ) ;
}
catch ( IOException e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}
l o g g e r . s e v e r e ( SEVERE : H e l l o ) ;
l o g g e r . warning ( WARNING : H e l l o ) ;
l o g g e r . i n f o ( INFO : H e l l o ) ;
}
9
10
11
12
13
14
15
16
17
18
19
20
21
22
java .
java .
java .
java .
package l o g t e s t ;
import o r g . s l f 4 j . Logger ;
import o r g . s l f 4 j . L o g g e r F a c t o r y ;
public c l a s s Exemplu{
s t a t i c Logger l o g g e r=L o g g e r F a c t o r y . g e t L o g g e r ( Exemplu ) ;
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
l o g g e r . t r a c e ( TRACE : H e l l o ) ;
l o g g e r . debug ( DEBUG : H e l l o ) ;
l o g g e r . i n f o ( INFO : H e l l o ) ;
l o g g e r . warn ( WARN : H e l l o ) ;
l o g g e r . e r r o r ( ERROR : H e l l o ) ;
}
}
cu fisierul de configurare
1
2
3
4
5
6
<c o n f i g u r a t i o n>
<appender name=STDOUT c l a s s= ch . q o s . l o g b a c k . c o r e . ConsoleAppender >
<e n c o d e r>
<p a t t e r n>
%d{HH:mm:ss . SSS} [% t h r e a d ] %5 l e v e l %l o g g e r {36} %msg%n
</ p a t t e r n>
375
</ e n c o d e r>
</ appender>
7
8
10
11
12
13
14
15
16
17
19
20
21
22
23
<r o o t l e v e l= t r a c e >
<appenderr e f r e f=STDOUT />
<appenderr e f r e f=FILE />
</ r o o t>
</ c o n f i g u r a t i o n>
7
8
9
10
11
12
13
cu fisierul de configurare
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
376
20
21
22
</ r o o t>
</ l o g g e r s>
</ c o n f i g u r a t i o n>
ANEXA D. JURNALIZARE
Anexa E
Component
a Java (Java Bean)
O componenta Java este o clasa care poate interactiona cu alte componente
Java, cu un document jsp, etc.
O componenta Java contine cel putin
Un constructor fara nici un argument;
O multime de campuri declarate private;
Pentru fiecare asemenea camp
private Tip xyz;
trebuie definite cel putin una din metodele
public void setXyz(Tip xyz){
this.xyz=xyz;
}
public Tip getXyz(){
return xyz;
}
377
378
JAVA
ANEXA E. COMPONENTA
Anexa F
Serializare f
ar
a XML
Scopul serializarii unor date are ca scop obtinerea unei reprezentari text n
vederea transmiterii prin retea. Orice solutie trebuie sa ofere si posibilitatea
refacerii datelor din forma serializata Serializarea se poate obtine prin
379
380
A
XML
ANEXA F. SERIALIZARE FAR
F.1
Marcaj YAML
Marcaj standard YAML
!!null
!!bool
!!int
!!float
!!binary
!!timestamp
!!omap, !!pairs
!!set
!!str
!!seq
!!map
Tip Java
null
Boolean
Integer, Long, BigInteger
Double
String
java.util.Date, java.sql.Date, java.sql.Timestamp
List of Object[ ]
Set
String
List
Map
public c l a s s D i s c i p l i n a {
private S t r i n g nume ;
Disciplina (){}
D i s c i p l i n a ( S t r i n g nume ) {
t h i s . nume=nume ;
}
public S t r i n g getNume ( ) {
return nume ;
}
public void setNume ( S t r i n g nume ) {
t h i s . nume=nume ;
}
5
6
7
8
9
10
11
12
13
14
Se instantiaza 3 obiecte care vor fi convertite n reprezentari YAML stringuri ce sunt retinute ntr-un obiect de tip java.util.Map. In final acest
obiect este reprezentat YAML, care este salvat ntr-un fisier.
1
2
3
4
5
7
8
import
import
import
import
import
j a v a . u t i l . Map ;
j a v a . u t i l . HashMap ;
o r g . yaml . snakeyaml . Yaml ;
o r g . yaml . snakeyaml . T y p e D e s c r i p t i o n ;
java . io . PrintWriter ;
public c l a s s G e n e r a r e {
// @SuppressWarnings ( unc hecked )
9
10
11
D i s c i p l i n a an=new D i s c i p l i n a ( A n a l i z a numerica ) ;
S t r i n g san=yaml . dump( an ) ;
data . put ( an , san ) ;
13
14
15
D i s c i p l i n a pd=new D i s c i p l i n a ( Programare d i s t r i b u i t a ) ;
S t r i n g spd=yaml . dump( pd ) ;
data . put ( pd , spd ) ;
17
18
19
D i s c i p l i n a sm=new D i s c i p l i n a ( S o f t matematic ) ;
S t r i n g ssm=yaml . dump( sm ) ;
data . put ( sm , ssm ) ;
21
22
23
System . out . p r i n t l n ( S e r i a l i z a r e a d a t e l o r ) ;
System . out . p r i n t l n ( C o n t i n u t u l o b t i n u t : \ n ) ;
try {
P r i n t W r i t e r pw=new P r i n t W r i t e r ( f i l e . yaml ) ;
S t r i n g objYAML=yaml . dump( data ) ;
System . out . p r i n t l n (objYAML ) ;
pw . w r i t e (objYAML ) ;
pw . f l u s h ( ) ;
}
catch ( E x c e p t i o n e ) {
e . printStackTrace ( ) ;
}
25
26
27
28
29
30
31
32
33
34
35
36
37
38
381
import
import
import
import
import
import
import
import
import
java . io . F i l e ;
java . io . FileInputStream ;
j a v a . i o . InputStream ;
j a v a . u t i l . Map ;
o r g . yaml . snakeyaml . Yaml ;
java . io . PrintWriter ;
o r g . yaml . snakeyaml . c o n s t r u c t o r . C o n s t r u c t o r ;
java . u t i l . Collection ;
java . u t i l . I t e r a t o r ;
public c l a s s U t i l i z a r e {
// @SuppressWarnings ( unc hecked )
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
C o n s t r u c t o r c o n s t r u c t o r=new C o n s t r u c t o r ( D i s c i p l i n a . c l a s s ) ;
try {
InputStream i n p u t = new F i l e I n p u t S t r e a m ( f i l e . yaml ) ;
Yaml yaml = new Yaml ( ) ;
O b j e c t data = yaml . l o a d ( i n p u t ) ;
System . out . p r i n t l n ( C o n t i n u t u l i n c a r c a t : \ n ) ;
System . out . p r i n t l n ( data . t o S t r i n g ( ) ) ;
Map<S t r i n g , S t r i n g > map = (Map) data ;
C o l l e c t i o n <S t r i n g > d i s c i p l i n e=map . v a l u e s ( ) ;
I t e r a t o r <S t r i n g > i t e r=d i s c i p l i n e . i t e r a t o r ( ) ;
382
A
XML
ANEXA F. SERIALIZARE FAR
26
27
28
29
30
31
32
33
34
}
catch ( E x c e p t i o n e ) {
e . printStackTrace ( ) ;
}
35
36
37
38
39
40
F.2
JSON ofera o modalitate simpla (mai simpla chiar decat XML) pentru
schimbul de date dintre un server si un client.
Pentru reprezentarea datelor n JSON se utilizeaza structurile de date:
colectie de atribute, adica perechi (nume, valoare). O colectie de atribute
este denumit obiect JSON.
sir de valori.
Aceste structuri de date sunt prezente n toate limbajele de programare de uz
general.
O colectie de atribute se reprezinta prin
{numeAtribut:valAtribut,numeAtribut:valAtribut,...}
Un sir de valori se reprezinta prin
[valoare,valoare,...]
valAtribut, valoare poate fi un string, numar, true, false, null, o colectie
sau un sir.
JSON n JavaScript
Utilizarea entitatilor JSON n javascript este exemplificat n aplicatia urmatoare.
Exemplul F.2.1
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
<HTML>
<HEAD>
<TITLE>Primul exemplu J a v a S c r i p t</TITLE>
<SCRIPT LANGUAGE= J a v a S c r i p t >
< !
var myJSONObj=[{ d i s c i p l i n a : A n a l i z a Numerica } ,
{ d i s c i p l i n a : Programare d i s t r i b u i t a } ,
{ d i s c i p l i n a : S o f t matematic } ] ;
f o r ( var i =0; i<myJSONObj . l e n g t h ; i ++){
document . w r i t e l n ( <br> ) ;
document . w r i t e l n (myJSONObj [ i ] . d i s c i p l i n a ) ;
}
document . w r i t e l n ( <br> ) ;
var myObj=e v a l (myJSONObj ) ;
document . w r i t e l n ( myObj . t o S t r i n g ( ) ) ;
f o r ( var i =0; i <myObj . l e n g t h ; i ++){
document . w r i t e l n ( <br> ) ;
document . w r i t e l n ( myObj [ i ] . d i s c i p l i n a ) ;
}
//>
</SCRIPT>
</HEAD>
<BODY>
</BODY>
</HTML>
JSON n Java
google-gson
Analogul aplicatiei javascript de mai sus, poate fi
Exemplul F.2.2
1
2
3
4
5
7
8
9
import
import
import
import
import
class D i s c i p l i n a {
private S t r i n g nume ;
Disciplina (){}
D i s c i p l i n a ( S t r i n g nume ) {
t h i s . nume=nume ;
}
public S t r i n g getNume ( ) {
return nume ;
}
11
12
13
14
15
16
17
383
384
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
A
XML
ANEXA F. SERIALIZARE FAR
public c l a s s TestGSON{
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
Gson gson=new Gson ( ) ;
D i s c i p l i n a an=new D i s c i p l i n a ( A n a l i z a numerica ) ;
D i s c i p l i n a pd=new D i s c i p l i n a ( Programare d i s t r i b u i t a ) ;
D i s c i p l i n a sm=new D i s c i p l i n a ( S o f t matematic ) ;
D i s c i p l i n a [ ] d i s c i p l i n e ={an , pd , sm } ;
S t r i n g j s o n=gson . t o J s o n ( d i s c i p l i n e ) ;
System . out . p r i n t l n ( j s o n ) ;
Type c o l l e c t i o n T y p e = new TypeToken<C o l l e c t i o n <D i s c i p l i n a > >(){}. getType ( ) ;
C o l l e c t i o n <D i s c i p l i n a > d = gson . fromJson ( j s o n , c o l l e c t i o n T y p e ) ;
I t e r a t o r <D i s c i p l i n a > i t e r=d . i t e r a t o r ( ) ;
while ( i t e r . hasNext ( ) ) {
D i s c i p l i n a d i s=i t e r . n e x t ( ) ;
System . out . p r i n t l n ( d i s . getNume ( ) ) ;
}
}
}
javax.json
Interfata javax.json.JsonValue introduce obiectele nemodificabile (immutable) JsonArray, JsonObject, JsonString, JsonNumber, JsonValue.TRUE,
JsonValue.FALSE, JsonValue.NULL.
Obiectele se instantiaza prin intermediul unor metode statice ale clasei
javax.json.Json.
Exista structura de interfete
JsonValue JsonStructure JsonArray
JsonObject
JsonString
JsonNumber
acopera tipurile de date Java numerice
BigDecimal, BigInteger, int, long,
double
Clasa javax.json.Json
Metode
static JsonObjectBuilder createObjectBuilder()
static JsonArrayBuilder createArrayBuilder()
static JsonWriter createWriter(java.io.Writer writer )
static JsonReader createReader(java.io.Reader reader )
385
Interfata javax.json.JsonObjectBuilder
Metode
JsonObjectBuilder add(String name, TipJson value)
TipJson{BigDecimal, BigInteger, int, long, double, boolean,
JsonObjectBuilder, JsonArrayBuilder, JsonValue, String}.
JsonObjectBuilder addNull()
JsonObject build()
Sablon de utilizare
JsonObject jsonObject=Json.createObjectBuilder()
.add("name", value)
. . .
.build();
Interfata javax.json.JsonArrayBuilder
Metode
JsonArrayBuilder add(TipJson value)
TipJson{BigDecimal, BigInteger, int, long, double, boolean,
JsonObjectBuilder, JsonArrayBuilder, JsonValue, String}.
JsonArrayBuilder addNull()
JsonArray build()
Sablon de utilizare
JsonArray jsonArray=Json.createArrayBuilder()
.add(value)
. . .
.build();
Interfata javax.json.WriterBuilder
Metode
void writeArray(JsonArray array)
void writeObject(JsonObject object)
void close()
Sablon de utilizare
PrintWriter printWriter=new PrintWriter(System.out)
JsonWriter jsonWriter=Json.createWriter(printWriter);
jsonWriter.writeArray(jsonArray);
jsonWriter.close();
386
A
XML
ANEXA F. SERIALIZARE FAR
Interfata javax.json.ReaderBuilder
Metode
void readArray()
void readObject()
void close()
Sablon de utilizare
String string=. . .
JsonReader jsonReader = Json.createReader(new StringReader(string));
JsonArray array = jsonReader.readArray();
jsonReader.close();
import
import
import
import
import
import
import
import
j a v a x . j s o n . JsonArray ;
javax . json . JsonArrayBuilder ;
javax . json . JsonObject ;
javax . json . JsonObjectBuilder ;
javax . json . JsonWriter ;
j a v a x . j s o n . Json ;
java . io . PrintWriter ;
j a v a . i o . IOException ;
public c l a s s GenerateJSON {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
JsonArray j s o n A r r a y=Json . c r e a t e A r r a y B u i l d e r ( )
. add ( Json . c r e a t e O b j e c t B u i l d e r ( )
. add ( nume , A n a l i z a numerica ) )
. add ( Json . c r e a t e O b j e c t B u i l d e r ( )
. add ( nume , Programare d i s t r i b u i t a ) )
. add ( Json . c r e a t e O b j e c t B u i l d e r ( )
. add ( nume , S o f t matematic ) )
. add ( 1 0 0 )
. add ( j a v a x . j s o n )
. add ( Json . c r e a t e A r r a y B u i l d e r ( )
. add ( 1 )
. add ( 2 )
. add ( 3 ) )
. add ( Json . c r e a t e A r r a y B u i l d e r ( )
. add ( 4 )
. add ( 5 )
. add ( 6 ) )
. build ( ) ;
System . out . p r i n t l n ( System . out : +j s o n A r r a y ) ;
S t r i n g f i l e N a m e= exemplu . j s o n ;
try {
J s o n W r i t e r j s o n W r i t e r=Json . c r e a t e W r i t e r (new P r i n t W r i t e r ( f i l e N a m e ) ) ;
jsonWriter . writeArray ( jsonArray ) ;
jsonWriter . clos e ( ) ;
}
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 ( ) ) ;
}
J s o n W r i t e r j s o n W r i t e r=Json . c r e a t e W r i t e r (new P r i n t W r i t e r ( System . out ) ) ;
jsonWriter . writeArray ( jsonArray ) ;
jsonWriter . c los e ( ) ;
38
39
40
41
42
43
44
45
import
import
import
import
import
import
import
import
import
import
import
import
j a v a x . j s o n . JsonArray ;
javax . json . JsonObject ;
j a v a x . j s o n . JsonReader ;
j a v a x . j s o n . Json ;
j a v a x . j s o n . JsonValue ;
javax . json . JsonString ;
j a v a x . j s o n . JsonNumber ;
java . io . FileReader ;
j a v a . i o . IOException ;
java . u t i l . I t e r a t o r ;
j a v a . u t i l . Map ;
java . u t i l . Set ;
public c l a s s ReadJSON{
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 f i l e N a m e= exemplu . j s o n ;
S t r i n g path=d : \ \mk\\DISTR2\\GSON\\JEE\\ ex1 \\ ;
JsonArray a r r a y=n u l l ;
try {
JsonReader j s o n R e a d e r =
Json . c r e a t e R e a d e r (new F i l e R e a d e r ( path+f i l e N a m e ) ) ;
array = jsonReader . readArray ( ) ;
jsonReader . c l o s e ( ) ;
}
catch ( IOException e ) {
System . out . p r i n t l n ( Ex : +e . g e t M e s s a g e ( ) ) ;
}
analyse ( array ) ;
}
private s t a t i c void a n a l y s e ( JsonArray v ) {
I t e r a t o r <JsonValue> i t e r a t o r=v . i t e r a t o r ( ) ;
while ( i t e r a t o r . hasNext ( ) ) {
JsonValue v a l u e =( JsonValue ) i t e r a t o r . n e x t ( ) ;
i f ( v a l u e instanceof JsonArray ) {
JsonArray a r r a y =( JsonArray ) v a l u e ;
analyse ( array ) ;
}
i f ( v a l u e instanceof J s o n O b j e c t ) {
J s o n O b j e c t o b j =( J s o n O b j e c t ) v a l u e ;
analyseJsonObject ( obj ) ;
}
i f ( v a l u e instanceof J s o n S t r i n g ) {
J s o n S t r i n g s t r i n g =( J s o n S t r i n g ) v a l u e ;
S t r i n g s=s t r i n g . g e t S t r i n g ( ) ;
System . out . p r i n t l n ( s ) ;
387
388
A
XML
ANEXA F. SERIALIZARE FAR
}
i f ( v a l u e instanceof JsonNumber ) {
JsonNumber number=(JsonNumber ) v a l u e ;
double d=number . d o u b l e V a l u e ( ) ;
System . out . p r i n t l n ( d ) ;
}
47
48
49
50
51
52
53
54
56
private s t a t i c void a n a l y s e J s o n O b j e c t ( J s o n O b j e c t o b j ) {
Map<S t r i n g , JsonValue> o b j e c t =(Map) o b j ;
Set<S t r i n g > k e y s=o b j e c t . k e y S e t ( ) ;
I t e r a t o r <S t r i n g > i t e r=k e y s . i t e r a t o r ( ) ;
while ( i t e r . hasNext ( ) ) {
S t r i n g name=i t e r . n e x t ( ) ;
System . out . p r i n t l n ( ) ;
System . out . p r i n t l n ( J s o n O b j e c t name : +name ) ;
JsonValue vv=( JsonValue ) o b j e c t . g e t ( name ) ;
i f ( vv instanceof JsonArray ) {
JsonArray a r r a y =( JsonArray ) vv ;
analyse ( array ) ;
}
i f ( vv instanceof J s o n O b j e c t ) {
J s o n O b j e c t o=( J s o n O b j e c t ) vv ;
analyseJsonObject ( o ) ;
}
i f ( vv instanceof J s o n S t r i n g ) {
J s o n S t r i n g s t r i n g =( J s o n S t r i n g ) vv ;
S t r i n g s=s t r i n g . g e t S t r i n g ( ) ;
System . out . p r i n t l n ( s ) ;
}
i f ( vv instanceof JsonNumber ) {
JsonNumber number=(JsonNumber ) vv ;
double d=number . d o u b l e V a l u e ( ) ;
System . out . p r i n t l n ( d ) ;
}
}
}
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
Anexa G
Adnot
ari
O adnotare este o completare, o nota sau o nsemnare care explica sau
ntregeste un text.
O metadata este o adnotare a unei date.
In Java o adnotare (annotation) este o metadata a unui element de cod
(identificator al unei entitati din codul Java).
O adnotare poate sa-si faca efectul:
asupra codului sursa, naintea compilarii;
asupra codului obiect, dupa compilare, dar naintea executarii;
n timpul executiei codului.
Din punctul de vedere al sintaxei intereseaza
definirea unei adnotari;
declararea unei adnotari;
procesarea unei adnotari.
G.1
390
ANEXA G. ADNOTARI
declarare Element 2
. . .
}
unde declarare Element poate fi:
tip numeElement();
tip numeElement() default valoare;
iar tip poate fi
predefinit (int, short, long, byte, char, float, double, boolean);
String
Class
enum
adnotare
tablou ale carei elemente sunt de un tip precizat anterior
Adnotarea se salveaza ca fisier text, sub numele NumeAdnotare.java.
Dupa numarul elementelor declarate ntr-o adnotare, acesta poate fi
0 - caz n care adnotarea este de tip marker;
1 sau mai multe elemente (single-element / multi-value annotation).
G.2
G.3. PROCESAREA UNEI ADNOTARI
G.3
391
Meta-adnotari
Target
Retention
Documented
Inherited
Adnotarea Override
Adnotarea Override precizeaza faptul ca se suprascrie un element al clasei
parinte.
1
2
3
4
5
6
import j a v a . u t i l . Date ;
public c l a s s T e s t O v e r r i d e extends Date {
@Override
public S t r i n g t o S t r i n g ( ) {
return super . t o S t r i n g ()+ T e s t O v e r r i d e ;
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
Date d=new T e s t O v e r r i d e ( ) ;
System . out . p r i n t l n ( d . t o S t r i n g ( ) ) ;
}
8
9
10
11
12
Daca n locul liniei 9 se pune Date d=new Date(); atunci nu mai apare
mesajul TestOverride.
Adnotarea Deprecated
Adnotarea Deprecated are ca efect afisarea unui mesaj de avertisment n
momentul compilarii.
Exemplificam cu clasele
1
2
3
4
5
6
1
2
3
4
5
6
public c l a s s MyDeprecated {
@Deprecated
public void doJob ( ) {
System . out . p r i n t l n ( This i s d e p r e c a t e d ) ;
}
}
public c l a s s T e s t D e p r e c a t e d {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
MyDeprecated o b j=new MyDeprecated ( ) ;
o b j . doJob ( ) ;
}
}
392
ANEXA G. ADNOTARI
Adnotarea SuppressWarnings
Adnotarea SuppressWarnings inhiba afisarea mesajelor de avertisment.
Reluam exemplul anterior schimband clasa Test. In urma compilarii nu mai
apar mesajele de avertisment mentionate mai sus.
1
2
@SuppressWarnings ( d e p r e c a t i o n )
public c l a s s T e s t S u p p r e s s W a r n i n g s {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
MyDeprecated o b j=new MyDeprecated ( ) ;
o b j . doJob ( ) ;
}
4
5
6
7
8
Adnotarea Target
Adnotarea Target precizeaza elementul asupra careia actioneaza:
ElementType.TYPE
ElementType.FIELD
ElementType.METHOD
ElementType.PARAMETER
ElementType.CONSTRUCTOR
ElementType.LOCAL VARIABLE
ElementType.ANNOTATION TYPE
Adnotarea Retention
Adnotarea Retention precizeaza momentul actiunii adnotarii:
RetentionPolicy.SOURCE
RetentionPolicy.CLASS
RetentionPolicy.RUNTIME
393
Adnotarea Documented
Adnotarea Documented are ca efect mentionarea adnotarii n documentul
obtinut prin javadoc.
Fie clasele
1
import j a v a . l a n g . a n n o t a t i o n . Documented ;
@Documented
public @ i n t e r f a c e MyDocumented{}
si
1
2
3
4
public c l a s s TestDocumented {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
new TestDocumented ( ) . doDocumented ( ) ;
}
@MyDocumented
public void doDocumented ( ) {
System . out . p r i n t l n ( Test Documented ) ;
}
6
7
8
9
10
import
import
import
import
@Retention ( R e t e n t i o n P o l i c y .RUNTIME)
1
2
3
394
7
8
9
10
11
ANEXA G. ADNOTARI
import j a v a . l a n g . r e f l e c t . Method ;
public c l a s s T e s t A n n o t a t i o n {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
T e s t A n n o t a t i o n o b j=new T e s t A n n o t a t i o n ( ) ;
obj . v e r i f ( obj ) ;
}
4
5
6
7
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Anexa H
Utilizarea SGBD n Java
Scopul acestei anexe este prezentarea bazelor utilizarii unui Sistem de
Gestiune a Bazelor de Date (SGBD - Data Bases Management System - DBMS)
din Java. Exemplificam modul de operare si utilizare pentru crearea si exploatarea unei baze de date corespunzatoare unei agende de adrese e-mail.
H.1
Derby / Javadb
395
396
Exemplul H.1.1
Baza de date AgendaEMail se creaza executand
run CreateAgendaE.sql;
unde fisierul CreateAgendaE.sql este
1
2
3
4
5
6
7
si ncarcarea cu date
run ValuesAgendaE.sql;
cu fisierul ValuesAgendaE.sql
1
2
3
H.2
mysql
Instalarea produsului. Pentru instalare s-a descarcat varianta fara instalare automata mysql-*.*.*-win*.zip. Acest fisier se dezarhiveaza ntr-un
catalog MYSQL HOME.
Dezarhivarea este urmata de initializare
Varianta nesecurizata, adica fara utilizarea parolelor:
set MYSQL_HOME=. . .
set PATH=%MYSQL_HOME%\bin;%PATH%
mysqld --initialize-insecure
Varianta securizata:
set MYSQL_HOME=. . .
set PATH=%MYSQL_HOME%\bin;%PATH%
mysqld --initialize
H.2. MYSQL
397
Implicit, serverul mysql utilizeaza portul 3306, iar fisierele bazelor de date vor
fi gazduite n catalogul MYSQL HOME\data.
Pentru utilizarea n aplicatii Java trebuie descarcat un conector mysqlconnector-java-*.*.*.tar.gz, continand fisierul mysql-connector-java*.*.*-bin.jar.
Utilizarea produsului.
Se ntreprind urmatoarele operatii:
1. Lansarea serverului mysql :
set MYSQL_HOME=. . .
set PATH=%MYSQL_HOME%\bin;%PATH%
mysqld
2. Exemplul H.2.1
Crearea bazei de date AgendaEMail se va face prin intermediul fisierului
de comenzi
set MYSQL_HOME=d:\mysql-*-win*\bin
set path=%MYSQL_HOME%;%PATH%
mysql -u root < CreateAgendaE.sql
mysql -u root < ValuesAgendaE.sql
create d a t a b a s e AgendaEMail ;
u s e AgendaEMail ;
create table a d r e s e (
i d i n t primary key a u t o i n c r e m e n t not null ,
nume char ( 2 0 ) not null ,
e m a i l char ( 3 0 ) not n u l l
);
u s e AgendaEMail ;
i n s e r t a d r e s e values ( 1 , aaa , aaa@yahoo . com ) ;
i n s e r t a d r e s e values ( 2 , bbb , bbb@gmail . com ) ;
i n s e r t a d r e s e values ( 3 , c c c , ccc @uni tbv . r o ) ;
i n s e r t a d r e s e values ( 1 , aaa , xyz@unitbv . r o ) ;
398
H.3
S
ablonul de utilizare a unei baze de date
ntr-un program Java
399
H.3. S
ABLONUL DE UTILIZARE A UNEI BAZE DE DATE
Driver
sun.jdbc.odbc.JdbcOdbcDriver
com.mysql.jdbc.Driver
derby
javadb
postgresql
hypeqsql
H2
oraclexe
org.apache.derby.jdbc.ClientDriver
org.postgresql.Driver
org.hsqldb.jdbcDriver
org.h2.Driver
oracle.jdbc.driver.OracleDriver
Fisierul driver-ului
mysql-connector-java-*.*.*-bin.jar
(www.mysql.com)
derbyclient.jar
(distributia derby)
postgresql-*.*-*.jdbc4.jar
hsqldb.jar
h2-*.jar
ojdbc14.jar
400
con=DriverManager.getConnection(URLBazaDate);
...
}
catch(ClassNotFoundException e){. . .}
catch(SQLException e){. . .}
Anumite SGBD asigura accesul la o baza de date daca sunt fixati parametrii
username si password. In acest caz se programeaza
con=DriverManager.getConnection(URLBazaDate,username,password);
Odata conexiunea cu baza de date stabilita se genereaza un obiect de tip
Statement prin intermediul caruia se executa interogarea SQL.
Statement instructiune=con.createStatement();
String sql=. . . //fraza select;
Rezultatele interogarii bazei de date se obtine prin
try{
ResultSet rs=instructiune.executeQuery(sql);
while(rs.next()){
prelucrarea rezultatului
}
}
catch(SQLException e){...}
Exemplul H.3.1
O interogare simpla a bazei de date AgendaEMail se realizeaza cu programul
1
2
3
4
5
6
8
9
10
11
12
14
15
16
import
import
import
import
import
import
java .
java .
java .
java .
java .
java .
s q l . Connection ;
s q l . DriverManager ;
sql . ResultSet ;
s q l . Statement ;
u t i l . Scanner ;
u t i l . InputMismatchException ;
public c l a s s AgendaE{
private s t a t i c S t r i n g jdbcURLDerby =
j d b c : derby : / / l o c a l h o s t : 1 5 2 7 / AgendaEMail ;
private s t a t i c S t r i n g j d b c D r i v e r D e r b y =
o r g . apache . derby . j d b c . C l i e n t D r i v e r ;
private s t a t i c S t r i n g jdbcURLMysql =
j d b c : mysql : / / l o c a l h o s t : 3 3 0 6 / AgendaEMail ? u s e r=r o o t ;
private s t a t i c S t r i n g j d b c D r i v e r M y s q l =
H.3. S
ABLONUL DE UTILIZARE A UNEI BAZE DE DATE
17
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
52
53
54
55
56
57
58
59
60
62
63
64
65
66
68
69
70
71
72
73
74
75
com . mysql . j d b c . D r i v e r ;
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 dbms=null , username=null , password=null , jdbcURL=n u l l ;
switch ( a r g s . l e n g t h ) {
case 0 :
System . out . p r i n t l n ( At l e a s t one argument r e q u i r e d ) ;
System . out . p r i n t l n ( DBMS username password ) ;
System . out . p r i n t l n ( DBMS derby , mysql ) ;
System . e x i t ( 0 ) ;
break ;
case 1 :
dbms=a r g s [ 0 ] ;
break ;
case 2 :
dbms=a r g s [ 0 ] ;
username=a r g s [ 1 ] ;
password= ;
break ;
default :
dbms=a r g s [ 0 ] ;
username=a r g s [ 1 ] ;
password=a r g s [ 2 ] ;
}
C o n n e c t i o n conn = n u l l ;
try {
switch ( dbms ) {
case derby :
C l a s s . forName ( j d b c D r i v e r D e r b y ) . n e w I n s t a n c e ( ) ;
jdbcURL=jdbcURLDerby ;
break ;
case mysql :
C l a s s . forName ( j d b c D r i v e r M y s q l ) . n e w I n s t a n c e ( ) ;
jdbcURL=jdbcURLMysql ;
break ;
default :
System . out . p r i n t l n ( Unknown DBMS . . . ) ;
System . e x i t ( 0 ) ;
}
System . out . p r i n t l n ( jdbcURL=+jdbcURL ) ;
i f ( password==n u l l )
conn = DriverManager . g e t C o n n e c t i o n ( jdbcURL ) ;
else
conn=DriverManager . g e t C o n n e c t i o n ( jdbcURL , username , password ) ;
Statement i n s t r u c t i u n e=conn . c r e a t e S t a t e m e n t ( ) ;
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 ) ;
i n t p r e l , no ;
S t r i n g ch=Y , nume= , e m a i l= , s q l= ;
R e s u l t S e t r s=n u l l ;
while ( ch . s t a r t s W i t h ( Y ) ) {
do{
System . out . p r i n t l n ( Continue ? (Y/N) ) ;
ch=s c a n n e r . n e x t ( ) . toUpperCase ( ) ;
}
while ( ( ! ch . s t a r t s W i t h ( Y ))&&(! ch . s t a r t s W i t h ( N ) ) ) ;
i f ( ch . s t a r t s W i t h ( Y ) ) {
System . out . p r i n t l n ( Natura i n t e r o g a r i i ? ) ;
401
402
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
}
catch ( E x c e p t i o n e ) {
// h a n d l e t h e e x c e p t i o n
e . printStackTrace ( ) ;
}
114
115
116
117
118
119
120
H.3. S
ABLONUL DE UTILIZARE A UNEI BAZE DE DATE
403
404
Anexa I
Injectarea dependintelor
Injectarea dependintelor (Dependency Injection - DI ) costa n oferirea spre
utilizare a unor obiecte instantiate de mediul de lucru (server Web, server de
aplicatii, container specializat) de catre o clasa.
Injectarea dependintelor este o tehnica uzuala n JEE, dar poate fi programata si utilizata si nafara unui cadru JEE. Produse informatice ce asigura
aceasta facilitate sunt:
Weld realizat de Jboss - RedHat si utilizat de Glassfish.
Guice realizat de Google.
I.1
Weld
package cmmdc ;
public c l a s s Cmmdc{
public long cmmdc( long m, long n ) { . . . }
}
4
5
Aplicatie de sine st
at
atoare
Structura aplicatiei este
catalogul_applicatiei
|--> cmmdc
|
|
Cmmdc.class
|
|
ApelCmmdc.class
405
406
|-->
|
|
META-INF
|
beans.xml
Client.class
Codurile claselor:
Clasa ApelCmmdc
2
package cmmdc ;
import j a v a x . i n j e c t . I n j e c t ;
public c l a s s ApelCmmdc{
@Inject
Cmmdc o b j ;
6
7
9
10
11
12
Clasa Client
1
2
3
4
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import
import
import
import
java . u t i l . Scanner ;
o r g . j b o s s . weld . e n vi r o nm e n t . s e . Weld ;
o r g . j b o s s . weld . e n vi r o nm e n t . s e . WeldContainer ;
cmmdc . ApelCmmdc ;
public c l a s s C l i e n t {
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 ) ;
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 ( ) ;
WeldContainer weld = new Weld ( ) . i n i t i a l i z e ( ) ;
ApelCmmdc o b j = weld . i n s t a n c e ( )
. s e l e c t ( ApelCmmdc . c l a s s )
. get ( ) ;
r=o b j . compute (m, n ) ;
System . out . p r i n t l n ( Cmmdc : +r ) ;
}
}
<beans></ beans>
Servlet
Structura aplicatiei Web:
I.1. WELD
contextul_Web
|--> WEB-INF
|
|--> classes
|
|
|
Cmmdc.class
|
|
CmmdcWebServlet.class
|
|--> lib
|
|
|
weld-servlet.jar
|
|
web.xml
|
|
beans.xml
|
index.html
10
import
import
import
import
import
import
import
import
import
import
12
@WebServlet ( u r l P a t t e r n s = /cmmdc )
14
1
2
3
4
5
6
7
8
9
15
16
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
42
43
44
45
46
j a v a . i o . IOException ;
javax . s e r v l e t . ServletException ;
javax . s e r v l e t . http . HttpServlet ;
javax . s e r v l e t . http . HttpServletRequest ;
javax . s e r v l e t . http . HttpServletResponse ;
javax . s e r v l e t . ServletConfig ;
j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
java . io . PrintWriter ;
javax . i n j e c t . I n j e c t ;
cmmdc . Cmmdc ;
407
408
beans.xml
1
2
3
4
5
6
Partea IV
TEME DE LABORATOR
409
Anexa J
Teme de aplicatii
J.1
Probleme propuse
412
6. Sa se determine zodia (chinezeasca) corespunzatoare unei date calendaristice. Obs. Inceputul anului nou chinezesc nu coincide cu nceputul
anului nou calendaristic.
(a) Varianta 1
Se va crea baza de date AN CHINEZESC alcatuita din tabelul
INCEPUT
AN
LUNA
ZI
(b) Varianta 2
Datele dintr-un fisier text se introduc ntr-o colectie Java. Rezolvarea cererii unui client se face utilizand facilitatile de programare oferite de interfata java.util.Collection din jdk.
M
INCH
T
ol
M
FEET (FT) Picior
Uncie (UK)
KG UK ONCE
KG UK POUND Livra (UK)
0.0254
0.3048
0.031103
0.373
MATERIA
COD-MATERIE
DENUMIRE
CURSURI
COD-CURS
COD-CADRU-DIDACTIC
COD-MATERIE
413
414
Judet
Alba
Arad
Arges
Bacau
Bihor
Bistrita-Nasaud
Botosani
Brasov
Braila
Buzau
Caras-Severin
Cluj
Constanta
Covasna
Dambovita
Cod
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Judet
Dolj
Galati
Gorj
Harghita
Hunedoara
Ialomita
Iasi
Ilfov
Maramures
Mehedinti
Mures
Neamt
Olt
Prahova
Satu Mare
Salaj
Cod
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
51
52
Judet
Sibiu
Suceava
Teleorman
Timis
Tulcea
Vaslui
Valcea
Vrancea
Bucuresti
Bucuresti-S1
Bucuresti-S2
Bucuresti-S3
Bucuresti-S4
Bucuresti-S5
Bucuresti-S6
Calarasi
Giurgiu
415
ACTIVITATE
ID
FEL
aterizare/decolare
ZI
TIMP
ora/minut
COMPANIE
OBSERVATIE de la/spre
Sa se realizeze o aplicatie de furnizare a datelor catre clienti (interogarea
bazei de date).
13. Se dau n tipuri de monede Mx1 , Mx2 , . . . , Mxn , xi reprezentand valoarea
monedei, i = 1, 2, . . . , n. Sa se determine variantele de plata a unei sume
S cu un numar minim de monede din cele disponibile.
Se vor trata cazurile:
(a) Numarul monedelor de fiecare tip este nelimitat.
(b) Numarul monedelor disponibile este marginit, respectiv de numerele
k1 , k2 , . . . , kn (k1 x1 + . . . + kn xn S).
14. Globul pamantesc este mpartit n 24 de fuse orare de cate 15o (24 15 =
360) pornind de la meridianul 0 spre stanga si dreapta.
Dandu-se longitudinile a 2 puncte de pe glob sa se calculeze diferenta
de fus orar.
Fixand ora n primul punct sa se indice ora n al doilea punct.
15. Sa se calculeze unghiurile unui triunghi dat prin coordonatele varfurilor.
16. Fixand coeficientii a, b, c, d, e, f ale conicei
ax2 + 2bxy + cy 2 + 2dx + 2ey + f = 0
sa se reduca conica la forma canonica.
17. Sa se calculeze suma multiplilor de 3 sau 5 mai mici decat un numar dat
n.
18. Fie p N fixat si n N, 0 n 2p 1 cu reprezentarea binara
n = ap1 ap2 . . . a1 a0 2 . Sa se determine numarul m care are reprezentarea
binara m = a0 a1 . . . ap2 ap1 2 .
De exemplu, pentru p = 6, n = 17 = 0100012 numarul cautat este m =
1000102 = 34.
416
Bn =
daca n = 0
Pn1
k=0
n+1
k
Bk
n+1
daca n > 0
Calculele se fac n Q.
21. Problema generalilor bizantini.1 Sunt n generali dintre care unul
este comandant si ceilalti locotenenti. Generalii pot fi loiali sau tradatori.
Numarul generalilor tradatori este m. Comandantul (loial sau tradator)
lanseaza o comanda (atac sau retragere). Toti locotenentii loiali urmeaza
ordinele comandantului si ei trebuie sa ajunga la aceasi concluzie privind
actiunea de urmat.
Algoritmul: Dupa ce un locotenent primeste ordinul comandantului el
retransmite ordinul primit tuturor celorlalti locotenenti. Comanda majoritara este cea care va fi urmata.
Ipoteze: Transmisia mesajelor este sigura. Mesajele nu pot fi interceptate
si modificate. Un tradator nu poate trimite decat un singur mesaj si este
obligat sa urmeze algoritmul.
Se arata ca
Daca n = 3m atunci problema n-are solutie.
Daca n 3m + 1 atunci problema are solutie.
Sa se simuleze problema generalilor bizantini printr-o aplicatie distribuita
utilizand tehnologia soclurilor.
22. Problema 3x + 1. Fie sirul de numere naturale (an )nN definit prin
formula de recurenta
3an + 1 daca an impar
an+1 =
an
daca an par
2
Pentru orice a0 exista n N astfel ncat an = 1.
1
Aplicatia distribuit
a nu este de tip client - server.
417
d
X
Pnj
d N, n N
j=0
Sa se calculeze Tnd .
Exemplu.
Pnd
n
= 1
2
3
0
1
1
1
1
1
2
3
d
2 3 4
1 1 1
3 4 5
6 10 15
Tnd
n
= 1
2
3
0
1
1
1
1
2
3
4
d
2 3 4
3 4 5
6 10 15
10 20 35
418
(a) 3x = 5
x=7
(b) 4x = 2
(c) 2x = 4
x {2, 6}
Bibliografie
[1] ALBOAIE L., BURAGA S., 2006, Servicii Web. Ed. Polirom, Iasi.
ERNEST SCHEIBER
PROGRAMARE
IN JAVA
DISTRIBUITA
Volumul II
Brasov
Prefat
a
Cursul Programare distribuita n Java 2 este continuarea cursului Programare distribuita n Java 1. Minimal, pentru ntelegerea cursului este nevoie
de cunoasterea capitolelor Servlet si JSP din partea ntai.
Tematica cursului cuprinde:
Cadre de dezvoltare (framework) a aplicatiilor Web:
Struts2
Java Server Faces
Spring
Google Web Toolkit
Servicii Web cu:
Servicii RPC
JAX-WS (Java API for XML Web Services) prin metro
Servicii REST
JAX-RS (Java API for RESTful Web Services) prin jersey
Modelul OSGi (Open Source Gateway initiative)
Sursele programele din curs sunt disponibile prin git:
https://github.com/e-scheiber/DistributedProgramming2.git
Cuprins
I
APLICAT
II WEB - CADRE DE LUCRU
1 Aplicatii Web
1.1 Modelul MVC . . . . . . . . . . . . . . . . . . .
1.2 Struts 2 . . . . . . . . . . . . . . . . . . . . . .
1.2.1 Aplicatii Struts2 prin modelul descriptiv
1.2.2 Marcaje Struts . . . . . . . . . . . . . .
1.2.3 Aplicatii Struts2 . . . . . . . . . . . . .
1.2.4 Interceptori . . . . . . . . . . . . . . . .
1.2.5 Aplicatii Struts2 prin modelul programat
1.2.6 Struts 2 prin maven . . . . . . . . . . .
1.3 Java Server Faces . . . . . . . . . . . . . . . . .
1.3.1 Structura unei aplicatii JSF . . . . . . .
1.3.2 Marcaje JSF . . . . . . . . . . . . . . . .
1.3.3 Aplicatii JSF cu pagini Facelets . . . . .
1.3.4 Aplicatii JSF cu pagini JSP . . . . . . .
1.3.5 Componente grafice Primefaces . . . . .
1.3.6 JSF dezvoltat prin maven . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
13
16
16
18
20
32
39
44
47
47
50
52
59
70
76
2 Spring
79
2.1 Aplicatie Spring elementara . . . . . . . . . . . . . . . . . . . . 79
2.2 Dezvoltarea unei aplicatii MVC Spring . . . . . . . . . . . . . . 82
3 Asynchronous JavaScript And Xml AJAX
3.1 AJAX Java . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Google Web Toolkit (GWT) . . . . . . . . . . . . . . . .
3.2.1 Dezvoltarea unei aplicatii GWT prin ant . . . . .
3.2.2 Aplicatie GWT fara apel de procedura la distanta
3.2.3 Aplicatie GWT cu apel de procedura la distanta .
3.2.4 Crearea unui widget client . . . . . . . . . . . . .
5
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
101
101
112
112
114
120
137
CUPRINS
3.2.5
3.2.6
3.2.7
II
SERVICII WEB
147
4 Servicii JAX-WS
4.1 Descrierea unui serviciu . . . . . . . . . . . . . . . . . . . .
4.1.1 XML Schema . . . . . . . . . . . . . . . . . . . . .
4.1.2 WSDL . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.3 Mesaje SOAP . . . . . . . . . . . . . . . . . . . . .
4.2 Modelul JAX-WS prin Metro . . . . . . . . . . . . . . . .
4.2.1 Serviciu Web ca servlet n apache-tomcat prin ant .
4.2.2 Componenta EJB sesiune stateless ca serviciu Web
4.2.3 Servicii jaxws dezvoltate prin maven . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
149
. 150
. 151
. 154
. 161
. 166
. 166
. 174
. 176
5 Servicii JAX-RS
5.1 Representational State Transfer . .
5.2 Jersey-2 . . . . . . . . . . . . . . .
5.2.1 Generarea resurselor . . . .
5.2.2 Preluarea parametrilor . . .
5.2.3 Date prin componenta Java
5.2.4 Aplicatie cu server asincron
5.2.5 Jersey n glassfish . . . . . .
5.2.6 Dezvoltare prin maven . . .
5.3 Serviciu Restful (jersey) n Heroku
5.4 MVC prin servicii RESTful . . . .
5.5 Serviciu Restful cu GWT . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
III
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
MODELUL OSGi
6 Modelul OSGi
6.1 Cadre de lucru OSGi . . . . . . . . . . . . . . . . . . .
6.2 Programare imperativa - Crearea unui modul OSGi . .
6.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . .
6.4 Dezvoltare OSGi prin apache-maven . . . . . . . . . .
6.5 Programare declarativa . . . . . . . . . . . . . . . . . .
6.5.1 Programare declarativa prin Declarative Service
179
179
180
180
191
200
205
207
210
212
215
220
227
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
229
230
233
235
238
242
243
CUPRINS
6.6
6.7
prin Blueprint . . .
prin apache-iPOJO
. . . . . . . . . . . .
. . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
246
248
250
252
7 OSGi distribuit
255
7.1 Medii OSGi pentru aplicatii distribuite . . . . . . . . . . . . . . 255
7.2 Servlet ca modul OSGi . . . . . . . . . . . . . . . . . . . . . . . 256
IV
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
261
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
263
. 264
. 264
. 266
. 270
. 273
. 274
289
CUPRINS
No.
1
2
3
4
5
6
7
8
9
10
11
10
CUPRINS
Partea I
APLICAT
II WEB
CADRE DE LUCRU
11
Capitolul 1
Aplicatii Web
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: Mozilla
Firefox, Google Chrome, Microsoft InternetExplorer, Opera, Apple Safari, etc.
Servicii Web: Cererea catre server se face de un program. Aplicatia
server si client se programeaza utilizand interfete de programare specifice.
Sunt cunoscute multe cadre de dezvoltare (framework) a aplicatiilor Web
gratuite (http://java-source.net/open-source/web-frameworks).
Cadrele de lucru pentru aplicatii Web asigura:
separarea preocuparilor prin modelul ModelViewController (MVC);
simplificarea gestiunii legaturilor dintre componentele unei aplicatii prin
fisiere de configurare sau metode alternative;
oferirea unor facilitati de programare (de exemplu, completarea prin program a unor casete de selectie, ncarcarea unui fisier, validarea datelor).
1.1
Modelul MVC
Modelul MVC este o schema de proiectare a aplicatiilor client-server. Modelul MVC este alcatuita din trei parti:
13
14
CAPITOLUL 1. APLICAT
II WEB
http://joel.inpointform.net/software-development/
mvvm-vs-mvp-vs-mvc-the-differences-explained/.
15
16
CAPITOLUL 1. APLICAT
II WEB
1.2
Struts 2
1.2.1
1.2. STRUTS 2
17
18
17
18
19
20
22
23
24
25
CAPITOLUL 1. APLICAT
II WEB
< f i l t e r mapping>
< f i l t e r name>s t r u t s 2</ f i l t e r name>
<u r l p a t t e r n>/</ u r l p a t t e r n>
</ f i l t e r mapping>
<welcomef i l e l i s t>
<welcome f i l e >i n d e x . html</ welcome f i l e >
</ welcomef i l e l i s t>
</webapp>
1.2.2
Marcaje Struts
Marcajele Struts sunt definite ntr-o biblioteca care se declara ntr-o pagina
JSP prin
<%@ taglib prefix="s" uri="/struts-tags" %>
Nu este nevoie de specificarea lor n fisierul de configurare web.xml.
Amintim marcajele:
s:form Pentru marcarea formularului.
Atribute ale marcajului:
Atribut Fel
Descriere
action obligatoriu defineste actiunea de executat.
19
1.2. STRUTS 2
Fel
optional
optional
obligatoriu
listKey
optional
listValue optional
s:hidden
Atribute ale marcajului:
Descriere
Textul explicativ al controlului grafic
Numele proprietatii
Lista optiunilor sau numele listei
Exemplu: {C2F,F2C}
Valorile cheii. Proprietatea ca avea
valoarea selectata.
Valorile afisate
20
CAPITOLUL 1. APLICAT
II WEB
Atribut Fel
Descriere
name
obligatoriu Numele proprietatii / campului
value
obligatoriu Valoarea transmisa
s:if
Atribute ale marcajului:
Atribut Fel
Descriere
test
obligatoriu Test
s:else
<s:if test="%{incercari > 0}">
Incercari <s:property value="%{incercari+1}"/>
</s:if>
<s:else>
Prima incercare
</s:else>
1.2.3
Aplicatii Struts2
Exemplificam prin aplicatia simpla de calcul a celui mai mare divizor comun
a doua numere naturale.
Exemplul 1.2.1
1.2. STRUTS 2
21
AlegeApp.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html>
<head>
< t i t l e> A l e g e A p p l i c a t i a </ t i t l e>
</head>
<body bgcolor=#a a e e a a >
<h1> A l e g e ţ i a p l i c a ţ i a </h1>
<ul>
< l i>
<a href= / my strut s2 app / j s p /Cmmdc . j s p >
C a l c u l u l c e l u i mai mare d i v i z o r comun a două
numere n a t u r a l e
</a>
</ l i>
</ ul>
</body
</html>
In cazul de fata este o singura optiune: calculul celui mai mare divizor
comun.
Componenta View a acestei aplicatii este alcatuita din doua fisiere:
Introducerea datelor (Cmmdc.jsp)
1
2
3
<%@ t a g l i b p r e f i x= s u r i= / s t r u t s t a g s %>
<html>
<head>
22
CAPITOLUL 1. APLICAT
II WEB
4
5
6
7
8
9
10
11
12
13
14
15
<%@ t a g l i b p r e f i x= s u r i= / s t r u t s t a g s %>
<html>
<head>
< t i t l e >Cmmdc</ t i t l e >
</head>
<body>
<h2>Cmmdc : </h2>
<!
<s : p r o p e r t y v a l u e= message />
>
<s : p r o p e r t y v a l u e=#s e s s i o n . cmmdc/>
</body>
</html>
package cmmdc ;
import com . opensymphony . xwork2 . A c t i o n S u p p o r t ;
import com . opensymphony . xwork2 . A c t i o n C o n t e x t ;
import j a v a . u t i l . Map ;
1
2
3
18
public S t r i n g computeCmmdc ( ) {
long c=cmmdc(m, n ) ;
// v a r i a n t a de t r a n s m i t e r e a r e z u l t a t u l u i p r i n t r un camp
//
// s e t M e s s a g e ( ( new Long ( c ) ) . t o S t r i n g ( ) ) ;
//
// v a r i a n t a de t r a n s m i t e r e a r e z u l t a t u l u i p r i n s e s s i o n
Map a t t r=A c t i o n C o n t e x t . g e t C o n t e x t ( ) . g e t S e s s i o n ( ) ;
a t t r . put ( cmmdc , (new Long ( c ) ) . t o S t r i n g ( ) ) ;
return SUCCESS ;
}
20
22
private long m;
public long getM ( ) {
return m;
}
public void setM ( long m) {
t h i s .m = m;
8
9
10
11
12
13
14
15
16
17
23
24
25
26
27
1.2. STRUTS 2
28
30
private long n ;
public long getN ( ) {
return n ;
}
public void setN ( long n ) {
this . n = n ;
}
31
32
33
34
35
36
/
p r i v a t e S t r i n g message ;
p u b l i c v o i d s e t M e s s a g e ( S t r i n g message ) {
t h i s . message = message ;
}
p u b l i c S t r i n g getMessage () {
r e t u r n message ;
}
/
38
39
40
41
42
43
44
45
46
47
23
<html>
<head>
<META HTTPEQUIV= R e f r e s h
CONTENT= 0 ;URL=h t t p : / / l o c a l h o s t : 8 0 8 0 / m ystru ts2 app / html / AlegeApp . html >
</head>
<body>
<p>A p e l a r e a a p l i c a t i e i . . . </p>
</body>
</html>
24
CAPITOLUL 1. APLICAT
II WEB
Verificarea caracterului numeric al datelor convertite de Struts n tipuri numerice este facuta de OGNL.
O facilitate interesanta oferita de Struts este completarea automata a unei
liste de optiuni (select).
Exemplul 1.2.2 Un fisier text contine informatiile {nume judet, capitala judetului,
abrevierea}, separate printr-un spatiu. Se cere construirea unei aplicatii Web
care pentru un judet indicat, afiseaza informatiile corespunzatoare din fisierul
mentionat.
Aplicatia este alcatuita din doua actiuni:
1. Completarea listei de optiuni n cadrul formularului. Aceasta actiune
este lansata la apelarea aplicatei dintr-o pagina html, de exemplu
<a href="http://localhost:8080/mystruts2-app/AlegeJudetul.action">
Referinte despre judete
</a>
Componenta Control :
<action name="AlegeJudetul" class="appjud.ListaJudeteAction">
<result>/jsp/AppJud.jsp</result>
</action>
package appjud ;
import com . opensymphony . xwork2 . A c t i o n S u p p o r t ;
import com . opensymphony . xwork2 . A c t i o n C o n t e x t ;
import j a v a . u t i l . Map ;
import j a v a . u t i l . L i s t ;
import j a v a . u t i l . A r r a y L i s t ;
import j a v a . u t i l . HashMap ;
import j a v a . i o . InputStream ;
import j a v a . i o . InputStreamReader ;
import j a v a . i o . B u f f e r e d R e a d e r ;
import j a v a . i o . IOException ;
25
1.2. STRUTS 2
13
14
15
public c l a s s L i s t a J u d e t e A c t i o n extends A c t i o n S u p p o r t {
private HashMap<S t r i n g , RefJudet> r e f J u d e t e=
new HashMap<S t r i n g , RefJudet > ( ) ;
public L i s t <RefJudet> g e t J u d e t e L i s t ( ) {
L i s t <RefJudet> l i s t =new A r r a y L i s t ( 5 0 ) ;
try (
InputStream f i s =
this . g e t C l a s s ( ) . getResourceAsStream ( j u d e t e . txt ) ;
InputStreamReader i s r =new InputStreamReader ( f i s ) ;
B u f f e r e d R e a d e r br=new B u f f e r e d R e a d e r ( i s r ) ; ) {
S t r i n g s= , jud , c a p i t , a b r e v ;
do{
s=br . r e a d L i n e ( ) ;
i f ( s != n u l l ) {
S t r i n g [ ] s t=s . s p l i t ( ) ;
j u d=s t [ 0 ] ;
c a p i t=s t [ 1 ] ;
a b r e v=s t [ 2 ] ;
R e f J u d e t bean=new R e f J u d e t ( ) ;
bean . s e t J u d ( j u d ) ;
bean . s e t C a p i t ( c a p i t ) ;
bean . s e t A b r e v ( a b r e v ) ;
l i s t . add ( bean ) ;
r e f J u d e t e . put ( jud , bean ) ;
}
}
while ( s != n u l l ) ;
}
catch ( IOException e ) {
e . printStackTrace ( ) ;
}
Map a t t r=A c t i o n C o n t e x t . g e t C o n t e x t ( ) . g e t S e s s i o n ( ) ;
a t t r . put ( r e f J u d e t e , r e f J u d e t e ) ;
return l i s t ;
}
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
package appjud ;
public c l a s s R e f J u d e t implements j a v a . i o . S e r i a l i z a b l e {
private S t r i n g j u d ;
private S t r i n g c a p i t ;
private S t r i n g a b r e v ;
public R e f J u d e t ( ) { }
public void s e t J u d ( S t r i n g j u d ) {
t h i s . j u d=j u d ;
}
public S t r i n g getJud ( ) {
return j u d ;
}
10
11
12
13
14
16
17
18
19
public void s e t C a p i t ( S t r i n g c a p i t ) {
t h i s . c a p i t=c a p i t ;
}
public S t r i n g g e t C a p i t ( ) {
26
CAPITOLUL 1. APLICAT
II WEB
return c a p i t ;
20
21
23
public void s e t A b r e v ( S t r i n g a b r e v ) {
t h i s . a b r e v=a b r e v ;
}
public S t r i n g getAbrev ( ) {
return a b r e v ;
}
24
25
26
27
28
29
<%@ t a g l i b p r e f i x= s u r i= / s t r u t s t a g s %>
<html>
<head>
< t i t l e>R e f e r i n t e Judet</ t i t l e>
</head>
<body>
<h1> R e f e r i n t e d e s p r e j u d e t e </h1>
<p/>
<s : form
action= R e f J u d e t . a c t i o n >
<s : s e l e c t name= s e l e c t a t l a b e l= J u d e t e
l i s t = j u d e t e L i s t l i s t K e y=%{j u d } l i s t V a l u e=%{j u d } />
<s : submit />
</ s : form>
</body>
</html>
27
1.2. STRUTS 2
<%@ t a g l i b p r e f i x= s u r i= / s t r u t s t a g s %>
<html>
<head>
< t i t l e>R e f e r i t e Judet</ t i t l e>
</head>
<body>
<h2> R e f e r i n t e l e d e s p r e j u d e t u l </h2>
<s : p r o p e r t y value= j u d />
<p/>
Capitala :
<s : p r o p e r t y value= c a p i t />
<p/>
Abrevierea :
<s : p r o p e r t y value= a b r e v />
</body>
</html>
package appjud ;
import j a v a . u t i l . Map ;
import j a v a . u t i l . HashMap ;
import com . opensymphony . xwork2 . A c t i o n S u p p o r t ;
import com . opensymphony . xwork2 . A c t i o n C o n t e x t ;
public c l a s s JudBean extends A c t i o n S u p p o r t {
private S t r i n g j u d=n u l l ;
private S t r i n g c a p i t=n u l l ;
private S t r i n g a b r e v=n u l l ;
private S t r i n g s e l e c t a t ;
13
public JudBean ( ) { }
15
public S t r i n g e x e c u t e ( ) throws E x c e p t i o n {
Map a t t r=A c t i o n C o n t e x t . g e t C o n t e x t ( ) . g e t S e s s i o n ( ) ;
HashMap<S t r i n g , RefJudet> r e f J u d e t e=
( HashMap<S t r i n g , RefJudet >) a t t r . g e t ( r e f J u d e t e ) ;
R e f J u d e t r j=r e f J u d e t e . g e t ( s e l e c t a t ) ;
j u d=r j . getJud ( ) ;
c a p i t=r j . g e t C a p i t ( ) ;
a b r e v=r j . getAbrev ( ) ;
return SUCCESS ;
}
16
17
18
19
20
21
22
23
24
26
27
28
30
31
32
34
35
36
public S t r i n g getJud ( ) {
return j u d ;
}
public S t r i n g g e t C a p i t ( ) {
return c a p i t ;
}
public S t r i n g getAbrev ( ) {
return a b r e v ;
}
28
CAPITOLUL 1. APLICAT
II WEB
public void s e t S e l e c t a t ( S t r i n g s e l e c t a t ) {
t h i s . s e l e c t a t=s e l e c t a t ;
}
public S t r i n g g e t S e l e c t a t ( ) {
return s e l e c t a t ;
}
38
39
40
41
42
43
44
Inc
arcarea unui fisier - Upload
Pentru ncarcarea unui fisier, Strut2 ofera o solutie prefabricata, bazata pe
produsul commons-fileupload de la apache.
Actiunea - partea de control - poate fi
<action name="doUpload" class="upload.UploadAction" method="upload">
<result name="success">/jsp/ResultUpload.jsp</result>
<result name="error">/jsp/ErrorUpload.jsp</result>
</action>
<%@ t a g l i b p r e f i x= s u r i= / s t r u t s t a g s %>
<html>
<head>< t i t l e>Upload</ t i t l e>
</head>
<body>
<h3> I n c a r c a r e a unui f i s i e r ( up lo ad ) </h3>
<s : form action= doUpload . a c t i o n
method= p o s t e n c t y p e= m u l t i p a r t / formdata >
<s : f i l e name= myFile l a b e l= F i l e />
<s : submit />
</ s : form>
</body>
</html>
1.2. STRUTS 2
29
package up l oad ;
import o r g . apache . s t r u t s 2 . S e r v l e t A c t i o n C o n t e x t ;
import com . opensymphony . xwork2 . A c t i o n S u p p o r t ;
import com . opensymphony . xwork2 . A c t i o n C o n t e x t ;
import j a v a . u t i l . Map ;
import j a v a . i o . F i l e ;
import j a v a . i o . F i l e I n p u t S t r e a m ;
import j a v a . i o . InputStreamReader ;
import j a v a . i o . B u f f e r e d R e a d e r ;
import j a v a . i o . OutputStreamWriter ;
import j a v a . i o . B u f f e r e d W r i t e r ;
import j a v a . i o . F i l e O u t p u t S t r e a m ;
public c l a s s UploadAction extends A c t i o n S u p p o r t {
private F i l e myFile ;
private S t r i n g myFileFileName ;
private S t r i n g myFileContentType ;
public F i l e g e t M y F i l e ( ) {
return myFile ;
}
public void s e t M y F i l e ( F i l e myFile ) {
t h i s . myFile = myFile ;
}
public S t r i n g getMyFileFileName ( ) {
return myFileFileName ;
}
public void s e t M y F i l e F i l e N a m e ( S t r i n g myFileFileName ) {
t h i s . myFileFileName = myFileFileName ;
}
30
public S t r i n g getMyFileContentType ( ) {
return myFileContentType ;
}
35
36
37
39
40
41
public S t r i n g u pl oa d ( ) throws E x c e p t i o n {
Map a t t r=A c t i o n C o n t e x t . g e t C o n t e x t ( ) . g e t S e s s i o n ( ) ;
ServletContext servletContext =
ServletActionContext . getServletContext ( ) ;
i f ( myFile != n u l l ) {
S t r i n g d a t a D i r = s e r v l e t C o n t e x t . g e t R e a l P a t h ( /WEBINF/ ) ;
System . out . p r i n t l n ( d a t a D i r = +d a t a D i r ) ;
System . out . p r i n t l n ( FileName = +myFileFileName ) ;
F i l e s a v e d F i l e = new F i l e ( dataDir , myFileFileName ) ;
myFile . renameTo ( s a v e d F i l e ) ;
43
44
45
46
47
48
49
50
51
52
S t r i n g B u f f e r sb=new S t r i n g B u f f e r ( ) ;
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 ( s a v e d F i l e ) ;
InputStreamReader i s r =new InputStreamReader ( f i s ) ;
B u f f e r e d R e a d e r br=new B u f f e r e d R e a d e r ( i s r ) ;
54
55
56
57
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
}
else {
a t t r . put ( e r r o r , Upload E r r o r ) ;
return ERROR;
}
80
81
82
83
84
85
86
CAPITOLUL 1. APLICAT
II WEB
1.2. STRUTS 2
31
Desc
arcarea unui fisier - Download
Si pentru aceasta problema Struts2 are o solutie predefinita: este declarat
un tip de raspuns stream, caz n care raspunsul este implicit un flux InputStream.
In acest caz, numai pentru rezultat este nevoie de un fisier jsp.
Exemplul 1.2.4 Aplicatie Web n care clientul alege dintr-o lista un fisier
care este descarcat.
In compunenta de control se introduce
<action name="doDownload" class="download.DownloadAction">
<result type="stream">
<param name="inputName">fileInputStream</param>
<param name="contentDisposition">attachment;filename=${fileName}</param>
<param name="bufferSize">2048</param>
<param name="contentType">application/octet-stream</param>
</result>
</action>
<%@ t a g l i b p r e f i x= s u r i= / s t r u t s t a g s %>
<html>
<head>< t i t l e>Download</ t i t l e>
</head>
<body>
<h3> D e s c a r c a r e a unui f i s i e r ( download ) </h3>
<s : form
action= doDownload . a c t i o n >
<s : s e l e c t name= f i l e l a b e l= A l e g e
l i s t = { c a p i t o l . t x t , xmlp i c . jpg , TomJones . mp3 , c l o c k . a v i } />
<s : submit value= D e s c a r c a />
</ s : form>
</body>
</html>
package download ;
im po rt j a v a x . s e r v l e t . S e r v l e t C o n t e x t ;
im po rt com . opensymphony . xwork2 . A c t i o n S u p p o r t ;
im po rt o r g . apache . s t r u t s 2 . S e r v l e t A c t i o n C o n t e x t ;
im po rt j a v a . i o . InputStream ;
im po rt j a v a . i o . F i l e ;
im po rt j a v a . i o . F i l e I n p u t S t r e a m ;
im po rt j a v a . n i o . f i l e . Paths ;
p u b l i c c l a s s DownloadAction e x t e n d s A c t i o n S u p p o r t {
private String f i l e ;
public void s e t F i l e ( String f i l e ) {
this . f i l e=f i l e ;
}
32
CAPITOLUL 1. APLICAT
II WEB
18
20
p r i v a t e InputStream f i l e I n p u t S t r e a m ;
22
p u b l i c InputStream g e t F i l e I n p u t S t r e a m ( ) {
return fileInputStream ;
}
p u b l i c S t r i n g e x e c u t e ( ) throws E x c e p t i o n {
S t r i n g f s=System . g e t P r o p e r t y ( f i l e . s e p a r a t o r ) ;
ServletContext servletContext =
ServletActionContext . getServletContext ( ) ;
S t r i n g path=s e r v l e t C o n t e x t . g e t R e a l P a t h ( / )+
f s+ r e s o u r c e s +f s ;
f i l e I n p u t S t r e a m = new F i l e I n p u t S t r e a m ( new F i l e ( path+ f i l e ) ) ;
r e t u r n SUCCESS ;
}
16
17
23
24
25
26
27
28
29
30
31
32
33
34
1.2.4
Interceptori
Componenta model
1.2. STRUTS 2
1
2
4
5
6
7
8
33
package exemplu ;
import com . opensymphony . xwork2 . A c t i o n S u p p o r t ;
public c l a s s MyAction extends A c t i o n S u p p o r t {
public S t r i n g e x e c u t e ( ) {
return s u c c e s s ;
}
}
success.jsp
1
2
3
4
5
<html>
<body>
Success
</body>
</html>
34
CAPITOLUL 1. APLICAT
II WEB
Componenta model
1
package exemplu ;
import
import
import
import
4
5
10
11
12
13
15
16
17
18
19
20
22
23
24
25
26
27
29
30
31
32
33
34
36
37
38
39
41
42
43
44
45
46
48
49
50
51
52
53
54
55
56
57
58
j a v a . u t i l . Map ;
j a v a . u t i l . Random ;
o r g . apache . s t r u t s 2 . i n t e r c e p t o r . S e s s i o n A w a r e ;
com . opensymphony . xwork2 . A c t i o n S u p p o r t ;
private
private
private
private
int
int
Map
int
numar ;
i n c e r c a r i =1;
session ;
m a x I n c e r c a r i =4;
public i n t getNumar ( ) {
return numar ;
}
public void setNumar ( i n t numar ) {
t h i s . numar = numar ;
}
public i n t g e t I n c e r c a r i ( ) {
return i n c e r c a r i ;
}
public void s e t I n c e r c a r i ( i n t i n c e r c a r i ) {
this . i n c e r c a r i = i n c e r c a r i ;
}
public void s e t M a x I n c e r c a r i ( i n t m a x I n c e r c a r i ) {
this . maxIncercari = maxIncercari ;
}
public i n t g e t M a x I n c e r c a r i ( ) {
return m a x I n c e r c a r i ;
}
@Override
public void s e t S e s s i o n (Map s e s s i o n ) {
this . s e s s i o n = s e s s i o n ;
}
public void v a l i d a t e ( ) {
i f ( getNumar ()==0)
a d d F i e l d E r r o r ( numar , I n t r o d u c e t i numerul ) ;
i f ( ( numar>10) | | ( numar <1))
a d d F i e l d E r r o r ( numar , T r e b u i e s a f i e c u p r i n s i n t r e 1 s i 10 ) ;
}
@Override
public S t r i n g e x e c u t e ( ) {
int deGhicit ;
I n t e g e r o b j I n c e r c a r i =( I n t e g e r ) s e s s i o n . g e t ( i n c e r c a r i ) ;
i f ( o b j I n c e r c a r i==n u l l ) {
Random random=new Random ( ) ;
d e G h i c i t=random . n e x t I n t ( 1 0 ) + 1 ;
s e s s i o n . put ( g u e s s ,new I n t e g e r ( d e G h i c i t ) ) ;
}
else {
d e G h i c i t =(( I n t e g e r ) s e s s i o n . g e t ( g u e s s ) ) . i n t V a l u e ( ) ;
1.2. STRUTS 2
i n c e r c a r i=o b j I n c e r c a r i . i n t V a l u e ( ) ;
}
i n c e r c a r i ++;
s e s s i o n . put ( i n c e r c a r i ,new I n t e g e r ( i n c e r c a r i ) ) ;
i f ( numar==d e G h i c i t ) {
s e s s i o n . remove ( g u e s s ) ;
s e s s i o n . remove ( i n c e r c a r i ) ;
return SUCCESS ;
}
else {
i f ( i n c e r c a r i==m a x I n c e r c a r i ) {
s e s s i o n . remove ( g u e s s ) ;
s e s s i o n . remove ( i n c e r c a r i ) ;
return ERROR;
}
else {
return INPUT ;
}
}
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
success.jsp
1
2
3
4
5
6
7
8
9
35
36
CAPITOLUL 1. APLICAT
II WEB
10
11
12
13
14
15
16
error.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package exemplu ;
import j a v a . u t i l . Map ;
import j a v a . u t i l . Random ;
import com . opensymphony . xwork2 . A c t i o n ;
import com . opensymphony . xwork2 . A c t i o n I n v o c a t i o n ;
import com . opensymphony . xwork2 . i n t e r c e p t o r . I n t e r c e p t o r ;
2
3
4
5
6
11
@Override
1.2. STRUTS 2
public void d e s t r o y ( ) {
// TODO Autog e n e r a t e d method s t u b
}
12
13
14
@Override
public void i n i t ( ) {
// TODO Autog e n e r a t e d method s t u b
}
16
17
18
19
@Override
public S t r i n g i n t e r c e p t ( A c t i o n I n v o c a t i o n a c t i o n I n v o c a t i o n )
throws E x c e p t i o n {
// Se p r e i a s e s i u n e a
Map s e s s i o n=a c t i o n I n v o c a t i o n . g e t I n v o c a t i o n C o n t e x t ( ) . g e t S e s s i o n ( ) ;
// F i x e a z a numarul a l e a t o r l a i n c e p u t u l a p l i c a t i e i
i f ( ! s e s s i o n . c o n t a i n s K e y ( g u e s s ) | | ! ( s e s s i o n . g e t ( g u e s s ) != n u l l ) ) {
Random random = new Random ( ) ;
i n t d e G h i c i t = random . n e x t I n t ( 1 0 ) + 1 ;
s e s s i o n . put ( g u e s s , d e G h i c i t ) ;
}
// I n v o c a r e a c e l o r l a l t e s a r c i n i
return a c t i o n I n v o c a t i o n . i n v o k e ( ) ;
}
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
37
Metoda invoke a clasei ActionInvocation apeleaza urmatorul pas din procesarea interceptorilor iar n final se returneaza un cod de retur.
Modificarile suferite de cele trei componente sunt
Componenta control
1
2
3
4
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Componenta model
1
2
package exemplu ;
import j a v a . u t i l . Map ;
38
3
4
6
7
8
9
10
11
13
14
15
16
17
18
20
21
22
23
24
25
27
28
29
30
31
32
34
35
36
37
39
40
41
42
43
44
45
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
CAPITOLUL 1. APLICAT
II WEB
import o r g . apache . s t r u t s 2 . i n t e r c e p t o r . S e s s i o n A w a r e ;
import com . opensymphony . xwork2 . A c t i o n S u p p o r t ;
public c l a s s GuessNumber extends A c t i o n S u p p o r t
implements S e s s i o n A w a r e {
private i n t numar ;
private i n t i n c e r c a r i =1;
private Map s e s s i o n ;
private i n t m a x I n c e r c a r i =4;
public i n t getNumar ( ) {
return numar ;
}
public void setNumar ( i n t numar ) {
t h i s . numar = numar ;
}
public i n t g e t I n c e r c a r i ( ) {
return i n c e r c a r i ;
}
public void s e t I n c e r c a r i ( i n t i n c e r c a r i ) {
this . i n c e r c a r i = i n c e r c a r i ;
}
public void s e t M a x I n c e r c a r i ( i n t m a x I n c e r c a r i ) {
this . maxIncercari = maxIncercari ;
}
public i n t g e t M a x I n c e r c a r i ( ) {
return m a x I n c e r c a r i ;
}
@Override
public void s e t S e s s i o n (Map s e s s i o n ) {
this . s e s s i o n = s e s s i o n ;
}
public void v a l i d a t e ( ) {
i f ( getNumar ()==0) {
a d d F i e l d E r r o r ( numar , I n t r o d u c e t i numerul ) ;
}
i f ( ( numar>10) | | ( numar <1))
a d d F i e l d E r r o r ( numar , T r e b u i e s a f i e c u p r i n s i n t r e 1 s i 10 ) ;
}
@Override
public S t r i n g e x e c u t e ( ) {
i n t d e G h i c i t =(( I n t e g e r ) s e s s i o n . g e t ( g u e s s ) ) . i n t V a l u e ( ) ;
I n t e g e r o b j I n c e r c a r i =( I n t e g e r ) s e s s i o n . g e t ( i n c e r c a r i ) ;
i f ( o b j I n c e r c a r i != n u l l ) {
i n c e r c a r i=o b j I n c e r c a r i . i n t V a l u e ( ) ;
}
System . out . p r i n t l n ( i n c e r c a r i+ +numar+ +d e G h i c i t ) ;
i n c e r c a r i ++;
s e s s i o n . put ( i n c e r c a r i ,new I n t e g e r ( i n c e r c a r i ) ) ;
i f ( numar==d e G h i c i t ) {
s e s s i o n . remove ( g u e s s ) ;
s e s s i o n . remove ( i n c e r c a r i ) ;
return SUCCESS ;
}
39
1.2. STRUTS 2
else {
i f ( i n c e r c a r i==m a x I n c e r c a r i ) {
s e s s i o n . remove ( g u e s s ) ;
s e s s i o n . remove ( i n c e r c a r i ) ;
return ERROR;
}
else {
return INPUT ;
}
}
62
63
64
65
66
67
68
69
70
71
72
73
1.2.5
<%@ t a g l i b p r e f i x= s u r i= / s t r u t s t a g s %>
<html>
<head>
<t i t l e >
C a l c u l u l c e l u i mai mare d i v i z o r comun a două numere n a t u r a l e
</ t i t l e >
</head>
<body>
<h3> I n t r o d u c e ţ i </h3>
<s : form a c t i o n=cmmdc>
<s : t e x t f i e l d l a b e l= Primul numar name=m/>
<s : t e x t f i e l d l a b e l= Al d o i l e a numar name=n />
<s : submit v a l u e= C a l c u l e a z a />
</s : form>
</body>
</html>
cu actiunea corespunzatoare
40
CAPITOLUL 1. APLICAT
II WEB
package a c t i o n s ;
import com . opensymphony . xwork2 . A c t i o n C o n t e x t ;
import j a v a . u t i l . Map ;
import o r g . apache . s t r u t s 2 . c o n v e n t i o n . a n n o t a t i o n . R e s u l t ;
public c l a s s CmmdcAction{
public S t r i n g e x e c u t e ( ) {
long c=cmmdc(m, n ) ;
Map a t t r=A c t i o n C o n t e x t . g e t C o n t e x t ( ) . g e t S e s s i o n ( ) ;
a t t r . put ( cmmdc , (new Long ( c ) ) . t o S t r i n g ( ) ) ;
return s u c c e s s ;
}
1
2
3
9
10
11
12
13
14
16
18
private long m;
public long getM ( ) {
return m;
}
public void setM ( long m) {
t h i s .m = m;
}
19
20
21
22
23
24
private long n ;
public long getN ( ) {
return n ;
}
public void setN ( long n ) {
this . n = n ;
}
private S t r i n g message ;
public void s e t M e s s a g e ( S t r i n g message ) {
t h i s . message = message ;
}
public S t r i n g g e t M e s s a g e ( ) {
return message ;
}
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package a c t i o n s ;
import com . opensymphony . xwork2 . A c t i o n S u p p o r t ;
import o r g . apache . s t r u t s 2 . c o n v e n t i o n . a n n o t a t i o n . A c t i o n ;
import o r g . apache . s t r u t s 2 . c o n v e n t i o n . a n n o t a t i o n . R e s u l t ;
@Result ( name= s u c c e s s , l o c a t i o n= / j s p /ResultCmmdc . j s p )
@Action ( cmmdc )
public c l a s s Cmmdc extends A c t i o n S u p p o r t {
public S t r i n g e x e c u t e ( ) throws E x c e p t i o n {
. . .
10
11
12
1.2. STRUTS 2
41
cu
1
2
3
4
6
7
9
10
11
13
14
15
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package a c t i o n s ;
import com . opensymphony . xwork2 . A c t i o n C o n t e x t ;
import j a v a . u t i l . ;
import j a v a . i o . ;
import o r g . apache . s t r u t s 2 . c o n v e n t i o n . a n n o t a t i o n . R e s u l t ;
@Result ( name= s u c c e s s , l o c a t i o n= / j s p /AppJud . j s p )
public c l a s s L i s t a j u d A c t i o n {
private HashMap<S t r i n g , RefJudet> r e f J u d e t e=
new HashMap<S t r i n g , RefJudet > ( ) ;
public S t r i n g e x e c u t e ( ) {
return s u c c e s s ;
}
public L i s t <RefJudet> g e t J u d e t e L i s t ( ) throws IOException {
L i s t <RefJudet> l i s t =new A r r a y L i s t <RefJudet > ( ) ;
InputStream f i s =t h i s . g e t C l a s s ( ) . g e t R e s o u r c e A s S t r e a m ( j u d e t e . t x t ) ;
InputStreamReader i s r =new InputStreamReader ( f i s ) ;
B u f f e r e d R e a d e r br=new B u f f e r e d R e a d e r ( i s r ) ;
S t r i n g s= , jud , c a p i t , a b r e v ;
do{
s=br . r e a d L i n e ( ) ;
i f ( s != n u l l ) {
S t r i n g [ ] s t=s . s p l i t ( ) ;
j u d=s t [ 0 ] ;
c a p i t=s t [ 1 ] ;
a b r e v=s t [ 2 ] ;
R e f J u d e t bean=new R e f J u d e t ( ) ;
bean . s e t J u d ( j u d ) ;
bean . s e t C a p i t ( c a p i t ) ;
bean . s e t A b r e v ( a b r e v ) ;
l i s t . add ( bean ) ;
r e f J u d e t e . put ( jud , bean ) ;
}
}
while ( s != n u l l ) ;
Map a t t r=A c t i o n C o n t e x t . g e t C o n t e x t ( ) . g e t S e s s i o n ( ) ;
a t t r . put ( r e f J u d e t e , r e f J u d e t e ) ;
42
return l i s t ;
41
42
43
CAPITOLUL 1. APLICAT
II WEB
<%@ t a g l i b p r e f i x= s u r i= / s t r u t s t a g s %>
<html>
<head>
< t i t l e>R e f e r i n t e Judet</ t i t l e>
</head>
<body>
<h1> R e f e r i n t e d e s p r e j u d e t e </h1>
<p/>
<s : form action= judbean >
<s : s e l e c t name= s e l e c t a t l a b e l= J u d e t e
l i s t = j u d e t e L i s t l i s t K e y=%{j u d } l i s t V a l u e=%{j u d } />
<s : submit />
</ s : form>
</body>
</html>
package a c t i o n s ;
import j a v a . u t i l . ;
import com . opensymphony . xwork2 . A c t i o n C o n t e x t ;
import o r g . apache . s t r u t s 2 . c o n v e n t i o n . a n n o t a t i o n . R e s u l t ;
@Result ( name= s u c c e s s , l o c a t i o n= / j s p / R e s u l t J u d . j s p )
public c l a s s JudbeanAction {
private S t r i n g j u d=n u l l ;
private S t r i n g c a p i t=n u l l ;
private S t r i n g a b r e v=n u l l ;
private S t r i n g s e l e c t a t ;
1
2
3
9
10
11
12
14
15
16
17
18
19
20
21
22
23
25
26
27
29
30
31
33
34
35
public S t r i n g e x e c u t e ( ) throws E x c e p t i o n {
Map a t t r=A c t i o n C o n t e x t . g e t C o n t e x t ( ) . g e t S e s s i o n ( ) ;
HashMap<S t r i n g , RefJudet> r e f J u d e t e =
( HashMap<S t r i n g , RefJudet >) a t t r . g e t ( r e f J u d e t e ) ;
R e f J u d e t r j=r e f J u d e t e . g e t ( s e l e c t a t ) ;
j u d=r j . getJud ( ) ;
c a p i t=r j . g e t C a p i t ( ) ;
a b r e v=r j . getAbrev ( ) ;
return s u c c e s s ;
}
public S t r i n g getJud ( ) {
return j u d ;
}
public S t r i n g g e t C a p i t ( ) {
return c a p i t ;
}
public S t r i n g getAbrev ( ) {
return a b r e v ;
}
1.2. STRUTS 2
public void s e t S e l e c t a t ( S t r i n g s e l e c t a t ) {
t h i s . s e l e c t a t=s e l e c t a t ;
}
37
38
39
public S t r i n g g e t S e l e c t a t ( ) {
return s e l e c t a t ;
}
41
42
43
44
43
Adnotarile
org.apache.struts2.convention.annotation.InterceptorRef
org.apache.struts2.convention.annotation.InterceptorRefs
declara interceptorii necesari unei actiuni.
In cazul exemplului tratat n sectiunea dedicata interceptorilor, clasa interceptorului actions.RandomNumber Interceptor ramane nemodificata iar interceptorul se declara n fisierul struts.xml
1
2
3
4
5
6
7
8
9
10
11
12
package a c t i o n s ;
import j a v a . u t i l . Map ;
import j a v a . u t i l . Random ;
import o r g . apache . s t r u t s 2 . i n t e r c e p t o r . S e s s i o n A w a r e ;
import com . opensymphony . xwork2 . A c t i o n S u p p o r t ;
import o r g . apache . s t r u t s 2 . c o n v e n t i o n . a n n o t a t i o n . R e s u l t ;
import o r g . apache . s t r u t s 2 . c o n v e n t i o n . a n n o t a t i o n . R e s u l t s ;
import o r g . apache . s t r u t s 2 . c o n v e n t i o n . a n n o t a t i o n . A c t i o n ;
import o r g . apache . s t r u t s 2 . c o n v e n t i o n . a n n o t a t i o n . I n t e r c e p t o r R e f ;
import o r g . apache . s t r u t s 2 . c o n v e n t i o n . a n n o t a t i o n . I n t e r c e p t o r R e f s ;
@Results ( {
@Result ( name= e r r o r , l o c a t i o n= / j s p / e r r o r . j s p ) ,
@Result ( name= s u c c e s s , l o c a t i o n= / j s p / s u c c e s s . j s p ) ,
@Result ( name= i n p u t , l o c a t i o n= / j s p / i n d e x . j s p ) ,
})
@org . apache . s t r u t s 2 . c o n v e n t i o n . a n n o t a t i o n . ParentPackage ( v a l u e = a n i n t )
@Action ( v a l u e= g u e s s ,
i n t e r c e p t o r R e f s ={@ I n t e r c e p t o r R e f ( r a n d o m I n t e r c e p t o r ) ,
44
CAPITOLUL 1. APLICAT
II WEB
21
23
24
25
1.2.6
Modelul descriptiv
Dezvoltarea aplicatiei consta din:
1. Generarea aplicatiei
set GroupID=action
set ArtifactID=mystruts2
set Version=1.0
set ArchetypeVersion=2.3.24.1
mvn archetype:generate -B
-DgroupId=%GroupID%
-DartifactId=%ArtifactID%
-Dversion=%Version%
-DarchetypeGroupId=org.apache.struts
-DarchetypeArtifactId=struts2-archetype-blank
-DarchetypeVersion=%ArchetypeVersion%
main
|-->
|
|
|
|
|
|
|
|-->
|
|
|-->
|
|
java
|--> action
|
|--> cmmdc
|
|
|
Cmmdc.java
|
|--> appjud
|
|
|
JudBean.java
|
|
|
ListaJudeteAction
|
|
|
RefJudet.java
resources
|
judete.txt
|
struts.xml
webapp
|--> html
|
|
AlegeApp.html
45
1.2. STRUTS 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pom.xml
|-->
|
|
|
|
|-->
|
|
jsp
|
Cmmdc.jsp
|
AppJud.jsp
|
ResultCmmdc.jsp
|
ResultJud.jsp
WEB-INF
|
web.xml
index.html
Modelul programat
Indicam doar diferentele fata de varianta anterioara:
1. In fisierul pom.xml se adauga:
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-convention-plugin</artifactId>
<version>${struts2.version}</version>
</dependency>
46
CAPITOLUL 1. APLICAT
II WEB
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pom.xml
|
|
|
|-->
|
|
|
AppJud.jsp
|
ResultCmmdc.jsp
|
ResultJud.jsp
WEB-INF
|
web.xml
index.html
1.3
47
1.3.1
48
CAPITOLUL 1. APLICAT
II WEB
taglibs-standard-impl-*.jar, taglibs-standard-spec-*.jar
primefaces-*.jar
Richfaces
In toate cazuri se utilizeaza biblioteca de marcaje specifice JSF.
Facelets se impune datorita incompatibilitatilor dintre JSF si JSP n
ciclul de activitati pe care le desfasoara pentru rezolvarea unei apelari.
Partea de model este alcatuita din componente Java (bean) care se
ncarca cu datele furnizate din paginile JSP/Facelets, asigura functionalitatea specifica aplicatiei si constituie sursa de date pentru paginile de
afisare a rezultatelor. Clasele Java trebuie sa implementeze interfata
java.io.Serializable.
JSF instantiaza componentele Java si injecteaza datele n aceste componente.
Controller -ul este dat de fisierul de configurare faces-config.xml n
care se fixeaza
legatura dintre paginile de furnizare a datelor si cele care afiseaza
rezultatul prelucrarii, prin elementele <navigation-rule>. Astfel
elementul <from-view-id> contine referinta la pagina Facelets
/ JSP furnizoare de date;
elementul <navigation-case> declara o posibilitate de iesire.
Corpul acestui element contine:
<from-outcome> element n care se declara stringul care
directioneaza iesirea.
<to-view-id> contine referinta la pagina Facelets / JSP
de afisare a rezultatelor obtinute n urma actiunii corespunzatoare stringului din <from-outcome>.
Toate referinta se raportateaza la contextul aplicatiei.
Elementul <navigation-rule> poate fi evitat prin precizarea n
instructiunea return, din codul actiunii, a fisierului care trateaza
prelucrarea care urmeaza, de exemplu
return "/cmmdcOutput.jsp";
49
50
15
16
17
18
19
20
CAPITOLUL 1. APLICAT
II WEB
<s e r v l e t mapping>
<s e r v l e t name>F a c e s S e r v l e t</ s e r v l e t name>
<u r l p a t t e r n> . f a c e s sau . j s f</ u r l p a t t e r n>
</ s e r v l e t mapping>
. . .
</webapp>
1.3.2
Marcaje JSF
51
Fel
obligatoriu
optional
optional
optional
Descriere
Campul componentei Java alimentat.
true / false, pentru validare.
Numele simbolic al campului.
Referinta la metoda de validare.
Fel
obligatoriu
optional
optional
optional
Descriere
Campul componentei Java alimentat.
true / false, pentru validare.
Numele simbolic al campului.
Referinta la metoda de validare.
52
CAPITOLUL 1. APLICAT
II WEB
1.3.3
<html>
<h : form>
<h : p a n e l G r i d columns= 2 >
<h : outputText value= Primul numă r />
<h : i n p u t T e x t value=#{cb . sm} />
<h : outputText value= Al d o i l e a numă r />
<h : i n p u t T e x t value=#{cb . sn } />
<h : commandButton action=#{cb . compute } value= C a l c u l e a z ă />
</h : p a n e l G r i d>
</h : form>
</html>
53
54
CAPITOLUL 1. APLICAT
II WEB
<ui:fragment>
. . .
</ui:fragment>
Prin elementul
<ui:param name="nume_parametru" value="#{componentaJava.camp}"/>
se pot transmite parametrii catre un document xhtml. Utilizarea acestei variante ofera o generalitate marita documentului xhtml
Fie sablonul template.xhtml
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
<html>
<body>
<i>F a c e l e t s t e c h n o l o g y</ i>
</body>
</html>
Intre titlu si subsol s-a introdus un tabel cu doua coloane pentru un meniu
(sidemenu) si pentru zona body.
55
Exemplul 1.3.1 Calculul celui mai mare divizor comun a doua numere naturale.
Pe acest sablon se dezvolta paginile Facelets de introducere a datelor (cmmdcInput.xhtml ) si de afisare a rezultatelor (cmmdcOutput.xhtml ):
1
2
3
4
5
6
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1
2
3
4
5
6
8
9
10
11
12
13
14
15
16
17
package cmmdc ;
4
5
6
56
public CmmdcBean ( ) { }
public S t r i n g getSm ( ) {
return sm ;
}
10
11
12
14
15
16
public S t r i n g getSn ( ) {
return sn ;
}
18
19
20
public void s e t S n ( S t r i n g sn ) {
t h i s . sn=sn ;
}
22
23
24
public S t r i n g g e t S r e s u l t ( ) {
return s r e s u l t ;
}
public S t r i n g compute ( ) {
long m=Long . par se Lon g ( sm ) ;
long n=Long . p ars eL ong ( sn ) ;
long c=cmmdc(m, n ) ;
s r e s u l t =(new Long ( c ) ) . t o S t r i n g ( ) ;
return OK ;
}
26
27
28
29
30
31
32
33
34
35
37
38
CAPITOLUL 1. APLICAT
II WEB
57
<html>
<body>
<center>
<h1> A p l i c a ţ i e JSF </h1>
<a href= / m y j s f F a c e l e t s /cmmdcInput . f a c e s >
A p l i c a ţ i e JSF
</a>
</ center>
</body>
</html>
5
6
7
8
9
10
public void s e t L a b e l ( S t r i n g l a b e l ) {
t h i s . l a b e l=l a b e l ;
}
public S t r i n g g e t L a b e l ( ) {
return l a b e l ;
}
12
13
14
15
16
17
public MenuItem ( ) { }
public MenuItem ( S t r i n g u r l , S t r i n g l a b e l ) {
t h i s . u r l=u r l ;
t h i s . l a b e l=l a b e l ;
}
19
20
21
22
23
24
si MenuBean
1
2
3
4
6
7
8
9
10
11
13
14
15
import j a v a . u t i l . C o l l e c t i o n ;
import j a v a . u t i l . A r r a y L i s t ;
public c l a s s MenuBean implements j a v a . i o . S e r i a l i z a b l e {
private C o l l e c t i o n <MenuItem> menus ;
public C o l l e c t i o n <MenuItem> getMenus ( ) {
return menus ;
}
public void setMenus ( C o l l e c t i o n <MenuItem> menus ) {
t h i s . menus=menus ;
}
public MenuBean ( ) {
menus=new A r r a y L i s t <MenuItem > ( ) ;
menus . add (new MenuItem ( cmmdcInput . f a c e s , CMMDC automat ) ) ;
58
16
17
18
19
CAPITOLUL 1. APLICAT
II WEB
59
Valoarea menus a atributului name din elementul <ui:param este introdus n randul 14 din fisierul cmmdcOutput.xhtml Fiecare element al colectiei
menuBean.menus genereaza o linie n sideMenu.
Valoarea menu a atributului var din elementul <c:forEach din liniile 11
si 13 din fisierul sideMenu.xhtml contine nregistrarea curenta din colectia care
se parcurge.
1.3.4
Extensia faces a unei ancore este semnalul prin care serverul Web apeleaza JSF si coincide cu declaratia din elementul <url-pattern> din fisierul
web.xml.
Reluam aplicatia dezvoltata mai sus cu pagini JSP pentru partea de view
Exemplul 1.3.2 Calculul celui mai mare divizor comun a doua numere naturale cu verificarea datelor.
Completam codul clasei cmmdc.CmmdcBean cu codul de verificare a datelor
care se injecteaza sm, sn
1
2
3
4
5
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package cmmdc ;
im po rt j a v a x . f a c e s
im po rt j a v a x . f a c e s
im po rt j a v a x . f a c e s
im po rt j a v a x . f a c e s
. a p p l i c a t i o n . FacesMessage ;
. component . UIComponent ;
. context . FacesContext ;
. validator . ValidatorException ;
p u b l i c c l a s s CmmdcBean implements j a v a . i o . S e r i a l i z a b l e {
. . .
p u b l i c v o i d v a l i d a t e S t r i n g ( F a c e s C o n t e x t c o n t e x t , UIComponent component ,
O b j e c t v a l u e ) throws V a l i d a t o r E x c e p t i o n {
i f ( ( c o n t e x t==n u l l ) | | ( component==n u l l ) ) {
throw new N u l l P o i n t e r E x c e p t i o n ( ) ;
}
i f ( value . t o S t r i n g ( ) . trim ( ) . equals ( ) ) {
throw new V a l i d a t o r E x c e p t i o n ( new FacesMessage (
Nu a t i c o m p l e t a t campul ) ) ;
}
else{
S t r i n g s=v a l u e . t o S t r i n g ( ) ;
try {
Long . pa rse Lo ng ( s ) ;
}
c a t c h ( NumberFormatException e ) {
throw new V a l i d a t o r E x c e p t i o n ( new FacesMessage ( Nu e s t e numar ) ) ;
}
}
}
}
60
CAPITOLUL 1. APLICAT
II WEB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html>
<body>
<center>
<h1> A p l i c a ţ i i JSF </h1>
<table border=2>
<tr>
<td>
<a href= / myjsfJSP /cmmdc . j s p >
Cmmdc cu p r e l u a r e automat ă a d a t e l o r
</a>
</td>
</ tr>
</ table>
</ center>
</body>
</html>
cmmdcInput.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
cmmdcOutput.jsp
1
2
3
4
5
6
7
8
9
61
4
5
6
7
9
10
11
12
13
14
15
16
17
19
20
21
22
23
24
25
<n a v i g a t i o n r u l e>
<d e s c r i p t i o n />
<fromviewi d>/cmmdcInput . j s p</ fromviewi d>
<n a v i g a t i o n c a s e>
<d e s c r i p t i o n />
<fromoutcome>OK</ fromoutcome>
<toviewi d>/cmmdcOutput . j s p</ toviewi d>
</ n a v i g a t i o n c a s e>
</ n a v i g a t i o n r u l e>
<managedbean>
<d e s c r i p t i o n />
<managedbeanname>cb</managedbeanname>
<managedbeanc l a s s>cmmdc . CmmdcBean</managedbeanc l a s s>
<managedbeans c o p e> s e s s i o n</managedbeans c o p e>
</managedbean>
</ f a c e s c o n f i g>
In exemplul dat, cadrul de lucru JSF injecteaza valorile celor doua numere
n componenta Java cb. Se pot prelua manual datele direct din formular
prin intermediul variabilei de tip ExternalContext, prin care avem acces la
variabile de tip HttpServletRequest, HttpSession.
ExternalContext context =
FacesContext.getCurrentInstance().getExternalContext();
HttpServletRequest request=(HttpServletRequest)context.getRequest();
HttpSession session=(HttpSession)context.getSession(true);
n care caz, n fisierul cmmdcInput.jsp trebuie denumita formularul de preluare
prin
<h:form id="myform" >
Fisierul CmmdcBean.java devine
1
2
3
4
6
7
package cmmdc1 ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e q u e s t ;
import j a v a x . f a c e s . c o n t e x t . F a c e s C o n t e x t ;
import j a v a x . f a c e s . c o n t e x t . E x t e r n a l C o n t e x t ;
public c l a s s CmmdcBean implements j a v a . i o . S e r i a l i z a b l e {
private S t r i n g s r e s u l t ;
62
CAPITOLUL 1. APLICAT
II WEB
public CmmdcBean ( ) { }
9
11
13
public S t r i n g g e t S r e s u l t ( ) {
return s r e s u l t ;
}
14
15
public S t r i n g compute ( ) {
ExternalContext context =
FacesContext . g e t C u r r e n t I n s t a n c e ( ) . getExternalContext ( ) ;
H t t p S e r v l e t R e q u e s t r e q u e s t =( H t t p S e r v l e t R e q u e s t ) c o n t e x t . g e t R e q u e s t ( ) ;
S t r i n g sm = r e q u e s t . g e t P a r a m e t e r ( myform : sm ) ;
S t r i n g sn = r e q u e s t . g e t P a r a m e t e r ( myform : sn ) ;
long m=Long . par se Lon g ( sm ) ;
long n=Long . p ars eL ong ( sn ) ;
long c=cmmdc(m, n ) ;
s r e s u l t =(new Long ( c ) ) . t o S t r i n g ( ) ;
return OK ;
}
17
18
19
20
21
22
23
24
25
26
27
28
29
public CmmdcBean ( ) { }
10
11
12
13
14
16
17
18
19
20
21
25
public long g e t R e s u l t ( ) {
return r e s u l t ;
}
27
23
24
r e s u l t=cmmdc(m, n ) ;
28
29
31
32
63
ackage
import
import
import
import
import
cmmdc . c o n t r o l l e r ;
j a v a x . f a c e s . component . UIInput ;
j a v a x . f a c e s . component . UIOutput ;
j a v a x . f a c e s . a p p l i c a t i o n . FacesMessage ;
javax . f a c e s . context . FacesContext ;
cmmdc . model . CmmdcBean ;
64
CAPITOLUL 1. APLICAT
II WEB
50
51
52
53
54
55
56
57
58
59
60
si cmmdcOutput.jsp
1
2
3
4
5
6
7
8
9
10
65
4
5
6
7
9
10
11
12
13
14
15
16
17
19
20
21
22
23
24
25
26
27
28
29
30
32
33
34
35
36
37
38
<n a v i g a t i o n r u l e>
<d e s c r i p t i o n />
<fromviewi d>/cmmdcInput . j s p</ fromviewi d>
<n a v i g a t i o n c a s e>
<d e s c r i p t i o n />
<fromoutcome>OK</ fromoutcome>
<toviewi d>/cmmdcOutput . j s p</ toviewi d>
</ n a v i g a t i o n c a s e>
</ n a v i g a t i o n r u l e>
<managedbean>
<d e s c r i p t i o n />
<managedbeanname>cmmdcController</managedbeanname>
<managedbeanc l a s s>
cmmdc . c o n t r o l l e r . CmmdcController
</managedbeanc l a s s>
<managedbeans c o p e>r e q u e s t</managedbeans c o p e>
<managedp r o p e r t y>
<p r o p e r t y name>cmmdcBean</ p r o p e r t y name>
<v a l u e>#{cmmdcBean}</ v a l u e>
</managedp r o p e r t y>
</managedbean>
<managedbean>
<d e s c r i p t i o n />
<managedbeanname>cmmdcBean</managedbeanname>
<managedbeanc l a s s>cmmdc . model . CmmdcBean</managedbeanc l a s s>
<managedbeans c o p e>none</managedbeans c o p e>
</managedbean>
</ f a c e s c o n f i g>
66
CAPITOLUL 1. APLICAT
II WEB
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
<p>
<h : form >
<h : p a n e l G r i d columns= 3 >
<h : outputText value= Primul numar e s t e />
<h : i n p u t T e x t id=m r e q u i r e d= t r u e
value=#{cmmdcController . cmmdcBean .m}
b i n d i n g=#{cmmdcController . primulNumar } />
<h : message f o r=m />
<h : outputText value= Al d o i l e a numar e s t e />
<h : i n p u t T e x t id=n r e q u i r e d= t r u e
value=#{cmmdcController . cmmdcBean . n}
b i n d i n g=#{cmmdcController . alDoileaNumar } />
<h : message f o r=n />
<h : commandButton id= submit value= C a l c u l e a z a
action=#{cmmdcController . cmmdc} />
</h : p a n e l G r i d>
</h : form>
<h : outputFormat b i n d i n g=#{cmmdcController . r e z u l t a t }
r e n d e r e d= f a l s e >
<h : outputText
value=Cmmdc = #{cmmdcController . cmmdcBean . r e s u l t } />
</h : outputFormat>
</ f : view> .
</body>
</html>
4
5
6
7
9
10
11
12
13
14
15
16
17
18
19
20
22
23
24
25
26
27
28
<managedbean>
<d e s c r i p t i o n />
<managedbeanname>cmmdcController</managedbeanname>
<managedbeanc l a s s>
cmmdc . c o n t r o l l e r . CmmdcController
</managedbeanc l a s s>
<managedbeans c o p e>r e q u e s t</managedbeans c o p e>
<managedp r o p e r t y>
<p r o p e r t y name>cmmdcBean</ p r o p e r t y name>
<v a l u e>#{cmmdcBean}</ v a l u e>
</managedp r o p e r t y>
</managedbean>
<managedbean>
<d e s c r i p t i o n />
<managedbeanname>cmmdcBean</managedbeanname>
<managedbeanc l a s s>cmmdc . model . CmmdcBean</managedbeanc l a s s>
<managedbeans c o p e>none</managedbeans c o p e>
</managedbean>
</ f a c e s c o n f i g>
Exemplul 1.3.3 Un fisier text contine informatiile {nume judet, capitala jude-
67
package appjud ;
public c l a s s R e f J u d e t implements j a v a . i o . S e r i a l i z a b l e {
private S t r i n g j u d ;
private S t r i n g c a p i t ;
private S t r i n g a b r e v ;
public R e f J u d e t ( ) { }
public void s e t J u d ( S t r i n g j u d ) {
t h i s . j u d=j u d ;
}
10
11
public S t r i n g getJud ( ) {
return j u d ;
}
13
14
15
public void s e t C a p i t ( S t r i n g c a p i t ) {
t h i s . c a p i t=c a p i t ;
}
17
18
19
public S t r i n g g e t C a p i t ( ) {
return c a p i t ;
}
21
22
23
public void s e t A b r e v ( S t r i n g a b r e v ) {
t h i s . a b r e v=a b r e v ;
}
25
26
27
public S t r i n g getAbrev ( ) {
return a b r e v ;
}
29
30
31
32
package appjud ;
import j a v a x . f a c e s . model . S e l e c t I t e m ;
import j a v a . u t i l . A r r a y L i s t ;
import j a v a . u t i l . HashMap ;
import j a v a . u t i l . C o l l e c t i o n ;
import j a v a . i o . InputStream ;
import j a v a . i o . InputStreamReader ;
import j a v a . i o . B u f f e r e d R e a d e r ;
import j a v a x . s e r v l e t . h t t p . H t t p S e s s i o n ;
import j a v a x . f a c e s . c o n t e x t . E x t e r n a l C o n t e x t ;
import j a v a x . f a c e s . c o n t e x t . F a c e s C o n t e x t ;
68
13
14
CAPITOLUL 1. APLICAT
II WEB
16
18
public CountyBean ( ) {
j u d e t e=new A r r a y L i s t <S e l e c t I t e m > ( 5 0 ) ;
try {
InputStream f i s =t h i s . g e t C l a s s ( ) . g e t R e s o u r c e A s S t r e a m ( j u d e t e . t x t ) ;
InputStreamReader i s r =new InputStreamReader ( f i s ) ;
B u f f e r e d R e a d e r br=new B u f f e r e d R e a d e r ( i s r ) ;
S t r i n g s= , jud , c a p i t , a b r e v ;
do{
s=br . r e a d L i n e ( ) ;
i f ( s != n u l l ) {
S t r i n g [ ] s t=s . s p l i t ( ) ;
j u d=s t [ 0 ] ;
c a p i t=s t [ 1 ] ;
a b r e v=s t [ 2 ] ;
j u d e t e . add (new S e l e c t I t e m ( jud , j u d ) ) ;
19
20
21
22
23
24
25
26
27
28
29
30
31
32
R e f J u d e t r j=new R e f J u d e t ( ) ;
r j . setJud ( jud ) ;
r j . setCapit ( capit ) ;
r j . setAbrev ( abrev ) ;
r e f J u d e t e . put ( jud , r j ) ;
34
35
36
37
38
}
}
while ( s != n u l l ) ;
E x t e r n a l C o n t e x t c o n t e x t=
FacesContext . g e t C u r r e n t I n s t a n c e ( ) . getExternalContext ( ) ;
H t t p S e s s i o n s e s s i o n =( H t t p S e s s i o n ) c o n t e x t . g e t S e s s i o n ( true ) ;
session . setAttribute ( refJudete , refJudete ) ;
br . c l o s e ( ) ;
isr . close ();
f i s . close ();
39
40
41
42
43
44
45
46
47
48
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( CountyBeanException : +e . g e t M e s s a g e ( ) ) ;
}
49
50
51
52
53
55
56
57
58
package appjud ;
import j a v a . u t i l . HashMap ;
import j a v a x . s e r v l e t . h t t p . H t t p S e s s i o n ;
import j a v a x . f a c e s . c o n t e x t . E x t e r n a l C o n t e x t ;
import j a v a x . f a c e s . c o n t e x t . F a c e s C o n t e x t ;
1
2
3
4
10
private S t r i n g j u d=n u l l ;
private S t r i n g c a p i t=n u l l ;
private S t r i n g a b r e v=n u l l ;
12
public JudBean ( ) { }
14
public S t r i n g e x e c u t e ( ) {
ExternalContext context =
FacesContext . g e t C u r r e n t I n s t a n c e ( ) . getExternalContext ( ) ;
H t t p S e s s i o n s e s s i o n =( H t t p S e s s i o n ) c o n t e x t . g e t S e s s i o n ( true ) ;
HashMap<S t r i n g , RefJudet> r e f J u d e t e =
( HashMap<S t r i n g , RefJudet >) s e s s i o n . g e t A t t r i b u t e ( r e f J u d e t e ) ;
R e f J u d e t r j=r e f J u d e t e . g e t ( j u d ) ;
c a p i t=r j . g e t C a p i t ( ) ;
a b r e v=r j . getAbrev ( ) ;
return OK ;
}
8
9
15
16
17
18
19
20
21
22
23
24
public void s e t J u d ( S t r i n g j u d ) {
t h i s . j u d=j u d ;
}
26
27
28
public S t r i n g getJud ( ) {
return j u d ;
}
30
31
32
public S t r i n g g e t C a p i t ( ) {
return c a p i t ;
}
34
35
36
public S t r i n g getAbrev ( ) {
return a b r e v ;
}
38
39
40
41
69
70
CAPITOLUL 1. APLICAT
II WEB
21
22
23
</ f : view>
</body>
</html>
appjudOutput.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1.3.5
71
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
Un fisier cu componente grafice primefaces va avea extensia xhtml si va avea
structura
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
. . .
</h:head>
<h:body>
. . .
</h:body>
</html>
Fel
optional
optional
optional
Descriere
Numele simbolic al elementului.
Textul din antet.
Text subsol.
p:panelGrid Tablou.
Atribute ale marcajului:
Atribut
id
columns
cellpadding
Fel
optional
optional
optional
Descriere
Numele simbolic al elementului.
Numarul coloanelor.
Distanta dintre coloane n pixeli.
72
CAPITOLUL 1. APLICAT
II WEB
Atribut
value
actionListener
update
Fel
optional
obligatoriu
optional
Descriere
textul butonului.
Numele actiunii.
Lista componentelor care vor
fi modificate.
Fel
optional
optional
optional
Descriere
Numele simbolic al elementului.
Campul componentei Java alimentat.
Lista componentelor care vor
fi modificate.
Exemplul 1.3.4
Componenta view pentru aplicatia de calcul a celui mai mare divizor comun.
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
33
73
Exemplul 1.3.5
Componenta view pentru exemplul cu afisarea datelor unui judet.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
74
25
26
27
28
29
30
31
32
33
CAPITOLUL 1. APLICAT
II WEB
<h : outputText
<h : outputText
<h : outputText
<h : outputText
</p : p a n e l G r i d>
</p : p a n e l>
</h : form>
</h : body>
</html>
id= out8
id= out4
id= out9
id= out5
Inc
arcarea unui fisier - Upload
Exemplul 1.3.6 Aplicatie de ncarcare a unui fisier text (cu extensia txt) de
dimensiune cel mult 1024 de octeti. Fisierul ncarcat va fi afisat.
Solutia bazata pe resursele JSF propriu-zise, utilizand adnotari are codul
1
2
3
4
5
6
7
8
9
10
11
12
14
15
16
17
19
20
21
22
23
25
26
27
28
29
30
31
32
33
34
35
36
37
import
import
import
import
import
import
import
import
import
import
import
import
j a v a x . f a c e s . a p p l i c a t i o n . FacesMessage ;
j a v a x . f a c e s . bean . ManagedBean ;
j a v a x . f a c e s . bean . ViewScoped ;
j a v a x . f a c e s . bean . RequestScoped ;
j a v a x . f a c e s . component . UIComponent ;
javax . f a c e s . context . FacesContext ;
javax . f a c e s . v a l i d a t o r . ValidatorException ;
j a v a x . s e r v l e t . h t t p . Part ;
j a v a . i o . IOException ;
java . u t i l . ArrayList ;
java . u t i l . List ;
java . u t i l . Scanner ;
import
import
import
import
java .
java .
java .
java .
io
io
io
io
. File ;
. FileOutputStream ;
. OutputStreamWriter ;
. BufferedWriter ;
public S t r i n g u p l o a d F i l e ( ) throws E x c e p t i o n {
try {
S c a n n e r s c a n n e r=new S c a n n e r ( u p l o a d F i l e . g e t I n p u t S t r e a m ( ) ) ;
S t r i n g B u f f e r sb=new S t r i n g B u f f e r ( ) ;
while ( s c a n n e r . h a s N e x t L i n e ( ) )
sb . append ( s c a n n e r . n e x t L i n e ()+ \n ) ;
f i l e C o n t e n t=sb . t o S t r i n g ( ) ;
}
catch ( IOException e ) {
FacesMessage msg =
new FacesMessage ( FacesMessage . SEVERITY ERROR,
e r r o r uploading f i l e ,
null ) ;
F a c e s C o n t e x t . g e t C u r r e n t I n s t a n c e ( ) . addMessage ( null , msg ) ;
}
S t r i n g myFileName=g e t F i l e n a m e ( u p l o a d F i l e ) ;
F i l e f=new F i l e ( webapps / myjsfUpload / up lo ad / +myFileName ) ;
F i l e O u t p u t S t r e a m f o s=new F i l e O u t p u t S t r e a m ( f ) ;
OutputStreamWriter osw=new OutputStreamWriter ( f o s ) ;
B u f f e r e d W r i t e r bw=new B u f f e r e d W r i t e r ( osw ) ;
bw . w r i t e ( f i l e C o n t e n t , 0 , f i l e C o n t e n t . l e n g t h ( ) ) ;
bw . c l o s e ( ) ;
osw . c l o s e ( ) ;
fos . close ();
return uploadOutput ;
}
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
public Part g e t U p l o a d F i l e ( ) {
return u p l o a d F i l e ;
}
66
67
68
70
71
72
public S t r i n g g e t F i l e C o n t e n t ( ) {
return f i l e C o n t e n t ;
}
74
75
76
78
79
80
81
82
83
84
85
86
87
88
89
90
75
76
CAPITOLUL 1. APLICAT
II WEB
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
uploadOutput.xhtml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1.3.6
GroupID=myjsfFacelets
ArtifactID=myjsf
Version=1.0
-B archetype:generate
-DgroupId=%GroupID%
-DartifactId=%ArtifactID%
-Dversion=%Version%
-DarchetypeArtifactId=maven-archetype-webapp
java
|--> myjsf
|
|--> cmmdc
|
|
|
CmmdBean.java
|
|--> cmmdc1
|
|
|
CmmdBean.java
|
|--> appjud
|
|
|
JudBean.java
|
|
|
CountyBean.java
|
|
|
RefJudet.java
resources
|
judete.txt
webapp
|--> WEB-INF
|
|
web.xml
|
|
faces-config.xml
|
footerTemplate.html
|
appjudInput.xhtml
|
appjudOutput.xhtml
|
apps.xhtml
|
cmmdcInput.xhtml
|
cmmdcInput1.xhtml
|
cmmdcOutput.xhtml
|
cmmdcOutput1.xhtml
|
sideMenu.xhtml
|
template.xhtml
|
index.html
77
78
CAPITOLUL 1. APLICAT
II WEB
<artifactId>javax.servlet.jsp.jstl</artifactId>
<version>1.2.1</version>
</dependency>
Capitolul 2
Spring
In prezent exista doua directii majore de realizare a aplicatiilor de tip
enterprise- ntretinerea si utilizarea unei baze de date prin clienti desktop
si/sau Web:
Interfata de programare Java Enterprise Edition (JEE) avand implementari realizate de Oracle si Red Hat - JBoss;
Cadrul de lucru Spring, directie sprijina si de Google.
Cadrul de lucru Spring permite realizarea de asemenea aplicatii care pot fi
executate ntr-un container de servlet si JSP (apache-tomcat, jetty) si nu doar
ntr-un container de aplicatie.
String permite realizarea de legaturi transversale (crosscutting concerns)
ntre componentele unei aplictii prin programare orientata pe aspecte (POA)
(Aspect Oriented Programming - AOP ).
Spring este compus din mai multe module care se pot descarca prin apachemaven.
Spring ofera posibilitatea dezvoltarii unei aplicatii dupa mai multe sabloane
de programare.
2.1
80
CAPITOLUL 2. SPRING
package h e l l o ;
public c l a s s HelloWorld {
private S t r i n g message ;
public void s e t M e s s a g e ( S t r i n g message ) {
t h i s . message = message ;
}
public S t r i n g s a y H e l l o ( ) {
return H e l l o ! + message ;
}
8
9
10
11
package h e l l o ;
import o r g . s p r i n g f r a m e w o r k . c o n t e x t . A p p l i c a t i o n C o n t e x t ;
import o r g . s p r i n g f r a m e w o r k . c o n t e x t . s u p p o r t . C l a s s P a t h X m l A p p l i c a t i o n
Context ;
public c l a s s Main{
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
ApplicationContext context =
new C l a s s P a t h X m l A p p l i c a t i o n C o n t e x t ( HelloWorld . xml ) ;
HelloWorld h e l l o W o r l d=
( HelloWorld ) c o n t e x t . getBean ( HelloWorldBean ) ;
System . out . p r i n t l n ( h e l l o W o r l d . s a y H e l l o ( ) ) ;
}
}
2.1. APLICAT
IE SPRING ELEMENTARA
1
2
3
4
5
6
8
9
10
11
81
<?xml v e r s i o n= 1 . 0 e n c o d i n g=UTF8?>
<beans xmlns= h t t p : / /www. s p r i n g f r a m e w o r k . o r g / schema / beans
xmlns : x s i= h t t p : / /www. w3 . o r g /2001/XMLSchemai n s t a n c e
xmlns : aop= h t t p : / /www. s p r i n g f r a m e w o r k . o r g / schema / aop
x s i : s c h e m a L o c a t i o n= h t t p : / /www. s p r i n g f r a m e w o r k . o r g / schema / beans
h t t p : / /www. s p r i n g f r a m e w o r k . o r g / schema / beans / s p r i n g beans 3 . 0 . xsd >
<bean i d= HelloWorldBean c l a s s= h e l l o . HelloWorld >
<p r o p e r t y name= message v a l u e=Cum va p l a c e S p r i n g ? />
</bean>
</beans>
package h e l l o ;
import o r g . s p r i n g f r a m e w o r k . beans . f a c t o r y . xml . XmlBeanFactory ;
import o r g . s p r i n g f r a m e w o r k . c o r e . i o . C l a s s P a t h R e s o u r c e ;
public c l a s s Main{
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
XmlBeanFactory b e a n F a c t o r y =
new XmlBeanFactory (new C l a s s P a t h R e s o u r c e ( HelloWorld . xml ) ) ;
HelloWorld myBean =
( HelloWorld ) b e a n F a c t o r y . getBean ( HelloWorldBean ) ;
System . out . p r i n t l n ( myBean . s a y H e l l o ( ) ) ;
}
}
3. Varianta cu adnotare
Responsabil de instantierea componentei Java si de injectarea n campul
message este clasa
82
CAPITOLUL 2. SPRING
1
2
3
5
6
7
8
9
10
11
12
package h e l l o ;
import o r g . s p r i n g f r a m e w o r k . c o n t e x t . a n n o t a t i o n . Bean ;
import o r g . s p r i n g f r a m e w o r k . c o n t e x t . a n n o t a t i o n . C o n f i g u r a t i o n ;
@Configuration
public c l a s s H e l l o W o r l d C o n f i g {
public @Bean HelloWorld h e l l o W o r l d ( ) {
HelloWorld bean=new HelloWorld ( ) ;
bean . s e t M e s s a g e ( Cum va p l a c e S p r i n g ? ) ;
return bean ;
}
}
package h e l l o ;
import o r g . s p r i n g f r a m e w o r k . c o n t e x t . a n n o t a t i o n . A n n o t a t i o n C o n f i g
ApplicationContext ;
public c l a s s Main{
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
AnnotationConfigApplicationContext context =
new A n n o t a t i o n C o n f i g A p p l i c a t i o n C o n t e x t ( H e l l o W o r l d C o n f i g . c l a s s ) ;
HelloWorld myBean = ( HelloWorld ) c o n t e x t . getBean ( h e l l o W o r l d ) ;
System . out . p r i n t l n ( myBean . s a y H e l l o ( ) ) ;
}
}
2.2
83
84
6
7
8
9
11
12
<bean i d= v i e w R e s o l v e r c l a s s=
o r g . s p r i n g f r a m e w o r k . web . s e r v l e t . view . I n t e r n a l R e s o u r c e V i e w R e s o l v e r >
14
15
17
18
19
20
CAPITOLUL 2. SPRING
Prin acest fisier de configurare Spring recunoaste clasa controller care participa
la generarea view -ului.
In liniile 11-12 se precizeaza clasa controller.
In liniile 14-15 se precizeaza clasa responsabila cu legatura cu fisierele view.
In liniile 17-18 se precizeaza locatia (prefix ) si extensia (suffix ) fisierelor
view.
Astfel serverul Web si Spring determin
a clasa controller din
fisierul de configurare iar metoda care satisface cererea din clasa
controller prin parametrul de leg
atur
a.
Clasa controller, HelloWorldController, are codul
1
2
3
4
5
7
8
package h e l l o w o r l d . web ;
import j a v a . i o . IOException ;
import o r g . s p r i n g f r a m e w o r k . web . s e r v l e t . ModelAndView ;
import o r g . s p r i n g f r a m e w o r k . s t e r e o t y p e . C o n t r o l l e r ;
import o r g . s p r i n g f r a m e w o r k . web . bind . a n n o t a t i o n . RequestMapping ;
@Controller
public c l a s s H e l l o W o r l d C o n t r o l l e r {
@RequestMapping ( /hw . htm )
public ModelAndView h a n d l e R e q u e s t ( ) {
ModelAndView modelAndView = new ModelAndView ( h e l l o ) ;
modelAndView . addObject ( message , H e l l o World MVC! ) ;
modelAndView . addObject ( d a t e , (new j a v a . u t i l . Date ( ) ) . t o S t r i n g ( ) ) ;
return modelAndView ;
}
10
11
12
13
14
15
16
17
unde
/hm.htm: Parametrul de legatura cu metoda clasei controller ;
hello: Denumirea fisierului view ;
message, date: campuri din view ce urmeaza a fi completate.
85
<html>
<body>
<h1><c : out value= $ { message } /></h1>
<p> Date <c : out value= $ { d a t e } /> </p>
<a href=<c : u r l v a l u e= h e l l o w o r l d . htm/>>R e l u a r e</a>
</body>
</html>
4
5
6
7
8
9
86
CAPITOLUL 2. SPRING
package h e l l o n a m e . model ;
public c l a s s Nume{
private S t r i n g nume= ;
6
7
8
public S t r i n g getNume ( ) {
return nume ;
}
10
11
12
13
package h e l l o n a m e . s e r v i c e ;
import h e l l o n a m e . model . Nume ;
public c l a s s NumeManager{
private Nume name=n u l l ;
1
7
8
9
public S t r i n g s a y H e l l o ( ) {
return Hi +name . getNume ( ) ;
}
11
12
13
14
package h e l l o n a m e . web ;
import o r g . s p r i n g f r a m e w o r k . web . s e r v l e t . ModelAndView ;
import o r g . s p r i n g f r a m e w o r k . s t e r e o t y p e . C o n t r o l l e r ;
import h e l l o n a m e . model . Nume ;
import h e l l o n a m e . s e r v i c e . NumeManager ;
import o r g . s p r i n g f r a m e w o r k . web . bind . a n n o t a t i o n . S e s s i o n A t t r i b u t e s ;
import o r g . s p r i n g f r a m e w o r k . web . bind . a n n o t a t i o n . RequestMapping ;
import o r g . s p r i n g f r a m e w o r k . web . bind . a n n o t a t i o n . M o d e l A t t r i b u t e ;
import o r g . s p r i n g f r a m e w o r k . web . bind . a n n o t a t i o n . RequestMethod ;
import o r g . s p r i n g f r a m e w o r k . u i . ModelMap ;
@Controller
public c l a s s H e l l o N a m e C o n t r o l l e r {
//VARIANTA 1 p e n t r u prima p a g i n a :
// prima p a g i n a ( i n c a z a p e l GET)
/
87
88
CAPITOLUL 2. SPRING
18
19
20
21
23
24
25
26
27
}
/
28
29
//VARIANTA 2 p e n t r u prima p a g i n a :
// prima p a g i n a ( i n c a z a p e l GET)
@RequestMapping ( v a l u e = /newname . htm , method = RequestMethod .GET)
public S t r i n g metodaPrimaPagina ( ModelMap modelMap ) {
Nume nume=new Nume ( ) ;
nume . setNume ( H e l l o World MVC! ) ;
31
32
33
34
35
36
38
39
40
41
42
44
// a 2a p a g i n a ( i n c a z a p e l POST)
@RequestMapping ( v a l u e = /newname . htm , method = RequestMethod . POST)
public ModelAndView metodaADouaPagina ( @ModelAttribute ( command )
Nume nume ) {
NumeManager nm=new NumeManager ( ) ;
nm . setName ( nume ) ;
45
46
47
48
49
S t r i n g myMessage = nm . s a y H e l l o ( ) ;
S t r i n g myDate=(new j a v a . u t i l . Date ( ) ) . t o S t r i n g ( ) ;
51
52
54
55
56
57
58
59
5
6
7
8
9
10
11
12
14
15
16
18
19
21
22
23
24
25
26
27
28
89
x m l n s : c o n t e x t= h t t p : //www. s p r i n g f r a m e w o r k . o r g / schema / c o n t e x t
xmlns:mvc= h t t p : //www. s p r i n g f r a m e w o r k . o r g / schema /mvc
x s i : s c h e m a L o c a t i o n= h t t p : //www. s p r i n g f r a m e w o r k . o r g / schema /mvc
h t t p : //www. s p r i n g f r a m e w o r k . o r g / schema /mvc/ s p r i n g mvc 3 . 0 . xsd
h t t p : //www. s p r i n g f r a m e w o r k . o r g / schema / beans
h t t p : //www. s p r i n g f r a m e w o r k . o r g / schema / beans / s p r i n g beans 3 . 0 . xsd
h t t p : //www. s p r i n g f r a m e w o r k . o r g / schema / c o n t e x t
h t t p : //www. s p r i n g f r a m e w o r k . o r g / schema / c o n t e x t / s p r i n g c o n t e x t 3 . 0 . xsd >
< ! Scaneaza c l a s s p a t h p e n t r u c l a s e a d n o t a t e cu @Components
p t a f i i n r e g i s t r a t e ca beanu r i >
<c o n t e x t : c o m p o n e n t s c a n basepackage= h e l l o n a m e />
< ! A c t i v e a z a a d n o t a r i d i n c o n t r o l e r e , a d n o t a r i v a l i d a r e e t c >
<m v c : a n n o t a t i o n d r i v e n />
<bean i d= v i e w R e s o l v e r c l a s s=
o r g . s p r i n g f r a m e w o r k . web . s e r v l e t . view . I n t e r n a l R e s o u r c e V i e w R e s o l v e r >
<p r o p e r t y name= v i e w C l a s s
v a l u e= o r g . s p r i n g f r a m e w o r k . web . s e r v l e t . view . J s t l V i e w />
<p r o p e r t y name= p r e f i x v a l u e= /WEBINF/ j s p / />
<p r o p e r t y name= s u f f i x v a l u e= . j s p />
</ bean>
</ beans>
90
CAPITOLUL 2. SPRING
4
5
6
7
8
9
10
11
12
15
16
17
19
20
22
23
24
25
26
27
28
30
31
package h e l l o n a m e . web ;
import o r g . s p r i n g f r a m e w o r k . web . s e r v l e t . ModelAndView ;
import o r g . s p r i n g f r a m e w o r k . web . s e r v l e t . view . R e d i r e c t V i e w ;
import o r g . s p r i n g f r a m e w o r k . s t e r e o t y p e . C o n t r o l l e r ;
import o r g . s p r i n g f r a m e w o r k . beans . f a c t o r y . a n n o t a t i o n . Autowired ;
import o r g . s p r i n g f r a m e w o r k . web . bind . a n n o t a t i o n . M o d e l A t t r i b u t e ;
import o r g . s p r i n g f r a m e w o r k . u i . ModelMap ;
import o r g . s p r i n g f r a m e w o r k . web . bind . a n n o t a t i o n . RequestMapping ;
import o r g . s p r i n g f r a m e w o r k . web . bind . a n n o t a t i o n . RequestMethod ;
import h e l l o n a m e . model . Nume ;
import h e l l o n a m e . s e r v i c e . NumeManager ;
@Controller
@RequestMapping ( /newname1 . htm )
public c l a s s F i r s t N a m e C o n t r o l l e r {
@Autowired
private NumeManager nm ;
@RequestMapping ( method = RequestMethod .GET)
public ModelAndView m e t o d a C e r e r e I n i t i a l a ( ) {
21
22
23
24
25
26
28
29
30
31
32
33
34
35
2.
1
2
3
4
5
6
7
9
10
11
12
13
package h e l l o n a m e . web ;
import o r g . s p r i n g f r a m e w o r k . web . s e r v l e t . ModelAndView ;
import o r g . s p r i n g f r a m e w o r k . s t e r e o t y p e . C o n t r o l l e r ;
import o r g . s p r i n g f r a m e w o r k . beans . f a c t o r y . a n n o t a t i o n . Autowired ;
import o r g . s p r i n g f r a m e w o r k . web . bind . a n n o t a t i o n . RequestMapping ;
import o r g . s p r i n g f r a m e w o r k . web . bind . a n n o t a t i o n . RequestMethod ;
import h e l l o n a m e . s e r v i c e . NumeManager ;
@Controller
@RequestMapping ( /newname2 . htm )
public c l a s s S e co n d Na m e Co n t ro l l er {
@Autowired
private NumeManager nm ;
@RequestMapping ( method = RequestMethod .GET)
public ModelAndView metoda ( ) {
S t r i n g myMessage = nm . s a y H e l l o ( ) ;
S t r i n g myDate=(new j a v a . u t i l . Date ( ) ) . t o S t r i n g ( ) ;
ModelAndView modelAndView = new ModelAndView ( h e l l o ) ;
modelAndView . addObject ( message , myMessage ) ;
modelAndView . addObject ( d a t e , myDate ) ;
return modelAndView ;
}
15
16
17
18
19
20
21
22
23
24
91
92
CAPITOLUL 2. SPRING
public c l a s s DouaNumere{
private S t r i n g sm= ;
private S t r i n g sn= ;
4
5
7
8
9
10
11
12
public void s e t S n ( S t r i n g sn ) {
t h i s . sn=sn ;
}
public S t r i n g getSn ( ) {
return sn ;
}
14
15
16
17
18
19
20
package cmmdc . s e r v i c e ;
import cmmdc . model . DouaNumere ;
public c l a s s CmmdcManager{
private DouaNumere data=n u l l ;
public void s e t D a t a ( DouaNumere data ) {
t h i s . data=data ;
}
7
8
9
public S t r i n g cmmdcService ( ) {
long m=Long . par se Lon g ( data . getSm ( ) ) ;
long n=Long . p ars eL ong ( data . getSn ( ) ) ;
return (new Long (cmmdc(m, n ) ) ) . t o S t r i n g ( ) ;
}
11
12
13
14
15
17
18
12
13
14
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
43
44
45
46
47
48
93
94
20
21
22
23
24
25
26
27
28
29
30
CAPITOLUL 2. SPRING
<html>
<body>
<h1> C a l c u l u l c e l u i mai mare d i v i z o r comun </h1>
<p>
Cmmdc(<c : out value= $ {sm} /> ,<c : out value= $ { sn } />)=
<c : out value= $ { message } />
</p>
</body>
</html>
4
5
6
7
8
9
10
11
95
package cmmdc . s e r v i c e ;
import o r g . s p r i n g f r a m e w o r k . v a l i d a t i o n . V a l i d a t o r ;
import o r g . s p r i n g f r a m e w o r k . v a l i d a t i o n . E r r o r s ;
import cmmdc . model . DouaNumere ;
1
2
3
public boolean s u p p o r t s ( C l a s s c l a z z ) {
return DouaNumere . c l a s s . e q u a l s ( c l a z z ) ;
}
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
39
96
CAPITOLUL 2. SPRING
package j u d e t e . model ;
public c l a s s Judet {
private S t r i n g nume= ;
private S t r i n g c a p i t a l a= ;
private S t r i n g a b r e v i e r e= ;
4
5
6
8
9
10
11
12
13
public void s e t A b r e v i e r e ( S t r i n g a b r e v i e r e ) {
t h i s . a b r e v i e r e=a b r e v i e r e ;
}
public S t r i n g g e t A b r e v i e r e ( ) {
return a b r e v i e r e ;
}
15
16
17
18
19
20
public void s e t C a p i t a l a ( S t r i n g c a p i t a l a ) {
t h i s . c a p i t a l a=c a p i t a l a ;
}
public S t r i n g g e t C a p i t a l a ( ) {
return c a p i t a l a ;
}
22
23
24
25
26
27
28
package j u d e t e . s e r v i c e ;
import j u d e t e . model . Judet ;
import j a v a . u t i l . L i s t ;
import j a v a . u t i l . HashMap ;
import j a v a . u t i l . L i n k e d L i s t ;
import j a v a . i o . InputStream ;
import j a v a . i o . F i l e I n p u t S t r e a m ;
import j a v a . i o . InputStreamReader ;
import j a v a . i o . B u f f e r e d R e a d e r ;
public c l a s s JudeteManager {
private HashMap<S t r i n g , Judet> r e f J u d e t e=n u l l ;
private L i s t <S t r i n g > l s t J u d=n u l l ;
JudeteManager ( ) {
r e f J u d e t e=new HashMap<S t r i n g , Judet > ( ) ;
l s t J u d=new L i n k e d L i s t <S t r i n g > ( ) ;
try {
InputStream i s=
new F i l e I n p u t S t r e a m ( / apachetomcat 6 . 0 . 2 6 / webapps / j u d e t e / j u d e t e . t x t ) ;
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
}
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 ( ) ) ;
}
38
39
40
41
42
44
45
46
48
49
50
51
97
Metoda citeste datele dintr-un fisier si creaza o variabila de tip List si una
de tip HashMap. Lista va fi utilizata n formularul adresat clientului iar variabila de tip HashMap se utilizeaza pentru regasirea datelor n vederea furnizarii
rezultatelor.
Clasa controller - judete.web.JudeteController are codul
1
2
3
4
5
6
7
8
9
10
11
12
14
15
16
17
18
20
package j u d e t e . web ;
import o r g . s p r i n g f r a m e w o r k . web . s e r v l e t . ModelAndView ;
import o r g . s p r i n g f r a m e w o r k . web . s e r v l e t . view . R e d i r e c t V i e w ;
import o r g . s p r i n g f r a m e w o r k . s t e r e o t y p e . C o n t r o l l e r ;
import o r g . s p r i n g f r a m e w o r k . beans . f a c t o r y . a n n o t a t i o n . Autowired ;
import o r g . s p r i n g f r a m e w o r k . web . bind . a n n o t a t i o n . M o d e l A t t r i b u t e ;
import o r g . s p r i n g f r a m e w o r k . u i . ModelMap ;
import o r g . s p r i n g f r a m e w o r k . web . bind . a n n o t a t i o n . RequestMapping ;
import o r g . s p r i n g f r a m e w o r k . web . bind . a n n o t a t i o n . RequestMethod ;
import j a v a . u t i l . HashMap ;
import j u d e t e . model . Judet ;
import j u d e t e . s e r v i c e . JudeteManager ;
@Controller
@RequestMapping ( / j u d e t e . htm )
public c l a s s J u d e t e C o n t r o l l e r {
@Autowired
private JudeteManager jm ;
@RequestMapping ( method = RequestMethod .GET)
98
public ModelAndView m e t o d a C e r e r e I n i t i a l a ( ) {
Judet j u d=new Judet ( ) ;
ModelAndView modelAndView=new ModelAndView ( judeteForm ) ;
modelAndView . addObject ( command , j u d ) ;
modelAndView . addObject ( l s t J u d , jm . g e t L s t J u d ( ) ) ;
return modelAndView ;
}
21
22
23
24
25
26
27
// a 2a p a g i n a ( i n c a z a p e l POST)
@RequestMapping ( method = RequestMethod . POST)
public ModelAndView metodaDupaSubmit ( @ModelAttribute ( command ) Judet j u d ) {
System . out . p r i n t l n ( j u d . getNume ( ) ) ;
S t r i n g nume=j u d . getNume ( ) ;
HashMap<S t r i n g , Judet> r e f J u d e t e=jm . g e t R e f J u d e t e ( ) ;
j u d=r e f J u d e t e . g e t ( nume ) ;
ModelAndView modelAndView = new ModelAndView ( j u d e t e ) ;
modelAndView . addObject ( nume , nume ) ;
modelAndView . addObject ( c a p i t a l a , j u d . g e t C a p i t a l a ( ) ) ;
modelAndView . addObject ( a b r e v i e r e a , j u d . g e t A b r e v i e r e ( ) ) ;
return modelAndView ;
}
29
30
31
32
33
34
35
36
37
38
39
40
41
42
CAPITOLUL 2. SPRING
judete.jsp
1
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<html>
<body>
<h1> R e z u l t a t u l c a u t a r i i </h1>
<table border= 1 >
<tr>
<td> Numele j u d e t u l u i </td>
<td> <c : out value= $ {nume} /></td>
</ tr>
<tr>
<td> C a p i t a l a j u d e t u l u i </td>
<td> <c : out value= $ { c a p i t a l a } /></td>
</ tr>
<tr>
<td> A b r e v i e r e a j u d e t u l u i </td>
<td> <c : out value= $ { a b r e v i e r e a } /></td>
</ tr>
</ table>
</body>
</html>
4
5
6
8
10
11
12
13
14
16
17
18
19
20
21
22
23
99
100
CAPITOLUL 2. SPRING
Capitolul 3
Asynchronous JavaScript And
Xml AJAX
AJAX - Asynchronous JavaScript And Xml - permite, pe partea de client,
un schimb de date cu un program server Web, prin functii JavaScript. La baza
se afla o interfata de programare (API - Application Programming Interface)
XMLHttpRequest (XHR), initiata de Microsoft, ce poate fi utilizata de un
limbaj de scripting (JavaScript, JScript, VBScript, etc) pentru
transfer de date catre un server Web utilizand protocolul HTTP;
manipularea datelor XML sau JSON (JavaScript Object Notation).
Caracterul asincron consta n faptul ca raspunsul furnizat de un program server
reface doar o parte din pagina html si nu ntrega pagina, asa cum, de exemplu,
este cazul utilizarii obisnuite a unui servlet.
3.1
AJAX Java
102
open(method,URL,async,userName)
open(method,URL,async,userName,password )
method poate fi get sau post.
async fixeaza natura comunicatiei - true pentru comunicatie asincrona.
send(content)
abord()
getAllResponseHeaders()
getResponseHeader(headerName)
setRequestHeader(label,value)
Propriet
atile interfetei XMLHttpRequest.
onreadystatechange
Contine numele functiei script care prelucreaza raspunsul.
readyState
Indicatorul obiectului XMLHttpRequest: 0 - neinitializat; 1 - deschis; 2 trimis; 3 - receptionat; 4 - ncarcat.
responseText / responseXML
Contine raspunsul sub forma text / xml.
status / statusText
404 - Not Found; 200 - OK.
Punctul de pornire al unei aplicatii AJAX - Java este o pagina Web html. La generarea unui eveniment legat de un element grafic al paginii Web
se apeleaza o serie de functii JavaScript a caror executie realizeaza comunicatia
cu un program server - servlet sau jsp. Uzual, programul server formuleaza un
raspuns sub forma unui fisier xml, care este prelucrat de o functie JavaScript
oferind date clientului.
Simplificand, punem n evidenta 3 functii JavaScript
1. Generarea unui obiect XMLHTTPRequest
1
2
3
4
5
6
7
8
9
103
function initRequest () {
i f ( window . XMLHttpRequest ) {
r e t u r n new XMLHttpRequest ( ) ;
}
else
i f ( window . ActiveXObject ){
r e t u r n new ActiveXObject ( M i c r o s o f t .XMLHTTP ) ;
}
}
f u n c t i o n XXX( ) {
var i d F i e l d=document . getElementById ( numeCimp ) ;
var u r l=
http : / / h o s t : p o r t / c o n t e x t / numeServlet ?numeCimp=+
escape ( idField . value ) ;
var r e q = i n i t R e q u e s t ( ) ;
req . onreadystatechange = function () {
i f ( r e q . r e a d y S t a t e == 4 ) {
i f ( r e q . s t a t u s == 200) {
f u n c t i a P r e l u c r a r e R a s p u n s ( r e q . responseXML ) ;
} else {
a l e r t ( r e q . s t a t u s+ : +r e q . s t a t u s T e x t ) ;
}
}
};
r e q . open ( GET , u r l , t r u e ) ;
r e q . send ( n u l l ) ;
}
Campul responseXML se utilizeaza pentru nmagazinarea unui raspuns
n format XML, iar responseText se utilizeaza pentru preluarea unui
raspuns JSON.
104
import
import
import
import
import
import
import
import
import
j a v a . i o . IOException ;
java . io . PrintWriter ;
javax . s e r v l e t . ServletException ;
javax . s e r v l e t . http . HttpServlet ;
javax . s e r v l e t . http . HttpServletRequest ;
javax . s e r v l e t . http . HttpServletResponse ;
j a v a x . j s o n . JsonArray ;
javax . json . JsonWriter ;
j a v a x . j s o n . Json ;
105
r e s . setContentType ( a p p l i c a t i o n / j s o n ) ;
// j e e
JsonArray j s o n A r r a y=Json . c r e a t e A r r a y B u i l d e r ( )
. add ( Json . c r e a t e O b j e c t B u i l d e r ( )
. add ( nume , A n a l i z a numerica ) )
. add ( Json . c r e a t e O b j e c t B u i l d e r ( )
. add ( nume , Programare d i s t r i b u i t a ) )
. add ( Json . c r e a t e O b j e c t B u i l d e r ( )
. add ( nume , S o f t matematic ) )
. build ( ) ;
J s o n W r i t e r j s o n W r i t e r=Json . c r e a t e W r i t e r ( out ) ;
jsonWriter . writeArray ( jsonArray ) ;
jsonWriter . c los e ( ) ;
33
34
35
36
37
38
39
40
41
42
43
44
45
}
out . c l o s e ( ) ;
46
47
48
50
51
52
53
54
106
1
2
3
4
5
6
8
9
10
11
12
13
14
15
16
17
18
19
import
import
import
import
import
import
j a v a . i o . IOException ;
java . io . PrintWriter ;
javax . s e r v l e t . ServletException ;
javax . s e r v l e t . http . HttpServlet ;
javax . s e r v l e t . http . HttpServletRequest ;
javax . s e r v l e t . http . HttpServletResponse ;
21
22
23
24
25
<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 initRequest () {
i f ( window . XMLHttpRequest ) {
r e t u r n new XMLHttpRequest ( ) ;
}
e l s e i f ( window . A c t i v e X O b j e c t ) {
r e t u r n new A c t i v e X O b j e c t ( M i c r o s o f t .XMLHTTP ) ;
}
}
f u n c t i o n doCompletion ( ) {
var t i p F i e l d=document . g e t E l e m e n t B y I d ( t i p ) ;
var u r l = h t t p : / / l o c a l h o s t : 8 0 8 0 / a j a x / c o m p l e t a r e ? t i p=+
e s c a p e ( t i p F i e l d . value ) ;
var r e q = i n i t R e q u e s t ( ) ;
i f ( r e q != n u l l ) {
r e q . open ( GET , u r l , t r u e ) ;
req . onreadystatechange = function () {
i f ( r e q . r e a d y S t a t e == 4) {
i f ( r e q . s t a t u s == 200) {
p a r s e M e s s a g e s ( r e q . responseXML ) ;
} else {
a l e r t ( r e q . s t a t u s+ : +r e q . s t a t u s T e x t ) ;
}
}
};
r e q . send ( n u l l ) ;
32
33
35
f u n c t i o n p a r s e M e s s a g e s ( responseXML ) {
var o p t i o n a l e = responseXML . getElementsByTagName ( o p t i o n a l e ) [ 0 ] ;
var s e l e c t=document . g e t E l e m e n t B y I d ( a l e g e r e ) ;
f o r ( l o o p = 0 ; l o o p < o p t i o n a l e . c h i l d N o d e s . l e n g t h ; l o o p ++){
var d i s c i p l i n a = o p t i o n a l e . c h i l d N o d e s [ l o o p ] ;
var denumire = d i s c i p l i n a . getElementsByTagName ( denumire ) [ 0 ] ;
var den=denumire . c h i l d N o d e s [ 0 ] . nodeValue ;
s e l e c t . o p t i o n s [ l o o p ]=new Option ( den , den , f a l s e , f a l s e ) ;
}
}
>
</ s c r i p t>
36
37
38
39
40
41
42
43
44
45
46
48
49
50
51
52
< t i t l e>
AutoCompletion u s i n g Asynchronous J a v a S c r i p t and XML (AJAX)
</ t i t l e>
</head>
<body onload= doCompletion ( ) >
54
56
<form name= a u t o f i l l f o r m
action= / a j a x / a l e g e r e a method= g e t >
57
60
62
63
65
66
67
68
69
70
71
<b>D i s c i p l i n a o p t i o n a l : </b>
<s e l e c t name= a l e g e r e id= a l e g e r e >
</ s e l e c t>
<p>
<input type= Submit value= Transmite >
<input type= r e s e t value=Abandon >
<input type= h id de n id= t i p value=xml >
</form>
</body>
</html>
respectiv (indexJSONAlegere.html )
1
2
4
5
6
7
8
9
10
11
12
13
15
16
<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 initRequest () {
i f ( window . XMLHttpRequest ) {
r e t u r n new XMLHttpRequest ( ) ;
}
e l s e i f ( window . A c t i v e X O b j e c t ) {
r e t u r n new A c t i v e X O b j e c t ( M i c r o s o f t .XMLHTTP ) ;
}
}
f u n c t i o n doCompletion ( ) {
var t i p F i e l d=document . g e t E l e m e n t B y I d ( t i p ) ;
107
108
var u r l = h t t p : / / l o c a l h o s t : 8 0 8 0 / a j a x / c o m p l e t a r e ? t i p=+
e s c a p e ( t i p F i e l d . value ) ;
var r e q = i n i t R e q u e s t ( ) ;
i f ( r e q != n u l l ) {
r e q . open ( GET , u r l , t r u e ) ;
req . onreadystatechange = function () {
i f ( r e q . r e a d y S t a t e == 4) {
i f ( r e q . s t a t u s == 200) {
parseMessages ( req . responseText ) ;
} else {
a l e r t ( r e q . s t a t u s+ : +r e q . s t a t u s T e x t ) ;
}
}
};
r e q . send ( n u l l ) ;
}
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
35
f u n c t i o n parseMessages ( responseText ){
var s=e v a l ( r e s p o n s e T e x t ) ;
var s e l e c t=document . g e t E l e m e n t B y I d ( a l e g e r e ) ;
f o r ( var i =0; i<s . l e n g t h ; i ++){
s e l e c t . o p t i o n s [ i ]=new Option ( s [ i ] . nume , s [ i ] . nume , f a l s e , f a l s e ) ;
}
}
>
</ s c r i p t>
36
37
38
39
40
41
42
43
45
46
47
48
49
< t i t l e>
AutoCompletion u s i n g Asynchronous J a v a S c r i p t and JSON (AJAX)
</ t i t l e>
</head>
<body onload= doCompletion ( ) >
51
53
<form name= a u t o f i l l f o r m
action= / a j a x / a l e g e r e a method= g e t >
54
57
59
60
62
63
64
65
66
67
68
<b>D i s c i p l i n a o p t i o n a l : </b>
<s e l e c t name= a l e g e r e id= a l e g e r e >
</ s e l e c t>
<p>
<input type= Submit value= Transmite >
<input type= r e s e t value=Abandon >
<input type= h id de n id= t i p value= j s o n >
</form>
</body>
</html>
Exemplul 3.1.2 Calcul celui mai mare divizor comun a doua numere naturale
cu client AJAX.
Programul servlet este
import
import
import
import
import
import
1
2
3
4
5
j a v a . i o . IOException ;
java . io . PrintWriter ;
javax . s e r v l e t . ServletException ;
javax . s e r v l e t . http . HttpServlet ;
javax . s e r v l e t . http . HttpServletRequest ;
javax . s e r v l e t . http . HttpServletResponse ;
10
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
109
<html>
<head>
<s c r i p t type= t e x t / j a v a s c r i p t >
< !
13
function initRequest () {
i f ( window . XMLHttpRequest ) {
r e t u r n new XMLHttpRequest ( ) ;
} e l s e i f ( window . A c t i v e X O b j e c t ) {
r e t u r n new A c t i v e X O b j e c t ( M i c r o s o f t .XMLHTTP ) ;
}
}
15
f u n c t i o n compute ( ) {
7
8
9
10
11
12
110
var
var
var
var
mField=document . g e t E l e m e n t B y I d ( m ) ;
n F i e l d=document . g e t E l e m e n t B y I d ( n ) ;
t i p F i e l d=document . g e t E l e m e n t B y I d ( t i p ) ;
u r l = h t t p : / / l o c a l h o s t : 8 0 8 0 / a j a x /cmmdc?m= +
e s c a p e ( mField . value)+&n=+e s c a p e ( n F i e l d . value ) +
&t i p= + e s c a p e ( t i p F i e l d . value ) ;
var r e q = i n i t R e q u e s t ( ) ;
req . onreadystatechange = function () {
i f ( r e q . r e a d y S t a t e == 4) {
i f ( r e q . s t a t u s == 200) {
p a r s e M e s s a g e s ( r e q . responseXML ) ;
} else {
a l e r t ( r e q . s t a t u s+ : +r e q . s t a t u s T e x t ) ;
}
}
};
r e q . open ( g e t , u r l , t r u e ) ;
r e q . send ( n u l l ) ;
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
36
37
38
39
40
41
42
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
}
f u n c t i o n p a r s e M e s s a g e s ( responseXML ) {
var r = responseXML . getElementsByTagName ( r e z u l t a t ) [ 0 ] ;
var cmmdc=r . c h i l d N o d e s [ 0 ] . nodeValue ;
document . g e t E l e m e n t B y I d ( r e z u l t a t ) . innerHTML=Cmmdc = +cmmdc ;
}
>
</ s c r i p t>
< t i t l e> Cmmdc AJAX</ t i t l e>
</head>
<body>
<h1>Cmmdc with AJAX</h1>
<p>
Primul numar :
<input type= t e x t id=m value= 1 s i z e= 15 >
<p>
Al d o i l e a numar :
<input type= t e x t id=n value= 1 s i z e= 15 >
<input type= h id de n id= t i p value=xml >
<p>
<input type= b ut to n value= C a l c u l e a z a onClick= compute ( ) >
<p>
Cel mai mare d i v i z o r comun a c e l o r doua numere e s t e
<p>
<div id= r e z u l t a t />
</body>
</html>
Functiile javascript pot fi salvate ntr-un fisier iar referinta la ele se da prin
<script language="javascript" src="fisier_functii.js"
</script>
111
S-au creat mai multe cadre de lucru (framework) pentru dezvoltarea aplicatiilor
Web bazate pe AJAX:
Dojo
GWT
MooTools
Prototype
Yahoo User Interface Library
Buidows
Isomorphic Smart Client
Nexaweb
Ext
jQuery
OpenRico
Scriptaculous
Backbase
Icefaces
JackBe
Dintre acestea se remarca prin eleganta solutiei Google Web Tooltit - (GWT).
112
3.2
3.2.1
113
src
|--> context
|
|--> client
|
|
|
MyApp.java
|
|
|
GreetingService.java
|
|
|
GreetingServiceAsync.java
|
|--> server
|
|
|
GreetingServiceImpl.java
|
|--> shared
|
|
|
FieldVerifier.java
|
|
MyApp.gwt.xml
test
war
|--> WEB-INF
|
|
web.xml
|
MyApp.css
|
MyApp.html
|
favicon.ico
.classpath
.project
MyApp.launch
README.txt
build.xml
114
12
14
20
22
>
24
< ! S p e c i f y t h e app e n t r y p o i n t c l a s s .
<e n t r y p o i n t c l a s s= u n i t b v . c s . td . c l i e n t . MyApp />
>
< ! S p e c i f y t h e p a t h s f o r t r a n s l a t a b l e code
<s o u r c e path= c l i e n t />
<s o u r c e path= s h a r e d />
>
15
16
17
18
19
25
27
28
29
31
</ module>
3.2.2
Aplicatie GWT f
ar
a apel de procedur
a la distant
a
115
1
2
3
4
5
6
7
9
10
11
12
14
15
16
17
18
20
21
22
23
25
26
27
28
29
30
31
32
34
35
36
37
38
39
41
42
43
44
>
>
>
>
>
55
57
<h1>Web A p p l i c a t i o n S t a r t e r P r o j e c t</h1>
46
47
48
49
50
51
52
53
54
116
59
60
61
62
63
64
65
66
67
68
69
70
<table a l i g n= c e n t e r >
<tr>
<td colspan= 2 s t y l e= f o n t w e i g h t : b o l d ; >
P l e a s e e n t e r your name :</td>
</ tr>
<tr>
<td id= n a m e F i e l d C o n t a i n e r ></td>
<td id= s e n d B u t t o n C o n t a i n e r ></td>
</ tr>
</ table>
</body>
</html>
117
TextBox
Constructori:
TextBox()
Metode:
public String getText()
Button
Constructori:
Button(String text)
Metode:
public HandlerRegistration addClickHandler(ClickHandler
clickHandler )
Containere de widget
VerticalPanel
VerticalSplitPanel
HorizontalPanel HorizontalSplitPanel
FlowPanel
DockPanel
Un widget se include ntr-un container cu metoda
void add(Widget widget)
3. Generarea evenimentelor. Activitatile / actiunile care constituie obiectivul aplicatiei GWT se lanseaza printr-un clic pe un buton. Fiecarui buton i se atribuie un obiect care implementeaza interfata ClickHandler.
Activitatile amintite mai sus sunt definite n codul metodei public void
onClick(ClickEvent event).
4. Programarea activitatilor corespunzatoare evenimentelor atasate butoanelor,
adica implementarea metodelor onClick.
5. Fixarea elementelor de stil ale elementelor grafice n fisierul MyApp.css.
Atasarea la un widget a unui element de stil se obtine cu metoda public
void addStyleName(String style).
Urmarim acesti pasi n
Exemplul 3.2.1 Calculul celui mai mare divizor comun a doua numere naturale.
Se genereaza proiectului GWT unitbv.cs.td.Cmmdc
118
Programarea activitatilor corespunzatoare evenimentelor. Acest pas corespunde realizarii clasei MyClickHandler. Pentru fiecare din cele doua
numere se verifica
1. daca sunt furnizare;
2. daca sirul de caractere introdus este numar.
119
c l a s s MyClickHandler implements C l i c k H a n d l e r {
TextBox mTextBox=null , nTextBox=n u l l ;
L a b e l cmmdcLabel=n u l l ;
MyClickHandler ( TextBox mTextBox , TextBox nTextBox , L a b e l cmmdcLabel ) {
t h i s . mTextBox=mTextBox ;
t h i s . nTextBox=nTextBox ;
t h i s . cmmdcLabel=cmmdcLabel ;
}
5
6
7
8
9
11
13
public void o n C l i c k ( C l i c k E v e n t e v e n t ) {
S t r i n g sm=mTextBox . g e t T e x t ( ) ;
S t r i n g sn=nTextBox . g e t T e x t ( ) ;
long m=0 ,n=0;
i f ( sm . e q u a l s ( ) ) {
Window . a l e r t ( \ m\ nu e s t e dat ) ;
//GWT. l o g ( \ m\ nu e s t e d a t , n u l l ) ;
cmmdcLabel . s e t T e x t ( ? ) ;
return ;
}
i f ( sn . e q u a l s ( ) ) {
Window . a l e r t ( \ n \ nu e s t e dat ) ;
//GWT. l o g ( \ n \ nu e s t e d a t , n u l l ) ;
cmmdcLabel . s e t T e x t ( ? ) ;
return ;
}
try {
m=Long . par se Lon g ( sm ) ;
}
catch ( NumberFormatException e ) {
Window . a l e r t ( \ m\ nu e s t e numar ) ;
cmmdcLabel . s e t T e x t ( ? ) ;
return ;
}
try {
n=Long . p ars eL ong ( sn ) ;
}
catch ( NumberFormatException e ) {
Window . a l e r t ( \ n \ nu e s t e numar ) ;
cmmdcLabel . s e t T e x t ( ? ) ;
return ;
}
long c =0;
i f ( (m!=0)&&(n ! = 0 ) ) c=cmmdc(m, n ) ;
cmmdcLabel . s e t T e x t ( Cmmdc=+(new Long ( c ) ) . t o S t r i n g ( ) ) ;
}
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
45
46
47
48
49
120
.pc-template-btn {
display: block;
font-size: 16pt;
}
.label-title{
font-family: Georgia, "Times New Roman", Times, serif;
font-weight: bold;
font-size: 18pt
}
package u n i t b v . c s . td . c l i e n t ;
import com . g o o g l e . gwt . e v e n t . dom . c l i e n t . C l i c k E v e n t ;
import com . g o o g l e . gwt . e v e n t . dom . c l i e n t . C l i c k H a n d l e r ;
import com . g o o g l e . gwt . c o r e . c l i e n t . E n t r y P o i n t ;
import com . g o o g l e . gwt . u s e r . c l i e n t . u i . Button ;
import com . g o o g l e . gwt . u s e r . c l i e n t . u i . RootPanel ;
import com . g o o g l e . gwt . u s e r . c l i e n t . u i . V e r t i c a l P a n e l ;
import com . g o o g l e . gwt . u s e r . c l i e n t . u i . TextBox ;
import com . g o o g l e . gwt . u s e r . c l i e n t . u i . L a b e l ;
import com . g o o g l e . gwt . u s e r . c l i e n t . Window ;
public c l a s s Cmmdc implements E n t r y P o i n t {
public void onModuleLoad ( ) {
f i n a l L a b e l t i t l e =new L a b e l ( CMMDC ) ;
t i t l e . addStyleName ( l a b e l t i t l e ) ;
f i n a l L a b e l mLabel=new L a b e l ( m= ) ;
f i n a l L a b e l nLabel=new L a b e l ( n= ) ;
f i n a l L a b e l cmmdcLabel=new L a b e l ( ) ;
f i n a l TextBox mTextBox=new TextBox ( ) ;
f i n a l TextBox nTextBox=new TextBox ( ) ;
f i n a l Button b ut to n = new Button ( Compute ) ;
bu tt on . addStyleName ( pct e m p l a t e btn ) ;
V e r t i c a l P a n e l cmmdcPanel = new V e r t i c a l P a n e l ( ) ;
cmmdcPanel . setWidth ( 100% ) ;
cmmdcPanel . s e t H o r i z o n t a l A l i g n m e n t ( V e r t i c a l P a n e l . ALIGN CENTER ) ;
cmmdcPanel . add ( t i t l e ) ;
cmmdcPanel . add ( mLabel ) ;
cmmdcPanel . add ( mTextBox ) ;
cmmdcPanel . add ( nLabel ) ;
cmmdcPanel . add ( nTextBox ) ;
MyClickHandler c l i c k H a n d l e r=new MyClickHandler ( mTextBox , nTextBox ,
cmmdcLabel ) ;
bu tt on . a d d C l i c k H a n d l e r ( c l i c k H a n d l e r ) ;
cmmdcPanel . add ( b ut to n ) ;
cmmdcPanel . add ( cmmdcLabel ) ;
RootPanel . g e t ( cmmdcPage ) . add ( cmmdcPanel ) ;
}
}
3.2.3
121
Client al unei aplicatii server exterioare aplicatiei GWT, caz n care vorbim de client http;
Serverul si clientul GWT trebuie sa ruleze n acelasi server Web (Same
Origin Policy).
Client si aplicatia server apartin aceleiasi aplicatii GWT, caz n care
vorbim de apel de procedura la distanta GWT.
Schimburile de date au loc potrivit tehnologiei AJAX. In terminologia
Google se vorbeste de servicii implementate printr-un server apelat de o
componenta client GWT. Serverul are o constructie specifica GWT.
Clientul este responsabil de trimiterea cererilor si de receptia raspunsurilor,
iar partea de server de rezolvarea cererilor. Astfel se justifica terminologia de apel de procedura la distanta GWT. Atat clientul cat si serverul
utilizeaza resurse GWT.
Client HTTP
La programarea unui client HTTP sarcina programatorului consta n
1. Lansarea cererii catre server, n cazul de fata un servlet;
2. Receptionarea si prelucrarea raspunsului.
Clasele implicate n comunicatia cu servlet-ul apartin pachetului com.google.
gwt.http.client.
Receptionarea si prelucrarea raspunsului se programeaza implementand
interfata RequestCallback, cu metodele
public void onError(Request request,Throwable exception)
public void onResponseReceived(Request request,Response response)
Un sablon simplu este
class MyRequestCallback implements RequestCallback{
private static final int STATUS_CODE_OK=200;
public void onError(Request request,Throwable exception){
// tratarea erorii
}
122
123
sb.append(encodedParam);
sb.append("&");
. . .
String postData=sb.toString();
O aplicatie client http se poate verifica doar n modul Web.
Exemplul 3.2.2 Client http dezvoltat pentru servlet-ul CmmdcServlet. Interfata
grafica este identica cu cea din aplicatia anterioara, de calcul a celui mai mare
divizor comun a doua numere naturale (Cmmdc.java).
Metodele onModuleLoad ale claselor HttpClient si Cmmdc coincid. Reamintim ca servlet-ul CmmdcServlet preia 3 parametrii: cele doua numere (m, n)
ale caror cel mai mare divizor comun se calculeaza si un parametru tip care
precizeaza natura raspunsului (text/html sau text/plain).
Apelarea servlet-ului este facuta n metoda onClick() a clasei ce implementeaza interfata ClickHandler, n cazul de fata MyClickHandler.
Codul clientului este
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
package u n i t b v . c s . td . c l i e n t ;
import com . g o o g l e . gwt . c o r e . c l i e n t . E n t r y P o i n t ;
import com . g o o g l e . gwt . u s e r . c l i e n t . u i . ;
import com . g o o g l e . gwt . h t t p . c l i e n t . ;
import com . g o o g l e . gwt . u s e r . c l i e n t . Window ;
import com . g o o g l e . gwt . e v e n t . dom . c l i e n t . ;
public c l a s s H t t p C l i e n t implements E n t r y P o i n t {
public void onModuleLoad ( ) {
L a b e l t i t l e =new L a b e l ( CMMDC ) ;
t i t l e . addStyleName ( l a b e l t i t l e ) ;
L a b e l mLabel=new L a b e l ( m= ) ;
L a b e l nLabel=new L a b e l ( n= ) ;
L a b e l cmmdcLabel=new L a b e l ( ) ;
TextBox mTextBox=new TextBox ( ) ;
TextBox nTextBox=new TextBox ( ) ;
Button b ut to n = new Button ( Compute ) ;
bu tt on . addStyleName ( pct e m p l a t e btn ) ;
V e r t i c a l P a n e l cmmdcPanel = new V e r t i c a l P a n e l ( ) ;
cmmdcPanel . setWidth ( 100% ) ;
cmmdcPanel . s e t H o r i z o n t a l A l i g n m e n t ( V e r t i c a l P a n e l . ALIGN CENTER ) ;
cmmdcPanel . add ( t i t l e ) ;
cmmdcPanel . add ( mLabel ) ;
cmmdcPanel . add ( mTextBox ) ;
cmmdcPanel . add ( nLabel ) ;
cmmdcPanel . add ( nTextBox ) ;
MyClickHandler c l i c k H a n d l e r=
new MyClickHandler ( mTextBox , nTextBox , cmmdcLabel ) ;
bu tt on . a d d C l i c k H a n d l e r ( c l i c k H a n d l e r ) ;
cmmdcPanel . add ( b ut to n ) ;
cmmdcPanel . add ( cmmdcLabel ) ;
RootPanel . g e t ( cmmdcPage ) . add ( cmmdcPanel ) ;
}
124
34
36
c l a s s MyClickHandler implements C l i c k H a n d l e r {
TextBox mTextBox=null , nTextBox=n u l l ;
L a b e l cmmdcLabel=n u l l ;
37
38
40
41
42
43
44
46
47
48
49
50
51
52
53
54
55
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
95
c l a s s MyRequestCallback implements R e q u e s t C a l l b a c k {
Label label ;
private s t a t i c f i n a l i n t STATUS CODE OK=200;
96
97
MyRequestCallback ( L a b e l l a b e l ) {
t h i s . l a b e l=l a b e l ;
}
99
100
101
103
104
105
107
108
109
110
111
112
113
114
115
116
125
Apel de procedur
a la distant
a GWT
Constructia clientului si a serverului este supusa unor restrictii: metodele
serviciului sunt definite ntr-o interfata care este implementata de server n
clase POJO.
Legatura dintre client si server se face prin intermediul fisierului web.xml
prin adaugarea elementelor
<servlet>
<servlet-name>nume-servlet</servlet-name>
<servlet-class>. . .server.ServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>nume-servlet</servlet-name>
<url-pattern>/myapp/urlPattern</url-pattern>
</servlet-mapping>
126
Dezvoltarea clientului
Partea de client este alcatuita din:
1. Interfata serviciului.
Metodele care pot fi invocate de client se declara ntr-o interfata
package ...client;
import com.google.gwt.user.client.rpc.RemoteService;
public interface InterfataService extends RemoteService{
public tip metoda1(tip var,. . .);
public tip metoda2(tip var,. . .);
. . .
}
2. Interfata asincrona.
Interfata asincrona are rolul de a semnala clientului receptionarea raspunsului
dat de server. Numele acestei interfete se formeaza din numele interfetei
serviciului plus sufixul Async. Cele doua interfete contin aceleasi metode
dar au semnaturi diferite.
package ...client;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface InterfataServiceAsync{
public void metoda1(tip var,. . .,AsyncCallback<tip> callback);
public void metoda2(tip var,. . .,AsyncCallback<tip> callback);
. . .
}
tip corespunde clasei obiectului returnat de metoda.
Daca o metoda returneaza o valoare de tip predefinit atunci tip va fi
clasa acoperitoare.
Daca metoda rentoarce void atunci tip=Void.
3. Interfata asincrona este implementata de client si contine prelucrarile
referitoare la receptia raspunsului furnizat de server. Interfata AsyncCallback
contine doua metode
127
com.google.gwt.user.client.rpc.AsyncCallback;
com.google.gwt.core.client.GWT;
com.google.gwt.user.client.Window;
com.google.gwt.user.client.ui.*;
com.google.gwt.core.client.EntryPoint;
com.google.gwt.core.client.GWT;
com.google.gwt.user.client.ui.*;
com.google.gwt.user.client.rpc.ServiceDefTarget;
128
InterfataServiceAsync myService=
(InterfataServiceAsync)GWT.create(InterfataService.class);
ServiceDefTarget target=(ServiceDefTarget)myService;
String relativeURL=GWT.getModuleBaseURL()+"urlPattern";
target.setServiceEntryPoint(relativeURL);
myService.metoda1(variabile actuale pentre metoda1,
new ClientCallback());
}
public void onModuleLoad(){
. . .
final Button button=new Button(. . .);
. . .
button.addClickHandler(new ClickHandler(){
public void onClick(ClickEvent event){
. . .
apelMetoda1(lista variabile);
}
}
});
. . .
RootPanel.get("slot").add(button);
}
}
unde
urlPattern este cel precizat n fisierul web.xml, fara numele catalogului.
slot corespunde containerului div n care se include butonul.
Dezvoltarea serverului
Programul server implementeaza metodele interfetei declarata n pachetul
client.
package ...server;
import client.*;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
129
package u n i t b v . c s . td . c l i e n t ;
import com . g o o g l e . gwt . u s e r . c l i e n t . r p c . R e m o t e S e r v i c e ;
public i n t e r f a c e CmmdcService extends R e m o t e S e r v i c e {
public long cmmdc( long m, long n ) ;
}
package u n i t b v . c s . td . c l i e n t ;
import com . g o o g l e . gwt . u s e r . c l i e n t . r p c . A s y n c C a l l b a c k ;
public i n t e r f a c e CmmdcServiceAsync {
public void cmmdc( long m, long n , AsyncCallback<Long> c a l l b a c k ) ;
}
package u n i t b v . c s . td . c l i e n t ;
import
import
import
import
import
import
4
5
6
7
8
10
11
12
13
14
15
16
17
18
19
20
21
22
23
com .
com .
com .
com .
com .
com .
google
google
google
google
google
google
. gwt .
. gwt .
. gwt .
. gwt .
. gwt .
. gwt .
user
core
user
user
user
user
.
.
.
.
.
.
client
client
client
client
client
client
. rpc . AsyncCallback ;
.GWT;
. Window ;
. u i . RootPanel ;
. ui . VerticalPanel ;
. u i .HTML;
130
// V a r i a n t a 2
// l o n g r e z =((Long ) r e s u l t ) . l o n g V a l u e ( ) ;
// Window . a l e r t (Cmmdc=+r e z ) ;
}
25
26
27
28
29
cu clientul
1
2
3
4
5
6
7
8
9
10
11
13
14
15
16
17
18
19
20
21
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
import
import
import
import
import
import
import
import
import
import
import
com .
com .
com .
com .
com .
com .
com .
com .
com .
com .
com .
google
google
google
google
google
google
google
google
google
google
google
. gwt . c o r e . c l i e n t . E n t r y P o i n t ;
. gwt . u s e r . c l i e n t . u i . Button ;
. gwt . u s e r . c l i e n t . u i . RootPanel ;
. gwt . u s e r . c l i e n t . u i . V e r t i c a l P a n e l ;
. gwt . u s e r . c l i e n t . u i . TextBox ;
. gwt . u s e r . c l i e n t . u i . L a b e l ;
. gwt . u s e r . c l i e n t . Window ;
. gwt . c o r e . c l i e n t .GWT;
. gwt . u s e r . c l i e n t . r p c . S e r v i c e D e f T a r g e t ;
. gwt . e v e n t . dom . c l i e n t . C l i c k E v e n t ;
. gwt . e v e n t . dom . c l i e n t . C l i c k H a n d l e r ;
i f ( sn . e q u a l s ( ) ) {
Window . a l e r t ( \ n \ nu e s t e dat ) ;
cmmdcLabel . s e t T e x t ( ? ) ;
return ;
}
try {
m=Long . par se Lon g ( sm ) ;
}
catch ( NumberFormatException e ) {
Window . a l e r t ( \ m\ nu e s t e numar ) ;
cmmdcLabel . s e t T e x t ( ? ) ;
return ;
}
try {
n=Long . p ars eL ong ( sn ) ;
}
catch ( NumberFormatException e ) {
Window . a l e r t ( \ n \ nu e s t e numar ) ;
cmmdcLabel . s e t T e x t ( ? ) ;
return ;
}
long c =0;
i f ( (m!=0)&&(n ! = 0 ) )
g e t R e s u l t (m, n ) ;
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
}
});
cmmdcPanel . add ( b ut to n ) ;
cmmdcPanel . add ( cmmdcLabel ) ;
RootPanel . g e t ( cmmdcPage ) . add ( cmmdcPanel ) ;
75
76
77
78
79
80
81
package u n i t b v . c s . td . s e r v e r ;
import com . g o o g l e . gwt . u s e r . s e r v e r . r p c . R e m o t e S e r v i c e S e r v l e t ;
import u n i t b v . c s . td . c l i e n t . CmmdcService ;
public c l a s s CmmdcServiceImpl extends R e m o t e S e r v i c e S e r v l e t
implements CmmdcService {
public long cmmdc( long m, long n ) { . . . }
}
web.xml se completeaza cu
<servlet>
<servlet-name>cmmdcrpc</servlet-name>
<servlet-class>unitbv.cs.td.server.CmmdcServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cmmdcrpc</servlet-name>
<url-pattern>/cmmdcclient/cmmdcrpc</url-pattern>
</servlet-mapping>
Test GWT
Generand modulul GWT cu optiunea suplimentara -junit
131
132
context
|--> client
|
|
MyAppTest.java
|
MyAppJUnit.gwt.xml
Obiectivele ant: test.dev si test.prod asigura efectuarea testelor prin intermediul lui junit.
In cazul unei aplicatii cu apel de procedura la distanta GWT sarcina
programatorului consta din (cu adaptarea corespunzatoare a denumirii clasei
MyApp):
Editarea clasei MyAppTest pe baza sablonului prezent;
Modificarea / adaptarea corespunzatoare a fisierului de configurare MyAppJUnit.gwt.xml.
Pentru aplicatia anterioara codul clasei unitbv.cs.td.client.CmmdcClientJUnit
este
1
package u n i t b v . c s . td . c l i e n t ;
import
import
import
import
import
4
5
6
11
12
13
15
16
17
18
19
20
21
23
24
25
26
27
u n i t b v . c s . td . s h a r e d .
com . g o o g l e . gwt . c o r e .
com . g o o g l e . gwt . j u n i t
com . g o o g l e . gwt . u s e r .
com . g o o g l e . gwt . u s e r .
FieldVerifier ;
c l i e n t .GWT;
. c l i e n t . GWTTestCase ;
c l i e n t . rpc . AsyncCallback ;
c l i e n t . rpc . ServiceDefTarget ;
public S t r i n g getModuleName ( ) {
return u n i t b v . c s . td . CmmdcClientJUnit ;
}
public void testCmmdcService ( ) {
// Crearea unui o b i e c t de a p e l a r e .
CmmdcServiceAsync cmmdcService = GWT. c r e a t e ( CmmdcService . c l a s s ) ;
S e r v i c e D e f T a r g e t t a r g e t = ( S e r v i c e D e f T a r g e t ) cmmdcService ;
t a r g e t . s e t S e r v i c e E n t r y P o i n t (GWT. getModuleBaseURL ( ) +
cmmdcclient /cmmdcrpc ) ;
delayTestFinish (10000);
// Apel s e r v e r .
cmmdcService . cmmdc ( 5 6 , 4 8 , new AsyncCallback<Long >() {
public void o n F a i l u r e ( Throwable ca ug ht ) {
f a i l ( Request f a i l u r e : + ca ug ht . g e t M e s s a g e ( ) ) ;
}
133
29
30
31
32
33
34
35
>
package u n i t b v . c s . td . c l i e n t ;
import j a v a . u t i l . L i s t ;
import com . g o o g l e . gwt . u s e r . c l i e n t . r p c . R e m o t e S e r v i c e ;
public i n t e r f a c e A d r e s e S e r v i c e extends R e m o t e S e r v i c e {
public L i s t <S t r i n g > getEMail ( S t r i n g nume ) ;
public S t r i n g getNume ( S t r i n g e m a i l ) ;
}
package u n i t b v . c s . td . c l i e n t ;
import com . g o o g l e . gwt . u s e r . c l i e n t . r p c . A s y n c C a l l b a c k ;
import j a v a . u t i l . L i s t ;
public i n t e r f a c e A d r e s e S e r v i c e A s y n c {
public void getEMail ( S t r i n g nume , AsyncCallback<L i s t <S t r i n g >> c a l l b a c k ) ;
public void getNume ( S t r i n g e m a i l , AsyncCallback<S t r i n g > c a l l b a c k ) ;
}
package u n i t b v . c s . td . c l i e n t ;
import
import
import
import
4
5
6
com .
com .
com .
com .
google
google
google
google
. gwt .
. gwt .
. gwt .
. gwt .
user
core
user
user
.
.
.
.
client
client
client
client
. rpc . AsyncCallback ;
.GWT;
. Window ;
. ui . ;
134
import j a v a . u t i l . ;
public c l a s s A d r e s e C a l l b a c k implements A s y n c C a l l b a c k {
public void o n F a i l u r e ( Throwable ca ug ht ) {
GWT. l o g ( E r r o r , ca ug ht ) ;
c aug ht . p r i n t S t a c k T r a c e ( ) ;
Window . a l e r t ( c au gh t . t o S t r i n g ( ) ) ;
}
10
11
12
13
14
public void o n S u c c e s s ( O b j e c t r e s u l t ) {
f i n a l L a b e l l a b e l R e z=new L a b e l ( ) ;
Grid g r i d=new Grid ( 1 , 2 ) ;
i f ( r e s u l t instanceof S t r i n g ) {
S t r i n g nume=( S t r i n g ) r e s u l t ;
f i n a l L a b e l labelNume=new L a b e l ( ( S t r i n g ) r e s u l t ) ;
l a b e l R e z . s e t T e x t ( Numele c a u t a t : ) ;
g r i d . setWidget ( 0 , 0 , labelRez ) ;
g r i d . s e t W i d g e t ( 0 , 1 , labelNume ) ;
RootPanel . g e t ( r e z ) . add ( g r i d ) ;
}
i f ( r e s u l t instanceof L i s t ) {
f i n a l L i s t B o x l i s t A d r e s e=new L i s t B o x ( ) ;
L i s t <S t r i n g > l i s t =( L i s t <S t r i n g >) r e s u l t ;
f o r ( i n t i =0; i < l i s t . s i z e ( ) ; i ++){
l i s t A d r e s e . addItem ( ( S t r i n g ) l i s t . g e t ( i ) ) ;
}
labelRez . setText ( Adresele cautate : ) ;
g r i d . setWidget ( 0 , 0 , labelRez ) ;
g r i d . setWidget ( 0 , 1 , l i s t A d r e s e ) ;
RootPanel . g e t ( r e z ) . add ( g r i d ) ;
}
}
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package u n i t b v . c s . td . c l i e n t ;
import
import
import
import
import
import
import
4
5
6
7
8
9
11
12
13
14
15
16
17
18
19
21
22
23
com . g o o g l e . gwt . c o r e . c l i e n t . E n t r y P o i n t ;
com . g o o g l e . gwt . c o r e . c l i e n t .GWT;
com . g o o g l e . gwt . u s e r . c l i e n t . u i . ;
com . g o o g l e . gwt . u s e r . c l i e n t . r p c . S e r v i c e D e f T a r g e t ;
com . g o o g l e . gwt . e v e n t . dom . c l i e n t . C l i c k E v e n t ;
com . g o o g l e . gwt . e v e n t . dom . c l i e n t . C l i c k H a n d l e r ;
java . u t i l . ;
S e r v i c e D e f T a r g e t t a r g e t =( S e r v i c e D e f T a r g e t ) a d r e s e S e r v i c e ;
S t r i n g r e l a t i v e U R L=GWT. getModuleBaseURL ()+ a d r e s e ;
t a r g e t . setServiceEntryPoint ( relativeURL ) ;
a d r e s e S e r v i c e . getNume ( e m a i l , new A d r e s e C a l l b a c k ( ) ) ;
24
25
26
27
28
30
31
32
33
34
35
V e r t i c a l P a n e l a d r e s e P a n e l=new V e r t i c a l P a n e l ( ) ;
L a b e l t i t l e =new L a b e l ( Agenda de a d r e s e EMAIL ) ;
t i t l e . addStyleName ( l a b e l t i t l e ) ;
Grid g r i d=new Grid ( 2 , 2 ) ;
g r i d . setWidget ( 0 , 0 , l a b e l C r i t e r i u ) ;
l i s t B o x C r i t e r i u . addItem ( nume ) ;
l i s t B o x C r i t e r i u . addItem ( e m a i l ) ;
listBoxCriteriu . setVisibleItemCount ( 1 ) ;
g r i d . setWidget ( 0 , 1 , l i s t B o x C r i t e r i u ) ;
g r i d . setWidget ( 1 , 0 , l a b e l E n t i t a t e ) ;
g r i d . setWidget ( 1 , 1 , textBoxEntitate ) ;
bu tt on . a d d C l i c k H a n d l e r (new C l i c k H a n d l e r ( ) {
public void o n C l i c k ( C l i c k E v e n t e v e n t ) {
S t r i n g s=t e x t B o x E n t i t a t e . g e t T e x t ( ) ;
i f ( ! . equals ( s ) ) {
i f ( l i s t B o x C r i t e r i u . g e t S e l e c t e d I n d e x ()==0)
findByNume ( s ) ;
else
findByEMail ( s ) ;
}
}
});
a d r e s e P a n e l . add ( t i t l e ) ;
a d r e s e P a n e l . add ( g r i d ) ;
a d r e s e P a n e l . add ( bu tt on ) ;
RootPanel . g e t ( a d r e s e P a n e l ) . add ( a d r e s e P a n e l ) ;
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
package u n i t b v . c s . td . s e r v e r ;
import u n i t b v . c s . td . c l i e n t . ;
import j a v a . u t i l . ;
import j a v a . s q l . ;
135
136
public c l a s s A d r e s e S e r v i c e I m p l extends R e m o t e S e r v i c e S e r v l e t
implements A d r e s e S e r v i c e {
public s t a t i c f i n a l S t r i n g DRIVER=
o r g . apache . derby . j d b c . C l i e n t D r i v e r ;
public s t a t i c f i n a l S t r i n g PROTOCOL=
j d b c : derby : / / l o c a l h o s t : 1 5 2 7 / AgendaEMail ;
8
9
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
38
public S t r i n g getNume ( S t r i n g e m a i l ) {
S t r i n g nume= ;
try {
C o n n e c t i o n con = DriverManager . g e t C o n n e c t i o n (PROTOCOL) ;
Statement s = con . c r e a t e S t a t e m e n t ( ) ;
ResultSet rs =
s . e x e c u t e Q u e r y ( SELECT nume FROM a d r e s e where e m a i l =\ +e m a i l+ \ ) ;
i f ( r s . next ( ) )
nume=r s . g e t S t r i n g ( nume ) ;
}
catch ( E x c e p t i o n e ) {
e . printStackTrace ( ) ;
nume=n u l l ;
}
finally {
try {
DriverManager . g e t C o n n e c t i o n ( j d b c : derby : ; shutdown=t r u e ) ;
}
catch ( SQLException i g n o r e ) {}
}
return nume ;
}
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
137
web.xml se completeaza cu
<servlet>
<servlet-name>adrese</servlet-name>
<servlet-class>unitbv.cs.td.server.AdreseServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>adrese</servlet-name>
<url-pattern>/agendaemail/adrese</url-pattern>
</servlet-mapping>
3.2.4
In paralel cu oferta de clase widget puse la dispozitie de GWT exista posibilitatea de a crea widget-e propri sau client.
O varianta de creare este prezentata n continuare.
O arhitectura posibila a unei asemenea aplicatii este data n Fig. 3.2.
Desfasurarea bibliotecii de widget-e este delimitata prin linii orizontale.
Widget-ele apartin pachetului mywidgets. . . client. MyWidget.css contine clasele
css utilizate de widget-uri. Acest fapt este specificat n fisierul de configurare
Widgets.gwt.xml, avand codul
1
2
3
4
5
6
7
9
10
138
catapp
|--> src
---------------------------------------|
|--> mywidgets
|
|
|. . .
|
|
|
|--> client
|
|
|
|
|
WidgetClass1.java
|
|
|
|
|
. . .
|
|
|
|--> public
|
|
|
|
|
MyWidget.css
|
|
|
|
Widgets.gwt.xml
---------------------------------------|
|--> context
|
|
|--> client
|
|
|
|
MyApp.java
|
|
|. . .
|
|--> war
|
|
|. . .
|
.classpath
|
.project
|
MyApp.launch
|
README.txt
|
build.xml
Figure 3.2: Aplicatie GWT cu biblioteca de widget-e.
139
package mywidgets . c l i e n t ;
import com . g o o g l e . gwt . u s e r . c l i e n t . u i . ;
import com . g o o g l e . gwt . e v e n t . dom . c l i e n t . ;
public c l a s s HelloNameWidget extends Composite {
public HelloNameWidget ( ) {
L a b e l t i t l e =new L a b e l ( H e l l o Name Widget ) ;
t i t l e . addStyleName ( l a b e l t i t l e ) ;
Button b ut to n = new Button ( Apasama ) ;
L a b e l nameLabel=new L a b e l ( I n t r o d u c e t i numele ) ;
f i n a l L a b e l s L a b e l=new L a b e l ( ) ;
f i n a l TextBox nameTextBox=new TextBox ( ) ;
bu tt on . addStyleName ( b ut to n ) ;
V e r t i c a l P a n e l vPanel = new V e r t i c a l P a n e l ( ) ;
vPanel . addStyleName ( v p a n e l ) ;
vPanel . add ( t i t l e ) ;
vPanel . setWidth ( 100% ) ;
vPanel . s e t H o r i z o n t a l A l i g n m e n t ( V e r t i c a l P a n e l . ALIGN CENTER ) ;
vPanel . add ( nameLabel ) ;
vPanel . add ( nameTextBox ) ;
vPanel . add ( b ut to n ) ;
vPanel . add ( s L a b e l ) ;
bu tt on . a d d C l i c k H a n d l e r (new C l i c k H a n d l e r ( ) {
public void o n C l i c k ( C l i c k E v e n t e v e n t ) {
S t r i n g name=nameTextBox . g e t T e x t ( ) ;
140
s L a b e l . s e t T e x t ( H e l l o +name+ ! ) ;
}
});
i n i t W i d g e t ( vPanel ) ;
27
28
29
30
31
32
si
1
2
3
4
6
7
8
9
10
11
12
13
14
15
16
package mywidgets . c l i e n t ;
import com . g o o g l e . gwt . u s e r . c l i e n t . u i . ;
import com . g o o g l e . gwt . u s e r . c l i e n t . Window ;
import com . g o o g l e . gwt . e v e n t . dom . c l i e n t . ;
public c l a s s CmmdcWidget extends Composite {
public CmmdcWidget ( ) {
L a b e l t i t l e =new L a b e l ( Cmmdc Widget ) ;
t i t l e . addStyleName ( l a b e l t i t l e ) ;
L a b e l mLabel=new L a b e l ( m= ) ;
L a b e l nLabel=new L a b e l ( n= ) ;
L a b e l cmmdcLabel=new L a b e l ( ) ;
TextBox mTextBox=new TextBox ( ) ;
TextBox nTextBox=new TextBox ( ) ;
Button b ut to n = new Button ( C a l c u l e a z a ) ;
bu tt on . addStyleName ( b ut to n ) ;
V e r t i c a l P a n e l cmmdcPanel = new V e r t i c a l P a n e l ( ) ;
cmmdcPanel . setWidth ( 100% ) ;
cmmdcPanel . addStyleName ( v p a n e l ) ;
cmmdcPanel . s e t H o r i z o n t a l A l i g n m e n t ( V e r t i c a l P a n e l . ALIGN CENTER ) ;
cmmdcPanel . add ( t i t l e ) ;
cmmdcPanel . add ( mLabel ) ;
cmmdcPanel . add ( mTextBox ) ;
cmmdcPanel . add ( nLabel ) ;
cmmdcPanel . add ( nTextBox ) ;
CmmdcWidgetClickHandler c l i c k H a n d l e r=
new CmmdcWidgetClickHandler ( mTextBox , nTextBox , cmmdcLabel ) ;
bu tt on . a d d C l i c k H a n d l e r ( c l i c k H a n d l e r ) ;
cmmdcPanel . add ( b ut to n ) ;
cmmdcPanel . add ( cmmdcLabel ) ;
18
19
20
21
22
23
24
25
26
27
28
29
30
31
i n i t W i d g e t ( cmmdcPanel ) ;
33
34
35
37
c l a s s CmmdcWidgetClickHandler implements C l i c k H a n d l e r { . . . }
Codul aplicatiei GWT care foloseste widget-ele client definite anterior este
package u n i t b v . c s . td . c l i e n t ;
import com . g o o g l e . gwt . c o r e . c l i e n t . E n t r y P o i n t ;
import com . g o o g l e . gwt . u s e r . c l i e n t . u i . ;
import mywidgets . c l i e n t . ;
1
2
3
8
9
10
11
12
13
14
15
16
17
141
3.2.5
Inc
arcarea unui fisier - GWT Upload
GWT ofera o solutie prefabricata problemei ncarcarii unui fisier al clientului pe calculatorul server.
Aplicatia GWT corespunde clientului care alege fisierul de ncarcat si transmite datele unui server receptor, reprezentat, n cazul exemplului dezvoltat, de
un servlet. Clasele widget ajutatoare sunt FormPanel si FileUpload. Intr-un
container FormPanel pot fi incluse widgete de tip TextBox, PasswordTextBox,
RadioButton, CheckBox, TextArea, FileUpload, Hidden.
Dintre metodele care intervin la ncarcarea unui fisier amintim:
public void setAction(String url )
public void setMethod(FormPanel.METHOD POST)
In alt context se poate folosi FormPanel.METHOD GET.
public void setEncoding(FormPanel.ENCODING MULTIPART)
In alt context se poate folosi FormPanel.ENCODING URLENCODED.
public void submit()
HandlerRegistration addSubmitHandler(FormPanel.SubmitHandler
handler )
Interfata SubmitHandler
HandlerRegistration addSubmitCompleteHandler(FormPanel.
SubmitCompleteHandler handler )
Fiecare din interfetele SubmitHandler si SubmitCompleteHandler declara metoda
void onSubmit(FormPanel.SubmitEvent event) n care se programeaza activitatile naintea expedierii formularului si respectiv, dupa receptia raspunsului
furnizat de servlet.
Widgetul UploadFile afiseaza o fereastra de dialog prin care se selecteaza
fisierul ce umeaza a fi ncarcat.
Codul clasei client este
142
package u n i t b v . c s . td . c l i e n t ;
import
import
import
import
import
4
5
6
7
9
10
11
12
13
14
com .
com .
com .
com .
com .
google
google
google
google
google
. gwt . c o r e . c l i e n t . ;
. gwt . u s e r . c l i e n t . Window ;
. gwt . u s e r . c l i e n t . u i . ;
. gwt . e v e n t . dom . c l i e n t . C l i c k E v e n t ;
. gwt . e v e n t . dom . c l i e n t . C l i c k H a n d l e r ;
16
17
20
V e r t i c a l P a n e l p a n e l = new V e r t i c a l P a n e l ( ) ;
form . s e t W i d g e t ( p a n e l ) ;
22
p a n e l . add ( t i t l e ) ;
24
// Crearea unui w i d g e t F i l e U p l o a d
F i l e U p l o a d up lo ad = new F i l e U p l o a d ( ) ;
up l oad . setName ( uploadFormElement ) ;
p a n e l . add ( u pl oa d ) ;
19
25
26
27
// Adaugarea unui b u t o n s u b m i t
p a n e l . add (new Button ( Submit , new C l i c k H a n d l e r ( ) {
public void o n C l i c k ( C l i c k E v e n t e v e n t ) {
form . submit ( ) ;
}
}));
29
30
31
32
33
34
// A c t i v i t a t i p r e m e r g a t o a r e e x p e d i e r i i f o r m u l a r u l u i .
form . addSubmitHandler (new FormPanel . SubmitHandler ( ) {
public void onSubmit ( FormPanel . SubmitEvent e v e n t ) {
}
});
36
37
38
39
40
// A c t i v i t a t i l a r e c e p t i o n a r e a r a s p u n s u l u i
form . addSubmitCompleteHandler (new FormPanel . SubmitCompleteHandler ( ) {
public void onSubmitComplete ( FormPanel . SubmitCompleteEvent e v e n t ) {
S t r i n g r e s u l t s=e v e n t . g e t R e s u l t s ( ) ;
Window . a l e r t ( r e s u l t s ) ;
}
});
RootPanel . g e t ( ) . add ( form ) ;
42
43
44
45
46
47
48
49
50
51
package up l oad ;
17
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
19
@WebServlet ( u r l P a t t e r n s = / u pl oad )
21
public c l a s s F i l e U p l o a d S e r v l e t extends H t t p S e r v l e t {
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
23
24
25
26
27
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
60
j a v a . i o . IOException ;
j a v a . i o . InputStream ;
java . i o . FileOutputStream ;
java . io . F i l e ;
javax . s e r v l e t . ServletException ;
javax . s e r v l e t . http . HttpServlet ;
javax . s e r v l e t . http . HttpServletRequest ;
javax . s e r v l e t . http . HttpServletResponse ;
javax . s e r v l e t . ServletOutputStream ;
j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
java . u t i l . List ;
java . u t i l . I t e r a t o r ;
java . u t i l . Vector ;
o r g . apache . commons . f i l e u p l o a d . s e r v l e t . S e r v l e t F i l e U p l o a d ;
o r g . apache . commons . f i l e u p l o a d . F i l e I t e m I t e r a t o r ;
o r g . apache . commons . f i l e u p l o a d . F i l e I t e m S t r e a m ;
143
144
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 ( ) ) ;
61
62
63
64
3.2.6
Aplicatia se genereaza cu
set groupId=. . .
set artifactid=. . .
set module=. . .
set version=. . .
set gwt-version=. . .
mvn archetype:generate -DarchetypeGroupId=org.codehaus.mojo
-DarchetypeArtifactId=gwt-maven-plugin
-DarchetypeVersion=%gwt-version%
-DgroupId=%groupId%
-DartifactId=%artifactId%
-Dmodule=%module%
-Dversion=%version%
-DinteractiveMode=false
Procesarea maven este mvn clean package.
3.2.7
145
Exemplul 3.2.6 Integrarea aplicatiei GWT de calcul a celui mai mare divizor
comun n platforma Google de Cloud Computing.
In urma operatiilor de mai sus rezulta structura
gwtcmmdc
|--> www
|
|-->
|
|
|
|-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmmdc
| . . .
WEB-INF
|--> classes
|
| . . .
|--> lib
|
| . . .
|
appengine-web.xml
|
web.xml
Cmmdc.html
Cmmdc.css
146
Partea II
SERVICII WEB
147
Capitolul 4
Servicii JAX-WS
Un serviciu Web este o aplicatie client-server cu serverul gazduit de un
server Web, apelabil prin aplicatia client si realizat potrivit unei interfete de
programare specifice. Protocolul de comunicatie este http.
Sunt cunoscute urmatoarele tipuri de servicii Web:
Servicii bazate pe modelul Remote Precedure Call (RPC) - Apel de Procedura de la Distanta.
Protocolul de reprezentare a cererii si a raspunsului (de serializare /
deserializare) variaza. Din acest punct de vedere sunt cunoscute:
Servicii xml-rpc (www.xmlrpc.org). Cererea si raspunsul sunt transmise prin cod xml cuprins n corpul mesajului http.
Servicii json-rpc (www.json-rpc.org) bazat pe reprezentarea JSON.
Servicii hessian. Se utilizeaza un protocol pentru serializare / deserealizare bazat pe reprezentarea binara a datelor. Protocolul a fost
dezvoltat de firma Caucho Technologies (2007).
Servicii bazate pe interfata de programare Java API for XML Web
Services - JAX-WS. Interfata de programare JAX-WS este varianta
cea mai recenta pentru serviciile cunoscute sub numele de servicii
soap-rpc.
Pentru fiecare caz semnalat mai sus sunt realizate implementari n mai
multe limbaje / platforme de programare.
Servicii REST.
149
150
4.1
REST a fost introdus de Roy Fielding, n teza sa de doctorat din 2000. Roy Fielding
este autorul principal al specificatiilor protocolului http.
4.1.1
151
XML Schema
O schema este un model pentru descrierea structurii informatiei. In contextul xml, o schema descrie un model pentru o familie de documente xml.
Primul obiectiv al unei scheme este de a permite validarea automata a
structurii unui document xml.
Familiarizarea cu elementele de continut si sintaza XML Schema se va
ncepe cu un exemplu:
Documentul struct.xml
1
2
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
152
22
24
26
34
36
38
40
14
15
16
17
18
19
20
21
27
28
29
30
31
32
33
41
Tipuri simple: string, byte, integer, decimal, boolean, time, date, etc.
Grupuri. Se pot defini grupuri de elemente si de atribute
<xsd:group name="tipElementDisciplina" >
<xsd:sequence>
<xsd:element name="nume" type="tipNume" />
<xsd:element name="fond-de-timp" type="tipFondTimp" />
</xsd:sequence>
</xsd:group>
<xsd:attributeGroup name="atribDisciplina" >
<xsd:attribute name="fel" type="xsd:string" use="required" />
<xsd:attribute name="finalizare" type="xsd:string" />
153
</xsd:attributeGroup>
<xsd:complexType name="tipdisciplina" >
<xsd:sequence>
<xsd:group ref="tipElementDisciplina" />
<xsd:attributeGroup ref="attribDisciplina" />
<xsd:sequence>
</xsd:complexType>
Comentariile
destinate a fi citite de oameni se introduc n marcajul xsd:documentation;
destinate a fi procesate se introduc n marcajul xsd:appinfo
Ambele marcaje trebuie inglobate n xsd:annotation.
<xsd:annotation>
<xsd:documentation xml:lang="en">
text
</xsd:documentation>
<xsd:appinfo source=". . ." >
<bind xmlns=". . ." >
<class name=". . ." />
</bind>
</xsd:appinfo>
</xsd:annotation>
154
4.1.2
WSDL
Pentru acest exemplu, operatia este definita de o metoda avand doi parametrii
si returneaza un rezultat:
|| Operatie
||
Nume local: cmmdc
||
Namespace: http://cs.unitbv.ro/ws
||
Parametrii:
||
m: string
||
n: string
||
Returneaza:
||
string
Tipurile (string, int, long, etc) utilizate sunt precizate n spatiul de nume
http://www.w3.org/2001/XMLSchema.
Definirea operatiei devine
|| Operatie
||
Nume local: cmmdc
||
Namespace: http://cs.unitbv.ro/ws
||
Parametrii:
||
m: string din http://www.w3.org/2001/XMLSchema
||
n: string din http://www.w3.org/2001/XMLSchema
||
Returneaza:
||
string din http://www.w3.org/2001/XMLSchema
155
156
2. operatia propriu-zisa
|| Operatie
||
Nume local: cmmdc
||
Namespace: http://cs.unitbv.ro/ws
||
Input message:
||
Part 1:
||
Name: cerereCmmdc
||
Type: cmmdcRequest din http://cs.unitbv.ro/ws
||
Output message:
||
Part 1:
||
Name: return
||
Type: string din http://www.w3.org/2001/XMLSchema
2. operatia propriu-zisa
|| Operatie
||
Nume local: cmmdc
||
Namespace: http://cs.unitbv.ro/ws
||
Input message:
||
Part 1:
||
Name: cerereCmmdc
||
Type: cmmdcRequest din http://cs.unitbv.ro/ws
||
Output message:
||
Part 1:
||
Name: raspunsCmmdc
||
Type: responseCmmdc din http://cs.unitbv.ro/ws
Raspunsul va fi
<pre:cmmdcResponse xmlns:pre="http://cs.unitbv.ro/ws">
8
</pre:cmmdcResponse>
157
Acest mod de definire a unui serviciu Web poarta numele de stilul document 2 . Acest stil este impus de WS-I (Web Services Interoperability organization).
Determinarea operatiei apelate se face exclusiv pe baza tipului din mesajul
de intrare. Nu pot exista doua operatii cu datele de intrare definite prin acelasi
nume calificat.
Asambland, se obtine
|| Server Web la adresa http://localhost:8080
||
Schema
||
. . .
||
Operatie
||
Nume local: cmmdc
||
Namespace: http://cs.unitbv.ro/ws
||
Input message:
||
Part 1:
||
Name: cerereCmmdc
||
Type: cmmdcRequest din http://cs.unitbv.ro/ws
||
Output message:
||
Part 1:
||
Name: raspunsCmmdc
||
Type: responseCmmdc din http://cs.unitbv.ro/ws
PortType. Operatiile sunt grupate n colectii numite PortType. Un PortType este denumita printr-un nume calificat (nume local si namespace).
|| Server Web la adresa http://localhost:8080
||
Schema
||
. . .
||
||
PortType
||
Nume local: functiiWS
||
Namespace: http://cs.unitbv.ro/ws
||
||
Operatie
||
Nume local: cmmdc
||
Namespace: http://cs.unitbv.ro/ws
||
Input message:
||
Part 1:
||
Name: cerereCmmdc
||
Type: cmmdcRequest din http://cs.unitbv.ro/ws
||
Output message:
||
Part 1:
||
Name: raspunsCmmdc
||
Type: responseCmmdc din http://cs.unitbv.ro/ws
||
||
Operatie
||
. . .
||
||
PortType
||
. . .
2
158
Name
Port type
Format
Transport
:
:
:
:
binding1
functiiWS
SOAP
HTTP
Toate notiunile introduse pentru descrierea serviciului Web vor face parte
dintr-un acelasi spatiu de nume targetNamespace
|| Serviciu Web
|| Target namespace: http://cs.unitbv.ro/ws
||
Schema
||
. . .
||
||
PortType
||
||
||
||
||
||
||
||
||
||
||
||
||
||
||
||
||
||
||
||
||
159
:
:
:
:
binding1
functiiWS
SOAP
HTTP
port1
binding1
160
Exemplul 4.1.1 Fisierul wsdl pentru serviciul Web de calcul a celui mai
mare divizor comun a doua numere naturale generat de Metro.
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
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
60
61
62
63
64
161
</ b i n d i n g>
< s e r v i c e name=CmmdcWSService>
<p o r t name=CmmdcWSPort
b i n d i n g= tns:CmmdcWSPortBinding >
<s o a p : a d d r e s s
l o c a t i o n= h t t p : // j o n a t h a n : 8 0 8 0 / jaxwscmmdc/cmmdcws />
</ p o r t>
</ s e r v i c e>
</ d e f i n i t i o n s>
4.1.3
Mesaje SOAP
162
SOAPPart part=soapMsg.getSOAPPart();
SOAPEnvelope envelope=part.getEnvelope();
SOAPHeader header=envelope.getHeader();
SOAPBody body=envelope.getBody();
Completarea corpului unui mesaj SOAP
Oricarui element n este asociat un obiect javax.xml.soap.Name. Din
acest obiect se pot afla
String getLocalName()
String getPrefix()
String getURI()
String getQualifiedName()
Numele calificat are structura
<prefix:NumeleLocal xmlns:prefix="uri">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<SOAPENV:Envelope
xmlns:SOAPENV= h t t p : // schemas . x m l s o a p . o r g / s o a p / e n v e l o p e / >
<SOAPENV:Header />
<SOAPENV:Body>
<e1>
primul
<e11>
al treilea
</ e11>
</ e1>
<e2>
al doilea
</ e2>
</SOAPENV:Body>
</SOAPENV:Envelope>
se obtine cu programul
1
2
3
4
5
6
7
8
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
import
import
import
import
import
import
import
import
public c l a s s MsgSOAP{
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
Name name=n u l l ;
try {
Me ss age Fa ct ory mf=Me ssa ge Fac to ry . n e w I n s t a n c e ( ) ;
SOAPMessage soapMsg=mf . c r e a t e M e s s a g e ( ) ;
SOAPPart p a r t=soapMsg . getSOAPPart ( ) ;
SOAPEnvelope e n v e l o p e=p a r t . g e t E n v e l o p e ( ) ;
SOAPBody body=e n v e l o p e . getBody ( ) ;
Name n1=e n v e l o p e . createName ( e1 ) ;
SOAPElement e1=body . addBodyElement ( n1 ) ;
e1 . addTextNode ( p r i m u l ) ;
Name n2=e n v e l o p e . createName ( e2 ) ;
SOAPElement e2=body . addBodyElement ( n2 ) ;
e2 . addTextNode ( a l d o i l e a ) ;
Name n11 =e n v e l o p e . createName ( e11 ) ;
SOAPElement e11=e1 . addChildElement ( n11 ) ;
e11 . addTextNode ( a l t r e i l e a ) ;
F i l e O u t p u t S t r e a m f=new F i l e O u t p u t S t r e a m ( MySOAPMessage . xml ) ;
soapMsg . w r i t e T o ( f ) ;
}
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 ( ) ) ;
}
}
}
163
164
soapMsg.writeTo(f);
Continutul fisierului este
SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/><SOAP-ENV:Body><e1>primul<e11>al treilea</e11></e1>
<e2>al doilea</e2></SOAP-ENV:Body></SOAP-ENV:Envelope>
11
import
import
import
import
import
import
import
import
import
import
import
13
public c l a s s MsgSOAPReceiver {
1
2
3
4
5
6
7
8
9
10
15
16
17
18
19
20
21
22
23
24
25
26
28
29
30
31
32
33
34
35
36
}
catch ( E x c e p t i o n ex ) {
ex . p r i n t S t a c k T r a c e ( ) ;
}
37
38
39
40
41
42
165
Observatia 4.1.1
Produsul Oracle-Open Message Queue ofera posibilitatea transformarii unui
mesaj SOAP n mesaj JMS si invers.
Transformarea unui mesaj SOAP n mesaj JMS
SOAPMessage soapMsg=. . .
Message msg=
MessageTransformer.SOAPMessageIntoJMSMessage(soapMsg,session);
Transformarea unui mesaj JMS n mesaj SOAP
MessageFactory mf=. . .
Message msg=. . .
SOAPMessage soapMsg =
MessageTransformer.SOAPMessageFromJMSMessage(msg,mf);
166
4.2
4.2.1
Functioneaz
a si n serverul Web jetty.
167
package cmmdc . s e r v e r ;
import j a v a x . j w s . WebMethod ;
import j a v a x . j w s . WebParam ;
import j a v a x . j w s . WebService ;
@WebService ( )
public c l a s s CmmdcWS {
@WebMethod
public long cmmdc(@WebParam( name = m ) long m,
@WebParam( name = n ) long n ) { }
9
10
11
12
168
? xml v e r s i o n= 1 . 0 e n c o d i n g=UTF8?>
4
5
6
7
8
9
web.xml
1
? xml v e r s i o n= 1 . 0 e n c o d i n g=UTF8?>
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
169
http://host:8080/jaxws-cmmdc/cmmdcws?wsdl
package cmmdc . c l i e n 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 ) {
try {
CmmdcWS p o r t=new CmmdcWSService ( ) . getCmmdcWSPort ( ) ;
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= ) ;
long m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
long n=s c a n n e r . nextLong ( ) ;
long r e s u l t=p o r t . cmmdc(m, n ) ;
System . out . p r i n t l n ( Cmmdc=+r e s u l t ) ;
170
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t f ( AnException : +e . g e t M e s s a g e ( ) ) ;
}
15
16
17
18
19
20
<html>
<body>
<form method= p o s t >
<table>
<tr>
<td>Primul numar e s t e </td>
<td><input type= t e x t name=m s i z e=5 value= 1 > </td>
</ tr>
<tr>
<td>Al d o i l e a numar e s t e </td>
<td><input type= t e x t name=n s i z e=5 value= 1 > </td>
</ tr>
<tr>
<td><input type= submit value= C a l c u l e a z a ></td>
<td/>
</ tr>
</ table>
</form>
<%
try {
cmmdc . c l i e n t . CmmdcWSService s e r v i c e=
new cmmdc . c l i e n t . CmmdcWSService ( ) ;
cmmdc . c l i e n t .CmmdcWS p o r t=s e r v i c e . getCmmdcWSPort ( ) ;
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=((sm==n u l l ) | | ( . e q u a l s ( sm ) ) ) ? 1 : Long . p ar se Lon g ( sm ) ;
l o n g n=(( sn==n u l l ) | | ( . e q u a l s ( sn ) ) ) ? 1 : Long . par se Lon g ( sn ) ;
l o n g r e z=p o r t . cmmdc(m, n ) ;
String r e s u l t =(new Long ( r e z ) ) . t o S t r i n g ( ) ;
out . p r i n t l n ( R e s u l t = +r e s u l t ) ;
}
catch ( Exception e ) {
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 ( ) ) ;
}
%>
<hr/>
</body>
</html>
171
172
Pe calculatorul clientului, n clasa reprezentand serviciul (CmmdcWS pentru exemplul tratat), pentru fiecare metoda a serviciului se genereaza una
din metodele
public Response<MetodaResponse> metodaAsync( lista parametrilor
formali )
public Future<?> metodaAsync( lista parametrilor formali,
AsyncHandler<MetodaResponse> asyncHandler )
Pentru exemplul tratat metoda=cmmdc.
Cele doua metode ofera posibilitatea construirii a cate unui program client
specific, denumite, respectiv modelul polling si modelul callback.
Au intervenit interfetele
public interface Response<T> extends
java.util.concurrent.Future<T>
Un obiect de acest tip contine raspunsul serviciului. Raspunsul se obtine
cu metoda T get(), mostenita de la Future.
Metoda boolean isDone() returneaza true daca s-a primit raspuns.
public interface AsyncHandler<T>
Interfata declara metoda void handleResponse(Response<T> res) responsabila de prelucrarea raspunsului.
Exemplul 4.2.1 Client construit pe modelul polling.
1
2
3
5
6
7
8
9
10
11
12
13
14
package cmmdc . c l i e n t ;
import j a v a x . xml . ws . Response ;
import j a v a . u t i l . S c a n n e r ;
public c l a s s CmmdcAsyncClient {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
long d e l t a =500;
try {
CmmdcWS p o r t=new CmmdcWSService ( ) . getCmmdcWSPort ( ) ;
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= ) ;
long m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
long n=s c a n n e r . nextLong ( ) ;
Response<CmmdcResponse> r e s p o n s e=p o r t . cmmdcAsync (m, n ) ;
while ( ! r e s p o n s e . i s D o n e ( ) ) {
System . out . p r i n t l n ( Wait +d e l t a+ ms ) ;
Thread . s l e e p ( d e l t a ) ;
}
CmmdcResponse out pu t=r e s p o n s e . g e t ( ) ;
long r e s u l t=o ut pu t . g e t R e t u r n ( ) ;
System . out . p r i n t l n ( Cmmdc=+r e s u l t ) ;
16
17
18
19
20
21
22
23
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t f ( AnException : +e . g e t M e s s a g e ( ) ) ;
}
24
25
26
27
28
29
package cmmdc . c l i e n t ;
import j a v a . u t i l . c o n c u r r e n t . E x e c u t i o n E x c e p t i o n ;
import j a v a . u t i l . c o n c u r r e n t . Future ;
import j a v a x . xml . ws . Response ;
import j a v a x . xml . ws . AsyncHandler ;
import j a v a . u t i l . S c a n n e r ;
public c l a s s CmmdcAsyncClient {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
long d e l t a =500;
try {
CmmdcWS p o r t=new CmmdcWSService ( ) . getCmmdcWSPort ( ) ;
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= ) ;
long m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
long n=s c a n n e r . nextLong ( ) ;
CmmdcAsyncHandler a s y n c H a n d l e r=new CmmdcAsyncHandler ( ) ;
Future <?> r e s p o n s e=p o r t . cmmdcAsync (m, n , a s y n c H a n d l e r ) ;
while ( ! r e s p o n s e . i s D o n e ( ) ) {
System . out . p r i n t l n ( Wait +d e l t a+ ms ) ;
Thread . s l e e p ( d e l t a ) ;
}
173
174
25
26
27
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t f ( AnException : +e . g e t M e s s a g e ( ) ) ;
}
28
29
30
31
32
33
35
36
38
39
40
41
42
43
44
45
46
47
48
49
50
CmmdcResponse g e t R e s p o n s e ( ) {
return ou tp ut ;
}
52
53
54
55
4.2.2
Component
a EJB sesiune stateless ca serviciu Web
javax.ejb.Stateless;
javax.jws.WebService;
javax.jws.WebMethod;
javax.jws.WebParam;
@WebService
@Stateless
public class Componenta{
@WebMethod
public tip metoda(@WebParam(name="numeVarFormala")tip numeVarFormala,. . .){. . .}
. . .
}
Exemplul 4.2.3 Cel mai mare divizor comun a doua numere naturale
Componentei EJB are codul
1
2
3
4
5
7
8
9
package cmmdcws ;
import j a v a x . j w s . WebService ;
import j a v a x . j w s . WebMethod ;
import j a v a x . j w s . WebParam ;
import j a v a x . e j b . S t a t e l e s s ;
@WebService
@Stateless
public c l a s s CmmdcEJB {
@WebMethod
public long cmmdc(@WebParam( name = m ) long m,
@WebParam( name = n ) long n ) { . . . }
11
12
13
14
175
Clientul este unul obisnuit pentru serviciul Web de tip JAX-WS. In cazul
de fata codul clientului este
1
2
3
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package c l i e n t ;
import cmmdcws . ;
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 ) {
try {
CmmdcEJB p o r t=new CmmdcEJBService ( ) . getCmmdcEJBPort ( ) ;
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= ) ;
long m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
long n=s c a n n e r . nextLong ( ) ;
long r e s u l t=p o r t . cmmdc(m, n ) ;
System . out . p r i n t l n ( Cmmdc=+r e s u l t ) ;
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t f ( AnException : +e . g e t M e s s a g e ( ) ) ;
}
}
}
Reamintim ca dezvoltarea clientului se face cu serviciul Web activ, fiind necesara generarea unor clase - reprezentante ale serviciului - pe calculatorul clientului. La generarea claselor de catre wsimport, referinta URL a serviciului
Web trebuie sa corespunda serverului Web care contine serviciul n timpul
utilizarii.
176
4.2.3
java
|--> cmmdc
|
|--> server
|
|
|
CmmdcWS.java
resources
webapp
|--> WEB-INF
|
|
web.xml
|
|
sun-jaxws.xml
<repository>
<id>maven2-repository.java.net</id>
<name>Java.net Repository for Maven 2</name>
<url>http://download.java.net/maven/2/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>maven2-repository.java.net</id>
<name>Java.net Repository for Maven 2</name>
<url>http://download.java.net/maven/2/</url>
<layout>default</layout>
</pluginRepository>
</pluginRepositories>
177
178
Capitolul 5
Servicii JAX-RS
5.1
180
5.2
5.2.1
Jersey-2
Generarea resurselor
5.2. JERSEY-2
181
package r e s o u r c e s ;
import j a v a x . ws . r s . Produces ;
import j a v a x . ws . r s . Path ;
import j a v a x . ws . r s .GET;
4
5
7
8
@Path ( h e l l o w o r l d )
public c l a s s H e l l o W o r l d R e s o u r c e {
10
public H e l l o W o r l d R e s o u r c e ( ) {}
12
@GET
@Produces ( t e x t / p l a i n )
public S t r i n g g e t T e x t ( ) {
return ( H e l l o World ) ;
}
13
14
15
16
18
19
20
21
@Path ( html )
@GET
@Produces ( t e x t / html )
public S t r i n g getAsHtml ( ) {
182
22
23
24
26
@Path ( xml )
@GET
@Produces ( a p p l i c a t i o n /xml )
public S t r i n g getAsXml ( ) {
return <r e s p o n s e >H e l l o World</r e s p o n s e > ;
}
27
28
29
30
31
32
5.2. JERSEY-2
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
183
<r e s p o n s e>
<r e p r e s e n t a t i o n mediaType= t e x t / html />
</ r e s p o n s e>
</ method>
</ r e s o u r c e>
<r e s o u r c e path=xml>
<method i d= getAsXml name=GET>
<r e s p o n s e>
<r e p r e s e n t a t i o n mediaType= a p p l i c a t i o n /xml />
</ r e s p o n s e>
</ method>
</ r e s o u r c e>
</ r e s o u r c e>
</ r e s o u r c e s>
</ a p p l i c a t i o n>
Apelarea serviciului prin internediul unui navigator se poate face prin intermediul fisierului index.html - client Web
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<html>
<body>
<table border= 2 >
<tr>
<td>
<a href= / HelloWorld / r e s o u r c e s / h e l l o w o r l d >
R e z u l t a t t e x t / p l a i n </a>
</td>
</ tr>
<tr>
<td>
<a href= / HelloWorld / r e s o u r c e s / h e l l o w o r l d / html >
R e z u l t a t t e x t / html </a>
</td>
</ tr>
<tr>
<td>
<a href= / HelloWorld / r e s o u r c e s / h e l l o w o r l d /xml>
R e z u l t a t a p p l i c a t i o n /xml</a>
</td>
</ tr>
</ table>
</body>
</html>
184
import
import
import
import
import
j a v a . n e t .URL;
j a v a . n e t . HttpURLConnection ;
j a v a . i o . IOException ;
j a v a . i o . InputStreamReader ;
java . i o . BufferedReader ;
public c l a s s C l i e n t {
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
System . out . p r i n t l n ( R e z u l t a t / \ t e x t / p l a i n \ ) ;
S t r i n g u r l S t r=
h t t p : / / l o c a l h o s t : 8 0 8 0 / HelloWorld / r e s o u r c e s / h e l l o w o r l d ;
try {
S t r i n g r e z u l t a t=httpGetText ( u r l S t r ) ;
System . out . p r i n t l n ( r e z u l t a t ) ;
}
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 message : +e . g e t M e s s a g e ( ) ) ;
}
System . out . p r i n t l n ( ) ;
System . out . p r i n t l n ( R e z u l t a t / \ t e x t / html \ ) ;
urlStr =
h t t p : / / l o c a l h o s t : 8 0 8 0 / HelloWorld / r e s o u r c e s / h e l l o w o r l d / html ;
try {
S t r i n g r e z u l t a t=httpGetText ( u r l S t r ) ;
System . out . p r i n t l n ( r e z u l t a t ) ;
}
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 message : +e . g e t M e s s a g e ( ) ) ;
}
System . out . p r i n t l n ( ) ;
System . out . p r i n t l n ( R e z u l t a t / \ a p p l i c a t i o n /xml \ ) ;
urlStr =
h t t p : / / l o c a l h o s t : 8 0 8 0 / HelloWorld / r e s o u r c e s / h e l l o w o r l d /xml ;
try {
S t r i n g r e z u l t a t=httpGetText ( u r l S t r ) ;
System . out . p r i n t l n ( r e z u l t a t ) ;
}
185
5.2. JERSEY-2
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 message : +e . g e t M e s s a g e ( ) ) ;
}
40
41
42
43
45
public s t a t i c S t r i n g httpGetText ( S t r i n g u r l S t r )
throws IOException {
URL u r l=new URL( u r l S t r ) ;
HttpURLConnection conn=(HttpURLConnection ) u r l . op enConn ection ( ) ;
46
47
48
i f ( conn . getResponseCode ( ) != 2 0 0 ) {
throw new IOException ( conn . g e t R e s p o n s e M e s s a g e ( ) ) ;
}
50
51
52
// B u f f e r t h e r e s u l t i n t o a s t r i n g
B u f f e r e d R e a d e r rd = new B u f f e r e d R e a d e r (
new InputStreamReader ( conn . g e t I n p u t S t r e a m ( ) ) ) ;
S t r i n g B u i l d e r sb = new S t r i n g B u i l d e r ( ) ;
String line ;
while ( ( l i n e = rd . r e a d L i n e ( ) ) != n u l l ) {
sb . append ( l i n e+ \n ) ;
}
rd . c l o s e ( ) ;
54
55
56
57
58
59
60
61
62
conn . d i s c o n n e c t ( ) ;
return sb . t o S t r i n g ( ) ;
64
65
66
67
2. Resursele interfetei de programare (API) Jersey Client, continute n pachetul com.sun.jersey.api.client. Aceasta varianta asigura o prelucrere mai simpla si unitara a rezultatelor furnizate de un serviciu RESTful.
Sablonul de prelucrare consta din:
(a) Crearea unei instante a clasei javax.ws.rs.client.Client
Client client = ClientBuilder.newClient();
186
package hw ;
import j a v a x . ws .
import j a v a x . ws .
import j a v a x . ws .
import j a v a x . ws .
rs
rs
rs
rs
.
.
.
.
client
client
client
client
. Client ;
. ClientBuilder ;
. WebTarget ;
. Invocation ;
public c l a s s J e r s e y C l i e n t {
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
C l i e n t c l i e n t = C l i e n t B u i l d e r . newClient ( ) ;
S t r i n g rootURL =
h t t p : / / l o c a l h o s t : 8 0 8 0 / HelloWorld / r e s o u r c e s / h e l l o w o r l d ;
S t r i n g r e s p o n s e= ;
187
5.2. JERSEY-2
WebTarget webTarget=n u l l ;
I n v o c a t i o n . B u i l d e r i n v o c a t i o n B u i l d e r=n u l l ;
13
14
webTarget=c l i e n t . t a r g e t ( rootURL ) ;
i n v o c a t i o n B u i l d e r=webTarget . r e q u e s t ( ) ;
r e s p o n s e=i n v o c a t i o n B u i l d e r . g e t ( S t r i n g . c l a s s ) ;
System . out . p r i n t l n ( PLAIN TEXT ) ;
System . out . p r i n t l n ( r e s p o n s e+ \n ) ;
16
17
18
19
20
i n v o c a t i o n B u i l d e r=webTarget
. path ( html )
. request ( ) ;
r e s p o n s e=i n v o c a t i o n B u i l d e r . g e t ( S t r i n g . c l a s s ) ;
System . out . p r i n t l n ( HTML ) ;
System . out . p r i n t l n ( r e s p o n s e+ \n ) ;
22
23
24
25
26
27
i n v o c a t i o n B u i l d e r=webTarget
. path ( xml )
. request ( ) ;
r e s p o n s e=i n v o c a t i o n B u i l d e r . g e t ( S t r i n g . c l a s s ) ;
System . out . p r i n t l n ( XML ) ;
System . out . p r i n t l n ( r e s p o n s e ) ;
29
30
31
32
33
34
35
36
package hw ;
import j a v a x . ws .
import j a v a x . ws .
import j a v a x . ws .
import j a v a . u t i l
import j a v a . u t i l
rs . c l i en t . Client ;
rs . client . ClientBuilder ;
rs . c l i e n t . InvocationCallback ;
. c o n c u r r e n t . CountDownLatch ;
. c o n c u r r e n t . TimeUnit ;
public c l a s s J e r s e y A s y n c C l i e n t {
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
System . out . p r i n t l n ( Asyncronous E x e c u t i o n \n ) ;
S t r i n g rootURL =
h t t p : / / l o c a l h o s t : 8 0 8 0 / HelloWorld / r e s o u r c e s / h e l l o w o r l d ;
S t r i n g [ ] u r l s ={rootURL , rootURL+ / html , rootURL+ /xml } ;
CountDownLatch c d l=new CountDownLatch ( u r l s . l e n g t h ) ;
C l i e n t c l i e n t=C l i e n t B u i l d e r . n e w C l i e n t ( ) ;
for ( S t r i n g u r l : u r l s ){
client . target ( url )
. request ()
. async ( )
. g e t (new I n v o c a t i o n C a l l b a c k <S t r i n g >(){
@Override
public void c o m p l e t e d ( S t r i n g msg ) {
System . out . p r i n t l n ( R e c e i v e d : + \n+msg ) ;
c d l . countDown ( ) ;
}
@Override
public void f a i l e d ( Throwable t h r o w a b l e ) {
System . out . p r i n t l n ( t h r o w a b l e . g e t M e s s a g e ( ) ) ;
c d l . countDown ( ) ;
}
});
}
188
try {
cdl . await ( ) ;
client . close ();
}
catch ( f i n a l I n t e r r u p t e d E x c e p t i o n e ) {
e . printStackTrace ( ) ;
}
33
34
35
36
37
38
39
40
41
package r e s o u r c e s ;
import j a v a . u t i l . S e t ;
import j a v a x . ws . r s . A p p l i c a t i o n P a t h ;
import j a v a x . ws . r s . c o r e . A p p l i c a t i o n ;
@ApplicationPath ( webresources )
public c l a s s MyApplication extends A p p l i c a t i o n {
@Override
public Set<C l a s s <?>> g e t C l a s s e s ( ) {
Set<C l a s s <?>> r e s o u r c e s = new j a v a . u t i l . HashSet < >();
r e s o u r c e s . add ( H e l l o W o r l d R e s o u r c e . c l a s s ) ;
return r e s o u r c e s ;
}
9
10
11
12
13
14
15
care leaga referinta virtuala webresources de clasa care genereaza resursa radacina,
HelloWorldResource . Clasa javax.ws.rs.core.Application contine metodele
public Set<Class<?>> getClasses()
public Set<Class<?>> getSingletons()
Prezenta arhivei jersey-container-servlet-*.jar permite eliminarea fisierului
web.xml.
Fiecare tip de resursa a fost generat ca o subresursa cu o cale specifica.
Aceasta abordare a facut posibila realizarea unui client Web si a unui client
bazat pe clasa java.net.URL. Un client jersey poate prelua o resursa pe baza
tipului MIME (Multipurpose Internet Mail Extensions). Modificam codul clasei HelloWorldResource n
1
package r e s o u r c e s ;
import j a v a x . ws . r s . Produces ;
import j a v a x . ws . r s . Path ;
189
5.2. JERSEY-2
5
6
8
9
import j a v a x . ws . r s .GET;
import j a v a x . ws . r s . c o r e . MediaType ;
@Path ( h e l l o w o r l d )
public c l a s s H e l l o W o r l d R e s o u r c e {
11
public H e l l o W o r l d R e s o u r c e ( ) {}
13
@GET
@Produces ( MediaType . TEXT PLAIN)
public S t r i n g g e t T e x t ( ) {
return ( H e l l o World ) ;
}
14
15
16
17
@GET
@Produces ( MediaType .TEXT HTML)
public S t r i n g getAsHtml ( ) {
return <html><head></head><body b g c o l o r=\#bbeebb\>< c e n t e r >
<p>H e l l o World</p></c e n t e r ></body></html> ;
}
19
20
21
22
23
24
@GET
@Produces ( MediaType .TEXT XML)
public S t r i n g getAsXml ( ) {
return <r e s p o n s e >H e l l o World</r e s p o n s e > ;
}
26
27
28
29
30
@GET
@Produces ( MediaType . APPLICATION XML)
public S t r i n g getAsAppXml ( ) {
return <r e s p o n s e >H e l l o World</r e s p o n s e > ;
}
32
33
34
35
36
@GET
@Produces ( MediaType . APPLICATION JSON)
public S t r i n g g e t A s J s o n ( ) {
return [ \ H e l l o World \ ] ;
}
38
39
40
41
42
43
package hw ;
import j a v a x . ws .
import j a v a x . ws .
import j a v a x . ws .
import j a v a x . ws .
import j a v a x . ws .
rs
rs
rs
rs
rs
.
.
.
.
.
c l i en t . Client ;
client . ClientBuilder ;
c l i e n t . WebTarget ;
c l i e n t . Invocation ;
c o r e . MediaType ;
public c l a s s J e r s e y C l i e n t {
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 serviceURL= h t t p : / / l o c a l h o s t : 8 0 8 0 / HelloWorld / r e s o u r c e s / h e l l o w o r l d ;
C l i e n t c l i e n t = C l i e n t B u i l d e r . newClient ( ) ;
WebTarget webTarget=c l i e n t . t a r g e t ( serviceURL ) ;
String response ;
System . out . p r i n t l n ( MediaType . TEXT PLAIN TYPE ) ;
r e s p o n s e=webTarget . r e q u e s t ( MediaType . TEXT PLAIN TYPE)
. get ( String . class ) ;
System . out . p r i n t l n ( r e s p o n s e ) ;
190
System . out . p r i n t l n ( ) ;
System . out . p r i n t l n ( MediaType .TEXT HTML TYPE ) ;
r e s p o n s e=webTarget . r e q u e s t ( MediaType .TEXT HTML TYPE)
. get ( String . class ) ;
System . out . p r i n t l n ( r e s p o n s e ) ;
System . out . p r i n t l n ( ) ;
System . out . p r i n t l n ( MediaType . TEXT XML TYPE ) ;
r e s p o n s e=webTarget . r e q u e s t ( MediaType . TEXT XML TYPE)
. get ( String . class ) ;
System . out . p r i n t l n ( r e s p o n s e ) ;
System . out . p r i n t l n ( ) ;
System . out . p r i n t l n ( MediaType . APPLICATION XML TYPE ) ;
r e s p o n s e=webTarget . r e q u e s t ( MediaType . APPLICATION XML TYPE)
. get ( String . class ) ;
System . out . p r i n t l n ( r e s p o n s e ) ;
System . out . p r i n t l n ( ) ;
System . out . p r i n t l n ( MediaType . APPLICATION JSON TYPE ) ;
r e s p o n s e=webTarget . r e q u e s t ( MediaType . APPLICATION JSON TYPE)
. get ( String . class ) ;
System . out . p r i n t l n ( r e s p o n s e ) ;
System . out . p r i n t l n ( ) ;
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package r e s o u r c e s ;
import j a v a . n e t .URL;
import j a v a x . ws . r s . Produces ;
import j a v a x . ws . r s . Path ;
import j a v a x . ws . r s .GET;
import j a v a x . a c t i v a t i o n . DataSource ;
import j a v a x . a c t i v a t i o n . F i l e D a t a S o u r c e ;
@Path ( i m a g i n e )
public c l a s s ImageResource {
5.2. JERSEY-2
12
public ImageResource ( ) {}
14
@GET
@Produces ( image / j p g )
public DataSource getImageRep ( ) {
URL jpgURL = t h i s . g e t C l a s s ( ) . g e t R e s o u r c e ( f o r e s t . j p g ) ;
return new F i l e D a t a S o u r c e ( jpgURL . g e t F i l e ( ) ) ;
}
15
16
17
18
19
20
191
5.2.2
Preluarea parametrilor
192
Interfata javax.ws.rs.core.MultivaluedMap<K,V>
extends java.util.Map<K,java.util.List<V>>
Metode
V getFirst(K key)
Returneaza valoarea corespunzatoare cheii key.
Clasa javax.ws.rs.core.Response
Metode
public static Response.ResponseBuilder ok(Object entity, String
mimetype)
Creaza un obiect care contine reprezentarea raspunsului.
Clasa javax.ws.rs.core.Response.ResponseBuilder
Metode
public abstract Response build()
Creaza obiectul Response n urma executarii metodei ok.
Pentru acelasi exemplu codul serviciului este:
1
2
3
4
5
6
7
8
10
11
package r e s o u r c e s ;
import j a v a x . ws . r s . c o r e . MultivaluedMap ;
import j a v a x . ws . r s . c o r e . Response ;
import j a v a x . ws . r s . c o r e . Context ;
import j a v a x . ws . r s . c o r e . U r i I n f o ;
import j a v a x . ws . r s . Path ;
import j a v a x . ws . r s .GET;
import j a v a . n e t . URLDecoder ;
@Path ( h e l l o )
public c l a s s H e l l o R e s o u r c e {
13
public H e l l o R e s o u r c e ( ) {}
15
@Context U r i I n f o u r i I n f o ;
@GET
public Response doGet ( ) {
MultivaluedMap<S t r i n g , S t r i n g > params=u r i I n f o . g e t Q u e r y P a r a m e t e r s ( ) ;
S t r i n g nume=params . g e t F i r s t ( nume ) ;
S t r i n g t i p=n u l l ;
try {
t i p=URLDecoder . d ec od e ( params . g e t F i r s t ( t i p ) , UTF8 ) ;
}
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 ( Param : +nume+ +t i p ) ;
Response r=n u l l ;
16
17
18
19
20
21
22
23
24
25
26
27
28
5.2. JERSEY-2
switch ( t i p ) {
case t e x t / p l a i n :
r=Response . ok ( g e t P l a i n R e p ( nume ) , t e x t / p l a i n ) . b u i l d ( ) ;
break ;
case t e x t / html :
r=Response . ok ( getHtmlRep ( nume ) , t e x t / html ) . b u i l d ( ) ;
break ;
}
return r ;
29
30
31
32
33
34
35
36
37
38
40
public S t r i n g g e t P l a i n R e p ( S t r i n g nume ) {
return H e l l o +nume+ ! ;
}
41
42
44
45
46
47
48
193
package r e s o u r c e s ;
import j a v a x . ws . r s . Path ;
import j a v a x . ws . r s .GET;
import j a v a x . ws . r s . QueryParam ;
import j a v a x . ws . r s . c o r e . Response ;
import j a v a . n e t . URLDecoder ;
@Path ( h e l l o )
public c l a s s H e l l o R e s o u r c e {
11
public H e l l o R e s o u r c e ( ) {}
13
@GET
public Response p r o c e s s Q u e r y (
@QueryParam ( nume ) S t r i n g nume ,
@QueryParam ( t i p ) S t r i n g t i p ) {
S t r i n g t i p 0=n u l l ;
try {
t i p 0=URLDecoder . de co de ( t i p , UTF8 ) ;
14
15
16
17
18
19
194
}
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 ( ) ) ;
}
Response r=n u l l ;
switch ( t i p 0 ) {
case t e x t / p l a i n :
r=Response . ok ( g e t P l a i n R e p ( nume ) , t e x t / p l a i n ) . b u i l d ( ) ;
break ;
case t e x t / html :
r=Response . ok ( getHtmlRep ( nume ) , t e x t / html ) . b u i l d ( ) ;
break ;
}
return r ;
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
36
public S t r i n g g e t P l a i n R e p ( S t r i n g nume ) {
return H e l l o +nume+ ! ;
}
37
38
40
41
42
43
44
<html>
<body>
<center>
<h1> S e r v i c i u H e l l o de t i p RESTful </h1>
<form method= g e t
action= / H e l l o / r e s o u r c e s / h e l l o >
<p> I n t r o d u c e t i numele </p>
<input type= t e x t name=nume s i z e= 10 />
<p> S e l e c t a t i t i p u l r a s p u n s u l u i </p>
<s e l e c t name= t i p >
<option value= t e x t / p l a i n > Text / P l a i n </ option>
<option value= t e x t / html > Text /Html </ option>
</ s e l e c t>
<p>
<input type= submit value= A p e l e a z a />
</form>
</ center>
</body>
</html>
import j a v a . n e t .URL;
import j a v a . n e t . HttpURLConnection ;
import j a v a . n e t . URLEncoder ;
195
5.2. JERSEY-2
4
5
6
7
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import
import
import
import
i o . IOException ;
i o . InputStreamReader ;
i o . BufferedReader ;
u t i l . Scanner ;
public c l a s s C l i e n t {
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 ) ;
try {
S t r i n g param= ? ;
System . out . p r i n t l n ( Numele ) ;
S t r i n g nume=URLEncoder . en code ( s c a n n e r . n e x t ( ) , UTF8 ) ;
param=param+nume=+nume+& ;
param=param+ t i p=+URLEncoder . e nc od e ( t e x t / p l a i n , UTF8 ) ;
S t r i n g u r l S t r= h t t p : / / l o c a l h o s t : 8 0 8 0 / H e l l o / r e s o u r c e s / h e l l o +param ;
System . out . p r i n t l n ( u r l S t r ) ;
S t r i n g r e z u l t a t=httpGetText ( u r l S t r ) ;
System . out . p r i n t l n ( r e z u l t a t ) ;
}
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 message : +e . g e t M e s s a g e ( ) ) ;
}
System . out . p r i n t l n ( ) ;
}
public s t a t i c S t r i n g httpGetText ( S t r i n g u r l S t r ) throws IOException { . . . }
29
30
java .
java .
java .
java .
package h e l l o ;
import j a v a x . ws .
import j a v a x . ws .
import j a v a x . ws .
import j a v a . u t i l
rs . c l i en t . Client ;
rs . client . ClientBuilder ;
r s . c l i e n t . WebTarget ;
. Scanner ;
public c l a s s J e r s e y C l i e n t {
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
C l i e n t c l i e n t = C l i e n t B u i l d e r . newClient ( ) ;
WebTarget webTarget=
c l i e n t . t a r g e t ( http :// l o c a l h o s t :8080/ Hello / r e s o u r c e s / h e l l o ) ;
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 t i p u l r a s p u n s u l u i : ) ;
System . out . p r i n t l n ( ( p l a i n / html ) ) ;
S t r i n g t i p=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( I n t r o d u c e t i numele : ) ;
S t r i n g nume=s c a n n e r . n e x t ( ) ;
S t r i n g r e s p o n s e=webTarget . queryParam ( nume , nume ) .
queryParam ( t i p , t e x t / +t i p ) . r e q u e s t ( ) . g e t ( S t r i n g . c l a s s ) ;
System . out . p r i n t l n ( r e s p o n s e ) ;
}
}
import
import
import
import
o r g . apache . h t t p . H t t p E n t i t y ;
o r g . apache . h t t p . HttpResponse ;
o r g . apache . h t t p . c l i e n t . methods . HttpPost ;
o r g . apache . h t t p . impl . c l i e n t . C l o s e a b l e H t t p C l i e n t ;
196
5
6
7
8
9
10
12
13
15
16
import
import
import
import
import
import
o r g . apache . h t t p . impl . c l i e n t . H t t p C l i e n t s ;
java . u t i l . List ;
java . u t i l . ArrayList ;
java . u t i l . Scanner ;
o r g . apache . h t t p . NameValuePair ;
o r g . apache . h t t p . message . BasicNameValuePair ;
18
19
20
21
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package h e l l o ;
import j a v a x . ws .
import j a v a x . ws .
import j a v a x . ws .
import j a v a x . ws .
import j a v a x . ws .
import j a v a x . ws .
import j a v a . u t i l
rs . c l i en t . Client ;
rs . c l i e n t . Entity ;
rs . client . ClientBuilder ;
r s . c l i e n t . WebTarget ;
r s . c o r e . Form ;
r s . c o r e . Response ;
. Scanner ;
public c l a s s J e r s e y C l i e n t {
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
C l i e n t c l i e n t = C l i e n t B u i l d e r . newClient ( ) ;
WebTarget webTarget=
c l i e n t . t a r g e t ( http :// l o c a l h o s t :8080/ Hello / r e s o u r c e s / h e l l o ) ;
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 ) ;
197
5.2. JERSEY-2
System . out . p r i n t l n ( I n t r o d u c e t i t i p u l r a s p u n s u l u i : ) ;
System . out . p r i n t l n ( ( p l a i n | html ) ) ;
S t r i n g t i p=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( I n t r o d u c e t i numele : ) ;
S t r i n g nume=s c a n n e r . n e x t ( ) ;
Form f=new Form ( ) . param ( nume , nume ) . param ( t i p , t e x t / +t i p ) ;
Response r e s p o n s e=webTarget . r e q u e s t ( ) . p o s t ( E n t i t y . form ( f ) ) ;
String r = response . readEntity ( String . class ) ;
System . out . p r i n t l n ( r ) ;
16
17
18
19
20
21
22
23
24
25
26
Adnotarea @PathParam
In cazul utilizarii metodei http GET o solutie mai simpla pentru fixarea
unui numar mic de parametri este introducerea lor n adnotarea @Path sub
forma
@Path("refCale/{param1},{param2},. . .")
Metoda care preia parametri utilizeaza adnotarea @PathParam:
public T getResursa(@PathParam("param1") String p1,
@PathParam("param2") String p2,. . .){. . .}
Stringul care fixeaza URL-ul de apelare va fi de forma
.../resources/refCale/valParam1,valParam2
Exemplul 5.2.3 Serviciu RESTful pentru calculul celui mai mare divizor comun a doua numere naturale.
Codul serviciului este
1
2
3
4
5
6
8
9
package r e s o u r c e s ;
import j a v a x . ws . r s
import j a v a x . ws . r s
import j a v a x . ws . r s
import j a v a x . ws . r s
import j a v a x . ws . r s
. Path ;
. PathParam ;
. Produces ;
.GET;
. c o r e . MediaType ;
11
public CmmdcResource ( ) { }
13
@GET
@Produces ( MediaType . APPLICATION XML)
public S t r i n g getCmmdcAsXML( @PathParam ( num1 ) S t r i n g sm ,
@PathParam ( num2 ) S t r i n g sn ) {
System . out . p r i n t l n ( sm+ +sn ) ;
14
15
16
17
198
18
19
20
21
22
23
24
26
27
iar al clientului
1
2
3
4
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import
import
import
import
com . sun . j e r s e y . a p i . c l i e n t . C l i e n t ;
com . sun . j e r s e y . a p i . c l i e n t . WebResource ;
j a v a x . ws . r s . c o r e . MediaType ;
java . u t i l . Scanner ;
public c l a s s J e r s e y C l i e n t {
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 ( Primul numar : ) ;
long m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( Al d o i l e a numar : ) ;
long n=s c a n n e r . nextLong ( ) ;
S t r i n g sm=(new Long (m) ) . t o S t r i n g ( ) ;
S t r i n g sn =(new Long ( n ) ) . t o S t r i n g ( ) ;
Client c l i e n t = Client . create ( ) ;
WebResource webResource = c l i e n t . r e s o u r c e (
h t t p : / / l o c a l h o s t : 8 0 8 0 / cmmdcapp/ r e s o u r c e s /cmmdc/ +sm+ , +sn ) ;
S t r i n g r e s p o n s e=
webResource . a c c e p t ( MediaType . APPLICATION XML ) . g e t ( S t r i n g . c l a s s ) ;
System . out . p r i n t l n ( ) ;
System . out . p r i n t l n ( MediaType . APPLICATION XML ) ;
System . out . p r i n t l n ( r e s p o n s e ) ;
}
}
5.2. JERSEY-2
20
21
22
23
24
25
26
27
28
29
30
31
33
34
35
36
37
38
39
41
42
43
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
}
f u n c t i o n p a r s e M e s s a g e s ( responseXML ) {
var r = responseXML . getElementsByTagName ( r e z u l t a t ) [ 0 ] ;
var cmmdc=r . c h i l d N o d e s [ 0 ] . nodeValue ;
document . g e t E l e m e n t B y I d ( r e z u l t a t ) . innerHTML=Cmmdc = +cmmdc ;
}
>
</ s c r i p t>
< t i t l e> Cmmdc AJAX</ t i t l e>
</head>
<body bgcolor=#bbccbb >
<h1>Cmmdc with AJAX</h1>
<form>
<table>
<tr>
<td><l a b e l> Primul numar </ l a b e l></td>
<td>
<input type=number id=m s i z e= 5
r e q u i r e d min= 1 >
</td>
</ tr>
<tr>
<td><l a b e l> Al d o i l e a numar </ l a b e l></td>
<td>
<input type=number id=n s i z e= 5
r e q u i r e d min= 1 >
</td>
</ tr>
<tr>
<td>
<p><input type= b ut to n value= C a l c u l e a z a onClick= compute ( ) >
</td>
</ tr>
</ table>
</form>
<p>
Cel mai mare d i v i z o r comun a l c e l o r doua numere e s t e
<p>
<div id= r e z u l t a t />
</body>
</html>
199
200
5.2.3
package r e s o u r c e s ;
// i m p o r t j a v a x . xml . b i n d . a n n o t a t i o n . XmlRootElement ;
// @XmlRootElement ( name=d a t e )
201
5.2. JERSEY-2
5
6
7
8
public c l a s s CmmdcBean{
private S t r i n g sm ;
private S t r i n g sn ;
private S t r i n g r e s u l t ;
public void setSm ( S t r i n g sm ) {
t h i s . sm=sm ;
}
public S t r i n g getSm ( ) {
return sm ;
}
10
11
12
13
14
15
public void s e t S n ( S t r i n g sn ) {
t h i s . sn=sn ;
}
public S t r i n g getSn ( ) {
return sn ;
}
17
18
19
20
21
22
public void s e t R e s u l t ( S t r i n g r e s u l t ) {
t h i s . r e s u l t=r e s u l t ;
}
public S t r i n g g e t R e s u l t ( ) {
return r e s u l t ;
}
24
25
26
27
28
29
30
package r e s o u r c e s ;
import j a v a x . ws . r s
import j a v a x . ws . r s
import j a v a x . ws . r s
import j a v a x . ws . r s
import j a v a x . ws . r s
. Consumes ;
. POST ;
. Path ;
. Produces ;
. c o r e . MediaType ;
@Path ( cmmdc )
public c l a s s CmmdcResource {
public CmmdcResource ( ) { }
@POST
@Produces ( MediaType . APPLICATION JSON)
@Consumes ( MediaType . APPLICATION JSON)
public CmmdcBean myJob (CmmdcBean o b j ) {
S t r i n g sm=o b j . getSm ( ) ;
S t r i n g sn=o b j . getSn ( ) ;
long m=Long . par se Lon g ( sm ) ;
long n=Long . p ars eL ong ( sn ) ;
long c=cmmdc(m, n ) ;
S t r i n g cmmdc=(new Long ( c ) ) . t o S t r i n g ( ) ;
CmmdcBean cb=new CmmdcBean ( ) ;
cb . s e t R e s u l t (cmmdc ) ;
return cb ;
}
202
27
28
package cmmdc ;
import j a v a x . ws . r s . c l i e n t . C l i e n t ;
import j a v a x . ws . r s . c l i e n t . C l i e n t B u i l d e r ;
import j a v a x . ws . r s . c l i e n t . WebTarget ;
import j a v a x . ws . r s . c l i e n t . E n t i t y ;
import j a v a x . ws . r s . c o r e . MediaType ;
import j a v a . u t i l . S c a n n e r ;
import j a v a . i o . P r i n t W r i t e r ;
import r e s o u r c e s . CmmdcBean ;
public c l a s s J e r s e y C l i e n t {
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 ( Primul numar : ) ;
long m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( Al d o i l e a numar : ) ;
long n=s c a n n e r . nextLong ( ) ;
S t r i n g sm=(new Long (m) ) . t o S t r i n g ( ) ;
S t r i n g sn =(new Long ( n ) ) . t o S t r i n g ( ) ;
CmmdcBean bean=new CmmdcBean ( ) ;
bean . setSm ( sm ) ;
bean . s e t S n ( sn ) ;
i n t t i p =1;
do{
System . out . p r i n t l n ( Encoder Type ) ;
System . out . p r i n t l n ( 1 : JSON ) ;
System . out . p r i n t l n ( 2 : XML ) ;
t i p=s c a n n e r . n e x t I n t ( ) ;
}
while ( ( t i p !=1) && ( t i p ! = 2 ) ) ;
C l i e n t c l i e n t = C l i e n t B u i l d e r . newClient ( ) ;
S t r i n g sURI= ;
i f ( t i p ==1){
sURI= h t t p : / / l o c a l h o s t : 8 0 8 0 / JsonCmmdc/ r e s o u r c e s /cmmdc ;
}
else {
sURI= h t t p : / / l o c a l h o s t : 8 0 8 0 /XmlCmmdc/ r e s o u r c e s /cmmdc ;
}
WebTarget t a r g e t=c l i e n t . t a r g e t ( sURI ) ;
CmmdcBean o b j ;
i f ( t i p ==1){
obj = target
. request ()
. p o s t ( E n t i t y . e n t i t y ( bean , MediaType . APPLICATION JSON ) ,
CmmdcBean . c l a s s ) ;
}
else {
obj = target
. request ()
203
5.2. JERSEY-2
52
53
}
System . out . p r i n t l n ( o b j . g e t R e s u l t ( ) ) ;
54
55
56
57
<html>
<head>
<s c r i p t type= t e x t / j a v a s c r i p t >
< !
function initRequest () {
i f ( window . XMLHttpRequest ) {
r e t u r n new XMLHttpRequest ( ) ;
} e l s e i f ( window . A c t i v e X O b j e c t ) {
r e t u r n new A c t i v e X O b j e c t ( M i c r o s o f t .XMLHTTP ) ;
}
}
f u n c t i o n compute ( ) {
var mField=document . g e t E l e m e n t B y I d ( m ) ;
var n F i e l d=document . g e t E l e m e n t B y I d ( n ) ;
var u r l = /JsonCmmdc/ r e s o u r c e s /cmmdc
var msg=JSON . s t r i n g i f y ( {
sm : mField . value ,
sn : n F i e l d . value
});
var r e q = i n i t R e q u e s t ( ) ;
req . onreadystatechange = function () {
i f ( r e q . r e a d y S t a t e == 4) {
i f ( r e q . s t a t u s == 200) {
parseMessages ( req . responseText ) ;
} else {
a l e r t ( r e q . s t a t u s+ : +r e q . s t a t u s T e x t ) ;
}
}
};
r e q . open ( p o s t , u r l , t r u e ) ;
r e q . s e t R e q u e s t H e a d e r ( ContentType , a p p l i c a t i o n / j s o n ) ;
r e q . send ( msg ) ;
23
24
25
26
27
28
29
30
31
32
33
34
35
37
38
39
40
41
42
43
44
45
46
47
48
49
}
f u n c t i o n parseMessages ( responseText ) {
var r e s=r e s p o n s e T e x t ;
var s=JSON . p a r s e ( r e s ) ;
document . g e t E l e m e n t B y I d ( r e z u l t a t ) . innerHTML=
Cmmdc = +s . r e s u l t ;
}
>
</ s c r i p t>
< t i t l e> Cmmdc AJAX</ t i t l e>
</head>
<body>
<h1>Cmmdc with AJAX</h1>
<p>
204
50
51
52
53
54
55
56
57
58
59
60
61
62
Primul numar :
<input type= t e x t id=m value= 1 s i z e= 15 >
<p>
Al d o i l e a numar :
<input type= t e x t id=n value= 1 s i z e= 15 >
<p>
<input type= b ut to n value= C a l c u l e a z a onClick= compute ( ) >
<p>
Cel mai mare d i v i z o r comun a c e l o r doua numere e s t e
<p>
<div id= r e z u l t a t />
</body>
</html>
respectiv
1
2
3
4
5
6
7
8
9
10
11
13
14
15
16
17
18
19
20
<html>
<head>
<s c r i p t type= t e x t / j a v a s c r i p t >
< !
function initRequest () {
i f ( window . XMLHttpRequest ) {
r e t u r n new XMLHttpRequest ( ) ;
} e l s e i f ( window . A c t i v e X O b j e c t ) {
r e t u r n new A c t i v e X O b j e c t ( M i c r o s o f t .XMLHTTP ) ;
}
}
f u n c t i o n compute ( ) {
var mField=document . g e t E l e m e n t B y I d ( m ) . value ;
var n F i e l d=document . g e t E l e m e n t B y I d ( n ) . value ;
var u r l = /XmlCmmdc/ r e s o u r c e s /cmmdc
var msg=
<?xml v e r s i o n =\ 1 . 0 \ e n c o d i n g=\UTF8\ s t a n d a l o n e =\ y e s \ ?>+
<date><sm>+mField+</sm><sn>+n F i e l d+</sn></date> ;
var r e q = i n i t R e q u e s t ( ) ;
req . onreadystatechange = function () {
i f ( r e q . r e a d y S t a t e == 4) {
i f ( r e q . s t a t u s == 200) {
parseMessages ( req . responseText ) ;
} else {
a l e r t ( r e q . s t a t u s+ : +r e q . s t a t u s T e x t ) ;
}
}
};
r e q . open ( p o s t , u r l , t r u e ) ;
r e q . s e t R e q u e s t H e a d e r ( ContentType , a p p l i c a t i o n /xml ) ;
r e q . send ( msg ) ;
22
23
24
25
26
27
28
29
30
31
32
33
34
36
37
38
39
40
41
42
}
f u n c t i o n parseMessages ( responseText ) {
var r e s=r e s p o n s e T e x t ;
document . g e t E l e m e n t B y I d ( r e z u l t a t ) . innerHTML=Cmmdc = +r e s ;
}
>
</ s c r i p t>
< t i t l e> Cmmdc AJAX</ t i t l e>
5.2. JERSEY-2
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
205
</head>
<body>
<h1>RESTful Cmmdc with AJAX cu mesaj XML</h1>
<p>
Primul numar :
<input type= t e x t id=m value= 1 s i z e= 15 >
<p>
Al d o i l e a numar :
<input type= t e x t id=n value= 1 s i z e= 15 >
<p>
<input type= b ut to n value= C a l c u l e a z a onClick= compute ( ) >
<p>
Cel mai mare d i v i z o r comun a c e l o r doua numere e s t e
<p>
<div id= r e z u l t a t />
</body>
</html>
5.2.4
206
import java.util.concurrent.TimeUnit;
. . .
int timeOut=. . .;
response.setTimeout(timeOut, TimeUnit.SECONDS);
response.setTimeoutHandler((asyncResp) -> {
asyncResp.resume(Response.status(Response.Status.REQUEST_TIMEOUT).build());
});
package r e s o u r c e s ;
import j a v a x . ws . r s . QueryParam ;
import j a v a x . ws . r s . c o r e . Response ;
import j a v a x . ws . r s . Path ;
import j a v a x . ws . r s .GET;
import j a v a x . ws . r s . c o n t a i n e r . Suspended ;
import j a v a x . ws . r s . c o n t a i n e r . AsyncResponse ;
import j a v a . u t i l . c o n c u r r e n t . TimeUnit ;
@Path ( query )
public c l a s s CmmdcResource {
@GET
public void processForm ( @Suspended AsyncResponse r e s p o n s e ,
@QueryParam ( m ) S t r i n g sm ,
@QueryParam ( n ) S t r i n g sn ) {
long m=Long . par se Lon g ( sm ) ;
long n=Long . p ars eL ong ( sn ) ;
new Thread (()>{
long c=cmmdc(m, n ) ;
S t r i n g s c=Cmmdc : +new Long ( c ) . t o S t r i n g ( ) ;
r e s p o n s e . resume ( s c ) ;
}). start ();
20
21
22
23
24
r e s p o n s e . s e t T i m e o u t ( 5 , TimeUnit .SECONDS ) ;
// c l i e n t w i l l r e c i e v e a HTTP 408 ( t i m e o u t e r r o r ) a f t e r 5 s e c o n d s
r e s p o n s e . s e t T i m e o u t H a n d l e r ( ( asyncResp ) > {
asyncResp . resume ( Response
. s t a t u s ( Response . S t a t u s .REQUEST TIMEOUT ) . b u i l d ( ) ) ;
});
26
27
28
29
30
31
32
34
35
36
37
38
39
5.2. JERSEY-2
n=r ;
}
while ( r ! = 0 ) ;
/
try {
Thread . s l e e p ( 1 0 0 0 0 ) ;
}
catch ( I n t e r r u p t e d E x c e p t i o n e ){}
/
return c ;
40
41
42
43
44
45
46
47
48
49
50
51
207
5.2.5
Jersey n glassfish
Pachetul jersey este continut n glassfish. In consecinta arhiva war destinata desfasurarii unei aplicatii nu trebuie sa contina resursele care tin de
jersey.
Aplicatiile dezvoltate anterior functioneaza fara nici o modificare n glassfish.
Semnalam arhitectura unei aplicatii care utilizeaza o componenta EJB de
tip session stateless, care este injectata n clasa serviciului RESTful. Injectarea
se poate programa utilizand:
adnotarile javax.annotation.ManagedBean si javax.inject.Inject.
In acest caz, este nevoie de prezenta unui fisier beans.xml, avand codul
1
2
3
4
5
6
<?xml v e r s i o n= 1 . 0 e n c o d i n g=UTF8?>
<beans xmlns= h t t p : / / j a v a . sun . com/xml/ ns / j a v a e e
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 / j a v a e e
h t t p : / / j a v a . sun . com/xml/ ns / j a v a e e / b e a n s 1 0 . xsd >
</beans>
adnotarea javax.ejb.EJB.
Exemplul 5.2.6 Calculul celui mai mare divizor comun a doua numere naturale.
Structura aplicatiei este
208
Cmmdc
|--> WEB-INF
|
|--> classes
|
|
|--> cmmdc
|
|
|
|
App.class
|
|
|--> resources
|
|
|
|
CmmdcQueryResources.class
|
|
beans.xml
|
|
web.xml
|
index.html
package r e s o u r c e s ;
import j a v a x . ws . r s . QueryParam ;
import j a v a x . s e r v l e t . S e r v l e t C o n t e x t ;
import j a v a x . ws . r s . c o r e . Response ;
import j a v a x . ws . r s . Produces ;
import j a v a x . ws . r s . Path ;
import j a v a x . ws . r s .GET;
import j a v a . n e t . URLDecoder ;
import j a v a x . a n n o t a t i o n . ManagedBean ;
import j a v a x . i n j e c t . I n j e c t ;
import cmmdc . App ;
@Path ( cmmdcquery )
@ManagedBean
public c l a s s CmmdcQueryResource {
@Inject
App o b j ;
@GET
public Response p r o c e s s Q u e r y (
@QueryParam ( m ) S t r i n g sm ,
@QueryParam ( n ) S t r i n g sn ,
@QueryParam ( t i p ) S t r i n g t i p ) {
S t r i n g t i p 0=URLDecoder . de co de ( t i p ) ;
long m=Long . par se Lon g ( sm ) ;
long n=Long . p ars eL ong ( sn ) ;
System . out . p r i n t l n (m+ : +n+ : +t i p 0 ) ;
long c=o b j . cmmdc(m, n ) ;
S t r i n g message =(new Long ( c ) ) . t o S t r i n g ( ) ;
Response r=n u l l ;
switch ( t i p 0 ) {
case t e x t / p l a i n :
r=Response . ok ( g e t P l a i n R e p ( message ) , t e x t / p l a i n ) . b u i l d ( ) ;
break ;
case t e x t / html :
r=Response . ok ( getHtmlRep ( message ) , t e x t / html ) . b u i l d ( ) ;
break ;
}
return r ;
}
public S t r i n g g e t P l a i n R e p ( S t r i n g msg ) {
return msg ;
}
public S t r i n g getHtmlRep ( S t r i n g msg ) {
return <html><head></head><body b g c o l o r=\#a a e e a a\>< c e n t e r >
5.2. JERSEY-2
48
49
50
209
package r e s o u r c e s ;
import j a v a x . ws . r s .GET;
import j a v a x . ws . r s . Path ;
import j a v a x . ws . r s . QueryParam ;
import j a v a x . ws . r s . c o n t a i n e r . Suspended ;
import j a v a x . ws . r s . c o n t a i n e r . AsyncResponse ;
import j a v a x . e j b . S t a t e l e s s ;
import j a v a x . e j b . Asynchronous ;
@Stateless
@Path ( /cmmdc )
public c l a s s AsynchronousCmmdcResource {
@GET
@Asynchronous
public void asyncRestMethod ( @Suspended f i n a l AsyncResponse asyncResponse ,
@QueryParam ( m ) S t r i n g sm ,
@QueryParam ( n ) S t r i n g sn ) {
long m=Long . par se Lon g ( sm ) ;
long n=Long . p ars eL ong ( sn ) ;
System . out . p r i n t l n (m+ : +n ) ;
long r=cmmdc(m, n ) ;
S t r i n g r e s u l t = new Long ( r ) . t o S t r i n g ( ) ;
a s y n c R e s p o n s e . resume ( r e s u l t ) ;
}
14
15
16
17
18
19
20
21
22
23
24
25
27
28
29
30
31
32
33
34
35
36
37
38
210
5.2.6
java
|--> HelloWorldResource.java
resources
webapp
|--> WEB-INF
|
|
web.xml
|
index.html
211
5.2. JERSEY-2
java
|--> hw
|
|
|
|
JerseyClient.java
Client.java
212
</dependency>
. . .
</dependencies>
<properties>
<jersey.version>2.22.1</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
5.3
s e t g r o u p I d=r e s o u r c e s
s e t a r t i f a c t I d=hw
s e t package= u n i t b v . c s . td
s e t j e r s e y v e r s i o n =2.13
mvn a r c h e t y p e : g e n e r a t e D a r c h e t y p e A r t i f a c t I d=j e r s e y herokuwebapp
DarchetypeGroupId=o r g . g l a s s f i s h . j e r s e y . a r c h e t y p e s
D i n t e r a c t i v e M o d e=f a l s e
DgroupId=%g r o u p I d%
D a r t i f a c t I d=%a r t i f a c t I d%
Dpackage=%package%
D a r c h e t y p e V e r s i o n=%j e r s e y v e r s i o n%
src
|-->
|
|
|
|
|
|
|
|
main
|-->
|
|
|
|
|
|
|-->
java
|--> unitbv
|
|--> cs
|
|
|-->
|
|
|
|
|
|
|
|
|
webapp
td
|--> heroku
|
|
Main.java
|
HelloWorldResources.java
|
|
|
|
|
213
|
|
|--> WEB-INF
|
|
|
|
web.xml
Procfile
system.properties
pom.xml
package u n i t b v . c s . td ;
import j a v a x . ws . r s . Produces ;
import j a v a x . ws . r s . Path ;
import j a v a x . ws . r s .GET;
4
5
7
8
@Path ( h e l l o w o r l d )
public c l a s s H e l l o W o r l d R e s o u r c e {
10
public H e l l o W o r l d R e s o u r c e ( ) {}
12
@GET
@Produces ( t e x t / p l a i n )
public S t r i n g g e t T e x t ( ) {
return ( H e l l o World ) ;
}
13
14
15
16
@Path ( html )
@GET
@Produces ( t e x t / html )
public S t r i n g getAsHtml ( ) {
return <html><head></head><body b g c o l o r=\#bbeebb\>
<c e n t e r ><p>H e l l o World</p></c e n t e r ></body></html> ;
}
18
19
20
21
22
23
24
@Path ( xml )
@GET
@Produces ( a p p l i c a t i o n /xml )
public S t r i n g getAsXml ( ) {
return <r e s p o n s e >H e l l o World</r e s p o n s e > ;
}
26
27
28
29
30
31
32
<html>
<body>
<table border= 2 >
<tr>
<td>
<a href= h t t p : / / l o c a l h o s t : 8 0 8 0 / h e l l o w o r l d >
214
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
R e z u l t a t t e x t / p l a i n </a>
</td>
</ tr>
<tr>
<td>
<a href= h t t p : / / l o c a l h o s t : 8 0 8 0 / h e l l o w o r l d / html >
R e z u l t a t t e x t / html </a>
</td>
</ tr>
<tr>
<td>
<a href= h t t p : / / l o c a l h o s t : 8 0 8 0 / h e l l o w o r l d /xml>
R e z u l t a t a p p l i c a t i o n /xml</a>
</td>
</ tr>
</ table>
</body>
</html>
215
5.4
Variant
a cu web.xml
Structura aplicatiei
|--> WEB-INF
|
|--> classes
|
|
|
Controller.class
|
|
|
Model.class
|
|
|
HandlebarsViewEngine.class
|
|--> lib
|
|
|
*.lib
|
|
beans.xml
|
|
web.xml
|
index.html
|
output.hbs
-> CmmdcController.class
-> CmmdcBean.class
Fisierul web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml v e r s i o n= 1 . 0 e n c o d i n g=UTF8?>
<! This web . xml f i l e i s not r e q u i r e d when u s i n g S e r v l e t 3 . 0 c o n t a i n e r ,
see implementation d e t a i l s
h t t p : // j e r s e y . j a v a . n e t / nonav / d o c u m e n t a t i o n / l a t e s t / j a x r s . html >
<webapp v e r s i o n= 2 . 5 xmlns= h t t p : / / j a v a . sun . com/xml/ ns / j a v a e e
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 / j a v a e e
h t t p : / / j a v a . sun . com/xml/ ns / j a v a e e /weba p p 2 5 . xsd >
<s e r v l e t >
<s e r v l e t name>J e r s e y Web A p p l i c a t i o n </ s e r v l e t name>
<s e r v l e t c l a s s >
org . g l a s s f i s h . j e r s e y . s e r v l e t . ServletContainer
</ s e r v l e t c l a s s >
<i n i t param>
<paramname>j e r s e y . c o n f i g . s e r v e r . p r o v i d e r . p ackage s </paramname>
<paramv a l u e >r e s o u r c e s </paramv a l u e >
</ i n i t param>
<l o a d ons t a r t u p >1</l o a d ons t a r t u p >
216
19
20
21
22
23
24
</ s e r v l e t >
<s e r v l e t mapping>
<s e r v l e t name>J e r s e y Web A p p l i c a t i o n </ s e r v l e t name>
<u r l p a t t e r n >/ r e s o u r c e s /</u r l p a t t e r n >
</ s e r v l e t mapping>
</webapp>
Fisierul beans.xml
1
<?xml v e r s i o n= 1 . 0 e n c o d i n g=UTF8?>
4
5
6
7
8
Variant
a cu glassfish-web.xml
Structura aplicatiei
|--> WEB-INF
|
|--> classes
|
|
|
App.class
|
|
|
Controller.class
|
|
|
Model.class
|
|
|
HandlebarsViewEngine.class
|
|--> lib
|
|
|
*.lib
|
|
beans.xml
|
|
glassfish-web.xml
|
index.html
|
output.hbs
-> CmmdcController.class
-> CmmdcBean.class
Fisierul glassfish-web.xml
1
2
3
4
5
6
7
8
9
10
11
<?xml v e r s i o n= 1 . 0 e n c o d i n g=UTF8?>
<!DOCTYPE g l a s s f i s h webapp PUBLIC
// G l a s s F i s h . o r g //DTD G l a s s F i s h A p p l i c a t i o n S e r v e r 3 . 1 S e r v l e t 3 . 0 / /EN
h t t p : / / g l a s s f i s h . o r g / d t d s / g l a s s f i s h weba p p 3 0 1. dtd >
< g l a s s f i s h webapp e r r o r u r l= >
<c o n t e x t r o o t >/mvc</c o n t e x t r o o t >
<l o c a l e c h a r s e t i n f o defaultl o c a l e=UTF8>
<l o c a l e c h a r s e t map l o c a l e= c h a r s e t= />
<parametere n c o d i n g defaultc h a r s e t=UTF8/>
</ l o c a l e c h a r s e t i n f o >
</ g l a s s f i s h webapp>
217
package r e s o u r c e s ;
import
import
import
import
4
5
6
8
9
rs . ApplicationPath ;
rs . core . Application ;
. Collections ;
. Set ;
@ A p p l i c a t i o n P a t h ( app )
public c l a s s App extends A p p l i c a t i o n {
@Override
public Set<C l a s s <?>> g e t C l a s s e s ( ) {
return C o l l e c t i o n s . s i n g l e t o n ( C o n t r o l l e r . c l a s s ) ;
}
11
12
13
14
15
j a v a x . ws .
j a v a x . ws .
java . u t i l
java . u t i l
package r e s o u r c e s ;
import
import
import
import
import
import
import
com . g i t h u b . j k n a c k . h a n d l e b a r s . H a n d l e b a r s ;
com . g i t h u b . j k n a c k . h a n d l e b a r s . H e l p e r ;
com . g i t h u b . j k n a c k . h a n d l e b a r s . O p ti on s ;
com . g i t h u b . j k n a c k . h a n d l e b a r s . Template ;
com . g i t h u b . j k n a c k . h a n d l e b a r s . h e l p e r . B l o c k H e l p e r ;
com . g i t h u b . j k n a c k . h a n d l e b a r s . h e l p e r . EachHelper ;
com . g i t h u b . j k n a c k . h a n d l e b a r s . h e l p e r . EmbeddedHelper ;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
4
5
6
7
8
9
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
27
28
30
31
33
34
35
36
38
39
@ P r i o r i t y ( P r i o r i t i e s .DEFAULT)
public c l a s s HandlebarsViewEngine implements ViewEngine {
@Inject
private S e r v l e t C o n t e x t s e r v l e t C o n t e x t ;
@Override
public boolean s u p p o r t s ( S t r i n g view ) {
return view . endsWith ( . hbs ) ;
}
@Override
public void p r o c e s s V i e w ( ViewEngineContext c o n t e x t )
218
throws ViewEngineException {
40
Models models = c o n t e x t . g e t M o d e l s ( ) ;
S t r i n g viewName = c o n t e x t . getView ( ) ;
i f ( ! viewName . s t a r t s W i t h ( / ) )
viewName = / + viewName ;
42
43
44
45
try ( P r i n t W r i t e r w r i t e r = c o n t e x t . g e t R e s p o n s e ( ) . g e t W r i t e r ( ) ;
InputStream r e s o u r c e A s S t r e a m =
s e r v l e t C o n t e x t . g e t R e s o u r c e A s S t r e a m ( viewName ) ;
InputStreamReader i n =
new InputStreamReader ( r e s o u r c e A s S t r e a m , UTF8 ) ;
B u f f e r e d R e a d e r b u f f e r e d R e a d e r = new B u f f e r e d R e a d e r ( i n ) ; ) {
47
48
49
50
51
52
S t r i n g viewContent =
bufferedReader . l i n e s ( ) . c o l l e c t ( Collectors . j o i n i n g ( ) ) ;
54
55
H a n d l e b a r s h a n d l e b a r s = new H a n d l e b a r s ( ) ;
Template t e m p l a t e = h a n d l e b a r s . c o m p i l e I n l i n e ( viewContent ) ;
t e m p l a t e . a p p l y ( models , w r i t e r ) ;
} catch ( IOException e ) {
throw new ViewEngineException ( e ) ;
}
57
58
59
60
61
62
63
64
Exemplul 5.4.1
Controller - CmmdcController
1
package r e s o u r c e s ;
import
import
import
import
import
import
import
import
import
import
import
4
5
6
7
8
9
10
11
12
13
15
16
17
19
20
22
23
24
25
27
javax . i n j e c t . I n j e c t ;
j a v a x . mvc . C o n t r o l l e r ;
j a v a x . mvc . Models ;
j a v a x . mvc . View ;
j a v a x . mvc . Viewable ;
javax . v a l i d a t i o n . Valid ;
j a v a x . ws . r s . ;
j a v a x . ws . r s . c o r e . Response ;
j a v a . n e t . URI ;
java . u t i l . ;
j a v a x . ws . r s . QueryParam ;
@Path ( / )
@Controller
public c l a s s CmmdcController {
@Inject
private Models models ;
@GET
@Path ( /cmmdc )
public S t r i n g computeCmmdc ( @QueryParam ( m ) S t r i n g sm ,
@QueryParam ( n ) S t r i n g sn ) {
CmmdcBean cb=new CmmdcBean ( ) ;
cb . setSm ( sm ) ;
cb . s e t S n ( sn ) ;
long r e s u l t =cmmdc( Long . p ars eL ong ( sm ) , Long . pa rse Lo ng ( sn ) ) ;
cb . s e t R e s u l t (new Long ( r e s u l t ) . t o S t r i n g ( ) ) ;
System . out . p r i n t l n ( sm+ : +sn+ : +r e s u l t ) ;
models . put ( cmmdc , cb ) ;
28
29
30
31
32
33
35
36
38
39
Model - CmmdcBean
1
package r e s o u r c e s ;
public c l a s s CmmdcBean{
private S t r i n g sm ;
private S t r i n g sn ;
private S t r i n g r e s u l t ;
public CmmdcBean ( ) { }
4
5
10
11
12
public S t r i n g getSm ( ) {
return sm ;
}
14
15
16
public void s e t S n ( S t r i n g sn ) {
t h i s . sn=sn ;
}
18
19
20
public S t r i n g getSn ( ) {
return sn ;
}
22
23
24
public void s e t R e s u l t ( S t r i n g r e s u l t ) {
t h i s . r e s u l t=r e s u l t ;
}
26
27
28
public S t r i n g g e t R e s u l t ( ) {
return r e s u l t ;
}
30
31
32
33
View
Fisierul index.html de lansare a aplicatiei
1
2
3
4
5
<! d o c t y p e html>
<head>
<meta c h a r s e t= u t f 8>
</head>
<body b g c o l o r=#bbccbb >
219
220
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
<c e n t e r >
<h1> Pagina de a p e l a r e CmmdcServlet </h1>
<form method= g e t
a c t i o n= / Ozark / app /cmmdc>
<t a b l e >
<t r >
<td><label> Primul numar </label ></td>
<td>
<i n p u t t y p e=number name=m s i z e= 5
r e q u i r e d min= 1 >
</td>
</t r >
<t r >
<td><label> Al d o i l e a numar </label ></td>
<td>
<i n p u t t y p e=number name=n s i z e= 5
r e q u i r e d min= 1 >
</td>
</t r >
<t r >
<td>
<p><i n p u t t y p e= submit v a l u e= C a l c u l e a z a >
</td>
</t r >
</ t a b l e >
</form>
<c e n t e r >
</body>
</html>
5.5
<!DOCTYPE html>
<html>
<head l a n g= en >
<meta c h a r s e t=UTF8>
< t i t l e >Cmmdc View</ t i t l e >
</head>
<body>
<h1> MVC REST
<p>
Cmmdc(<span >{{cmmdc . sm}}</span >,<span >{{cmmdc . sn }}</span >)=
<span >{{cmmdc . r e s u l t }}</span>
</p>
</body>
</html>
Dintr-un client GWT se poate apela un server care poate fi n interiorul sau
exteriorul aplicatiei GWT (3.2.3). Cazul serverului exterior nu ridica nici o
problema (3.2.3). Pentru cazul serverului interior aplicatiei GWT se utilizeaza:
modelul de programare prezentat n (3.2.3) ;
221
. . .
|--> client
|
|
RestClient.java
|
|
AsyncClientInterface.java
|--> server
|
|
CmmdcResource.java
|--> shared
|
|
CmmdcBean.java
|
RestClient.wgt.xml
WEB-INF
|--> lib
|
|
*.jar
|
web.xml
RestClient.html
RestClient.css
Raportandu-ne la aplicatia din sectiunea (5.2.3) codurile claselor CmmdcBean.java, CmmdcResources.java sunt nemodificate (mai putin numele pachetului), la fel coincid fisierele html si css (mai putin numele fisierelor).
Codurile celorlalte claselor sunt
222
package u n i t b v . c s . td . c l i e n t ;
import j a v a x . ws . r s . POST ;
import j a v a x . ws . r s . Path ;
import o r g . f u s e s o u r c e . r e s t y g w t . c l i e n t . MethodCallback ;
import o r g . f u s e s o u r c e . r e s t y g w t . c l i e n t . R e s t S e r v i c e ;
import u n i t b v . c s . td . s h a r e d . CmmdcBean ;
10
11
13
14
15
16
package u n i t b v . c s . td . c l i e n t ;
import o r g . f u s e s o u r c e . r e s t y g w t . c l i e n t . D e f a u l t s ;
import o r g . f u s e s o u r c e . r e s t y g w t . c l i e n t . Method ;
import o r g . f u s e s o u r c e . r e s t y g w t . c l i e n t . MethodCallback ;
4
5
16
import
import
import
import
import
import
import
import
import
import
18
import u n i t b v . c s . td . s h a r e d . CmmdcBean ;
20
public c l a s s R e s t C l i e n t implements E n t r y P o i n t {
public void onModuleLoad ( ) {
f i n a l L a b e l t i t l e =new L a b e l ( CMMDC ) ;
t i t l e . addStyleName ( l a b e l t i t l e ) ;
f i n a l L a b e l mLabel=new L a b e l ( m= ) ;
f i n a l L a b e l nLabel=new L a b e l ( n= ) ;
f i n a l L a b e l cmmdcLabel=new L a b e l ( ) ;
f i n a l TextBox mTextBox=new TextBox ( ) ;
f i n a l TextBox nTextBox=new TextBox ( ) ;
f i n a l Button b ut to n = new Button ( Compute ) ;
bu tt on . addStyleName ( pct e m p l a t e btn ) ;
7
8
9
10
11
12
13
14
15
21
22
23
24
25
26
27
28
29
30
32
33
34
35
36
37
38
com .
com .
com .
com .
com .
com .
com .
com .
com .
com .
google
google
google
google
google
google
google
google
google
google
. gwt . e v e n t . dom . c l i e n t . C l i c k E v e n t ;
. gwt . e v e n t . dom . c l i e n t . C l i c k H a n d l e r ;
. gwt . c o r e . c l i e n t . E n t r y P o i n t ;
. gwt . u s e r . c l i e n t . u i . Button ;
. gwt . u s e r . c l i e n t . u i . RootPanel ;
. gwt . u s e r . c l i e n t . u i . V e r t i c a l P a n e l ;
. gwt . u s e r . c l i e n t . u i . TextBox ;
. gwt . u s e r . c l i e n t . u i . L a b e l ;
. gwt . u s e r . c l i e n t . Window ;
. gwt . c o r e . c l i e n t .GWT;
V e r t i c a l P a n e l cmmdcPanel = new V e r t i c a l P a n e l ( ) ;
cmmdcPanel . setWidth ( 100% ) ;
cmmdcPanel . s e t H o r i z o n t a l A l i g n m e n t ( V e r t i c a l P a n e l . ALIGN CENTER ) ;
cmmdcPanel . add ( t i t l e ) ;
cmmdcPanel . add ( mLabel ) ;
cmmdcPanel . add ( mTextBox ) ;
cmmdcPanel . add ( nLabel ) ;
39
40
41
42
43
44
45
46
47
49
c l a s s MyClickHandler implements C l i c k H a n d l e r {
TextBox mTextBox=null , nTextBox=n u l l ;
L a b e l cmmdcLabel=n u l l ;
50
51
53
54
55
56
57
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
223
224
cmmdcLabel . s e t T e x t ( Cmmdc = +r e s p o n s e . g e t R e s u l t ( ) ) ;
98
99
101
102
103
104
105
106
}
else {
long c=Math . max( Math . abs (m) , Math . abs ( n ) ) ;
cmmdcLabel . s e t T e x t ( Cmmdc = +c ) ;
}
107
108
109
110
111
112
113
225
226
Partea III
MODELUL OSGi
227
Capitolul 6
Modelul OSGi
OSGi - Open Sourse Gateway initiative, 1999, (semnificatia numelui fiind
astazi depasita) a dezvoltat un model de cadru de lucru (platforma) privind:
gestiunea ciclului de viata a unei aplicatii (application life cycle management);
registru de servicii;
mediu de executie;
module.
Pe aceasta baza au fost dezvoltate interfete de programare (API), servicii,
extensii OSGi (OSGi layers).
Cadrul de lucru contine un model specific de aplicatie sub forma de componenta sau modul OSGi (bundle for deployment). O asemenea componenta
poate pune la dispozitia altor componente functionalitati, comportandu-se ca
un serviciu (ofertant de servicii) sau poate executa o actiune punctuala. O
componenta OSGi se prezinta sub forma unei arhive jar.
In esenta, scopul unui cadru de lucru OSGi este oferirea unui mediu pentru
crearea si integrarea uniforma de unitati (module, componente) de soft.
Un modul este dat de
O interfata de programare (API), pentru rezolvarea unei problemei (optional);
O familie de clase realizate n vederea solutionarii unei probleme;
Multimea resurselor necesare claselor.
229
230
6.1
231
Functionalitatea
Afiseaza lista modulelor OSGi instalate.
Paraseste si nchide cadrul de lucru.
Instaleaza modulul OSGi
La instalare unui modul i se atribuie n
vederea identificarii un numar natural id.
start id
Lanseaza modulul OSGi id.
start file: modulOSGi .jar
Instaleaza si lanseaza modulul OSGi
stop id
Opreste modulul OSGi id.
uninstall id
Dezinstaleaza modulul OSGi id.
Interfata de lucru, Apache Felix Gogo, implementeaza RFC (Request for
Comments) 147 publicat de Internet Engineering Task Force (IETF).
Lansarea se poate realiza si dintr-un program Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import j a v a . u t i l . A r r a y L i s t ;
import j a v a . u t i l . HashMap ;
import j a v a . u t i l . L i s t ;
import j a v a . u t i l . Map ;
import j a v a . u t i l . S e r v i c e L o a d e r ;
import o r g . o s g i . framework . Bundle ;
import o r g . o s g i . framework . BundleContext ;
import o r g . o s g i . framework . B u n d l e E x c e p t i o n ;
import o r g . o s g i . framework . l a u n c h . Framework ;
import o r g . o s g i . framework . l a u n c h . FrameworkFactory ;
public c l a s s Launcher {
public s t a t i c void main ( S t r i n g a r g s [ ] ) throws B u n d l e E x c e p t i o n {
FrameworkFactory frameworkFactory =
S e r v i c e L o a d e r . l o a d ( FrameworkFactory . c l a s s ) . i t e r a t o r ( ) . n e x t ( ) ;
Map<S t r i n g , S t r i n g > c o n f i g = new HashMap< >();
Framework framework = frameworkFactory . newFramework ( c o n f i g ) ;
framework . s t a r t ( ) ;
BundleContext c o n t e x t = framework . g e t B u n d l e C o n t e x t ( ) ;
L i s t <Bundle> b u n d l e s = new A r r a y L i s t < >();
b u n d l e s . add ( c o n t e x t . i n s t a l l B u n d l e (
f i l e : l i b / o r g . apache . f e l i x . gogo . command 0 . 1 4 . 0 . j a r ) ) ;
b u n d l e s . add ( c o n t e x t . i n s t a l l B u n d l e (
f i l e : l i b / o r g . apache . f e l i x . gogo . runtime 0 . 1 2 . 1 . j a r ) ) ;
232
b u n d l e s . add ( c o n t e x t . i n s t a l l B u n d l e (
f i l e : l i b / o r g . apache . f e l i x . gogo . s h e l l 0 . 1 0 . 0 . j a r ) ) ;
f o r ( Bundle bu nd le : b u n d l e s ) {
bu nd l e . s t a r t ( ) ;
}
24
25
26
27
28
29
30
o s g i . b u n d l e s= f i l e \ : o r g . e c l i p s e . e q u i n o x . c o n s o l e . j a r @ s t a r t ,
f i l e : \ o r g . apache . f e l i x . gogo . r u n t i m e . j a r @ s t a r t ,
f i l e : \ o r g . apache . f e l i x . gogo . s h e l l . j a r @ s t a r t ,
f i l e : \ o r g . apache . f e l i x . gogo . command . j a r @ s t a r t
233
6.2
Programare imperativ
a - Crearea unui modul
OSGi
234
Proprietati OSGi
Numele proprietatii
Bundle-Name
Bundle-Version
Bundle-Activator
Semnificatia
Numele modului OSGi
Versiunea modulului OSGi
Clasa modulului care implementeaza interfata
BundleActivator
Bundle-SymbolicName
Numele simbolic atribuit modulului OSGi
Bundle-Description
Descrierea modulului OSGi
Manifest-Version
Versiunea tipului de manifest
Bundle-ManifestVersion Versiunea manifestului atasat modulului OSGi
Bundle-Vendor
Producatorul modulului OSGi
Bundle-Classpath
Calea catre resursele suplimentare utilizate
Import-Package
Lista pachetelor utilizate de modulul OSGi
Export-Package
Lista pachetelor ce pot fi utilizate de alte
module OSGi
Structura arhivei jar a unei componente OSGi este
structura de cataloage corespunzatoare pachetului aplicatiei
| . . .
*.class
META-INF
| manifest.mf
Programarea se bazeaza pe interfata BundleContext, care este implementat de fiecare cadru de lucru OSGi n parte.
Metode
ServiceRegistration registerService(String clazz, Object service,
java.util.Dictionary properties)
Inregistreaza n cadrul de lucru serviciul definit de obiectul service, de tip
clazz si cu proprietaile adiacente date de al treilea parametru. Rezultatul
este folosit de cadrul de lucru OSGi.
ServiceReference[] getServiceReferences(String clazz, String filter ) throws InvalidSyntaxException
Returneaza referintele de tip clazz.
Object getService(ServiceReference reference)
Returneaza obiectul corespunzator referintei.
235
6.3. EXEMPLE
6.3
Exemple
Exemplul 6.3.1 Calculul celui mai mare divizor comun a doua numere naturale - ca serviciu OSGi.
Aplicatia se compune din 3 module OSGi:
interfata;
1. Clasa interfetei cmmdc.ICmmdc.java
1
package cmmdc ;
public i n t e r f a c e ICmmdc{
public long cmmdc( long m, long n ) ;
}
4
5
2. Fisierul manifest.mf
1
2
3
4
5
BundleM a n i f e s t V e r s i o n : 2
BundleSymbolicName : icmmdc
BundleName : I n t e r f a t a Cmmdc
BundleV e r s i o n : 1 . 0 . 0
ExportPackage : cmmdc ; v e r s i o n= 1 . 0 . 0
package cmmdc . s e r v i c e ;
import cmmdc . ICmmdc ;
import o r g . o s g i . framework . B u n d l e A c t i v a t o r ;
import o r g . o s g i . framework . BundleContext ;
public c l a s s A c t i v a t o r implements B u n d l e A c t i v a t o r {
public void s t a r t ( BundleContext c o n t e x t ) {
c o n t e x t . r e g i s t e r S e r v i c e (ICmmdc . c l a s s . getName ( ) ,
new CmmdcService ( ) , n u l l ) ;
System . out . p r i n t l n ( R e g i s t e r i n g Cmmdc s e r v i c e . ) ;
}
public void s t o p ( BundleContext c o n t e x t ) {}
13
14
236
package cmmdc . s e r v i c e ;
4
5
3. Fisierul manifest.mf
1
2
3
4
5
6
BundleM a n i f e s t V e r s i o n : 2
BundleSymbolicName : cmmdcservice
BundleName : Cmmdc S e r v i c e
BundleV e r s i o n : 1 . 0 . 0
BundleA c t i v a t o r : cmmdc . s e r v i c e . A c t i v a t o r
ImportPackage : o r g . o s g i . framework , cmmdc
package cmmdc . c l i e n t ;
import cmmdc . ICmmdc ;
import j a v a . u t i l . S c a n n e r ;
import o r g . o s g i . framework . B u n d l e A c t i v a t o r ;
import o r g . o s g i . framework . BundleContext ;
import o r g . o s g i . framework . S e r v i c e R e f e r e n c e ;
public c l a s s A c t i v a t o r implements B u n d l e A c t i v a t o r {
public void s t a r t ( BundleContext c o n t e x t ) {
try {
S e r v i c e R e f e r e n c e [ ] r e f s=
c o n t e x t . g e t S e r v i c e R e f e r e n c e s (ICmmdc . c l a s s . getName ( ) ,
null ) ;
i f ( r e f s != n u l l ) {
ICmmdc o b j =(ICmmdc) c o n t e x t . g e t S e r v i c e ( r e f s [ 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 ( C l i e n t Cmmdc 1 ) ;
System . out . p r i n t l n ( Primul numar : ) ;
long m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( a l d o i l e a numar : ) ;
long n=s c a n n e r . nextLong ( ) ;
long c=o b j . cmmdc(m, n ) ;
System . out . p r i n t l n ( Cmmdc = +c ) ;
}
}
237
6.3. EXEMPLE
catch ( E x c e p t i o n 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 ( ) ) ;
}
26
27
28
29
31
32
BundleM a n i f e s t V e r s i o n : 2
BundleSymbolicName : clientcmmdc1
BundleName : Cmmdc C l i e n t
BundleV e r s i o n : 1 . 0 . 0
BundleA c t i v a t o r : cmmdc . c l i e n t . A c t i v a t o r
ImportPackage : o r g . o s g i . framework , cmmdc
package cmmdc . c l i e n t ;
import cmmdc . ICmmdc ;
import j a v a . u t i l . S c a n n e r ;
import o r g . o s g i . framework . B u n d l e A c t i v a t o r ;
import o r g . o s g i . framework . BundleContext ;
import o r g . o s g i . u t i l . t r a c k e r . S e r v i c e T r a c k e r ;
public c l a s s A c t i v a t o r implements B u n d l e A c t i v a t o r {
public void s t a r t ( BundleContext c o n t e x t ) {
S e r v i c e T r a c k e r s e r v i c e T r a c k e r=new S e r v i c e T r a c k e r ( c o n t e x t ,
ICmmdc . c l a s s . getName ( ) , n u l l ) ;
s e r v i c e T r a c k e r . open ( ) ;
ICmmdc o b j =(ICmmdc) s e r v i c e T r a c k e r . g e t S e r v i c e ( ) ;
System . out . p r i n t l n ( C l i e n t Cmmdc 2 ) ;
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 ) ;
238
16
17
18
19
20
21
22
24
25
BundleM a n i f e s t V e r s i o n : 2
BundleSymbolicName : clientcmmdc2
BundleName : Cmmdc C l i e n t
BundleV e r s i o n : 1 . 0 . 0
BundleA c t i v a t o r : cmmdc . c l i e n t . A c t i v a t o r
ImportPackage : o r g . o s g i . framework , o r g . o s g i . u t i l . t r a c k e r , cmmdc
6.4
respectiv cu datele
set GroupID=cmmdc
set ArtifactID=interface
set Version=1.0.0
239
set GroupID=cmmdc.service
set ArtifactID=impl
set Version=1.0.0
set GroupID=cmmdc.client
set ArtifactID=client
set Version=1.0.0
240
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<p l u g i n>
<g r o u p I d>o r g . apache . f e l i x</ g r o u p I d>
< a r t i f a c t I d>mavenbundlep l u g i n</ a r t i f a c t I d>
<version> 3 . 0 . 1</ version>
<e x t e n s i o n s>t r u e</ e x t e n s i o n s>
<c o n f i g u r a t i o n>
< i n s t r u c t i o n s>
<BundleSymbolicName>
${ p r o j e c t . a r t i f a c t I d }
</ BundleSymbolicName>
<ImportPackage>
o r g . o s g i . framework , cmmdc ,
</ ImportPackage>
<BundleA c t i v a t o r>cmmdc . s e r v i c e . A c t i v a t o r</ BundleA c t i v a t o r>
<ExportPackage />
</ i n s t r u c t i o n s>
</ c o n f i g u r a t i o n>
</ p l u g i n>
</ p l u g i n s>
</ b u i l d>
</ p r o j e c t>
241
242
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
6.5
Programare declarativ
a
Modelul declarativ de realizare a unui modul OSGi nu mai necesita realizarea unei clase care sa implementeze interfata BundleActivator. Prezenta
fisierului manifest.mf ramane obligatorie. Exista mai multe variante dezvoltate de programare declarativa:
243
Declarative Service
Blueprint
iPOJO
6.5.1
Programare declarativ
a prin Declarative Service
Cu exceptia interfetelor, programatorul trebuie sa editeze un fisier de configurare OSGI-INF\component.xml, care se include n arhiva jar a componentei OSGi. Acest fisierul de configurare este mentionat n fisierul manifest.mf
prin linia
Service-Component:
OSGI-INF/component.xml
244
interfata
1.
1
package cmmdc ;
public i n t e r f a c e ICmmdc{
public long cmmdc( long m, long n ) ;
}
4
5
2. manifest.mf
1
2
3
4
5
6
BundleM a n i f e s t V e r s i o n : 2
BundleSymbolicName: icmmdc
BundleName: I n t e r f a t a Cmmdc
BundleVendor: u n i t b v
BundleV e r s i o n : 1 . 0 . 0
ExportP a c k a g e : cmmdc ; v e r s i o n= 1 . 0 . 0
package cmmdc . s e r v i c e ;
4
5
2. manifest.mf
1
2
3
4
5
6
BundleM a n i f e s t V e r s i o n : 2
BundleSymbolicName: cmmdcservice
BundleName: Cmmdc S e r v i c e
BundleV e r s i o n : 1 . 0 . 0
ImportP a c k a g e : cmmdc
S e r v i c e Component: OSGIINF/ component . xml
3. component.xml
1
2
3
4
5
6
7
8
Client declarativ
Pentru compilarea aplicatiei client este nevoie de osgi R4 compendium-*.jar.
1.
1
2
3
package cmmdc . c l i e n t ;
import j a v a . u t i l . S c a n n e r ;
import cmmdc . ICmmdc ;
6.5. PROGRAMARE DECLARATIVA
5
6
public c l a s s CmmdcClient {
private ICmmdc s e r v i c e ;
public void b i n d M y S e r v i c e (ICmmdc a ) {
System . out . p r i n t l n ( S e r v i c e was s e t ) ;
service = a ;
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= ) ;
long m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
long n=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( Cmmdc = +s e r v i c e . cmmdc(m, n ) ) ;
}
8
9
10
11
12
13
14
15
16
17
19
20
21
22
23
24
2. manifest.mf
1
2
3
4
5
6
7
8
BundleM a n i f e s t V e r s i o n : 2
BundleSymbolicName: c l i e n t d s
S e r v i c e Component: OSGIINF/ component . xml
P r i v a t e P a c k a g e : cmmdc . c l i e n t
BundleName: D e c l a r a t i v e S e r v i c e Cmmdc C l i e n t
BundleD e s c r i p t i o n : DS Cmmdc C l i e n t
BundleV e r s i o n : 1 . 0 . 0
ImportP a c k a g e : cmmdc
3. component.xml
1
2
3
4
5
6
7
8
9
245
246
6.5.2
Programare declarativ
a prin Blueprint
6.5. PROGRAMARE DECLARATIVA
247
package cmmdc . c l i e n t ;
import j a v a . u t i l . Map ;
import j a v a . u t i l . S c a n n e r ;
import cmmdc . ICmmdc ;
public c l a s s R e g i s t r a t i o n L i s t e n e r {
public void r e g i s t e r (ICmmdc obj , Map p r o p e r t i e s ) {
VisualCmmdcClient myApp=new VisualCmmdcClient ( o b j ) ;
}
public void u n r e g i s t e r (ICmmdc obj , Map p r o p e r t i e s ) {
System . out . p r i n t l n ( Cmmmdc s e r v i c e u n r e g i s t e r e d ) ;
}
11
12
13
14
BundleM a n i f e s t V e r s i o n : 2
BundleSymbolicName: b l u e p r i n t
BundleName: B l u e p r i n t Cmmdc C l i e n t
BundleD e s c r i p t i o n : B l u e p r i n t Cmmdc App
BundleV e r s i o n : 1 . 0 . 0
ImportP a c k a g e : o r g . o s g i . framework , j a v a x . swing ,
o r g . o s g i . s e r v i c e . b l u e p r i n t ; v e r s i o n= [ 1 . 0 . 0 , 2 . 0 . 0 )
ExportP a c k a g e : cmmdc , b l u e p r i n t ;
u s e s := o r g . o s g i . framework ; v e r s i o n= 1 . 0 . 0 . SNAPSHOT
OSGI-INF\blueprint\config.xml
1
2
3
4
6
7
8
9
10
11
12
13
14
15
16
248
6.5.3
Programare declarativ
a prin apache-iPOJO
package cmmdc ;
public i n t e r f a c e ICmmdc{
public long cmmdc( long m, long n ) ;
}
4
5
package cmmdc . s e r v i c e ;
4
5
metadata.xml
1
2
3
4
5
6
8
9
10
12
13
client OSGi
249
package cmmdc . c l i e n t ;
import cmmdc . ICmmdc ;
/
I n t a r z i e r e i n t r e doua a p e l a r i automate
/
private s t a t i c f i n a l i n t DELAY = 1 0 0 0 0 ;
7
8
9
12
13
14
15
17
18
19
20
22
23
24
25
26
27
29
30
31
32
33
34
35
36
37
38
39
40
41
43
44
45
46
47
48
49
50
51
52
54
55
56
57
58
/
Reprezentant a l s e r v i c i u l u i
/
private ICmmdc m cmmdc ;
i n j e c t a t de iPOJO
/
Indicator pentru d e p i s ta r e a s t a r s i t u l u i
/
private boolean m end ;
/
Argumente p e n t r u m e t o d e l e i n v o c a t e
i n j e c t a t e de c o n t a i n e r u l OSGi
/
private S t r i n g sm ;
private S t r i n g sn ;
/
Metoda run ( j a v a . l a n g . Runnable )
/
public void run ( ) {
while ( ! m end ) {
try {
invokeCmmdcServices ( ) ;
Thread . s l e e p (DELAY) ;
} catch ( I n t e r r u p t e d E x c e p t i o n i e ) {
/ s e v e r i f i c a c o n d i t i a de s f a r s i t /
}
}
}
/
Invocarea s e r v i c i u l u i
/
public void invokeCmmdcServices ( ) {
i n t i =0;
long m=Long . par se Lo ng ( sm ) ;
long n=Long . p ars eL ong ( sn ) ;
System . out . p r i n t l n (m cmmdc . cmmdc(m, n ) ) ;
m end=true ;
}
/
Start
/
public void s t a r t i n g ( ) {
Thread t h r e a d = new Thread ( t h i s ) ;
250
m end = f a l s e ;
thread . s t a r t ( ) ;
59
60
61
63
/
Stop
/
public void s t o p p i n g ( ) {
m end = true ;
}
64
65
66
67
68
69
metadata.xml
1
2
3
4
5
6
8
9
10
11
12
13
14
15
16
18
19
20
21
22
6.6
251
Interfata org.osgi.service.log.LogService
Clasa care implementeaza aceasta interfata asigura jurnalizarea. Mesajele
sunt retinute de mediul OSGi.
Sunt declarate nivelele LogService.LOG ERROR, LogService.LOG WARNING,
LogService.LOG INFO, LogService.LOG DEBUG.
Metode
void log(int level, String message)
Interfata org.osgi.service.log.LogReaderService
Are ca scop preluarea mesajelor de jurnalizare. Uzual aceste mesaje sunt
prelucrate de un ascultator, un obiect care implementeaza interfata LogListener
Metode
void addLogListener(LogListener listener )
Interfata org.osgi.service.log.LogListener
Metode
void logged(LogEntry entry)
Instalarea tuturor serviciilor se obtine cu o componenta OSGi avand activatorul
import
import
import
import
import
import
import
public c l a s s A c t i v a t o r implements B u n d l e A c t i v a t o r {
1
2
3
4
5
6
11
12
13
14
15
16
17
18
19
20
21
22
23
24
org .
org .
org .
org .
org .
org .
org .
osgi
osgi
osgi
osgi
osgi
osgi
osgi
. framework . B u n d l e A c t i v a t o r ;
. framework . BundleContext ;
. framework . S e r v i c e R e f e r e n c e ;
. s e r v i c e . log . LogService ;
. s e r v i c e . log . LogReaderService ;
. s e r v i c e . log . LogListener ;
. s e r v i c e . l o g . LogEntry ;
252
26
28
c l a s s LogWriter implements L o g L i s t e n e r {
public void l o g g e d ( LogEntry e n t r y ) {
System . out . p r i n t l n ( e n t r y . g e t M e s s a g e ( ) ) ;
}
}
29
30
31
32
33
BundleM a n i f e s t V e r s i o n : 2
BundleSymbolicName : L o g S e r v i c e
BundleName : L o g S e r v i c e
BundleV e r s i o n : 1 . 0 . 0
BundleA c t i v a t o r : A c t i v a t o r
ImportPackage : o r g . o s g i . framework , o r g . o s g i . s e r v i c e . l o g
6.7
Apache-karaf
In catalogul %KARAF HOME% se genereaza catalogul instances iar n fereastra DOS va apare prompt-ul karaf@root>.
Oprirea se obtine apasand tastele CTRL+D.
Karaf poseda o consola DOS dar si o consola Web. Consola Web trebuie
instalata
feature:install webconsole
Consola Web se apeleaza dintr-un navigator prin
http://localhost:8181/system/console
Pentru a schimba portul se creaza n prealabil fisierul etc\org.ops4j.pax.web.cfg
cu continutul
org.osgi.service.http.port=8080
Instalarea componentelor OSGi se poate face
6.7. APACHE-KARAF
253
copiindu-le n catalogul
%KARAF HOME%\deploy
n mod obisnuit, prin comanda install file:. . .
In acest caz fisierul MANIFEST.mf trebuie sa contina atributele
Bundle-ManifestVersion: 2
Bundle-SymbolicName: numeComponentaOSGi
254
Capitolul 7
OSGi distribuit
Integrarea unei aplicatii Web ntr-o platforma OSGi necesita o abordare
specifica. Integrata ntr-o platforma OSGi, aplicatia Web nu mai este desfasurata
nemijlocit n serverul Web, dar apelurile se vor adresa n continuare serverului
Web. In consecinta, este nevoie de o punte ntre platforma OSGi si serverul
Web, care eventual sa asigure functionalitati suplimentare.
7.1
Apache-Karaf
Mediul OSGi apache-karaf utilizeaza serverul Web incorporat Jetty. Se va
instala suportul pentru protocolul http
feature:install http
Apelarea aplicatiei servlet va fi http://host:port/fisier.html
Glassfish
Mediul OSGi are la baza platforma apache-felix. Glassfish ofera posibilitati
OSGi pentru serviciile
HttpService
TransactionService
JDBC Data Source Service
255
256
7.2
www.eclipse.org/equinox/server/http_in_container.php
257
META-INF
|
MANIFEST.MF
ClasaServlet.class
Activator.class
fisier.html
import
import
import
import
public c l a s s A c t i v a t o r implements B u n d l e A c t i v a t o r {
1
2
3
osgi
osgi
osgi
osgi
. framework . B u n d l e A c t i v a t o r ;
. framework . BundleContext ;
. framework . S e r v i c e R e f e r e n c e ;
. s e r v i c e . http . HttpService ;
8
9
10
11
12
13
14
15
16
18
19
org .
org .
org .
org .
258
M a n i f e s t V e r s i o n : 1 . 0
BundleM a n i f e s t V e r s i o n : 2
BundleName: H e l l o S e r v l e t
BundleSymbolicName: H e l l o S e r v l e t
BundleV e r s i o n : 1 . 0 . 0
BundleA c t i v a t o r : A c t i v a t o r
ImportP a c k a g e : j a v a x . s e r v l e t ,
j a v a x . s e r v l e t . http ,
o r g . o s g i . framework ; v e r s i o n= 1 . 3 . 0 ,
o r g . o s g i . s e r v i c e . h t t p ; v e r s i o n= 1 . 2 . 0
import
import
import
import
import
org .
org .
org .
org .
org .
osgi
osgi
osgi
osgi
osgi
. framework . B u n d l e A c t i v a t o r ;
. framework . BundleContext ;
. framework . S e r v i c e R e f e r e n c e ;
. s e r v i c e . http . HttpService ;
. u t i l . tracker . ServiceTracker ;
public c l a s s A c t i v a t o r implements B u n d l e A c t i v a t o r {
private S e r v i c e T r a c k e r h t t p S e r v i c e T r a c k e r ;
13
15
10
11
12
httpServiceTracker . close ( ) ;
h t t p S e r v i c e T r a c k e r = null ;
16
17
18
20
private c l a s s H t t p S e r v i c e T r a c k e r extends S e r v i c e T r a c k e r {
22
public H t t p S e r v i c e T r a c k e r ( BundleContext c o n t e x t ) {
super ( c o n t e x t , H t t p S e r v i c e . c l a s s . getName ( ) , n u l l ) ;
}
23
24
public O b j e c t a d d i n g S e r v i c e ( S e r v i c e R e f e r e n c e r e f e r e n c e ) {
HttpService httpService = ( HttpService ) context . getService ( ref ere nce ) ;
try {
h t t p S e r v i c e . r e g i s t e r R e s o u r c e s ( /cmmdc . html , /cmmdc . html , n u l l ) ;
h t t p S e r v i c e . r e g i s t e r S e r v l e t ( /cmmdc ,new CmmdcServlet ( ) , null , n u l l ) ;
}
catch ( E x c e p t i o n e ) {
e . printStackTrace ( ) ;
}
return h t t p S e r v i c e ;
}
26
27
28
29
30
31
32
33
34
35
36
public void r e m o v e d S e r v i c e ( S e r v i c e R e f e r e n c e r e f e r e n c e , O b j e c t s e r v i c e ) {
HttpService httpService = ( HttpService ) s e r v i c e ;
h t t p S e r v i c e . u n r e g i s t e r ( /cmmdc . html ) ;
h t t p S e r v i c e . u n r e g i s t e r ( /cmmdc ) ;
super . r e m o v e d S e r v i c e ( r e f e r e n c e , s e r v i c e ) ;
}
38
39
40
41
42
43
44
45
259
M a n i f e s t V e r s i o n : 1 . 0
BundleM a n i f e s t V e r s i o n : 2
BundleName: CmmdcServlet
BundleSymbolicName: CmmdcServlet
BundleV e r s i o n : 1 . 0 . 0
BundleA c t i v a t o r : A c t i v a t o r
BundleL o c a l i z a t i o n : p l u g i n
ImportP a c k a g e : j a v a x . s e r v l e t , j a v a x . s e r v l e t . http ,
o r g . o s g i . framework ; v e r s i o n= 1 . 3 . 0 ,
o r g . o s g i . s e r v i c e . h t t p ; v e r s i o n= 1 . 2 . 0 ,
o r g . o s g i . u t i l . t r a c k e r ; v e r s i o n= 1 . 3 . 1
Variant
a descriptiv
a n Bridge
Clasa care implementeaza interfata BundleActivator este nlocuita cu un
fisier de configurare plugin.xml. Structura componentei OSGi este
|--> META-INF
|
|
MANIFEST.MF
|
ClasaServlet.class
260
|
|
fisier.html
plugin.xml
M a n i f e s t V e r s i o n : 1 . 0
BundleM a n i f e s t V e r s i o n : 2
BundleName: CmmdcServlet P l u g I n
BundleSymbolicName: CmmdcServlet P l u g I n ; s i n g l e t o n :=t r u e
BundleV e r s i o n : 1 . 0 . 0
BundleL o c a l i z a t i o n : p l u g i n
ImportP a c k a g e : j a v a x . s e r v l e t , j a v a x . s e r v l e t . h t t p
Require B u n d l e : o r g . e c l i p s e . e q u i n o x . h t t p . r e g i s t r y
Partea IV
JAVA MANAGEMENT
EXTENSIONS
261
Capitolul 8
Java Management Extensions
Java Management Extensions (JMX) face posibila ca un obiect Java sa
permita gestionarea metodelor si a anumitor campuri de catre alte obiecte.
Obiectele Java care si expun astfel resursele se numesc MBean - uri si formeaza
temelia cadrului de lucru JMX.
Exista mai multe tipuri de MBean-uri:
Standard MBean;
Dynamic MBean;
Open MBean;
Model MBean;
MXBean;
Un obiect care gestioneaza resursele unui MBean se numeste agent sau server
MBean. Agentul dispune de mijloace care interactioneaza cu un MBean,
permitandu-i:
accesul la valorile unui camp si la modificarea lor;
invocarea metodelor.
In general, un agent poate fi definit ca
autorul unei actiuni;
factor care provoaca actiuni;
reprezentant al unei institutii nsarcinat cu ndeplinirea unor actiuni.
263
264
8.1
8.1.1
Standard MBean
Crearea unui Standard MBean
O componenta MBean este alcatuita dintr-o interfata si o clasa care implementeaza interfata satisfacand urmatoarele restrictii:
1. interfata are numele clasei care o implementeaza avand n plus sufixul
MBean;
2. Interfata si clasa care o implementeaza apartin aceluiasi pachet;
3. constructorii si metodele expuse trebuie sa fie publice.
In continuare campurile si metodele destinate expunerii se vor denumi
atribute, respectiv operatii. Fiecarui atribut xxx i se ataseaza cel putin una
din metodele
public void setXxx(tip xxx){
this.xxx=xxx;
}
si / sau
public tip getXxx(){
return xxx;
}
Un atribut se precizeaza doar prin aceste metode, fara definirea / declararea
campului corespunzator. Campul se defineste n clasa ce implementeaza interfata
MBean-ului.
Astfel, un MBean este caracterizat de
265
atribute
care pot fi consultate (citite), modificate (scrise) sau cu ambele optiuni.
operatii
notificari
cu evidenta modificarilor suferite de atribute.
Exemplul 8.1.1
Construim un MBean cu
atributele
label
ce poate fi numai citit;
cursEuro
care poate fi consultat si modificat;
operatiile
public String sayHello()
afiseaza un mesaj;
public long cmmdc(long m, long n);
de calcul a celui mai mare divizor comun a doua numere naturale.
Interfata IntroMBean este
1
package b a s i c ;
public i n t e r f a c e IntroMBean {
// O p e r a t i i
public S t r i n g s a y H e l l o ( ) ;
public long cmmdc( long m, long n ) ;
4
5
6
// A t r i b u t e
// reado n l y
public S t r i n g g e t L a b e l ( ) ;
// readw r i t e
public double getCursEuro ( ) ;
public void s e t C u r s E u r o ( double c u r s E u r o ) ;
8
9
10
11
12
13
14
266
package b a s i c ;
5
6
7
public S t r i n g g e t L a b e l ( ) {
return l a b e l ;
}
9
10
11
13
14
15
17
18
19
// O p e r a t i i
public S t r i n g s a y H e l l o ( ) {
S t r i n g message= H e l l o World ! ;
System . out . p r i n t l n ( message ) ;
return message ;
}
21
22
23
24
25
26
28
29
8.1.2
267
domeniu
este un nume simbolic (String). Daca domeniul este stringul vid atunci
se considera valoarea implicita DefaultDomain.
atribute uzuale:
type=numele MBean-ului
index=numar de identificare a MBean-ului
Cel putin un atribut este obligatoriu.
Clasa ObjectName
Constructori
ObjectName(String nume)
Parametrul nume are structura descrisa mai sus.
ObjectName(String domeniu, Hashtable<String,String> tabel )
ObjectName(String domeniu, String numeAtribut, String
valAtribut)
Metode
static ObjectName getInstance(String nume)
Inregistrarea si utilizarea MBean-ului face apel la metodele interfetei MBeanServer.
ObjectInstance
Un obiect de tip ObjectInstance este folosit pentru reprezentarea ansamblului alcatuit de un obiect ObjectName asociat unui MBean si numele clasei
corespunzatoare.
Interfata MBeanServer
Metode
ObjectInstance registerMBean(Object obj , ObjectName nume)
Inregistreaza pe platforma, instanta obj a unui MBean avand numele
nume.
268
In acest caz, este nevoie ca variabilele de tip clasa acoperitoare Double, Long sa fie
nlocuite prin tipuri predefinite.
1
2
3
4
6
7
8
9
10
11
12
package b a s i c ;
import j a v a . l a n g . management . ManagementFactory ;
import j a v a x . management . ObjectName ;
import j a v a x . management . MBeanServer ;
public c l a s s Main{
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 domeniu= ;
i f ( a r g s . l e n g t h >0) domeniu=a r g s [ 0 ] ;
try {
// S e r v e r u l p l a t f o r m e i
MBeanServer mbs = ManagementFactory . getPlatformMBeanServer ( ) ;
// V a r i a n t a 1
// C o n s t r u i r e a ObjectName c o r e s p u n z a t o r MBeanu l u i
ObjectName mbeanObjectName =
new ObjectName ( domeniu+ : t y p e=I n t r o , i n d e x=1 ) ;
14
15
16
17
// Crearea MBeanu l u i
I n t r o mbean = new I n t r o ( ) ;
19
20
// I n r e g i s t r a r e a MBeanu l u i
mbs . r e g i s t e r M B e a n ( mbean , mbeanObjectName ) ;
22
23
// V a r i a n t a 2
mbeanObjectName=new ObjectName ( domeniu+ : t y p e=I n t r o , i n d e x=2 ) ;
mbs . createMBean ( b a s i c . I n t r o , mbeanObjectName ) ;
25
26
27
// A s t e p t a r e n e d e f i n i t a
System . out . p r i n t l n ( Waiting f o r e v e r . . . ) ;
while ( true ) ;
29
30
31
}
catch ( E x c e p t i o n e ) {
System . e r r . 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 ( ) ) ;
}
32
33
34
35
36
37
269
270
8.1.3
Notific
ari
271
a clasei NotificationBroadcasterSupport.
Suplimentar se defineste metoda
public MBeanNotificationInfo[] getNotificationInfo()
n care se precizeaza
tipul notificarii - (constanta definita de clasa AttributeChangeNotification);
clasa n care s-a generat notificarea
String name = AttributeChangeNotification.class.getName();
o descriere a modificarii.
Astfel, introducerea notificarilor presupune familiarizarea cu clasele
NotificationBroadcasterSupport
Constructori
NotificationBroadcasterSupport()
Metode
void sendNotification(Notification notificare)
Notification
Constructori
Notification(String type, Object source, long sequenceNumber )
Notification(String type, Object source, long sequenceNumber , long timeStamp)
Notification(String type, Object source, long sequenceNumber , long timeStamp, String mesaj )
Notification(String type, Object source, long sequenceNumber , String mesaj )
Metode
public void setUserData(Object userData)
public Object getUserData()
272
package ag en tn ;
import j a v a x . management . N o t i f i c a t i o n ;
import j a v a x . management . A t t r i b u t e C h a n g e N o t i f i c a t i o n ;
import j a v a x . management . N o t i f i c a t i o n B r o a d c a s t e r S u p p o r t ;
import j a v a x . management . M B e a n N o t i f i c a t i o n I n f o ;
public c l a s s I nt r oN extends N o t i f i c a t i o n B r o a d c a s t e r S u p p o r t
implements IntroNMBean {
private long sequenceNumber =1;
13
// A t r i b u t e
private f i n a l S t r i n g l a b e l = Fac . Matematica s i I n f o r m a t i c a ;
private double c u r s E u r o = 4 . 5 0 ;
15
public S t r i n g g e t L a b e l ( ) { . . . }
17
19
11
12
20
21
22
23
24
25
26
27
28
29
30
31
sendNotification (n ) ;
32
33
35
public M B e a n N o t i f i c a t i o n I n f o [ ] g e t N o t i f i c a t i o n I n f o ( ) {
S t r i n g [ ] t y p e s = new S t r i n g [ ] {
A t t r i b u t e C h a n g e N o t i f i c a t i o n .ATTRIBUTE CHANGE
};
S t r i n g name = A t t r i b u t e C h a n g e N o t i f i c a t i o n . c l a s s . getName ( ) ;
S t r i n g d e s c r i p t i o n = An a t t r i b u t e o f t h i s MBean has changed ;
MBeanNotificationInfo info =
new M B e a n N o t i f i c a t i o n I n f o ( t y p e s , name , d e s c r i p t i o n ) ;
return new M B e a n N o t i f i c a t i o n I n f o [ ] { i n f o } ;
}
36
37
38
39
40
41
42
43
44
// O p e r a t i i
public S t r i n g s a y H e l l o ( ) { . . . }
46
47
49
50
273
8.1.4
Agent MBean
In exemplelele anterioare resursele unui MBean au fost utilizate prin jconsole. Valorificarea resurselor unui MBean Intro, dintr-un MBeanServer (agent)
se programeaza prin
Exemplul 8.1.4
1
2
3
4
5
6
7
9
10
11
12
13
15
16
17
18
19
20
22
23
24
package a g e n t ;
import j a v a . i o . IOException ;
import j a v a x . management . ObjectName ;
import j a v a x . management . MBeanServer ;
import j a v a x . management . MBeanServerFactory ;
import j a v a x . management . A t t r i b u t e ;
import j a v a . u t i l . S c a n n e r ;
public c l a s s Agent {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
try {
// Crearea A g e n t u l u i MBeanServer
MBeanServer mbs = MBeanServerFactory . c r e a t e M B e a n S e r v e r ( ) ;
// Crearea unui MBean
S t r i n g domain = mbs . g e t D e f a u l t D o m a i n ( ) ;
S t r i n g className= a g e n t . I n t r o ;
S t r i n g sObjectName=domain+ : t y p e=+className ;
ObjectName mbeanObjectName = new ObjectName ( sObjectName ) ;
mbs . createMBean ( className , mbeanObjectName ) ;
// U t i l i z a r e a MBeanu l u i
// A p e l a r e a o p e r a t i i l o r
S t r i n g o p e r a t i a= s a y H e l l o ;
274
25
27
o p e r a t i a=cmmdc ;
System . out . p r i n t l n ( Cmmdc a l n u m e r e l o 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 ( Primul numar : ) ;
long m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( Al d o i l e a numar : ) ;
long n=s c a n n e r . nextLong ( ) ;
O b j e c t [ ] param={m, n } ;
S t r i n g [ ] s i g n ={ l o n g , l o n g } ;
Long r =(Long ) mbs . i n v o k e ( mbeanObjectName , o p e r a t i a , param , s i g n ) ;
System . out . p r i n t l n ( cmmdc=+r . t o S t r i n g ( ) ) ;
28
29
30
31
32
33
34
35
36
37
// U t i l i z a r e a A t r i b u t e l o r
S t r i n g l a b e l =( S t r i n g ) mbs . g e t A t t r i b u t e ( mbeanObjectName , L a b e l ) ;
System . out . p r i n t l n ( V a l o a r e a a t r i b u t u l u i l a b e l : +l a b e l ) ;
39
40
41
System . out . p r i n t l n ( I n t r o d u c e t i c u r s u l e u r o ) ;
double c u r s E u r o=s c a n n e r . nextDouble ( ) ;
A t t r i b u t e c u r s=new A t t r i b u t e ( CursEuro , c u r s E u r o ) ;
mbs . s e t A t t r i b u t e ( mbeanObjectName , c u r s ) ;
Double e u r o =(Double ) mbs . g e t A t t r i b u t e ( mbeanObjectName , CursEuro ) ;
System . out . p r i n t l n ( V a l o a r e a a t r i b u t u l u i c u r s E u r o : +e u r o ) ;
43
44
45
46
47
48
}
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 ( ) ) ;
}
49
50
51
52
53
54
8.1.5
Invocarea la distant
a
275
package s e r v e r ;
import j a v a x . management . MBeanServer ;
import j a v a x . management . MBeanServerFactory ;
import j a v a x . management . remote . JMXServiceURL ;
import j a v a x . management . remote . JMXConnectorServer ;
import j a v a x . management . remote . JMXConnectorServerFactory ;
public c l a s s MBServer {
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= 1099 ;
// S t r i n g p o r t =1050;
i f ( a r g s . l e n g t h ==0){
System . out . p r i n t l n ( The name o f t h e s e r v e r i s r e q u i r e d ) ;
System . e x i t ( 0 ) ;
}
i f ( a r g s . l e n g t h >=2)
h o s t=a r g s [ 1 ] ;
i f ( a r g s . l e n g t h >=3)
p o r t=a r g s [ 2 ] ;
try {
// Crearea MBeanServer
MBeanServer mbs = MBeanServerFactory . c r e a t e M B e a n S e r v e r ( ) ;
276
// Crearea unui s e r v e r c o n e c t o r
S t r i n g s u r l= s e r v i c e : jmx : rmi : / / / j n d i / rmi : / / +
h o s t+ : +p o r t+ / +a r g s [ 0 ] ;
// S t r i n g s u r l = s e r v i c e : jmx : i i o p : / / / j n d i / i i o p ://+
//
h o s t +:+ p o r t +/+ a r g s [ 0 ] ;
JMXServiceURL u r l=new JMXServiceURL ( s u r l ) ;
JMXConnectorServer c s=
JMXConnectorServerFactory . newJMXConnectorServer ( u r l , null , mbs ) ;
25
26
27
28
29
30
31
32
// P o r n i r e a s e r v e r c o n e c t o r u l u i
cs . st art ( ) ;
System . out . p r i n t l n ( P r e s s Enter t o f i n i s h ! ) ;
System . i n . r e a d ( ) ;
cs . stop ( ) ;
34
35
36
37
38
}
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 ( ) ) ;
e . printStackTrace ( ) ;
}
39
40
41
42
43
44
45
Primul argument care trebuie furnizat programului anterior (args[0] ) este numele serverului.
Clientul, la randul lui, este nevoit sa creeze un conector catre server (agent),
prin intermediul caruia obtine un obiect ce implementeaza interfata MBeanServerConnection.
Prin acest obiect, clientul va putea crea MBean-uri - n agent - si le va putea
utiliza resursele.
Sablonul de programare pentru crearea obiectului MBeanServerConnection
poate fi
JMXServiceURL url =
new JMXServiceURL("service:jmx:rmi:///jndi/rmi://host:port/numeServer");
JMXConnector jmxc = JMXConnectorFactory.connect(url,null);
// Obtinerea obiectului de tip MBeanServerConnection
MBeanServerConnection cs = jmxc.getMBeanServerConnection();
277
package c l i e n t ;
import j a v a . u t i l . S c a n n e r ;
import j a v a x . management . MBeanServerConnection ;
import j a v a x . management . ObjectName ;
import j a v a x . management . A t t r i b u t e ;
import j a v a x . management . M B e a n S e r v e r I n v o c a t i o n H a n d l e r ;
import j a v a x . management . remote . JMXServiceURL ;
import j a v a x . management . remote . JMXConnector ;
import j a v a x . management . remote . JMXConnectorFactory ;
public c l a s s C l i e n t {
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= 1099 ;
i f ( a r g s . l e n g t h <=1){
System . out . p r i n t l n ( The s e r v e r and domain names a r e r e q u i r e d ) ;
System . e x i t ( 0 ) ;
}
S t r i n g serverName=a r g s [ 0 ] ;
S t r i n g domain=a r g s [ 1 ] ;
i f ( a r g s . l e n g t h >=3) h o s t=a r g s [ 2 ] ;
i f ( a r g s . l e n g t h >=4) p o r t=a r g s [ 4 ] ;
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 {
// Crearea unui c o n e c t o r s i a o b i e c t u l u i de t i p M B e a n S e r v e r c s e c t i o n
S t r i n g s u r l= s e r v i c e : jmx : rmi : / / / j n d i / rmi : / / +
h o s t+ : +p o r t+ / +a r g s [ 0 ] ;
// S t r i n g s u r l = s e r v i c e : jmx : i i o p : / / / j n d i / i i o p ://+
//
h o s t +:+ p o r t +/+ a r g s [ 0 ] ;
JMXServiceURL u r l = new JMXServiceURL ( s u r l ) ;
JMXConnector jmxc = JMXConnectorFactory . c o n n e c t ( u r l , n u l l ) ;
MBeanServerConnection c s = jmxc . getMBeanServerConnection ( ) ;
// Domeniile a g e n t u l u i s u n t
System . out . p r i n t l n ( Domains : ) ;
S t r i n g domains [ ] = c s . getDomains ( ) ;
f o r ( i n t i = 0 ; i < domains . l e n g t h ; i ++) {
System . out . p r i n t l n ( \ tDomain [ + i + ] = + domains [ i ] ) ;
}
// i a r domeniul i m p l i c i t
System . out . p r i n t l n ( DefaultDomain : +c s . g e t D e f a u l t D o m a i n ( ) ) ;
System . out . p r i n t l n ( Domain : +domain ) ;
// Crearea unui MBean I n t r o
S t r i n g className= b a s i c . I n t r o ;
S t r i n g sObjectName=domain+ : t y p e=+className ;
ObjectName mbeanObjectName = new ObjectName ( sObjectName ) ;
c s . createMBean ( className , mbeanObjectName , null , n u l l ) ;
double c u r s E u r o ;
long m, n ;
// U t i l i z a r e a MBeanu l u i
// V a r i a n t a 1 de i n v o c a r e p r i n p r o x y
278
System . out . p r i n t l n ( V a r i a n t a de i n v o c a r e p r i n p r o x i ) ;
IntroMBean proxy=
( IntroMBean ) M B e a n S e r v e r I n v o c a t i o n H a n d l e r . n e w P r o x y I n s t a n c e (
cs ,
mbeanObjectName ,
c l i e n t . IntroMBean . c l a s s ,
true ) ;
56
57
58
59
60
61
62
// U t i l i z a r e a o p e r a t i i l o r
// o p e r a t i a s a y H e l l o
proxy . s a y H e l l o ( ) ;
64
65
66
// o p e r a t i a cmmdc
System . out . p r i n t l n ( Cmmdc a l n u m e r e l o r : ) ;
System . out . p r i n t l n ( Primul numar : ) ;
m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( Al d o i l e a numar : ) ;
n=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( Cmmdc=+proxy . cmmdc(m, n ) ) ;
68
69
70
71
72
73
74
// U t i l i z a r e a a t r i b u t e l o r
System . out . p r i n t l n ( Numele : +proxy . g e t L a b e l ( ) ) ;
System . out . p r i n t l n ( I n t r o d u c e t i c u r s u l e u r o ) ;
c u r s E u r o=s c a n n e r . nextDouble ( ) ;
proxy . s e t C u r s E u r o ( c u r s E u r o ) ;
System . out . p r i n t l n ( Euro : +proxy . getCursEuro ( ) ) ;
76
77
78
79
80
81
// V a r i a n t a 2 de i n v o c a r e p r i n c o n e x i u n e
System . out . p r i n t l n ( V a r i a n t a de i n v o c a r e p r i n c o n e x i u n e ) ;
// A p e l a r e a o p e r a t i i l o r
S t r i n g o p e r a t i a= s a y H e l l o ;
c s . i n v o k e ( mbeanObjectName , o p e r a t i a , null , n u l l ) ;
o p e r a t i a=cmmdc ;
System . out . p r i n t l n ( Cmmdc a l n u m e r e l o r : ) ;
System . out . p r i n t l n ( Primul numar : ) ;
m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( Al d o i l e a numar : ) ;
n=s c a n n e r . nextLong ( ) ;
O b j e c t [ ] param={m, n } ;
S t r i n g [ ] s i g n ={ l o n g , l o n g } ;
Long r =(Long ) c s . i n v o k e ( mbeanObjectName , o p e r a t i a , param , s i g n ) ;
System . out . p r i n t l n ( Cmmdc=+r . t o S t r i n g ( ) ) ;
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// U t i l i z a r e a A t r i b u t e l o r
S t r i n g l a b e l =( S t r i n g ) c s . g e t A t t r i b u t e ( mbeanObjectName , L a b e l ) ;
System . out . p r i n t l n ( V a l o a r e a a t r i b u t u l u i l a b e l : +l a b e l ) ;
99
100
101
System . out . p r i n t l n ( I n t r o d u c e t i c u r s u l e u r o ) ;
c u r s E u r o=s c a n n e r . nextDouble ( ) ;
A t t r i b u t e c u r s=new A t t r i b u t e ( CursEuro , c u r s E u r o ) ;
c s . s e t A t t r i b u t e ( mbeanObjectName , c u r s ) ;
Double newEuro=(Double ) c s . g e t A t t r i b u t e ( mbeanObjectName , CursEuro ) ;
System . out . p r i n t l n ( V a l o a r e a a t r i b u t u l u i e u r o : +newEuro ) ;
c s . u n r e g i s t e r M B e a n ( mbeanObjectName ) ;
103
104
105
106
107
108
109
}
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 ( ) ) ;
}
110
111
112
113
114
115
279
Aceasta metoda poate fi inserata n oricare din programele agent sau client.
280
Notificarea la distant
a
Notificarea la distanta presupune utilizarea unui MBean posedand aceasta
facilitate. Pe partea de client trebuie implementat interfata NotificationListener
care declara metoda
public void handleNotification(Notification notification, Object
handback )
Atasarea si disponibilizarea clasei ce implementeaza interfata Notification
Listener se obtin prin metodele interfetei MBeanServerConnection:
void addNotificationListener(ObjectName name, NotificationListener
listener , NotificationFilter filter , Object handback )throws InstanceNotFoundException, IOException
void removeNotificationListener(ObjectName name, ObjectName listener )throws InstanceNotFoundException, ListenerNotFoundException,
IOException
Exemplul 8.1.7 Folosind exemplul 8.1.6 - dar cu MBean-ul creat pentru 8.1.3
se creaza un client cu notificare, care sesiseaza modificarea valoarii atributului
cursEuro a MBean-ului IntroN.
Implementarea interfetei NotificationListener este
1
2
3
4
6
7
8
9
10
11
12
13
14
15
16
17
package c l i e n t ;
import j a v a x . management . N o t i f i c a t i o n ;
import j a v a x . management . N o t i f i c a t i o n L i s t e n e r ;
import j a v a x . management . A t t r i b u t e C h a n g e N o t i f i c a t i o n ;
public c l a s s C l i e n t L i s t e n e r implements N o t i f i c a t i o n L i s t e n e r {
public void h a n d l e N o t i f i c a t i o n ( N o t i f i c a t i o n n o t i f i c a t i o n ,
O b j e c t handback ) {
System . out . p r i n t l n ( \ n R e c e i v e d n o t i f i c a t i o n : + n o t i f i c a t i o n ) ;
A t t r i b u t e C h a n g e N o t i f i c a t i o n myNotif=
( AttributeChangeNotification ) n o t i f i c a t i o n ;
System . out . p r i n t l n ( Curs i n i t i a l : +
myNotif . ge t O l d V a l u e ( ) . t o S t r i n g ( ) ) ;
System . out . p r i n t l n ( Curs c u r e n t
: +
myNotif . getNewValue ( ) . t o S t r i n g ( ) ) ;
}
}
package c l i e n t ;
import j a v a x . management . ObjectName ;
import j a v a x . management . MBeanInfo ;
import j a v a x . management . M B e a n A t t r i b u t e I n f o ;
import j a v a x . management . MBeanConstructorInfo ;
6
7
8
9
10
11
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import
import
import
import
import
import
public c l a s s C l i e n t N o t i f {
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= 1099 ;
i f ( a r g s . l e n g t h <=1){
System . out . p r i n t l n ( The s e r v e r and domain names a r e r e q u i r e d ) ;
System . e x i t ( 0 ) ;
}
S t r i n g serverName=a r g s [ 0 ] ;
S t r i n g domain=a r g s [ 1 ] ;
i f ( a r g s . l e n g t h >=3) h o s t=a r g s [ 2 ] ;
i f ( a r g s . l e n g t h >=4) p o r t=a r g s [ 3 ] ;
C l i e n t N o t i f o b j=new C l i e n t N o t i f ( ) ;
try {
// Crearea unui c o n e c t o r s i a o b i e c t u l u i
// de t i p MBeanServerConnection
S t r i n g s u r l= s e r v i c e : jmx : rmi : / / / j n d i / rmi : / / +
h o s t+ : +p o r t+ / +a r g s [ 0 ] ;
JMXServiceURL u r l = new JMXServiceURL ( s u r l ) ;
JMXConnector jmxc = JMXConnectorFactory . c o n n e c t ( u r l , n u l l ) ;
MBeanServerConnection c s = jmxc . getMBeanServerConnection ( ) ;
// Crearea o b i e c t u l u i OBjectName a t a s a t MBeanu l u i IntroN
S t r i n g className= b a s i c n . I nt r oN ;
S t r i n g sObjectName=domain+ : t y p e=+className ;
ObjectName mbeanObjectName = new ObjectName ( sObjectName ) ;
35
36
37
38
40
41
// U t i l i z a r e a n o t i f i c a r i i
// Crearea unui a s c u l t a t o r
C l i e n t L i s t e n e r l i s t e n e r = new C l i e n t L i s t e n e r ( ) ;
// A c t i v a r e a n o t i f i c a t o r u l u i
c s . a d d N o t i f i c a t i o n L i s t e n e r ( mbeanObjectName , l i s t e n e r , null , o b j ) ;
43
44
45
46
47
Thread . s l e e p ( 5 0 0 ) ;
// D i s p o n i b i l i z a r e a a s c u l t a t o r u l u i de n o t i f i c a r i
System . out . p r i n t l n ( P r e s s Enter t o f i n i s h ! ) ;
try {
System . i n . r e a d ( ) ;
}
catch ( j a v a . i o . IOException e ) { }
c s . r e m o v e N o t i f i c a t i o n L i s t e n e r ( mbeanObjectName , l i s t e n e r ) ;
// D i s p o n i b i l i z a r e a o b i e c t u l u i MBeanObjectName
c s . u n r e g i s t e r M B e a n ( mbeanObjectName ) ;
49
50
51
52
53
54
55
56
57
58
}
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 ( ) ) ;
e . printStackTrace ( ) ;
}
59
60
61
62
63
64
j a v a x . management . MBeanOperationInfo ;
j a v a x . management . M B e a n N o t i f i c a t i o n I n f o ;
j a v a x . management . MBeanServerConnection ;
j a v a x . management . remote . JMXServiceURL ;
j a v a x . management . remote . JMXConnector ;
j a v a x . management . remote . JMXConnectorFactory ;
281
282
66
68
Clasa Client care creaza MBean-ul trebuie lansata naintea clasei ClientNotif.
Aceste doua clase pot rula pe calculatoare distincte.
Exemplul 8.1.8 O aplicatie servlet ntretine un cont. Actiunile ce pot fi
ntreprinse sunt: depunerea unei sume, extragerea unei sume n limita soldului si consultarea contului. Contul este implementat ca un MBean standard.
Se cere urmarirea la distanta a modificarilor suferite de cont.
Interfata contului (a MBean-ului) este
1
2
3
4
5
6
public i n t e r f a c e ContMBean {
// A t r i b u t e
// readw r i t e
public double getCont ( ) ;
public void s e t C o n t ( double c o n t ) ;
}
implementat prin
1
2
3
4
6
7
8
9
11
12
13
15
16
17
18
19
20
21
22
23
24
25
26
27
28
30
31
32
import
import
import
import
j a v a x . management . N o t i f i c a t i o n ;
j a v a x . management . A t t r i b u t e C h a n g e N o t i f i c a t i o n ;
j a v a x . management . N o t i f i c a t i o n B r o a d c a s t e r S u p p o r t ;
j a v a x . management . M B e a n N o t i f i c a t i o n I n f o ;
};
S t r i n g name = A t t r i b u t e C h a n g e N o t i f i c a t i o n . c l a s s . getName ( ) ;
S t r i n g d e s c r i p t i o n = An a t t r i b u t e o f t h i s MBean has changed ;
MBeanNotificationInfo info =
new M B e a n N o t i f i c a t i o n I n f o ( t y p e s , name , d e s c r i p t i o n ) ;
return new M B e a n N o t i f i c a t i o n I n f o [ ] { i n f o } ;
33
34
35
36
37
38
39
40
283
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
j a v a . i o . IOException ;
javax . s e r v l e t . ServletException ;
javax . s e r v l e t . http . HttpServlet ;
javax . s e r v l e t . http . HttpServletRequest ;
javax . s e r v l e t . http . HttpServletResponse ;
javax . s e r v l e t . ServletOutputStream ;
javax . s e r v l e t . ServletConfig ;
j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
j a v a x . s e r v l e t . a n n o t a t i o n . WebInitParam ;
j a v a x . management . ObjectName ;
j a v a x . management . A t t r i b u t e ;
j a v a x . management . MBeanServerConnection ;
j a v a x . management . remote . JMXServiceURL ;
j a v a x . management . remote . JMXConnector ;
j a v a x . management . remote . JMXConnectorFactory ;
@WebServlet ( u r l P a t t e r n s = / a p p d e p o z i t ,
initParams = {
@WebInitParam ( name = j m x S e r v e r H o s t , v a l u e = l o c a l h o s t )
}
)
public c l a s s D e p o z i t S e r v l e t extends H t t p S e r v l e t {
MBeanServerConnection c s=n u l l ;
ObjectName mbeanObjectName=n u l l ;
String host ;
S t r i n g p o r t= 1099 ;
S t r i n g s e r v e r= s e r v e r ;
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 ) {
try {
super . i n i t ( c o n f i g ) ;
h o s t=c o n f i g . g e t I n i t P a r a m e t e r ( j m x S e r v e r H o s t ) ;
S t r i n g s u r l= s e r v i c e : jmx : rmi : / / / j n d i / rmi : / / +h o s t+ : +p o r t+ / +s e r v e r ;
// S t r i n g s u r l = s e r v i c e : jmx : i i o p : / / / j n d i / i i o p ://+ h o s t +:+ p o r t +/+ s e r v e r ;
JMXServiceURL u r l = new JMXServiceURL ( s u r l ) ;
JMXConnector jmxc = JMXConnectorFactory . c o n n e c t ( u r l , n u l l ) ;
c s = jmxc . getMBeanServerConnection ( ) ;
S t r i n g domain = c s . g e t D e f a u l t D o m a i n ( ) ;
S t r i n g className= Cont ;
S t r i n g sObjectName=domain+ : t y p e=+className ;
mbeanObjectName = new ObjectName ( sObjectName ) ;
c s . createMBean ( className , mbeanObjectName , null , n u l l ) ;
}
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 . e x i t ( 0 ) ;
}
}
284
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
out .
out .
out .
out .
108
109
110
111
p r i n t l n ( message ) ;
p r i n t l n ( </p> ) ;
p r i n t l n ( </body></html> ) ;
close ();
112
114
115
116
117
118
<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 bgcolor=#a a e e a a >
<center>
<h1> Pagina de î n t r e ţ i n e r e a d e p o z i t u l u i </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 / appcont / a p p d e p o z i t >
<p>I n t r o d u c e ţ i :
<p>Operaţ i a : <s e l e c t name= o p e r >
<option value= dep >Depunere
<option value= e x t >E x t r a g e r e
<option value= con >C o n s u l t a r e
</ s e l e c t>
<p>
<input type= t e x t name=suma value= 0 >
<p>
<input type= submit value= Executa >
</form>
</ center>
</body>
</html>
import
import
import
import
import
import
import
import
import
import
import
import
import
j a v a x . management . ObjectName ;
j a v a x . management . MBeanInfo ;
j a v a x . management . M B e a n A t t r i b u t e I n f o ;
j a v a x . management . MBeanConstructorInfo ;
j a v a x . management . MBeanOperationInfo ;
j a v a x . management . M B e a n N o t i f i c a t i o n I n f o ;
j a v a x . management . MBeanServerConnection ;
j a v a x . management . N o t i f i c a t i o n ;
j a v a x . management . N o t i f i c a t i o n L i s t e n e r ;
j a v a x . management . A t t r i b u t e C h a n g e N o t i f i c a t i o n ;
j a v a x . management . remote . JMXServiceURL ;
j a v a x . management . remote . JMXConnector ;
j a v a x . management . remote . JMXConnectorFactory ;
public c l a s s C l i e n t N o t i f {
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= 1099 ;
i f ( a r g s . l e n g t h ==0){
285
286
20
21
}
i f ( a r g s . l e n g t h >=2)
h o s t=a r g s [ 1 ] ;
i f ( a r g s . l e n g t h >=3)
p o r t=a r g s [ 2 ] ;
C l i e n t N o t i f o b j=new C l i e n t N o t i f ( ) ;
try {
// Crearea unui c o n e c t o r s i a o b i e c t u l u i de
// t i p MBeanServerConnection
S t r i n g s u r l= s e r v i c e : jmx : rmi : / / / j n d i / rmi : / / +
h o s t+ : +p o r t+ / +a r g s [ 0 ] ;
JMXServiceURL u r l = new JMXServiceURL ( s u r l ) ;
JMXConnector jmxc = JMXConnectorFactory . c o n n e c t ( u r l , n u l l ) ;
MBeanServerConnection c s = jmxc . getMBeanServerConnection ( ) ;
22
23
24
25
26
27
28
29
30
31
32
33
S t r i n g domain = c s . g e t D e f a u l t D o m a i n ( ) ;
System . out . p r i n t l n ( DefaultDomain : +domain ) ;
// Crearea o b i e c t u l u i OBjectName a t a s a t MBeanu l u i Cont
S t r i n g className= Cont ;
S t r i n g sObjectName=domain+ : t y p e=+className ;
ObjectName mbeanObjectName = new ObjectName ( sObjectName ) ;
35
36
37
38
39
40
42
43
// U t i l i z a r e a n o t i f i c a r i i
// Crearea unui a s c u l t a t o r
C l i e n t L i s t e n e r l i s t e n e r = new C l i e n t L i s t e n e r ( ) ;
// A c t i v a r e a n o t i f i c a t o r u l u i
c s . a d d N o t i f i c a t i o n L i s t e n e r ( mbeanObjectName , l i s t e n e r , null , o b j ) ;
45
46
47
48
49
Thread . s l e e p ( 5 0 0 ) ;
// D i s p o n i b i l i z a r e a a s c u l t a t o r u l u i de n o t i f i c a r i
System . out . p r i n t l n ( P r e s s Enter t o f i n i s h ! ) ;
try {
System . i n . r e a d ( ) ;
}
catch ( j a v a . i o . IOException e ) { }
c s . r e m o v e N o t i f i c a t i o n L i s t e n e r ( mbeanObjectName , l i s t e n e r ) ;
// D i s p o n i b i l i z a r e a o b i e c t u l u i MBeanObjectName
c s . u n r e g i s t e r M B e a n ( mbeanObjectName ) ;
51
52
53
54
55
56
57
58
59
60
}
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 ( ) ) ;
e . printStackTrace ( ) ;
}
61
62
63
64
65
66
68
69
71
c l a s s C l i e n t L i s t e n e r implements N o t i f i c a t i o n L i s t e n e r {
public void h a n d l e N o t i f i c a t i o n ( N o t i f i c a t i o n n o t i f i c a t i o n ,
O b j e c t handback ) {
System . out . p r i n t l n ( \ n R e c e i v e d n o t i f i c a t i o n : + n o t i f i c a t i o n ) ;
A t t r i b u t e C h a n g e N o t i f i c a t i o n myNotif=
( AttributeChangeNotification ) n o t i f i c a t i o n ;
System . out . p r i n t l n ( S o l d i n i t i a l : +
myNotif . ge t O l d V a l u e ( ) . t o S t r i n g ( ) ) ;
72
73
74
75
76
77
78
System . out . p r i n t l n ( S o l d c u r e n t
: +
myNotif . getNewValue ( ) . t o S t r i n g ( ) ) ;
79
80
81
82
287
Intreb
ari recapitulative
1. Ce posibilitate ofera Java Management Extensions (JMX) ?
2. Care este structute unui MBean standard ?
3. Precizati continutul unui server MBean cu agenti la distanta.
4. Precizati termenul de notificare n legatura cu MBean.
288
Bibliografie
290
[14] * * * , J2EE Tutorial 1.5, Sun Microsystems.
[15] * * * , Java 2 Tutorial, Sun Microsystems.
BIBLIOGRAFIE