Sunteți pe pagina 1din 179

Universitatea Transilvania din Brasov

Facultatea de MatematicaInformatica
Catedra de Informatica
ERNEST SCHEIBER

IN
PROGRAMARE DISTRIBUITA
JAVA

Brasov

Introducere

Obiectivele cursului
Retelele locale, internetul, raspandirea pe o arie geografica a resurselor si a
locatiilor n care se petrec actiuni ce tin de o activitate bine definita sau sunt
urm
arite, gestionate din alte locuri au drept consecinta existenta aplicatiilor
distribuite. Termenul distribuit se refera tocmai la faptul ca componente ale
aplicatiei se afl
a pe calculatoare diferite dar ntre care au loc schimburi de date.
Dac
a p
artile unei aplicatii sau resursele utilizate se gasesc pe calculatoare distincte atunci aplicatia se numeste distribuita.
Intre p
artile sau resursele unei aplicatii distribuite au loc schimburi de date,
ceea ce se face utiliz
and diferite mecanisme la realizarea carora concura sistemul
de calcul, sistemul de operare si limbajul de programare.
Astfel se vorbeste de programare distribuita ca mijloc de realizare a aplicatiilor
distribuite. Pe l
ang
a algortm, structuri de date, limbaj de programare, la realizarea unei aplicatii distribuite intervin comunicatiile: schimbul de date dintre
dou
a componente aflate pe calculatoare diferite.
Punem n evident
a doua modele de aplicatii distribuite:
client-server: Programul server executa cererile clientilor. Amintim urm
atoarele
tehnologii Java pentru realizarea aplicatiilor client-server:
RMI (Remote Method Invocation)
CORBA (Common Object Request Brocker Arhitecture)
JMS (Java Message Service)
2

3
Servlet si JSP (Java Server Pages)
Portlet
dispecer-lucr
ator: Programul dispecer distribuie sarcinile de executat
lucr
atorilor si le coordoneaz
a activitatea.
Obiectivul acestui curs este prezentarea tehnologiilor de programare Java care
permit programarea aplicatiilor client - server:
socluri Java;
apelarea metodelor de la distanta (Remote Method Invocation - RMI );
mesageria Java;
servlet;
Java server Pages - JSP;
Portlet si Portal.
Modelul dispecer-lucr
ator nu face parte din obiectivul cursului.

Competente conferite
Se dezvolt
a deprinderile de programare distribuita.

Resurse si mijloace de lucru


Toate resursele utilizate sunt gratuite, ele se descarca din Internet.
Metodele si instrumentele de programare vor fi exemplificate pe problema
foarte simpl
a de calcul a celui mai mare divizor comun a doua numere naturale.
Codul metodei de calcul este
public long cmmdc(long m,long n){
long r,c;
do{
c=n;
r=m%n;
m=n;
n=r;
}
while(r!=0);
return c;
}

Pentru aplicatiile care utilizeaza o baza de date, sistemul de gestiune a bazei


de date (SGBD) va fi una dintre sistemele Derby sau mysql.
Tiparul de nv
atare poate fi
1. Se instaleaz
a toate resursele necesare (Se exemplifica la laborator).
2. Se execut
a aplicatia / aplicatiile din curs (Se exemplifica la laborator).
3. Pentru fiecare tehnologie, citind cursul, se programeaza o alta aplicatie.
Propunem problemele:
conversia ntre grade Celsius n 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 rezolv
a tema pentru examen.

Structura cursului
1. Modulul 1: Programare distribuita cu comunicatii ce nu folosesc pe protocolul http - HyperText Transfer Protocol.

5
(a) UI 1. Socluri TCP.
(b) UI 2. Datagrame si canale de comunicatii.
(c) UI 3. Reg
asirea obiectelor prin servicii de nume.
(d) UI 4. RMI.
(e) UI 5. Tipare de programare RMI.
(f) UI 6. CORBA.
(g) UI 7. JMS cu comunicatie punctuala.
(h) UI 8. JMS cu comunicatie bazata pe subiect si protocolul AMPQ.
2. Modulul 2: Programare distribuita cu comunicatii bazate pe protocolul
http.
(a) UI 9. Servlet.
(b) UI 10. Facilit
ati de programare cu servlet.
(c) UI 11. JSP.
(d) UI 12. Portlet.

Cerinte preliminare
Intelegerea cursului presupune cunostinte si deprinderi de programare n limbajul Java.

Evaluarea
Evaluarea se termin
a cu un examen care consta din

6
1. Test scris alc
atuit din 10 intrebari, cu calificative (foarte bine (8-10 raspunsuri
corecte), bine (6-7), satisfator (4-5) si nesatisfacator (0-3),) avand rol orientator pentru aprecierea probei practice. Durata testului este de 12-15
minute
2. Proba practic
a consta din prezentarea unui aplicatii din fiecare din tehnologiile studiate (socluri, RMI sau CORBA, mesagerie, servlet, JSP, portlet),
in total sapte aplicatii. Temele aplicatiilor cat si detalii tehnice privind
tehnologia de programare se stabilesc de comun acord cu ndrumatorul laboratorului.
Toate aplicatiile se executa pe calculatoarele unui laborator.
Programele nu contin comentarii explicative. Pentru examen tema si textele
surs
a ale programelor vor fi listate.
Ponderea examenului este 100%.
Materialul de fat
a este orientativ. Documentatia la zi este disponibila prin
intranetul din corpul P al universitatii.

Cuprins
I

Programare distribuit
a f
ar
a HTTP

1 Programare cu socluri Java


1.1 Aplicatii client server . .
1.2 Notiuni despre retele . . .
1.3 Soclu TCP . . . . . . . .
1.4 Aplicatie client server cu

. . . . .
. . . . .
. . . . .
socluri

.
.
.
.

.
.
.
.

10

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

2 Datagrame si canale de comunicatii


2.1 Datagrame . . . . . . . . . . . . . . . . . . .
2.1.1 Aplicatii client server cu datagrame.
2.1.2 Multicast vs. Broadcast . . . . . . . .
2.2 Canale de comunicatie . . . . . . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

12
12
13
14
16

.
.
.
.

22
22
27
31
35

3 Reg
asirea obiectelor prin servicii de nume
47
3.1 Java Naming and Directory Interface . . . . . . . . . . . . . . . . . 48
3.1.1 LDAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
4 Remote Method Invocation - RMI
56
4.1 Remote Method Invocation . . . . . . . . . . . . . . . . . . . . . . 57
4.1.1 Crearea unei aplicatii RMI . . . . . . . . . . . . . . . . . . 60
5 Tipare de programare RMI
66
5.1 Fabrica de obiecte . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
5.2 Apelul invers Callback . . . . . . . . . . . . . . . . . . . . . . . . 69
6 CORBA
6.1 CORBA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.1.1 Conexiunea RMI - CORBA . . . . . . . . . . . . . . . . . .
6.1.2 Aplicatie Java prin CORBA . . . . . . . . . . . . . . . . . .
7

73
73
74
79

CUPRINS

7 JMS cu comunicatie punctual


a
7.1 Java Message Service (JMS) . . . . . . .
7.2 Open Message Queue . . . . . . . . . . .
7.3 Apache ActiveMQ . . . . . . . . . . . .
7.4 Elemente de programare - JMS . . . . .
7.4.1 Trimiterea unui mesaj . . . . . .
7.4.2 Receptia sincrona a unui mesaj .
7.4.3 Receptia asincrona a unui mesaj

.
.
.
.
.
.
.

84
85
86
87
87
87
92
94

8 JMS cu comunicatie bazat


a pe subiect
8.1 Publicarea mesajelor . . . . . . . . . . . . . . . . . . . . . . . . . .
8.1.1 Publicarea mesajelor . . . . . . . . . . . . . . . . . . . . . .
8.1.2 Subscrierea si receptia mesajelor . . . . . . . . . . . . . . .

97
97
97
98

II

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

Programare distribuit
a cu HTTP

9 Servlet
9.1 Marcajul <form> . . . . . . . . .
9.2 Server Web - container de servlet .
9.3 Realizarea unui servlet . . . . . . .
9.3.1 Codul unui servlet . . . . .
9.4 Procesare asincrona n Java Servlet

. .
. .
. .
. .
3.0

10 Facilit
ati de programare cu servlet
10.1 Program client al unui servlet . . . . .
10.2 Servlete nl
antuite . . . . . . . . . . .
10.3 Sesiune de lucru . . . . . . . . . . . .
10.4 Cookie . . . . . . . . . . . . . . . . . .
10.5 Servlet cu conexiune la o baza de date
10.6 Imagini furnizate de servlet . . . . . .
10.7 Filtru . . . . . . . . . . . . . . . . . .

101
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

11 Java Server Page JSP


11.1 Tehnologia JSP . . . . . . . . . . . . . . .
11.1.1 Declaratii JSP . . . . . . . . . . .
11.1.2 Directive JSP . . . . . . . . . . . .
11.1.3 Marcaje JSP predefinite . . . . . .
11.1.4 Componenta Java (Java Bean) . .
11.1.5 Pagini JSP cu componente Java .
11.2 JSP Standard Tag Library JSTL . . . . .
11.2.1 Biblioteca de baza . . . . . . . . .
11.2.2 Biblioteca de lucru cu baze de date

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

103
. 104
. 105
. 107
. 109
. 116

.
.
.
.
.
.
.

120
. 120
. 123
. 125
. 126
. 128
. 130
. 132

.
.
.
.
.
.
.
.
.

136
. 136
. 142
. 143
. 144
. 145
. 145
. 149
. 149
. 154

CUPRINS

12 Portlet
12.1 Apache-pluto . . . . . .
12.2 Dezvoltarea unui portlet
12.3 Elemente de programare
12.4 Produse Portal . . . . .
12.4.1 uPortal . . . . .
12.4.2 Jetspeed-2 . . . .
Bibliografie

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

157
159
160
164
173
173
177
179

Modulul I

Programare distribuit
a cu
comunicatii ce nu folosesc
protocolul HTTP

10

11

Introducere
Se prezint
a programarea Java bazate pe
Protocoalele TCP si UDP;
modelul de apel de procedura la distanta (Remote Procedure Call) RMI si
CORBA;
serviciul de mesagerie java.

Unitatea de nv
atare 1

Programare cu socluri Java

Durata: 3 ore.

Introducere
Limbajul de programare Java ofera facilitati de elaborare ale unor programe
care utilizeaz
a si interactioneaza cu resurse din Internet si din World Wide Web.
In plus limbajul Java permite utilizarea URL-ului (Universal Resource Locator adresa resurselor n Internet), a soclurilor (socket) si a datagramelor.

1.1

Aplicatii client server

O aplicatie client server se compune din:


componenta server - alcatuita din programe / clase ce asigura una sau mai
multe functiuni (servicii), care pot fi apelate de catre clienti.
12

1.2. NOT
IUNI DESPRE RET
ELE

13

componenta client - alc


atuita din programe / clase care permit accesul la
server si apelarea serviciilor acestuia.
Serverul si clientul (clientii) ruleaza, de obicei, pe calculatoare distincte. Un
server trebuie s
a satisfac
a cererile mai multor clienti.
Durata de viat
a a unei aplicatii client server este data de durata functionarii
serverului. Aceast
a durat
a poate fi alcatuita din intervale disjuncte de timp, ntre
acele intervale, din diverse motive, serverul este inactiv.
Intervalul de timp determinat de conectarea unui client la server si pana la
deconectare poart
a numele de sesiune. In aceasta perioada, clientul poate invoca
mai multe servicii ale serverului. Un client poate initia mai multe sesiuni.
Un client trebuie s
a-si reg
aseasca datele n cadrul unei sesiuni, ntre sesiuni, pe
toata durata de viat
a a aplicatiei. Astfel se pune problema retinerii / persistentei
datelor pentru fiecare client n parte.

Autentificare si autorizare
Uzual, pentru a folosi serviciul unui server, un client trebuie sa se nregistreze,
moment n care i se stabilesc drepturile de care dispune la utilizarea serviciilor
oferite de server.
La apelarea serverului, clientul este autentificat - adica i se recunoaste identitatea - si apoi i se asigur
a accesul la servicii n limita drepturilor pe care le
are.

1.2

Notiuni despre retele

Calculatoarele ce ruleaz
a n Internet comunica ntre ele folosind protocolul
TCP (Transport Control Protocol) sau UDP (User Datagram Protocol).
Intr-un program Java se utilizeaza clasele pachetului java.net prin intermediul c
arora se acceseaz
a nivelele deservite de protocoalele TCP sau UDP. In
felul acesta se pot realiza comunicatii independente de platforma de calcul. Pentru a alege care clas
a Java s
a fie utilizata trebuie cunoscuta diferenta dintre TCP
si UDP.
TCP C
and dou
a aplicatii comunica ntre ele se stabileste o conexiune prin
intermediul c
areia se schimb
a date. Folosind protocolul TCP, comunicatia garanteaza ca datele trimise dintr-un capat ajung n celalalt capat cu pastrarea ordinii
n care au fost trimise. Acest tip de comunicatie seamana cu o convorbire telefonica. TCP furnizeaz
a un canal sigur de comunicatie ntre aplicatii.
UDP Utilizarea protocolului UDP presupune trimiterea unor pachete de date
numite datagrame de la o aplicatie la alta fara sa se asigure faptul ca data-

14

ARE 1. PROGRAMARE CU SOCLURI JAVA


UNITATEA DE INVAT

gramele ajung la destinatie si nici ordinea lor de sosire. Acest tip de comunicatie
seam
an
a cu trimiterea scrisorilor prin posta.

1.3

Soclu TCP

Conexiunile bazate pe protocolul HTTP (Hyper Text Transfer Protocol ) reprezint


a
un mecanism de nivel nalt pentru accesarea resurselor din Internet.
Aplicatii de tip client server se pot realiza utilizand comunicatii de nivel
sc
azut. Pentru a comunica utilizand TCP programul client si programul server
stabilesc o conexiune sigura. Fiecare program se leaga la conexiune printr-un
soclu (socket). Un soclu este capatul unei cai de comunicatie bidirectional ntre
dou
a programe ce ruleaza n retea. Un soclu este legat de un port prin care
nivelul TCP poate identifica aplicatia careia i sunt transmise datele. Din punct
de vedere fizic, un port este o adresa de memorie cuprinsa ntre 0 si 65535.
Pentru a comunica atat clientul cat si serverul citesc date de la si scriu date
la soclul legat la conexiunea dintre ele.
In pachetul java.net clasele Socket si ServerSocket implementeaza un soclu
din partea clientului si respectiv din partea serverului.
Clientul cunoaste numele calculatorului pe care ruleaza serverul cat si portul
la care acesta este conectat. Pentru stabilirea conexiunii, clientul ncearca un
rendez-vous cu serverul de pe masina serverului si la portul serverului. Dac
a
totul decurge bine, serverul accepta conexiunea. Dupa acceptare, serverul creaz
a
pentru client un nou soclu legat la un alt port n asa fel ncat ascultarea cererilor
la soclul initial s
a poat
a continua n timp ce sunt satisfacute cererile clientului
conectat. Din partea clientului, dupa acceptarea conexiunii soclul este creat si
este utilizat pentru comunicatia cu serverul.

Clasa java.net.Socket
Resursele clasei Socket sunt destinate clientului.
Constructori
public Socket(String host, int port) throws UnknownHostException,
IOException
Creaz
a un soclu conectat la calculatorul cu portul specificat.
public Socket(InetAddress host, int port) throws IOException
Creaz
a un soclu conectat la calculatorul cu portul specificat.
Metode

1.3. SOCLU TCP

15

public InputStream getInputStream() throws IOException


Returneaz
a un flux de intrare atasat soclului, pentru citirea (preluarea)
informatiilor de la soclu.
public OutputStream getOutputStream() throws IOException
Returneaz
a un flux de iesire atasat soclului, pentru scrierea (transmiterea)
informatiilor la soclu.
public synchronized void close() throws IOException
nchide soclul de referint
a.

Clasa java.net.ServerSocket
Resursele clasei ServerSocket sunt destinate serverului.
Constructori
public ServerSocket(int port) throws IOException
Creaz
a un soclu la portul specificat. Daca port=0, atunci va fi utilizat
orice port disponibil. Capacitatea sirului (tamponului) de asteptare pentru
cererile de conectare se fizeaza la valoarea implicita 50. Cererile n exces
vor fi refuzate.
public ServerSocket(int port, int lung) throws IOException
In plus fixeaz
a lungimea sirului (tamponului) de asteptare.
public ServerSocket(int port, int lung, InetAddress adr )
throws IOException
Se specific
a n plus calculatorul de la care se asteapta cereri. Daca adr =null,
atunci se accept
a cereri de la orice calculator.
Metode
public Socket accept() throws IOException
Metoda blocheaz
a procesul (firul de executie) apelant pana la sosirea unei
cereri de conectare si creaz
a un soclu client prin care se va desfasura comunicarea cu solicitantul acceptat.
public synchronized void close() throws IOException
nchide soclul de referint
a.

16

1.4

ARE 1. PROGRAMARE CU SOCLURI JAVA


UNITATEA DE INVAT

Aplicatie client server cu socluri

Serverul trebuie s
a satisfaca simultan solicitarile mai multor clienti. Fiecare
client apeleaz
a programul server la acelasi port si n consecinta cererile de conectare
sunt receptionate de acelasi ServerSocket. Serverul receptioneaza apelurile secvential.
La un apel, se creaz
a de partea severului un soclu prin care se va face schimbul
de date cu clientul. Cererile clientilor pot fi satisface concurent/paralel, utilizand
fire de executie ce implementeaza serviciul oferit sau secvential - n cazul unor
servicii de durat
a scurt
a.
Exemplul 1.4.1 Sistem client - server pentru calculul celui mai mare divizor
comun a dou
a numere naturale. Portul obiectului de tip ServerSocket este 7999.
Programul client CmmdcClient se conecteaza la server, transmite serverului
cele dou
a numere naturale si receptioneaza rezultatul pe care apoi l afiseaza.
In esent
a orice program client trebuie sa execute:
1. Deschide/creaz
a un soclu.
2. Deschide/creaz
a fluxuri de date pentru comunicatia cu serverul.
3. Transmite si receptioneaza date potrivit specificului aplicatiei (protocolului
serverului). Acest pas variaza de la un program client la altul.
4. Inchiderea fluxurilor de date.
5. Inchiderea soclului.
1
2
3
5
6
7
8
9
10
11
12
13
14
15
17
18
19
20
21
22
23

import j a v a . i o . ;
import j a v a . n e t . ;
import j a v a . u t i l . S c a n n e r ;
public c l a s s CmmdcClient {
public s t a t i c void main ( S t r i n g [ ] a r g s ) throws IOException {
S t r i n g h o s t= l o c a l h o s t ;
i n t p o r t =7999;
i f ( a r g s . l e n g t h >0)
h o s t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
S o c k e t cmmdcSocket = n u l l ;
DataInputStream i n=n u l l ;
DataOutputStream out=n u l l ;
try {
cmmdcSocket = new S o c k e t ( hos t , p o r t ) ;
out=new DataOutputStream ( cmmdcSocket . getOutputStream ( ) ) ;
i n=new DataInputStream ( cmmdcSocket . g e t I n p u t S t r e a m ( ) ) ;
}
catch ( E x c e p t i o n e ) {
System . e r r . p r i n t l n ( C o n n e c t i o n E r r o r : +e . g e t M e s s a g e ( ) ) ;

1.4. APLICAT
IE CLIENT SERVER CU SOCLURI

System . e x i t ( 1 ) ;

24
25

27

S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
long m, n , r ;
System . out . p r i n t l n ( m= ) ;
m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
n=s c a n n e r . nextLong ( ) ;

28
29
30
31
32

try {
out . w r i t e L o n g (m) ;
out . w r i t e L o n g ( n ) ;
r=i n . readLong ( ) ;
System . out . p r i n t l n ( Cmmdc : +r ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( Comunication e r r o r +e . g e t M e s s a g e ( ) ) ;
}

34
35
36
37
38
39
40
41
42

out . c l o s e ( ) ;
in . close ( ) ;
cmmdcSocket . c l o s e ( ) ;

44
45
46

47
48

17

Se presupune c
a programul server ruleaza pe calculatorul local si utilizeaza
portul 7999. Dac
a acesti parametri se modifica - de exemplu serverul ruleaza n
retea pe calculatorul atlantis la portul 8200 - atunci la apelare transmitem acesti
parametri prin java CmmdcClient atlantis 8200
Partea server este alc
atuit
a din mai multe clase:
Clasa MyMServer, independenta de un serviciu anume, preia apelurile clientilor
si lanseaz
a satisfacerea cererii.
1
2
4
5
6
7
8
9
10
11
12
13
14
15
16
18
19
20
21
22

import j a v a . n e t . ;
import j a v a . i o . ;
public c l a s s MyMServer {
public s t a t i c void main ( S t r i n g [ ] a r g s ) throws IOException {
i n t p o r t =7999;
boolean l i s t e n i n g=true ;
ServerSocket s e r v e r S o c k e t = null ;
try {
s e r v e r S o c k e t = new S e r v e r S o c k e t ( p o r t ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( Could not l i s t e n on p o r t : +p o r t ) ;
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 1 ) ;
}
while ( l i s t e n i n g )
// v a r i a n t a 1
new AppThread ( s e r v e r S o c k e t . a c c e p t ( ) ) . s t a r t ( ) ;
// v a r i a n t a 2
/

18

ARE 1. PROGRAMARE CU SOCLURI JAVA


UNITATEA DE INVAT

23

S o c k e t s o c k e t=s e r v e r S o c k e t . a c c e p t ( ) ;
try {
DataOutputStream o u t=
new DataOutputStream ( s o c k e t . g e t O u t p u t S t r e a m ( ) ) ;
DataInputStream i n=
new DataInputStream ( s o c k e t . g e t I n p u t S t r e a m ( ) ) ;
l o n g m=0,n=0, r ;
App app=new App ( ) ;
m=i n . readLong ( ) ;
n=i n . readLong ( ) ;
r=app . cmmdc(m, n ) ;
out . writeLong ( r ) ;
out . c l o s e ( ) ;
in . c l o s e ( ) ;
socket . close ();
}
c a t c h ( IOException e ) {
System . e r r . p r i n t l n ( S e r v e r c o m u n i c a t i o n e r r o r : +
e . getMessage ( ) ) ;
}

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

}
/
serverSocket . close ( ) ;

44
45
46

47
48

In ciclul while, la receptia unei solicitari de conexiune se creaza si se


lanseaz
a un fir de executie a carei metoda run contine actiunile ce raspund
solicit
arii.
O solutie mai eficienta este utilizarea unui bazin de fire de executie:
static final int NTHREADS=100;
static ExecutorService exec=Executors.newFixedThreadPool(NTHREADS);
. . .
while(listening){
AppThread obj=new AppThread(serverSocket.accept());
exec.execute(obj);
}
. . .

Clasa AppTread - fir de executie responsabil de preluarea datelor si de


transmitere a rezultatului.
1
2
4
5
7
8
9
11

import j a v a . n e t . ;
import j a v a . i o . ;
public c l a s s AppThread extends Thread {
S o c k e t s o c k e t=n u l l ;
public AppThread ( S o c k e t s o c k e t ) {
t h i s . s o c k e t=s o c k e t ;
}
public void run ( ) {

1.4. APLICAT
IE CLIENT SERVER CU SOCLURI

try {
DataOutputStream out=new DataOutputStream ( s o c k e t . getOutputStream ( ) ) ;
DataInputStream i n=new DataInputStream ( s o c k e t . g e t I n p u t S t r e a m ( ) ) ;
long m=0 ,n=0 , r ;
App app=new App ( ) ;
m=i n . readLong ( ) ;
n=i n . readLong ( ) ;
r=app . cmmdc(m, n ) ;
out . w r i t e L o n g ( r ) ;
out . c l o s e ( ) ;
in . close ( ) ;
socket . close ( ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( S e r v e r c o m u n i c a t i o n e r r o r : +e . g e t M e s s a g e ( ) ) ;
}

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29

19

Clasa App corespunz


atoare calcului celui mai mare divizor comul a doua
numere naturale.
1
2
3

public c l a s s App{
public long cmmdc( long m, long n ) { . . . }
}

Rularea programelor. Se porneste la nceput programul server MyMServer


iar apoi clientul CmmdcClient. Clientul se poate rula de pe orice calculator al
retelei. Dac
a programul client se executa pe alt calculator decat cel pe care
ruleaza programul server, atunci la apelarea clientului trebuie precizat numele
calculatorului server si eventual portul utilizat.
O alt
a arhitectur
a a aplicatiei este dezvoltata n continuare. Aceasta arhitectura este mai bun
a n sensul c
a poate fi utilizata n alte cadre de lucru / de
dezvoltare (de exemplu OSGi, Junit).
Aplicatia se va compune din:
Aplicatia server alc
atuit
a din:
Interfat
a
1
2
3
4
5
6

package i s e r v e r ;
import j a v a . n e t . S e r v e r S o c k e t ;
public i n t e r f a c e IMyMServer {
public S e r v e r S o c k e t g e t S e r v e r S o c k e t ( i n t p o r t ) ;
public void myAction ( S e r v e r S o c k e t s e r v e r S o c k e t ) ;
}

Implementarea interfetei
1
2
3

package s e r v e r . impl ;
import s e r v e r . ;
import i s e r v e r . IMyMServer ;

20

ARE 1. PROGRAMARE CU SOCLURI JAVA


UNITATEA DE INVAT

import j a v a . n e t . ;
import j a v a . i o . ;
import j a v a . u t i l . c o n c u r r e n t . ;

public c l a s s MyMServer implements IMyMServer {

4
5

public S e r v e r S o c k e t g e t S e r v e r S o c k e t ( i n t p o r t ) {
ServerSocket s e r v e r S o c k e t = null ;
try {
s e r v e r S o c k e t = new S e r v e r S o c k e t ( p o r t ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( Could not l i s t e n on p o r t : +p o r t ) ;
System . e r r . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 1 ) ;
}
System . out . p r i n t l n ( S e r v e r S o c k e t i s r e a d y . . . ) ;
return s e r v e r S o c k e t ;
}

10
11
12
13
14
15
16
17
18
19
20
21
22

public void myAction ( S e r v e r S o c k e t s e r v e r S o c k e t ) {


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) ;
while ( true ) {
try {
AppThread o b j=new AppThread ( s e r v e r S o c k e t . a c c e p t ( ) ) ;
exec . execute ( obj ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( MyActionException : +e . g e t M e s s a g e ( ) ) ;
}
}
}

24
25
26
27
28
29
30
31
32
33
34
35
36
37

Clasele AppThread, App sunt cele utilizate anterior.


Clas
a de lansare a serverului
1
2
3
4
6
7
8
9
10
11
12
13
14
15

package s e r v e r ;
import j a v a . n e t . S e r v e r S o c k e t ;
import s e r v e r . impl . MyMServer ;
import i s e r v e r . IMyMServer ;
public c l a s s AppServer {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
i n t p o r t =7999;
i f ( a r g s . l e n g t h >0)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 0 ] ) ;
IMyMServer myMServer=new MyMServer ( ) ;
S e r v e r S o c k e t s e r v e r S o c k e t=myMServer . g e t S e r v e r S o c k e t ( p o r t ) ;
myMServer . myAction ( s e r v e r S o c k e t ) ;
}
}

Aplicatia client este nemodificata.

1.4. APLICAT
IE CLIENT SERVER CU SOCLURI

21

Test de evaluare a cunostintelor


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.

Unitatea de nv
atare 2

Datagrame si canale de
comunicatii

Durata: 4 ore.

2.1

Datagrame

Pentru utilizarea datagramelor pachetul java.net pune la dispozitie clasele


DatagramSocket
DatagramPacket
MulticastSocket
O aplicatie trimite si receptioneaza pachete DatagramPacket prin intermediul
unui DatagramSocket. Un pachet DatagramPacket poate fi trimis la mai multi
destinatari prin intermediul unui MulticastSocket.
Reamintim c
a o datagrama este un mesaj trimis prin retea a carei sosire nu
este garantat
a iar momentul de sosire este neprecizat.
22

2.1. DATAGRAME

23

Clasa java.net.DatagramPacket.
Trimiterea unui pachet UDP necesita crearea unui obiect
DatagramPacket care contine corpul mesajului si adresa destinatiei. Apoi acest
obiect DatagramPacket poate fi pus n retea n vederea trimiterii sale. Primirea unui pachet UDP necesit
a crearea unui obiect DatagramPacket si apoi acceptarea unui pachet UDP din retea. Dupa primire, se poate extrage din obiectul
DatagramPacket adresa surs
a si continutul mesajului.
Constructori
Exist
a doi constructori pentru datagrame UDP. Primul constructor este folosit
pentru primirea de pachete si necesita doar furnizarea unei memorii tampon, iar
celalalt este folosit pentru trimiterea de pachete si necesita specificarea adresei
destinatarului.
DatagramPacket(byte[ ] buffer ,int lung)
Acest contructor este folosit pentru primirea pachetelor. Un pachet se memoreaz
a n tamponul buffer avand lung octeti. Daca lungimea pachetului
dep
aseste aceast
a lungime, atunci pachetul este trunchiat iar octetii n plus
se pierd.
DatagramPacket(byte[ ] buffer ,int lung ,InetAddress adresa ,int port)
Acest constructor este folosit pentru crearea unui pachet n vederea expedierii. Corpul pachetului este continut n tamponul buffer avand lung
octeti. Pachetul va fi trimis catre adresa si portul specificat. Trebuie sa
existe un server UDP care asculta la portul specificat pentru trimiterea
pachetelor. Un server UDP poate coexista cu un server TCP care asculta
acelasi port.
Metode
InetAddress getAddress()
returneaz
a adresa IP a expeditorului.
int getPort()
returneaz
a portul expeditorului.
byte[] getData()
returneaz
a continutul pachetului.
int getLength()
returneaz
a lungimea pachetului.
void setAddress(InetAddress adresa)
fixeaz
a adresa IP a pachetului.

24

ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II

void setPort(int port)


fixeaz
a portul.
void setData(byte[] buffer )
fixeaz
a continutul pachetului.
void setLength(int lung)
fixeaz
a lungimea pachetului.

Clasa java.net.DatagramSocket
Aceast
a clas
a se foloseste atat pentru trimiterea, cat si pentru primirea obiectelor
DatagramPacket. Un obiect DatagramSocket asculta la un port cuprins ntre 1
si 65535 (porturile cuprinse ntre 1 si 1023 sunt rezervate pentru aplicatiile sistem). Deoarece UDP nu este orientat pe conexiune, se va crea un singur obiect
DatagramSocket pentru trimiterea pachetelor catre diferite destinatii si primirea
pachetelor de la diferite surse.
Constructori
DatagramSocket() throws SocketException
Creaz
a un obiect DatagramSocket cu un numar de port aleator;
DatagramSocket(int port) throws SocketException
Creaz
a un obiect DatagramSocket cu numarul de port specificat;
DatagramSocket(int port, InetAddress adres
a ) throws SocketException
Creaz
a un obiect DatagramSocket la adresa si portul specificat.
Metode
Clasa DatagramSocket contine metode pentru trimiterea si primirea de obiecte
DatagramPacket, nchiderea soclului, determinarea informatiilor adresei locale
si setarea timpului de primire.
void send(DatagramPacket pachet) throws IOException
Trimite pachetul prin retea. Daca se trimit pachete la o destinatie necunoscut
a sau care nu asculta, n cele din urma se genereaza o exceptie
IOException.
void receive(DatagramPacket pachet) throws IOException
Metoda primeste un singur pachet UDP n obiectul pachet specificat. Apoi,
pachetul poate fi inspectat pentru determinarea adresei IP sursa, portul
surs
a si lungimea mesajului. Executia metodei este blocata pana cand se
primeste cu succes un pachet sau se scurge timpul de asteptare.

2.1. DATAGRAME

25

InetAddress getLocalAddress()
Returneaz
a adresa local
a c
atre care este legat acest DatagramSocket;
int getLocalPort()
Returneaz
a num
arul de port unde asculta DatagramSocket.
void close()
Inchide DatagramSocket.
void setSoTimeout(int timpDeAsteptere) throws SocketException
Metoda fixeaz
a timpul de asteptare (n milisecunde) a soclului. Metoda
receive() se va bloca pentru timpul de asteptare specificat pentru primirea
unui pachet UDP, dup
a care va arunca o exceptie Interrupted Exception.
Dac
a valoarea parametrului este 0, atunci soclul este blocat.
int getSoTimeout() throws SocketException
Returneaz
a timpul de asteptare.
void setSendBufferSize(int lungime) throws SocketException
Fixeaz
a lungimea tamponului de trimitere a soclului la valoarea specificata.
Nu poate fi trimis mesaj UDP de lungime mai mare de aceasta valoare.
int getSendBufferSize() throws SocketException
Returneaz
a lungimea tamponului de trimitere a soclului.
void setReceiveBufferSize(int lungime) throws SocketException
Fixeaz
a lungimea tamponului de primire a soclului la valoarea specificata.
Nu poate fi primit un mesaj UDP de lungime mai mare de aceasta valoare.
int getReceiveBufferSize() throws SocketException
Returneaz
a lungimea tamponului de primire a soclului.
void connect(InetAddress adresa, int port) throws SocketException
Conecteaz
a soclul la adresa si portul specificat. Aceasta metoda nu este
cerut
a pentru operatiile uzuale UDP.
void disconnect()
Deconecteaz
a soclul conectat.
InetAddress getInetAddress()
Returneaz
a obiectul InetAddress catre care este conectat soclul sau null
dac
a acesta nu este conectat.

26

ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II

int getPort()
Returneaz
a portul la care este conectat soclul sau -1 daca acesta nu este
conectat.

Clasa java.net.InetAddress
Datele pot fi trimise prin retea indicand adresa IP corespunzatoare masinii
destinatie. Clasa InetAddress furnizeaza acces la adresele IP.
Nu exist
a constructori pentru aceasta clasa. Instantele trebuie create folosind
metodele statice:
InetAddress getLocalHost() throws UnknownHostException
Returneaz
a un obiect InetAddress corespunzator masinii locale.
InetAddress getByName(String host) throws UnknownHostException
Returneaz
a un obiect InetAddress corespunzator masinii host, parametru
care poate fi specificat prin nume (de exemplu atlantis) sau prin adresa
IP (168.192.0.1).
InetAddress [ ]getAllByName(String host)
throws UnknownHostException
Returneaz
a un sir de obiecte InetAddress corespunzator fiecarei adrese IP
a masinii host.
Metodele clasei InetAddress
byte [ ] getAddress()
Returneaz
a sirul de octeti corespunzator obiectului InetAddress de referint
a.
String getHostName()
Returneaz
a numele masinii gazda.
String getHostAddress()
Returneaz
a adresa IP a masinii gazda.
boolean isMulticastAddress()
Returneaz
a true daca obiectul InetAddress reprezinta o adresa IP multicast (cuprins ntre 224.0.0.0 si 239.255.255.255).
Exemplul urm
ator afiseaza numele si adresa calculatorului gazda cat si acela
al calculatoarelor ale c
aror nume este transmis programului ca parametru.
Exemplul 2.1.1

27

2.1. DATAGRAME

import j a v a . n e t . ;

public c l a s s AdreseIP {
public s t a t i c void main ( S t r i n g a r g [ ] ) {
I n e t A d d r e s s a d r e s a=n u l l ;
try {
a d r e s a=I n e t A d d r e s s . g e t L o c a l H o s t ( ) ;
System . out . p r i n t l n ( C a l c u l a t o r u l gazda a r e : ) ;
System . out . p r i n t l n ( numele : +a d r e s a . getHostName ( ) ) ;
System . out . p r i n t l n ( a d r e s a IP : +a d r e s a . g e t H o s t A d d r e s s ( ) ) ;
}
catch ( UnknownHostException e ) {
System . out . p r i n t l n ( UnknownHostException : +e . g e t M e s s a g e ( ) ) ;
}
i f ( a r g . l e n g t h >0){
f o r ( i n t i =0; i <a r g . l e n g t h ; i ++){
try {
a d r e s a=I n e t A d d r e s s . getByName ( a r g [ i ] ) ;
System . out . p r i n t l n ( C a l c u l a t o r u l +a r g [ i ]+ a r e : ) ;
System . out . p r i n t l n ( a d r e s a IP \ getByName \ : +a d r e s a ) ;
byte [ ] b=a d r e s a . g e t A d d r e s s ( ) ;
f o r ( i n t j =0; j <b . l e n g t h ; j ++)
i f ( b [ j ] <0)
System . out . p r i n t (256+b [ j ]+ . ) ;
else
System . out . p r i n t ( b [ j ]+ . ) ;
System . out . p r i n t l n ( ) ;
}
catch ( UnknownHostException e ) {
System . out . p r i n t l n ( UnknownHostException : +
e . getMessage ( ) ) ;
}
}
}
}
}

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

2.1.1

Aplicatii client server cu datagrame.

Un pachet de tip DatagramPacket este alcatuit dintr-un sir de octeti. Este


datoria programatorului s
a transforme datele (mesajul) n siruri de octeti la expediere si la receptie.
Transformarea unui obiect serializabil ntr-un sir de octeti si invers se poate
realiza cu schema
Object

Object

ObjectInputStream

ByteArrayInputStream

input - DatagramPacket

ObjectOutputStream
ByteArrayOutputStream
output - DatagramPacket
?

6
6
6
6

28

ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II

Fie socket un obiect de tip DatagramSocket prin intermediul caruia se execut


a
expedierea / receptionarea pachetelor de tip DatagramPacket.
In principiu expedierea si transformarea obiectului obj ntr-un sir de octeti se
poate realiza cu secventa de cod
ByteArrayOutputStream baos=new ByteArrayOutputStream(256);
ObjectOutputStream out=new ObjectOutputStream(baos);
out.writeObject(obj);
byte[] bout=baos.toByteArray();
DatagramPacket packet=new DatagramPacket(bout,bout.length,
address,port);
socket.send(packet);
unde address si port sunt adresa si portul destinatarului. Daca packet este un
obiect DatagramPacket receptionat atunci metodele getAddress() si getPort()
furnizeaz
a adresa si portul expeditorului
Receptionarea si transformarea inversa este
byte[] bin=new byte[256];
packet=new DatagramPacket(bin,bin.length);
socket.receive(packet);
ByteArrayInputStream bais=new ByteArrayInputStream(bin);
ObjectInputStream in=new ObjectInputStream(bais);
obj=in.readObject();
Dac
a mesajul este un obiect String atunci el se transforma ntr-un sir de
octeti cu metoda byte[] String.getByte() si invers, el se obtine prin new
String(bin) sau new String(packet.getData()).
Exemplul 2.1.2 Program
am serviciul calculului celui mai mare divizor comun
a dou
a numere.
In vederea transportului definim clasa
1
2
4
5
6
7
8
9
10

package s e r v e r ;
import j a v a . i o . ;
public c l a s s P r o t o c o l implements S e r i a l i z a b l e {
long x , y ;
P r o t o c o l ( long x , long y ) {
t h i s . x=x ;
t h i s . y=y ;
}
}

2.1. DATAGRAME

29

Clientul va trimite un obiect Protocol, care va contine datele problemei si va


receptiona un obiect de acelasi tip cu rezultatul (cel mai mare divizor comun) n
primul c
amp al obiectului. Aceasta clasa este disponibila atat serverului cat si
clientului.
Se va utiliza arhitectura de aplicatie dezvoltata n finalul sectiunii anterioare.
Aplicatia se va compune din:
Aplicatia server alc
atuit
a din:
Interfat
a
1
2
3
4
5
6

package i s e r v e r ;
import j a v a . n e t . DatagramSocket ;
public i n t e r f a c e IMyMServer {
public DatagramSocket getDatagramSocket ( i n t p o r t ) ;
public void myAction ( DatagramSocket datagramSocket ) ;
}

Implementarea interfetei

package s e r v e r . impl ;
import s e r v e r . ;
import i s e r v e r . IMyMServer ;
import j a v a . n e t . ;
import j a v a . i o . ;
import j a v a . u t i l . c o n c u r r e n t . ;

public c l a s s MyMServer implements IMyMServer {

1
2
3
4
5

public DatagramSocket getDatagramSocket ( i n t p o r t ) {


DatagramSocket datagramSocket = n u l l ;
try {
datagramSocket = new DatagramSocket ( 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 ( DatagramSocket i s r e a d y . . . ) ;
return datagramSocket ;
}

10
11
12
13
14
15
16
17
18
19
20
21
22

public void myAction ( DatagramSocket datagramSocket ) {


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) ;
while ( true ) {
try {
AppThread o b j=new AppThread ( datagramSocket ) ;
exec . execute ( obj ) ;
}
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 ( ) ) ;
}
}
}

24
25
26
27
28
29
30
31
32
33
34
35
36
37

30

ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II

Clasa AppThread
1
2
3
5
6

package s e r v e r ;
import j a v a . n e t . ;
import j a v a . i o . ;
public c l a s s AppThread extends Thread {
DatagramSocket s o c k e t=n u l l ;
public AppThread ( DatagramSocket s o c k e t ) {
t h i s . s o c k e t=s o c k e t ;
}

8
9
10

public void run ( ) {


DatagramPacket p a c k e t=n u l l ;
App app=new App ( ) ;
P r o t o c o l p=n u l l ;
try {
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 ( ) ;
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 ( ) ;
I n e t A d d r e s s a d d r e s s=p a c k e t . g e t A d d r e s s ( ) ;
i n t p o r t=p a c k e t . g e t P o r t ( ) ;
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 o c k e t . send ( p a c k e 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 ( ) ) ;
}
}

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

Clas
a de lansare a serverului
1
2
3
4
6
7
8
9
10
11
12
13
14
15

package s e r v e r ;
import j a v a . n e t . DatagramSocket ;
import s e r v e r . impl . MyMServer ;
import i s e r v e r . IMyMServer ;
public c l a s s AppServer {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
i n t p o r t =7999;
i f ( a r g s . l e n g t h >0)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 0 ] ) ;
IMyMServer myMServer=new MyMServer ( ) ;
DatagramSocket datagramSocket=myMServer . getDatagramSocket ( p o r t ) ;
myMServer . myAction ( datagramSocket ) ;
}
}

2.1. DATAGRAME

31

Aplicatia client
1
2
3
4
5

package c l i e n t ;
import j a v a . n e t . ;
import j a v a . i o . ;
import s e r v e r . P r o t o c o l ;
import j a v a . u t i l . S c a n n e r ;

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

2.1.2

public c l a s s CmmdcClient {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
S t r i n g h o s t S e r v e r= l o c a l h o s t ;
i n t p o r t S e r v e r =7999;
i f ( a r g s . l e n g t h >0)
h o s t S e r v e r=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t S e r v e r=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
try {
DatagramSocket s o c k e t=new DatagramSocket ( ) ;
P r o t o c o l p=new P r o t o c o l ( 0 , 0 ) ;
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( I n t r o d u c e t i p r i m u l numar : ) ;
p . x=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( I n t r o d u c e t i a l d o i l e a numar : ) ;
p . y=s c a n n e r . nextLong ( ) ;
ByteArrayOutputStream baos=new ByteArrayOutputStream ( 2 5 6 ) ;
ObjectOutputStream out=new ObjectOutputStream ( baos ) ;
out . w r i t e O b j e c t ( p ) ;
byte [ ] bout=baos . toByteArray ( ) ;
I n e t A d d r e s s a d d r e s s=I n e t A d d r e s s . getByName ( h o s t S e r v e r ) ;
DatagramPacket p a c k e t =
new DatagramPacket ( bout , bout . l e n g t h , a d d r e s s , p o r t S e r v e r ) ;
s o c k e t . send ( p a c k e t ) ;
byte [ ] b i n=new byte [ 4 0 4 8 ] ;
p a c k e t=new DatagramPacket ( bin , b i n . l e n g t h ) ;
socket . r e c e i v e ( packet ) ;
ByteArrayInputStream b a i s=new ByteArrayInputStream ( b i n ) ;
O b j e c t I n p u t S t r e a m i n=new O b j e c t I n p u t S t r e a m ( b a i s ) ;
p=( P r o t o c o l ) i n . r e a d O b j e c t ( ) ;
System . out . p r i n t l n ( Cmmdc = +p . x ) ;
socket . close ( ) ;
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}
}
}

Multicast vs. Broadcast

Clasa java.net.MulticastSocket
Prin intermediul unui soclu de tip MulticastSocket se pot receptiona datagrame expediate de un server c
atre toti clientii cu un asemenea soclu.
Constructori
MulticastSocket(int port) throws SocketException

32

ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II

Metode
void joinGroup(InetAddress adres
a ) throws SocketException
Soclul se conecteaza la grupul definit de adresa IP (de tip D, adica cuprins
ntre 224.0.0.0 si 239.255.255.255).
void leaveGroup(InetAddress adres
a ) throws SocketException
Soclul se deconecteaza la grupul definit de adresa IP.
void close()
Preg
atirea clientului n vederea receptionarii datagramelor printr-un soclu de
tip MulticastSocket consta din
MulticastSocket socket= new MulticastSocket(port);
InetAddress adresa=InetAddress.getByName("230.0.0.1");
socket.joinGroup(adresa);
In final, clientul se deconecteaza si nchide soclul.
socket.leaveGroup(adresa);
socket.close();
Pachetele trimise de programul server trebuie sa se adreseze grupului, identificat prin adresa IP de tip D.
Astfel prin multicast serverul trimite pachete la o adresa de grup si la un
port fixat. Pachetele emise de server sunt receptionate de orice client ce creaz
a
un soclu de tip MulticastSocket pentru portul la care emite serverul si care se
al
atur
a grupului.
Prin broadcast serverul emite datagrame catre orice calculator al retelei locale
la un anumit port. Faptul ca emiterea datagramelor este de tip broadcast se indic
a
prin
DatagramSocket.setBroadcast(true)
Orice client care si creaza un soclu la portul la care emite serverul receptioneaz
a
datagramele trimise de server. Adresa utilizata de server la crearea datagramelor
trebuie s
a identifice reteaua.
Observatie. In cazul unui calculator izolat este nevoie de instalarea driverului Microsoft Loopback Adapter, care simuleaza existenta unei placi de retea active.
Exemplul 2.1.3 Multicast
si Broadcast: programele server emit din cinci n
cinci secunde ora exact
a. Un client va receptiona c
ate cinci datagrame.
Codurile sunt date n Fig. 2.1 si Fig. 2.2, respectiv pentru partea de server
si cea de client.

33

2.1. DATAGRAME

MulticastServer
import java.io.*;
import java.net.*;
import java.util.*;
import java.text.DateFormat;

BroadcastServer
import java.io.*;
import java.net.*;
import java.util.*;
import java.text.DateFormat;

public class MulticastServer{


public static void main(String[] args){
long FIVE_SECONDS = 5000;
boolean sfarsit=false;
DatagramSocket socket = null;
int serverPort=7000;
int clientPort=7001;
byte[] buf = new byte[256];
Date data=null;
DatagramPacket packet = null;
try{
socket=new DatagramSocket(serverPort);
}
catch(SocketException e){
System.out.println(e.getMessage());
}
while (! sfarsit){
try{
data=new Date();
String df=DateFormat.
getTimeInstance().format(data);
buf = df.getBytes();
// send it
InetAddress group =
InetAddress.getByName("230.0.0.1");
packet=new DatagramPacket(buf,
buf.length,group,clientPort);

public class BroadcastServer{


public static void main(String[] args){
long FIVE_SECONDS = 5000;
boolean sfarsit=false;
DatagramSocket socket = null;
int serverPort=7000;
int clientPort=7001;
byte[] buf = new byte[256];
Date data = null;
DatagramPacket packet = null;
try{
socket=new DatagramSocket(serverPort);
}
catch(SocketException e){
System.out.println(e.getMessage());
}
while (! sfarsit) {
try{
data=new Date();
String df=DateFormat.
getTimeInstance().format(data);
buf = df.getBytes();

socket.send(packet);
// sleep for a while
Thread.sleep(FIVE_SECONDS);
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
socket.close();
}
}

InetAddress group =
InetAddress.getByName("192.168.0.255");
packet=new DatagramPacket(buf,
buf.length,group,clientPort);
socket.setBroadcast(true);
socket.send(packet);
Thread.sleep(FIVE_SECONDS);
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
socket.close();
}
}

Table 2.1: Clasele server.

34

ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II

MulticastClient
import java.io.*;
import java.net.*;

BroadcastClient
import java.io.*;
import java.net.*;

public class MulticastClient {

public class BroadcastClient {

public static void main(String[] args)


throws IOException {
DatagramPacket packet;
byte[] buf = new byte[256];
int clientPort=7001;
MulticastSocket socket=
new MulticastSocket(clientPort);
InetAddress address=
InetAddress.getByName("230.0.0.1");
socket.joinGroup(address);
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.leaveGroup(address);
socket.close();
}
}

public static void main(String[] args)


throws IOException {
DatagramPacket packet;
byte[] buf = new byte[256];
int clientPort=7001;
DatagramSocket socket=
new DatagramSocket(clientPort);

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();
}
}

Table 2.2: Clasele client.

2.2. CANALE DE COMUNICAT


IE

2.2

35

Canale de comunicatie

Odat
a cu versiunea j2sdk1.4 apar clase noi pentru operatii de intrare - iesire
n pachetele java.nio si java.nio.channels. Pachetul java.nio.channels
contine clase pentru comunicatia n retea, si anume canalele de comunicatie.
Utiliz
am clasele java.nio.channels.SocketChannel, java.nio.channel.
DatagramChannel. Informatia transportata n aceste canale de comunicatie trebuie nglobat
a n obiecte container de tip Buffer.

Clasa java.nio.Buffer
Ierarhia claselor Buffer
abstract Buffer
ByteBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
CharBuffer
Un obiect de tip typeBuffer este un tampon (container) care contine date
de tipul specificat de denumirea clasei.
Un obiect de tip Buffer este caracterizat de
capacitate (capacity) num
arul elementelor care pot fi nmagazitate n tampon;
limit
a (limit) marginea superiora a indicelui;
indice (position) valoarea curenta a indicelui, ce corespunde unui cursor
ce indic
a nceputul zonei unde se introduc sau de unde se extrag date din
tampon.
Metode generale
clear() permite unui obiect de tip Buffer sa fie rencarcat. Fixeaza limita =
capacitate si indice = 0.
flip() preg
ateste obiectul de tip Buffer pentru consultare (citire). Fixeaza
limita =num
arul elementelor din tampon si indice = 0.
rewind() preg
ateste obiectul de tip Buffer pentru re-citire.

36

ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II

Clasa java.nio.ByteBuffer
Instantierea unui obiect se obtine prin metoda statica
static ByteBuffer allocate(capacitate)
Introducerea si extragerea datelor din tampon se poate face n mod
relativ - implic
a modificarea indicelui tamponului;
absolut - far
a modificarea indicelui.
Metode
Introducerea datelor n mod relativ:
ByteBuffer put(byte b)
ByteBuffer putTip(tip x )
Extragerea datelor n mod relativ:
byte get()
tip getTip()
Introducerea datelor n mod absolut:
ByteBuffer put(int index ,byte b)
ByteBuffer putTip(int index ,tip x )
Extragerea datelor n mod absolut:
byte get(int index )
tip getTip(int index )
unde tip poate fi char, short, int, long, float, double.
Alte metode
public final boolean hasRemaining()
Dac
a indicele nu este egal cu limita atunci returneaza true, semnaland
existenta n tampon a unor octeti.
static ByteBuffer wrap(byte[] array)
public static ByteBuffer wrap(byte[] array,int offset,int length)
Converteste sirul de octeti ntr-un obiect Bytebuffer.

2.2. CANALE DE COMUNICAT


IE

37

public final byte[] array()


Transformarea invers
a, 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();

Clasa java.net.InetSocketAddress
Clasa InetSocketAddress extinde clasa SocketAddress si ncapsuleaza adresa
unui calculator din Internet mpreuna cu un port n vederea leg
arii la un ServerSocket.
Constructori:
InetSocketAddress(InetAddress addr ,int port)
InetSocketAddress(String numeCalculator ,int port)
InetSocketAddress(int port)

Clasa java.nio.channels.ServerSocketChannel
Crearea unui obiect de tip ServerSocketChannel se realizeaza prin
static ServerSocketChannel open() throws IOException
Unui asemenea obiect i se asociaza un ServerSocket prin metoda
ServerSocket socket() throws IOException.
Obiectul de tip ServerSocket trebuie leagat la un port de comunicatie prin
metoda
void bind(InetSocketAddress endpoint) throws IOException.
Sablonul de utilizare este
try{
ServerSocketChannel ssc=ServerSocketChannel.open();
ServerSocket ss=ssc.socket();
InetSocketAddress isa=new InetSocketAddress(addr,port);
ss.bind(isa);
}
catch(Exception e){. . .}
La apelul unui client, serverul trebuie sa genereze un obiect de tip Socket
Channel prin care se vor derula comunicatiile cu clientul. Acest canal de comunicatie
se obtine cu metoda accept().

38

ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II

Clasa java.nio.channels.SocketChannel
Crearea unui obiect de tip SocketChannel se realizeaza prin
static SocketChannel open() throws IOException
Acest obiect trebuie conectat la obiectul ServerSocketChannel al serverului cu
metoda connect(InetSocketAddress addr ).
Datele vehiculate printr-un SocketChannel sunt de tip ByteBuffer. Datele
se transmit prin metoda
int write(ByteBuffer surs
a)
si se receptioneaz
a prin metoda
int read(ByteBuffer destinatie)
Valoarea returnat
a de cele doua metode reprezinta numarul octetilor trimisi
/ receptionati.
Doar octetii unui obiect de tip ByteBuffer cuprinsi ntre indice si limita sunt
transmisi prin canal. Astfel, dupa ncarcarea unui obiectului ByteBuffer cu
metode relative trebuie apelata metoda flip().
Canalul se nchide cu metoda close().
Exemplul 2.2.1 Calculul celui mai mare divizor comun a dou
a numere naturale.
Aplicatie client-server bazat pe canale de comunicatie prin socluri se compune
din:
Aplicatia server alcatuita din:
Interfat
a
1
2
3
4
5
6

package i s e r v e r ;
import j a v a . n i o . c h a n n e l s . S e r v e r S o c k e t C h a n n e l ;
public i n t e r f a c e IMyMServer {
public S e r v e r S o c k e t C h a n n e l g e t S e r v e r S o c k e t C h a n n e l ( i n t p o r t ) ;
public void myAction ( S e r v e r S o c k e t C h a n n e l s e r v e r S o c k e t C h a n n e l ) ;
}

Implementarea interfetei

package s e r v e r . impl ;
import s e r v e r . ;
import i s e r v e r . IMyMServer ;
import j a v a . n e t . ;
import j a v a . n i o . ;
import j a v a . n i o . c h a n n e l s . S e r v e r S o c k e t C h a n n e l ;
import j a v a . u t i l . c o n c u r r e n t . ;
import j a v a . i o . IOException ;

10

public c l a s s MyMServer implements IMyMServer {

1
2
3
4
5
6
7

2.2. CANALE DE COMUNICAT


IE

public S e r v e r S o c k e t C h a n n e l g e t S e r v e r S o c k e t C h a n n e l ( i n t p o r t ) {
S e r v e r S o c k e t C h a n n e l s e r v e r S o c k e t C h a n n e l=n u l l ;
try {
s e r v e r S o c k e t C h a n n e l = S e r v e r S o c k e t C h a n n e l . open ( ) ;
I n e t S o c k e t A d d r e s s i s a=new I n e t S o c k e t A d d r e s s ( p o r t ) ;
S e r v e r S o c k e t s s=s e r v e r S o c k e t C h a n n e l . s o c k e t ( ) ;
s s . bind ( i s a ) ;
}
catch ( IOException e ) {
System . out . p r i n t l n ( S e r v e r S o c k e t C h a n n e l E r r o r : +
e . getMessage ( ) ) ;
System . e x i t ( 0 ) ;
}
System . out . p r i n t l n ( S e r v e r r e a d y . . . ) ;
return s e r v e r S o c k e t C h a n n e l ;
}

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

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;
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 {
AppThread o b j=new AppThread ( s e r v e r S o c k e t C h a n n e l . a c c e p t ( ) ) ;
exec . execute ( obj ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( MyActionException : +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

Clasa AppThread
1
2
3
4
5
7
8
10
11
12
14
15
16
17
18
19
20
21
22
23
24

39

package s e r v e r ;
import j a v a . n e t . ;
import j a v a . i o . ;
import j a v a . n i o . c h a n n e l s . S o c k e t C h a n n e l ;
import j a v a . n i o . ;
public c l a s s AppThread extends Thread {
S o c k e t C h a n n e l s o c k e t C h a n n e l=n u l l ;
public AppThread ( S o c k e t C h a n n e l s o c k e t C h a n n e l ) {
t h i s . s o c k e t C h a n n e l=s o c k e t C h a n n e l ;
}
public void run ( ) {
try {
B y t e B u f f e r bb = B y t e B u f f e r . a l l o c a t e ( 1 6 ) ;
// L o n g B u f f e r l b = bb . a s L o n g B u f f e r ( ) ;
s o c k e t C h a n n e l . r e a d ( bb ) ;
// V a r i a n t a 1
long m=bb . getLong ( 0 ) ;
long n=bb . getLong ( 8 ) ;
// V a r i a n t a 2
// l o n g m=l b . g e t ( 0 ) ;
// l o n g n=l b . g e t ( 1 ) ;

40

ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II

App app=new App ( ) ;


long r=app . cmmdc(m, n ) ;
bb . c l e a r ( ) ;
// V a r i a n t a 1
bb . putLong ( 0 , r ) ;
// V a r i a n t a 2
// l b . p u t ( r ) ;
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 ( ) ;

25
26
27
28
29
30
31
32
33

}
catch ( IOException e ) {
System . e r r . p r i n t l n ( S e r v e r c o m u n i c a t i o n e r r o r : +
e . getMessage ( ) ) ;
}

34
35
36
37
38

39
40

Clas
a de lansare a serverului
1
2
3
4
6
7
8
9
10
11
12
13
14
15
16

package s e r v e r ;
import j a v a . n i o . c h a n n e l s . S e r v e r S o c k e t C h a n n e l ;
import s e r v e r . impl . MyMServer ;
import i s e r v e r . IMyMServer ;
public c l a s s AppServer {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
i n t p o r t =7999;
i f ( a r g s . l e n g t h >0)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 0 ] ) ;
IMyMServer myMServer=new MyMServer ( ) ;
ServerSocketChannel serverSocketChannel =
myMServer . g e t S e r v e r S o c k e t C h a n n e l ( p o r t ) ;
myMServer . myAction ( s e r v e r S o c k e t C h a n n e l ) ;
}
}

Aplicatia client
1
2
3
4
5
6
8
9
10
11
12
13
14
15
16
17
18
19
20

package c l i e n t ;
import j a v a . i o . ;
import j a v a . n e t . ;
import j a v a . n i o . ;
import j a v a . n i o . c h a n n e l s . ;
import j a v a . u t i l . S c a n n e r ;
public c l a s s CmmdcClient {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
S t r i n g h o s t= l o c a l h o s t ;
i n t p o r t =7999;
i f ( a r g s . l e n g t h >0)
h o s t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
S o c k e t C h a n n e l s c=n u l l ;
try {
I n e t S o c k e t A d d r e s s i s a=new I n e t S o c k e t A d d r e s s ( ho st , p o r t ) ;
s c=S o c k e t C h a n n e l . open ( ) ;
sc . connect ( i s a ) ;

2.2. CANALE DE COMUNICAT


IE

}
catch ( UnknownHostException e ) {
System . e r r . p r i n t l n ( S e r v e r n e c u n o s c u t : +h o s t+ +e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 1 ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( C o n e c t a r e i m p o s i b i l a l a : +
h o s t+ pe p o r t u l +p o r t+ +e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 1 ) ;
}
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
long m, n , r ;
System . out . p r i n t l n ( m= ) ;
m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
n=s c a n n e r . nextLong ( ) ;

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

B y t e B u f f e r bb=B y t e B u f f e r . a l l o c a t e ( 1 6 ) ;
// V a r i a n t a 1
bb . putLong ( 0 ,m) . putLong ( 8 , n ) ;
// V a r i a n t a 2
// L o n g B u f f e r l b=bb . a s L o n g B u f f e r ( ) ;
// l b . p u t ( 0 ,m) . p u t ( 1 , n ) ;
try {
s c . w r i t e ( bb ) ;
bb . c l e a r ( ) ;
s c . r e a d ( bb ) ;
// V a r i a n t a 1
r=bb . getLong ( 0 ) ;
// V a r i a n t a 2
// r=l b . g e t ( 0 ) ;
System . out . p r i n t l n ( Cmmdc : +r ) ;
sc . clos e ( ) ;
}
catch ( E x c e p t i o n e ) {
System . e r r . p r i n t l n ( E r o a r e de c o m u n i c a t i e +e . g e t M e s s a g e ( ) ) ;
}

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

58
59

41

Varianta comentat
a corespunde cazului n care se utilizeara clasa acoperitoare
LongBuffer.

Clasa java.nio.channels.DatagramChannel
Sablonul de programare pentru instantierea unui obiect de tip DatagramChannel
este
DatagramChannel dc=null;
InetSocketAddress isa=new InetSocketAddress(port);
try{
dc=DatagramChannel.open();
DatagramSocket datagramSocket=dc.socket();
datagramSocket.bind(isa);

42

ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II

}
catch(Exception e){. . .}
unde port este portul folosit de DatagramChannel. Daca port=0 atunci se alege
aleator un port disponibil.
Transmiterea unui obiect ByteBuffer se face cu metoda
public int send(ByteBuffer src, SocketAddress target) throws
IOException
Metoda returneaz
a numarul de octeti expediati. Receptia unui ByteBuffer se
obtine cu metoda
public SocketAddress receive(ByteBuffer dst) throws IOException
Obiectul returnat reprezinta adresa expeditorului.
Exemplul 2.2.2 Calculul celui mai mare divizor comun a dou
a numere naturale.
Aplicatia server este alcatuita din:
Interfat
a
1
2
3
4
5
6

package i s e r v e r ;
import j a v a . n i o . c h a n n e l s . DatagramChannel ;
public i n t e r f a c e IMyMServer {
public DatagramChannel getDatagramChannel ( i n t p o r t ) ;
public void myAction ( DatagramChannel datagramChannel ) ;
}

Implementarea interfetei
1
2
3
4
5
6
7
8
10
12
13
14
15
16
17
18
19
20
21
22

package s e r v e r . impl ;
import s e r v e r . ;
import i s e r v e r . IMyMServer ;
import j a v a . n e t . ;
import j a v a . n i o . ;
import j a v a . n i o . c h a n n e l s . DatagramChannel ;
import j a v a . u t i l . c o n c u r r e n t . ;
import j a v a . i o . IOException ;
public c l a s s MyMServer implements IMyMServer {
public DatagramChannel getDatagramChannel ( i n t p o r t ) {
DatagramChannel datagramChannel=n u l l ;
I n e t S o c k e t A d d r e s s i s a=new I n e t S o c k e t A d d r e s s ( p o r t ) ;
try {
datagramChannel = DatagramChannel . open ( ) ;
DatagramSocket datagramSocket=datagramChannel . s o c k e t ( ) ;
datagramSocket . bind ( i s a ) ;
}
catch ( IOException e ) {
System . out . p r i n t l n ( DatagramChannelError : +e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 0 ) ;

2.2. CANALE DE COMUNICAT


IE

43

}
System . out . p r i n t l n ( S e r v e r r e a d y . . . ) ;
return datagramChannel ;

23
24
25
26

28

public void myAction ( DatagramChannel datagramChannel ) {


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) ;
while ( true ) {
try {
AppThread o b j=new AppThread ( datagramChannel ) ;
exec . execute ( obj ) ;
}
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 ( ) ) ;
}
}
}

29
30
31
32
33
34
35
36
37
38
39
40
41

Clasa AppThread
1
2
3
4
5
7
8
10
11
12
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

package s e r v e r ;
import j a v a . n e t . S o c k e t A d d r e s s ;
import j a v a . i o . IOException ;
import j a v a . n i o . c h a n n e l s . DatagramChannel ;
import j a v a . n i o . ;
public c l a s s AppThread extends Thread {
DatagramChannel datagramChannel=n u l l ;
public AppThread ( DatagramChannel datagramChannel ) {
t h i s . datagramChannel=datagramChannel ;
}
public void run ( ) {
App app=new App ( ) ;
try {
B y t e B u f f e r bb = B y t e B u f f e r . a l l o c a t e ( 1 6 ) ;
// L o n g B u f f e r l b = bb . a s L o n g B u f f e r ( ) ;
S o c k e t A d d r e s s s a=datagramChannel . r e c e i v e ( bb ) ;
// V a r i a n t a 1
long m=bb . getLong ( 0 ) ;
long n=bb . getLong ( 8 ) ;
// V a r i a n t a 2
// l o n g m=l b . g e t ( 0 ) ;
// l o n g n=l b . g e t ( 1 ) ;
long r=app . cmmdc(m, n ) ;
bb . c l e a r ( ) ;
// V a r i a n t a 1
bb . putLong ( 0 , r ) ;
// V a r i a n t a 2
// l b . p u t ( r ) ;
datagramChannel . send ( bb , s a ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( S e r v e r c o m u n i c a t i o n e r r o r : +
e . getMessage ( ) ) ;
}

44

ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II

38
39

Clas
a de lansare a serverului
1
2
3
4
6
7
8
9
10
11
12
13
14
15
16

package s e r v e r ;
import j a v a . n i o . c h a n n e l s . DatagramChannel ;
import s e r v e r . impl . MyMServer ;
import i s e r v e r . IMyMServer ;
public c l a s s AppServer {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
i n t p o r t =7999;
i f ( a r g s . l e n g t h >0)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 0 ] ) ;
IMyMServer myMServer=new MyMServer ( ) ;
DatagramChannel datagramChannel =
myMServer . getDatagramChannel ( p o r t ) ;
myMServer . myAction ( datagramChannel ) ;
}
}

Aplicatia client
1
2
3
4
5
6
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

package c l i e n t ;
import j a v a . i o . ;
import j a v a . n e t . ;
import j a v a . n i o . ;
import j a v a . n i o . c h a n n e l s . ;
import j a v a . u t i l . S c a n n e r ;
public c l a s s CmmdcClient {
public s t a t i c void main ( S t r i n g [ ] a r g s ) throws IOException {
S t r i n g s e r v e r H o s t= l o c a l h o s t ;
i n t p o r t =7999;
i f ( a r g s . l e n g t h >0)
s e r v e r H o s t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
I n e t S o c k e t A d d r e s s s e r v e r=null , i s a=n u l l ;
try {
s e r v e r=
new I n e t S o c k e t A d d r e s s ( I n e t A d d r e s s . getByName ( s e r v e r H o s t ) , p o r t ) ;
}
catch ( UnknownHostException e ) {
System . out . p r i n t l n ( Unknown h o s t : +e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 1 ) ;
}
i s a=new I n e t S o c k e t A d d r e s s ( 0 ) ;
DatagramChannel dc=n u l l ;
try {
dc=DatagramChannel . open ( ) ;
DatagramSocket s o c k e t = dc . s o c k e t ( ) ;
s o c k e t . bind ( i s a ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( Couldn t open t h e DatagramChannel +
e . getMessage ( ) ) ;

2.2. CANALE DE COMUNICAT


IE

System . e x i t ( 1 ) ;
}
long m, n , r ;
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( m= ) ;
m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
n=s c a n n e r . nextLong ( ) ;
B y t e B u f f e r bb=B y t e B u f f e r . a l l o c a t e ( 1 6 ) ;
// V a r i a n t a 1
bb . putLong ( 0 ,m) . putLong ( 8 , n ) ;
// V a r i a n t a 2
// L o n g B u f f e r l b=bb . a s L o n g B u f f e r ( ) ;
// l b . p u t ( 0 ,m) . p u t ( 1 , n ) ;
try {
dc . send ( bb , s e r v e r ) ;
bb . c l e a r ( ) ;
dc . r e c e i v e ( bb ) ;
// V a r i a n t a 1
r=bb . getLong ( 0 ) ;
// V a r i a n t a 2
// r=l b . g e t ( 0 ) ;
System . out . p r i n t l n ( Cmmdc = +r ) ;
}
catch ( E x c e p t i o n e ) {
System . e r r . p r i n t l n ( C l i e n t e r r o r : +e . g e t M e s s a g e ( ) ) ;
}
finally {
i f ( dc != n u l l ) dc . d i s c o n n e c t ( ) ;
}

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

65
66

Test de evaluare a cunostintelor


1. Precizati termenul multicast.
2. In ce const
a participarea serverului la transmisie multicast ?
3. In ce const
a participarea unui client la receptia multicast ?
4. Precizati termenul broadcast.
5. In ce const
a participarea serverului la transmisie broadcast ?

45

46

ARE 2. DATAGRAME S
UNITATEA DE INVAT
I CANALE DE COMUNICAT
II

6. In ce const
a participarea unui client la receptia broadcast ?
7. Care este rolul unui obiect de tip DatagramPacket ?
8. Precizati metodele clasei DatagramSocket utilizate la expedierea si la receptia
unui datagram.
9. Ce parametri caracterizeaza un obiect de tip Buffer ?
10. Ce asem
anare exista ntre comunicatia bazata de datagrame si cea prin
intermediul canalelor ?

Unitatea de nv
atare 3

Reg
asirea obiectelor prin
servicii de nume

Durata: 2 ore.

Introducere
Oric
arui obiect i sunt asociate un nume si o referinta. Regasirea / cautarea
obiectului se face pornind de la numele obiectului, prin referinta se ajunge la
obiect.
Exemple date prin sablonul (Nume Referinta Obiect)
1. Accesul la o carte ntr-o biblioteca:
Titlul c
artii Referint
a c
artii din biblioteca Carte
2. Contactul telefonic cu o persoana:
47

48

ARE 3. REGASIREA

UNITATEA DE INVAT
OBIECTELOR PRIN SERVICII DE NUME

Nume persoan
a Numar telefon Persoana
Un serviciu de nume contine asocieri dintre nume de obiecte si obiecte si poate
oferi facilit
ati de reg
asire a obiectelor.

3.1

Java Naming and Directory Interface

Java Naming and Directory Interface - JNDI este o interfata de programare


(Application Programming Interface - API ) care descrie functionalitatea unui
serviciu de nume.
Cuv
antul servici este utilizat n sens comun, entitate care pune la dispozitie
facilit
ati de folosire.
Al
aturi de interfata JNDI, arhitectura JNDI mai contine interfata Service
Provider Interface - SPI. Implementarea interfetei SPI de un furnizor de servicii
JNDI are ca efect independenta programului Java de furnizorul de servicii JNDI.
JNDI este implementat de serviciile de nume:
Filesystem are ca obiect asocierea dintre numele de fisier sau catalog cu
obiectul corespunzator.
DNS - Domain Name System are ca obiect asocierea dintre adresa Internet
cu adresa IP.
RMI registry utilizat n aplicatii RMI, din Java. Are ca obiect asocierea
ntre un nume de serviciu de invocare ale obiectelor la distanta cu un delegat
al serviciului (stub).
COS - Common Object Service Naming utilizat n aplicatii CORBA. Are
ca obiect asocierea ntre numele unui serviciu de invocare ale obiectelor la
distant
a cu referinta la serviciu.
LDAP - Lightweight Directory Access Protocol defineste un protocol pentru
accesarea datelor retinute ntr-un catalog LDAP (LDAP directory, information directory). Un catalog LDAP permite retinerea si regasirea referintelor
obiectelor definite pe un calculator.

Interfata javax.naming.Context
Printr-un context se va ntelege o multime de asocieri nume - obiect. Corespunz
ator unui context, JNDI defineste interfata Context, cu metodele
void bind(String nume,Object object)
void rebind(String nume,Object object)

3.1. JAVA NAMING AND DIRECTORY INTERFACE

49

void unbind(String nume)


Object lookup(String nume)
NamingEnumeration list(String nume)
Returneaz
a lista cu nume obiectelor mpreuna cu tipul lor.
NamingEnumeration listBindings(String nume)
Returneaz
a lista cu nume obiectelor mpreuna cu tipul si locatia acestora.
Specificatiile JNDI prev
ad definirea unui context initial, implementat prin
clasa javax.naming.InitialContext, clasa ce implementeaza interfata Context.
Constructori.
public InitialContext() throws NamingException
public void InitialContext(Hashtable<?,?> environment)throws
NamingException
Pentru crearea contextului initial trebuie specificata clasa care creaza contextul initial prin parametrul java.naming.factory.initial sau constanta
Context.INITIAL CONTEXT FACTORY.
Acest parametru se poate da n mai multe moduri:
Includerea n obiectul Hashtable care apare n constructorul clasei InitalContext.
Hashtable env=new Hashtable()
env.put("java.naming.factory.initial",...);
Context ctx=InitialContext(env);
sau
Hashtable env=new Hashtable()
env.put(Context.INITIAL_CONTEXT_FACTORY,...);
Context ctx=new InitialContext(env);
Ca parametru de sistem furnizat la lansarea programului Java, prin
java -Djava.naming.factory.initial=... ClasaJava
Parametrul se poate da n interiorul programului prin
System.setProperty("java.naming.factory.initial",...);

50

ARE 3. REGASIREA

UNITATEA DE INVAT
OBIECTELOR PRIN SERVICII DE NUME

sau
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,...);
Atribut n fisierul de proprietati jndi.properties.
In aceste ultime doua cazuri, contextul initial se creaza prin
Context ctx=new InitialContext();
Functie de serviciul de nume, clasa care creaza contextul initial este dat n
tabelul
Serviciul de nume
Filesystem
COS
RMI
DNS
LDAP

Clasa
com.sun.jndi.fscontext.RefFSContextFactory
com.sun.jndi.cosnaming.CNCtxFactory
com.sun.jndi.rmi.registry.RegistryContextFactory
com.sun.jndi.dns.DnsContextFactory
com.sun.jndi.ldap.LdapCtxFactory

Exemplul 3.1.1 Utiliz


and serviciul JNDI Filesystem se creaz
a un context prin
intermediul c
areia se afiseaz
a continutul unui catalog indicat de client.
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

import
import
import
import

j a v a x . naming . ;
java . io . F i l e ;
java . u t i l . Hashtable ;
java . u t i l . Scanner ;

c l a s s Lookup {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
Context c t x=n u l l ;
/
// V a r i a n t a 1
H a s h t a b l e env = new H a s h t a b l e ( 1 1 ) ;
env . p u t ( C o n t e x t . INITIAL CONTEXT FACTORY,
com . sun . j n d i . f s c o n t e x t . RefFSContextFactory ) ;
try {
c t x = new I n i t i a l C o n t e x t ( env ) ;
}
c a t c h ( NamingException e ) {
System . o u t . p r i n t l n ( I n i t i a l C o n t e x t E r r o r : +e . g e t M e s s a g e ( ) ) ;
}
/
/
// V a r i a n t a 2
System . s e t P r o p e r t y ( j a v a . naming . f a c t o r y . i n i t i a l ,
com . sun . j n d i . f s c o n t e x t . RefFSContextFactory ) ;
try {
c t x = new I n i t i a l C o n t e x t ( ) ;
}
c a t c h ( NamingException e ) {

3.1. JAVA NAMING AND DIRECTORY INTERFACE

System . o u t . p r i n t l n ( I n i t i a l C o n t e x t E r r o r : +e . g e t M e s s a g e ( ) ) ;

29

}
/

30
31

// V a r i a n t a 3
try {
c t x = new I n i t i a l C o n t e x t ( ) ;
}
catch ( NamingException e ) {
System . out . p r i n t l n ( I n i t i a l C o n t e x t E r r o r : +e . g e t M e s s a g e ( ) ) ;
}

33
34
35
36
37
38
39

S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( I n t r o d u c e t i r e f e r i n t a a b s o l u t a a unui c a t a l o g : ) ;
S t r i n g myName=s c a n n e r . n e x t ( ) ;
try {
System . out . p r i n t l n ( \n c t x . l o o k u p ( +myName+ ) p r o d u c e ) ;
System . out . p r i n t l n ( c t x . l o o k u p (myName ) ) ;

41
42
43
44
45
46

System . out . p r i n t l n ( \ n C o n t i n u t u l c a t a l o g u l u i +myName+ e s t e : \ n ) ;


NamingEnumeration l s t =c t x . l i s t (myName ) ;
while ( l s t . hasMore ( ) ) {
NameClassPair nc = ( NameClassPair ) l s t . n e x t ( ) ;
System . out . p r i n t l n ( nc ) ;
}

48
49
50
51
52
53

System . out . p r i n t l n ( \ n C o n t i n u t u l c a t a l o g u l u i +myName+ e s t e : \ n ) ;


NamingEnumeration l s t 1 = c t x . l i s t B i n d i n g s (myName ) ;
while ( l s t 1 . hasMore ( ) ) {
B i n d i n g bd = ( B i n d i n g ) l s t 1 . n e x t ( ) ;
System . out . p r i n t l n ( bd ) ;
}
ctx . c l o s e ( ) ;

55
56
57
58
59
60
61

}
catch ( NamingException e ) {
System . out . p r i n t l n ( Lookup f a i l e d : + e . g e t M e s s a g e ( ) ) ;
}

62
63
64
65

66
67

51

Apelarea clasei, n varianta data, consta din


java -Djava.naming.factory.initial=com.sun.jndi.fscontext.RefFSContextFactory Lookup

sau
java

Lookup

caz, n care, n catalogul curent se gaseste fisierul jndi.properties cu continutul


java.naming.factory.initial=com.sun.jndi.fscontext.RefFSContextFactory

Serviciul de nume Filesystem este dat de fisierele: fscontext.jar si


providerutil.jar.

52

ARE 3. REGASIREA

UNITATEA DE INVAT
OBIECTELOR PRIN SERVICII DE NUME

3.1.1

LDAP

LDAP poate fi privit ca un sistem de gestiune a unei baze de date (ne


relational). Baza de date este alcatuita din atribute ale caror nume este precizat de protocolul LDAP.
Punctele de intrare (radacinile) sunt date de DN (Distinguished Name). Uzual
DN se defineste printr-una din variantele
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.
Implement
ari gratuite LDAP sunt:
OpenDS (Open Directory Service);
ApacheDS (Apache Directory Service). Apache Directory Studio incorporeaz
a si ofer
a interfata grafica pentru ApacheDS.
Vom utiliza produsul OpenDS.
Instalarea const
a din:
1. dezarhivarea distributiei;
2. se completeaz
a sursa fisierului OpenDS-*\setup.bat cu
set OPENDS JAVA HOME=... ca prima linie;
3. se execut
a OpenDS-*\setup.bat. Prin intermediul unei interfete grafice se
fixeaz
a
o parola pentru cn=Directory Manager. Fie 1q2w3e aceasta parola.
un punct de intrare, fie acesta DN: dc=example,dc=com.
Implicit, serverul OpenDS utilizeaza portul 389.
Operatiile de configurare se fac utilizand interfata grafica a componentei
OpenDS Directory Server Control Panel, lansat prin
set OPENDS_JAVA_HOME=. . .
set OpenDS_HOME=. . .\OpenDS-*
%OpenDS_HOME%\bat\control-panel.bat

3.1. JAVA NAMING AND DIRECTORY INTERFACE

53

Declararea unui punct de intrare (utilizator) se face prin Manage Entries


Entries New User, urmat de completarea datelor cerute.
Schimbarea parolei unui utilizator se face tot din Manage Entries urmat de
clic-dreapta pe DN si Reset User Password.
Prin aceast
a component
a se poate porni si opri serverul OpenDS, ambele
operatii put
and fi executate si apeland start-ds, stop-ds din catalogul
OpenDS HOME\bat.
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
implic
a 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
2
3
4
5
6
8
9
10
11
12
13
14
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

import
import
import
import
import
import

java . u t i l . Hashtable ;
java . u t i l . Scanner ;
j a v a x . naming . Context ;
j a v a x . naming . NamingException ;
j a v a x . naming . d i r e c t o r y . D i r C o n t e x t ;
j a v a x . naming . d i r e c t o r y . I n i t i a l D i r C o n t e x t ;

public c l a s s LDAPServerCmmdc {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( A l e g e t i f u r n i z o r u l LDAP: ) ;
System . out . p r i n t l n ( 1 : OpenDS ) ;
System . out . p r i n t l n ( 2 : Apache D i r e c t o r y S e r v i c e ) ;
i n t p r o v i d e r=s c a n n e r . n e x t I n t ( ) ;
H a s h t a b l e env = new H a s h t a b l e ( ) ;
env . put ( Context . INITIAL CONTEXT FACTORY,
com . sun . j n d i . l d a p . LdapCtxFactory ) ;
i f ( p r o v i d e r ==1){
env . put ( Context . PROVIDER URL,
l d a p : / / l o c a l h o s t : 3 8 9 / dc=example , dc=com ) ;
env . put ( Context . SECURITY PRINCIPAL , cn=D i r e c t o r y Manager ) ;
env . put ( Context . SECURITY CREDENTIALS, 1 q2w3e ) ;
}
else {
env . put ( Context . PROVIDER URL,
l d a p : / / l o c a l h o s t : 1 0 3 8 9 / u i d=admin , ou=system ) ;
env . put ( Context . SECURITY PRINCIPAL , u i d=admin , ou=system ) ;
env . put ( Context . SECURITY CREDENTIALS, s e c r e t ) ;
}
DirContext ctx = null ;
System . out . p r i n t l n ( A l e g e t i o p e r a t i a : 1 bind ; 2 unbind ) ;
i n t o p e r=s c a n n e r . n e x t I n t ( ) ;

54

System . out . p r i n t l n ( I n t r o d u c e t i v a l o a r e a a t r i b u t u l u i \ cn \ +
+ a o b i e c t u l u i Cmmdc ) ;
System . out . p r i n t l n ( cn= ) ;
S t r i n g cmmdcObj=s c a n n e r . n e x t ( ) . t r i m ( ) ;

34
35
36
37

try {
c t x = new I n i t i a l D i r C o n t e x t ( env ) ;
i f ( o p e r ==1){
Cmmdc o b j=new Cmmdc ( ) ;
S t r i n g s t r= cn=+cmmdcObj ;
c t x . bind ( s t r , o b j ) ;
}
else {
c t x . unbind ( cn=+cmmdcObj ) ;
}
ctx . c l o s e ( ) ;
}
catch ( NamingException e ) {
System . out . p r i n t l n ( LDAPserverCmmdc :
}

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

+e . g e t M e s s a g e ( ) ) ;

54
55

ARE 3. REGASIREA

UNITATEA DE INVAT
OBIECTELOR PRIN SERVICII DE NUME

Codul clasei Cmmdc este


1
2
3
4
5
6
7
8
9
10

public c l a s s Cmmdc implements j a v a . i o . S e r i a l i z a b l e {


public long cmmdc( long a , long b ) {
while ( b != 0 ) {
long r = a % b ;
a = b;
b = r;
}
return a ;
}
}

Exemplul 3.1.3 Utilizarea unui obiect de tip Cmmdc reg


asit pe baza referintei
din serverul LDAP.
1
2
3
4
5
6
8
9
10
11
12
13
14
15
16
17
18

import
import
import
import
import
import

java . u t i l . Hashtable ;
j a v a x . naming . Context ;
j a v a x . naming . NamingException ;
j a v a x . naming . d i r e c t o r y . D i r C o n t e x t ;
j a v a x . naming . d i r e c t o r y . I n i t i a l D i r C o n t e x t ;
java . u t i l . Scanner ;

public c l a s s LDAPClientCmmdc {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( A l e g e t i f u r n i z o r u l LDAP: ) ;
System . out . p r i n t l n ( 1 : OpenDS ) ;
System . out . p r i n t l n ( 2 : Apache D i r e c t o r y S e r v i c e ) ;
i n t p r o v i d e r=s c a n n e r . n e x t I n t ( ) ;
H a s h t a b l e env = new H a s h t a b l e ( ) ;
env . put ( Context . INITIAL CONTEXT FACTORY,
com . sun . j n d i . l d a p . LdapCtxFactory ) ;
i f ( p r o v i d e r ==1){

3.1. JAVA NAMING AND DIRECTORY INTERFACE

env . put ( Context . PROVIDER URL,


l d a p : / / l o c a l h o s t : 3 8 9 / dc=example , dc=com ) ;
env . put ( Context . SECURITY PRINCIPAL , cn=D i r e c t o r y Manager ) ;
env . put ( Context . SECURITY CREDENTIALS, 1 q2w3e ) ;

19
20
21
22

}
else {
env . put ( Context . PROVIDER URL,
l d a p : / / l o c a l h o s t : 1 0 3 8 9 / u i d=admin , ou=system ) ;
env . put ( Context . SECURITY PRINCIPAL , u i d=admin , ou=system ) ;
env . put ( Context . SECURITY CREDENTIALS, s e c r e t ) ;
}
DirContext ctx = null ;
try {
c t x=new I n i t i a l D i r C o n t e x t ( env ) ;
i f ( c t x != n u l l ) {
System . out . p r i n t l n ( I n t r o d u c e t i v a l o a r e a a t r i b u t u l u i \ cn \ +
a o b i e c t u l u i Cmmdc ) ;
System . out . p r i n t l n ( cn= ) ;
S t r i n g cmmdcObj=s c a n n e r . n e x t ( ) . t r i m ( ) ;
O b j e c t o b j e c t = c t x . l o o k u p ( cn=+cmmdcObj ) ;
System . out . p r i n t l n ( Primul numar ) ;
long a=s c a n n e r . n e x t I n t ( ) ;
System . out . p r i n t l n ( Al d o i l e a numar ) ;
long b=s c a n n e r . n e x t I n t ( ) ;
Cmmdc o b j =(Cmmdc) o b j e c t ;
System . out . p r i n t l n ( R e z u l t a t u l cmmdc e s t e : +o b j . cmmdc( a , b ) ) ;
}
}
catch ( NamingException e ) {
System . out . p r i n t l n ( LDAPClientCmmdc : +e . g e t M e s s a g e ( ) ) ;
}

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

50
51

55

Unitatea de nv
atare 4

Remote Method Invocation RMI

Durata: 3 ore.

Introducere
Invocarea procedurilor la distanta (Remote Procedure Call RPC ) nseamn
a
apelarea unei metode a unui obiect aflat pe un alt calculator ca si cum acesta
s-ar afla pe calculatorul local.
Se vor prezenta dou
a cazuri:
Invocarea procedurilor la distanta n cazul mediului omogen Java. Denumirea tehnologiei n acest caz este Invocarea metodelor la distant
a Remote
Method Invocation (RMI). Prin mediu omogen se ntelege faptul ca at
at
compontenta server cat si componenta client sunt programate n acelasi
56

4.1. REMOTE METHOD INVOCATION

57

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 Brocker Arhitecture (CORBA).

4.1

Remote Method Invocation

Reg
asirea obiectelor la distant
a. Ideea gasirii unui obiect la distanta
este ca serverul nscrie un reprezentant al sau numit stub (ciot) ntr-un obiect
registry - registru. Acest obiect se creaza cu programul rmiregistry.exe din
distributia java si se lanseaz
a n executie prin
start rmiregistry [port]
unde valoarea implicit
a a portului este 1099. Comanda start apartine sistemului
de operare. rmiregistry este un serviciu de nume JNDI.
Un client obtine din registry stub-ul serverului, prin intermediul caruia realizeaza comunicatia cu programul server.
Cand un obiect al clientului apeleaza o metoda a unui obiect aflat la distanta,
se va face, de fapt, un apel de metoda a unui obiect care reprezinta serverul.
Acesta este stub-ul, aflat pe aceasi masina cu clientul.
Rolul acestui obiect este s
a mpacheteze (marshalling) parametrii de apel ai
metodei ntr-un mesaj ce va fi transferat prin retea. Impachetarea se face ntr-o
maniera independent
a de calculator, mai precis sirurile de caractere si obiecte
sunt transmise ntr-un format care nu se bazeaza pe referinte. Pentru obiecte se
utilizeaz
a serializarea obiectelor Java.
Serializarea datelor reprezint
a transformarea acestora din tipuri de date diferite
ntr-un sir de octeti care va fi transportat prin retea fara interpretare, dar care
pastreaz
a informatiile despre structura initiala a datelor.
Deserializarea este procesul invers de refacere a structurilor trimise prin retea.
Mesajul asamblat este transmis catre server, care stie sa desfaca mesajul
receptionat invoc
and n mod corespunzator metoda referita de client.
Atunci c
and clientul face apel la o metoda aflata pe o alta masina, este invocat stub-ul client, care ncepe conversatia cu serverul. Acest lucru este complet
transparent utilizatorului, care are impresia ca invoca o metoda locala.
Metodele apelate la distant
a trebuie declarate ca apartinand unei interfete ce
extinde interfata java.rmi.Remote. Fiecare asemenea metoda trebuie sa arunce
o exceptie java.rmi.RemoteException. Obiectele care circula prin retea trebuie
sa implementeze interfata java.io.Serializable.
Structura unei aplicatii RMI. O aplicatie RMI este alcatuita din trei
componente:
1. O interfat
a la distant
a (remote) n care se declara serviciile puse la dispozitie
de server;

58

ARE 4. REMOTE METHOD INVOCATION - RMI


UNITATEA DE INVAT

2. Aplicatia server care poate implementa serviciile interfetei la distanta si


nscrie n registry stub-ul corespunzator;
3. Aplicatia client ce apeleaza unul sau mai multe servicii ale serverului.
Nici o clip
a nu trebuie scapat din vedere faptul ca cele trei componente
evolueaz
a pe calculatoare diferite.
Registrul rmiregistry implementeaza interfata java.rmi.registry.Registry1 .
Metodele oferite sunt:
void bind(String numeServiciu, Remote obj )throws
RemoteException, AlreadyBoundException, AccessException
Inregistreaz
a n registry obiectul obj ce implementeaza interfata Remote sub
numele numeServiciu.
void rebind(String numeServiciu, Remote obj )throws
RemoteException, AccessException
Renregistreaz
a n registry obiectul obj ce implementeaza interfata Remote
sub numele numeServiciu.
Aceast
a metod
a poate fi apelata doar daca programul care face nregistrarea
se afl
a pe aceasi masina ca registrul registry.
String[] list()throws RemoteException, AccessException
Returneaz
a o list
a a tuturor serviciilor nregistrate n registry.
Remote lookup(String numeServiciu)throws
RemoteException, NotBoundException, AccessException
Returneaz
a stub-ul serviciului nregistrat sub numele numeServiciu.
void unbind(String numeServiciu)throws
RemoteException, NotBoundException, AccessException
S
terge din registru serviciul.
Localizarea registrului se obtine utilizand metoda statica getRegistry a clasei LocateRegistry.
public static Registry getRegistry() throws RemoteException
public static Registry getRegistry(String host)
throws RemoteException
public static Registry getRegistry(int port)
throws RemoteException
1

Varianta direct
a, f
ar
a a folosi facilit
atile JNDI pentru rmiregistry.

4.1. REMOTE METHOD INVOCATION

59

public static Registry getRegistry(String host,int port)


throws RemoteException
Metoda public static Registry createRegistry(int port)
throws RemoteException creaz
a un registru la portul specificat pe calculatorul
local.
Ansamblul (host,port) determina n mod univoc o aplicatie / serviciu.
Interfata Remote serveste la marcarea interfetelor ale caror metode urmeaza
a fi apelate de pe alt
a masin
a virtuala Java.
Un obiect de tip UnicastRemoteObject mijloceste transmiterea obiectelor si
serveste la generarea unui stub unui serviciu. Generarea stub-ului unui serviciu
se obtine prin intermediul metodei statice
static Remote UnicastRemoteObject.exportObject(Remote obj ,int port)
Inregistrarea stub-ului unui serviciu descris de interfata IService si implementat de clasa ServiceImpl n registry se face prin
ServiceImpl obj=new ServiceImpl();
IService stub=(IService)UnicastRemoteObject.exportObject(obj,0);
// Varianta cu apel rmiregistry direct
/*
Registry registry=LocateRegistry.getRegistry(host,port);
registry.bind("MyServiceName",stub);
*/
// Varianta JNDI
String sPort=(new Integer(port)).toString();
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"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 s
a foloseasca trebuie sa cunoasca :
calculatorul pe care se g
aseste obiectul registry si portul la care asculta
serviciul;
numele sub care serviciul s-a nregistrat n registry;
metodele puse la dispozitie de serviciu.

60

ARE 4. REMOTE METHOD INVOCATION - RMI


UNITATEA DE INVAT

4.1.1

Crearea unei aplicatii RMI

Exemplific
am construirea unei aplicatii RMI n care serviciul asigurat de
server este calculul celui mai mare divizor comun a doua numere naturale.
Pentru exemplele2 care urmeaza, presupunem ca textele sursa se retin n
subcataloage ale unui catalog src, la care are acces doar programatorul, iar clasele
obtinute prin compilare se depun n subcataloagele unui catalog public\classes,
accesibil prin retea.
Dezvoltarea unei aplicatii se va face pe un calculator. In acest sens, celor 3
componente li se asociaza cataloagele \i - pentru interfata la distanta, \s - pentru
componenta server si \c - pentru componenta client. Pasi necesari compilarii si
desf
asur
arii componentelor aplicatiei se vor realiza prin intermediul lui ant.
Pentru fiecare componenta se vor executa succesiv obiectivele:
1. Install - creaz
a o structura de cataloage src si public\classes.
2. Init - creaz
a structura de cataloage specifica aplicatiei.
3. Compile - compileaza programele sursa.
Dezvoltarea unei aplicatii RMI consta din parcurgerea urmatorilor pasi:
1. Definitea interfetei la distanta.

1
2
3
4

package cmmdc ;
public i n t e r f a c e ICmmdc extends j a v a . rmi . Remote{
long cmmdc( long a , long b ) throws j a v a . rmi . RemoteException ;
}

Presupunem ca programatorul interfetei retine textul sursa


ICmmdc.java n catalogul \i\src\cmmdc.
2. Compilarea si arhivarea interfetei se poate realiza fisierul ant-build
1
2
3
5

<property name= package v a l u e=cmmdc />

<target name= I n s t a l l >


< ! C r e a t e t h e b u i l d d i r e c t o r y s t r u c t u r e used by c o m p i l e >
<delete d i r= s r c />
<mkdir d i r= s r c />
<delete d i r= p u b l i c />
<mkdir d i r= p u b l i c />
<delete d i r= p u b l i c / c l a s s e s />

8
9
10
11
12
13
2

<project name= I n t e r f a c e d e f a u l t= I n s t a l l b a s e d i r= . >


<description> I n t e r f a c e a c t i o n s </ description>
< ! s e t g l o b a l p r o p e r t i e s f o r t h i s b u i l d >

Sistemul de operare utilizat este Windows

4.1. REMOTE METHOD INVOCATION

14
15
17
18
19
20
21
22
24
25
26
27
28
29
30
31
32

<mkdir d i r= p u b l i c / c l a s s e s />
</ target>
<target name= I n i t >
< ! C r e a t e t h e time stamp >
<tstamp/>
<mkdir d i r= s r c /${ package } />
<mkdir d i r= p u b l i c / c l a s s e s /${ package } />
</ target>
<target name= Compile depends= I n i t
description= c o m p i l e t h e s o u r c e >
<javac s r c d i r= s r c i n c l u d e s= ${ package }/
d e s t d i r= p u b l i c / c l a s s e s />
<j a r b a s e d i r= p u b l i c / c l a s s e s
d e s t f i l e = p u b l i c / c l a s s e s /${ package }/${ package } . j a r
i n c l u d e s= ${ package } / . c l a s s />
</ target>
</ project>

3. Implementarea interfetei remote prin construirea aplicatiei server.

package s e r v e r ;

import cmmdc . ;
import j a v a . rmi . ;
import j a v a . rmi . s e r v e r . ;
// V a r i a n t a d i r e c t a
// i m p o r t j a v a . rmi . r e g i s t r y . ;
// V a r i a n t a JNDI
import j a v a x . naming . ;

4
5
6
7
8
9
11

public c l a s s CmmdcImpl

implements ICmmdc{

13

public long cmmdc( long a , long b ) { . . . }

15

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 ] ) ;
try {
CmmdcImpl o b j=new CmmdcImpl ( ) ;
ICmmdc s t u b =(ICmmdc) UnicastRemoteObject . e x p o r t O b j e c t ( obj , 0 ) ;

16
17
18
19
20
21
22
23
24
26
27
28
29
30
32
33
34

// V a r i a n t a d i r e c t a
/
R e g i s t r y r e g i s t r y=L o c a t e R e g i s t r y . g e t R e g i s t r y ( h o s t , p o r t ) ;
r e g i s t r y . b i n d ( CmmdcServer , s t u b ) ;
/
// V a r i a n t a JNDI
S t r i n g s P o r t =(new I n t e g e r ( p o r t ) ) . t o S t r i n g ( ) ;
System . s e t P r o p e r t y ( Context . INITIAL CONTEXT FACTORY,

61

62

ARE 4. REMOTE METHOD INVOCATION - RMI


UNITATEA DE INVAT

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 ) ;

35
36
37
38

System . out . p r i n t l n ( CmmdcServer r e a d y ) ;


}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( CmmdcImpl e r r : + e . g e t M e s s a g e ( ) ) ;
}

40
41
42
43
44

45
46

Textul surs
a al programului server CmmdcImpl.java se retine n catalogul
\s\src\server
4. (a) Compilarea programului server;
(b) Crearea obiectului registry;
(c) Lansarea serverului n lucru
se obtin cu ant cu
1
2
3
4
5
7
8
9
10
11
12
14
15
16
17
18
19
20
21
22
23
24
26
27
28
29
30
32
33
34
35

<project name= S e r v e r d e f a u l t= I n s t a l l b a s e d i r= . >


<description>
Server actions
</ description>
< ! s e t g l o b a l p r o p e r t i e s f o r t h i s b u i l d >
<property
<property
<property
<property
<property
<property

name= package v a l u e= s e r v e r />


name= i n t e r f a c e j a r l oc a t io n= / i / p u b l i c / c l a s s e s /cmmdc />
name= j a r f i l e v a l u e=cmmdc . j a r />
name= s e r v i c e c l a s s v a l u e=CmmdcImpl />
name= h o s t v a l u e= l o c a l h o s t />
name= p o r t v a l u e= 1099 />

<target name= I n s t a l l >


< ! C r e a t e t h e time stamp >
<tstamp/>
< ! C r e a t e t h e b u i l d d i r e c t o r y s t r u c t u r e used by c o m p i l e >
<delete d i r= s r c />
<mkdir d i r= s r c />
<delete d i r= p u b l i c />
<mkdir d i r= p u b l i c />
<delete d i r= p u b l i c / c l a s s e s />
<mkdir d i r= p u b l i c / c l a s s e s />
</ target>
<target name= I n i t >
<mkdir d i r= s r c /${ package } />
<mkdir d i r= p u b l i c / c l a s s e s /${ package } />
<copy f i l e = ${ i n t e r f a c e j a r }/${ j a r f i l e } t o d i r= p u b l i c / c l a s s e s />
</ target>
<target name= Compile depends= I n i t
description= c o m p i l e t h e s o u r c e >
<javac s r c d i r= s r c
i n c l u d e s= ${ package }/ d e s t d i r= p u b l i c / c l a s s e s

4.1. REMOTE METHOD INVOCATION

36
37
38
40
41
42
43
44
46
47
48
49
50
51
52
53
54

63

classpath= p u b l i c / c l a s s e s /${ j a r f i l e } />


<unjar src= p u b l i c / c l a s s e s /${ j a r f i l e } d e s t= p u b l i c / c l a s s e s />
</ target>
<target name=Rmi>
<exec e x e c u t a b l e= r m i r e g i s t r y >
<arg v a l u e= 1099 />
</ exec>
</ target>
<target name= S e r v e r >
<java c l a s s n a m e= ${ package } . $ { s e r v i c e c l a s s }
classpath= / s / p u b l i c / c l a s s e s f o r k= t r u e >
<jvmarg
v a l u e=Djava . rmi . s e r v e r . c o d e b a s e= f i l e : / s / p u b l i c / c l a s s e s / />
<arg l i n e= ${ h o s t } ${ p o r t } />
</ java>
</ target>
</ project>

Parametrul -Djava.rmi.server.codebase fixeaza locatia interfetei la distanta


de pe calculatorul server.
Obiectivele Rmi si Server se lanseaza n ferestre dos distincte care raman
active pe durata de viat
a a aplicatiei server.
5. Realizarea programului client

package c l i e n t ;

import cmmdc . ;
import j a v a . u t i l . S c a n n e r ;
// V a r i a n t a d i r e c t a
// i m p o r t j a v a . rmi . r e g i s t r y . ;
// V a r i a n t a JNDI
import j a v a x . naming . ;

4
5
6
7
8
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

public c l a s s CmmdcClient {
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
S t r i n g h o s t= l o c a l h o s t ;
i n t p o r t =1099;
i f ( a r g s . l e n g t h >0)
h o s t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( Primul numar : ) ;
long m=Long . par se Lon g ( s c a n n e r . n e x t ( ) ) ;
System . out . p r i n t l n ( Al d o i l e a numar : ) ;
long n=Long . p ars eL ong ( s c a n n e r . n e x t ( ) ) ;
long x =0;
try {
// V a r i a n t a d i r e c t a
/
R e g i s t r y r e g i s t r y=L o c a t e R e g i s t r y . g e t R e g i s t r y ( h o s t , p o r t ) ;

64

ARE 4. REMOTE METHOD INVOCATION - RMI


UNITATEA DE INVAT

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 ) ;

28
29
30
31
32
33
34
35
36

x=o b j . cmmdc(m, n ) ;
System . out . p r i n t l n ( Cmmdc=+x ) ;

38
39

}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( CmmdcClient e x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}

40
41
42
43

44
45

Sursa programului client CmmdcClient.java apartine catalogului


\c\src\client
6. Compilarea programului client si lansarea acestuia n executie.
1
2
3
5
6
7
8
9
10
12
13
14
15
16
17
18
20
21
22
23
24
25
26
28
29
30
31
32
33

<project name= C l i e n t d e f a u l t= I n s t a l l b a s e d i r= . >


<description> C l i e n t a c t i o n s </ description>
< ! s e t g l o b a l p r o p e r t i e s f o r t h i s b u i l d >
<property
<property
<property
<property
<property
<property

name= package v a l u e= c l i e n t />


name= i n t e r f a c e j a r l oc a t io n= / i / p u b l i c / c l a s s e s /cmmdc />
name= j a r f i l e v a l u e=cmmdc . j a r />
name= h o s t v a l u e= l o c a l h o s t />
name= p o r t v a l u e= 1099 />
name= c l i e n t c l a s s v a l u e= CmmdcClient />

<target name= I n s t a l l >


< ! C r e a t e t h e b u i l d d i r e c t o r y s t r u c t u r e used by c o m p i l e >
<delete d i r= s r c />
<mkdir d i r= s r c />
<delete d i r= c l a s s e s />
<mkdir d i r= c l a s s e s />
</ target>
<target name= I n i t >
< ! C r e a t e t h e time stamp >
<tstamp/>
<mkdir d i r= s r c /${ package } />
<mkdir d i r= c l a s s e s /${ package } />
<copy f i l e = ${ i n t e r f a c e j a r }\${ j a r f i l e } t o d i r= c l a s s e s />
</ target>
<target name= Compile depends= I n i t
description= c o m p i l e t h e s o u r c e >
<javac s r c d i r= s r c
i n c l u d e s= ${ package } / . j a v a d e s t d i r= c l a s s e s
classpath= c l a s s e s \${ j a r f i l e } />
</ target>

4.1. REMOTE METHOD INVOCATION

35
36
37
38
39
40
41
42
43
44
45

65

<target name=Run depends= Compile


description= S t a r t t h r c l i e n t >
<java c l a s s n a m e= ${ package } . $ { c l i e n t c l a s s } f o r k= t r u e >
<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>

Test de evaluare a cunostintelor


1. Precizati abrevierea RMI.
2. Care sunt componentele unei aplicatii client-server bazat pe RMI?
3. C
ate si care sunt entit
atile care participa la executia unei aplicatii clientserver bazat pe RMI?
4. Care este rolul unui (rmi)registry?

Unitatea de nv
atare 5

Tipare de programare RMI

Durata: 3 ore.

5.1

Fabrica de obiecte

Tiparul fabrica de obiecte va permite crearea dinamica a unui server, fapt care
nu este posibil pe schema prezentata n paragraful precedent. Prin aceea schem
a,
se va crea o clas
a - fabrica de obiecte - care implementeaza cate o metoda get, ce
returneaz
a o instant
a de server. Aceste metode sunt declarate ntr-o interfata la
distant
a. Un client, apeland o asemenea metoda, va instantia serverul dorit si va
obtine stub-ul corespunzator.
Programarea unui server care poate fi lansat dinamic trebuie sa satisfac
a
restrictiile:
Clasa serverului extinde clasa UnicastRemoteObject.
Exist
a un constructor fara argumente ce arunc
a exceptia java.rmi.Remote
Exception.
Pentru exemplificarea tehnicii de lucru reluam aplicatia pentru calculul celui
mai mare divizor comun a doua numere naturale, considerand interfata
1
2

package cmmdc0 ;
im po rt j a v a . rmi . ;

66

5.1. FABRICA DE OBIECTE

3
4
5

67

p u b l i c i n t e r f a c e ICmmdc0 e x t e n d s Remote{
p u b l i c l o n g compute ( l o n g m, l o n g n ) throws RemoteException ;
}

Aceas
a interfat
a va fi implementata de clasa ServerCmmdc. Metoda compute
este o metod
a de calcul a celui mai mare divizor comun a doua numere.
Obiecte de tip ServerCmmdc se creaza, de la distanta prin fabrica de obiecte
FabObiecte, o clas
a ce implementeaza interfata
1
2
3
4
5

package cmmdc0 ;
im po rt j a v a . rmi . ;
p u b l i c i n t e r f a c e I F a b O b i e c t e e x t e n d s Remote{
p u b l i c ICmmdc0 getCmmdc ( ) throws RemoteException ;
}

Codurile claselor ServerCmmdc si FabObiecte sunt

package cmmdc0 ;
im po rt j a v a . rmi . ;
im po rt j a v a . rmi . s e r v e r . ;
im po rt j a v a . i o . ;
im po rt j a v a . u t i l . ;

p u b l i c c l a s s ServerCmmdc e x t e n d s UnicastRemoteObject implements ICmmdc0{

1
2
3
4

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 ) throws RemoteException {


. . .
}

11
12
13
14

respectiv

package cmmdc0 ;
im po rt j a v a . rmi . ;
im po rt j a v a . rmi . s e r v e r . ;
im po rt j a v a . rmi . r e g i s t r y . ;

p u b l i c c l a s s FabObiecte implements I F a b O b i e c t e {

1
2
3

8
9
10
11
13
14
15
16
17
18
19
20
21
22
23
24

p u b l i c ICmmdc0 getCmmdc ( ) throws RemoteException {


ServerCmmdc cmmdc=new ServerCmmdc ( ) ;
r e t u r n 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 [ ] ) {
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 ] ) ;
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 ) ;

68

System . out . p r i n t l n ( O b j e c t F a c t o r y r e a d y ) ;
}
catch ( Exception e ){
System . out . p r i n t l n ( F a c t o r y e r r +e . g e t M e s s a g e ( ) ) ;
}

25
26
27
28
29

30
31

ARE 5. TIPARE DE PROGRAMARE RMI


UNITATEA DE INVAT

Aplicatia client se compune din doua clase


1. RemoteClient
Clientul obtine stub-ul serviciului, prin intermediul caruia apeleaza metada
getCmmdc() a fabricii de obiecte, obtinand un obiect remote de tip ServerCmmdc, ce implementeaza interfata la distanta ICmmdc0.

package cmmdc0 ;
im po rt j a v a . rmi . ;
im po rt j a v a . rmi . s e r v e r . ;
im po rt j a v a . rmi . r e g i s t r y . ;

p u b l i c c l a s s RemoteClient e x t e n d s UnicastRemoteObject {

1
2
3

ICmmdc0 remote=n u l l ;

8
10

p u b l i c RemoteClient ( ) throws RemoteException {}

12

p u b l i c RemoteClient ( S t r i n g hos t , i n t p o r t ) throws RemoteException {


I F a b O b i e c t e f a b r i c a=n u l l ;
try {
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 ost , p o r t ) ;
I F a b O b i e c t e o b j =( I F a b O b i e c t e ) r e g i s t r y . l o o k u p ( O b j e c t F a c t o r y ) ;
remote=o b j . getCmmdc ( ) ;
}
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 ( ) ) ;
}
}

13
14
15
16
17
18
19
20
21
22
23

2. ClientCmmdc0
Apeleaz
a metoda compute a obiectului remote.
2

package cmmdc0 ;
im po rt j a v a . u t i l . S c a n n e r ;

p u b l i c c l a s s ClientCmmdc0 {

6
7
8
9
10
11
12
13
14

p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) {
S t r i n g h o s t= l o c a l h o s t ;
i n t p o r t =1099;
i f ( a r g s . l e n g t h >0)
h o s t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
try {

5.2. APELUL INVERS CALLBACK

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 ) ;

15
16
17
18
19
20
21

}
catch ( Exception e ){
System . out . p r i n t l n ( C l i e n t E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}
System . e x i t ( 0 ) ;

22
23
24
25
26

27
28

5.2

69

Apelul invers Callback

Se numeste apel invers apelarea de catre programul server a unei metode a


clientului.
In RMI realizarea unui apel invers presupune:
1. definirea unei interfete la distanta ce va fi implementat de programul client;
2. programul client ce implementeaza interfata extinde clasa UnicastRemote
Object si are un constructor ce arunca o exceptie java.rmi.RemoteException.
Extindem aplicatia anterioar
a cu posibilitatea suplimentara a serverului (ServerCmmdc) de a alege metoda de calcul a celui mai mare divizor comun dintre
varianta nerecursiv
a si cea recursiva a algorimului lui Euclid.
Extindem interfata ICmmdc0 cu metoda
public void setMethod(ICallbackCmmdc obj)throws RemoteException;
1
2
3
4
5
6

package cmmdc0 ;
im po rt j a v a . rmi . ;
p u b l i c i n t e r f a c e ICmmdc0 e x t e n d s Remote{
p u b l i c l o n g compute ( l o n g m, l o n g n ) throws RemoteException ;
p u b l i c v o i d setMethod ( ICallbackCmmdc o b j ) throws RemoteException ;
}

unde ICallbackCmmdc este interfata


1
2
3
4
5

package cmmdc0 ;
im po rt j a v a . rmi . ;
p u b l i c i n t e r f a c e ICallbackCmmdc e x t e n d s Remote{
p u b l i c S t r i n g getMethod ( ) throws RemoteException ;
}

ce va fi implementat
a n clasa RemoteClient.
Programul ServerCmmdc devine

70

1
2
3
4
6
7
8

ARE 5. TIPARE DE PROGRAMARE RMI


UNITATEA DE INVAT

package cmmdc0 ;
im po rt j a v a . rmi . ;
im po rt j a v a . rmi . s e r v e r . ;
im po rt j a v a . i o . ;
p u b l i c c l a s s ServerCmmdc e x t e n d s UnicastRemoteObject
implements ICmmdc0{
p r i v a t e S t r i n g method=n u l l ;

10

p u b l i c ServerCmmdc ( ) throws RemoteException {}

12

p u b l i c l o n g compute ( l o n g m, l o n g n ) {
l o n g x =0;
i f ( method . e q u a l s ( NERECURSIV ) )
x=n e r e c u r s i v (m, n ) ;
i f ( method . e q u a l s ( RECURSIV ) )
x=r e c u r s i v (m, n ) ;
return x ;
}

13
14
15
16
17
18
19

p u b l i c v o i d setMethod ( ICallbackCmmdc o b j ) throws RemoteException {


method=o b j . getMethod ( ) ;
}

21
22
23

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 ) ;
}

25
26
27
28
29
30
31
32
33

p r i v a t e l o n g n e r e c u r s i v ( l o n g m, l o n g n ) {
long r , c ;
do {
c=n ;
r=m%n ;
m=n ;
n=r ;
}
while ( r !=0);
return c ;
}

35
36
37
38
39
40
41
42
43
44
45
46

Dup
a obtinerea stub-ului, clientul apeleaza metoda setMethod a serverului
remote, care, prin apel invers, apeleaza metoda getMethod din RemoteClient.
Clientul stabileste metoda de calcul si apeleaza metoda compute a lui remote.
Programele client devin
1
2
3
4
5

package cmmdc0 ;
im po rt j a v a . rmi . ;
im po rt j a v a . rmi . s e r v e r . ;
im po rt j a v a . rmi . r e g i s t r y . ;
im po rt j a v a . u t i l . S c a n n e r ;

5.2. APELUL INVERS CALLBACK

7
8
9

p u b l i c c l a s s RemoteClient e x t e n d s UnicastRemoteObject
implements ICallbackCmmdc {
ICmmdc0 remote=n u l l ;

11

p u b l i c RemoteClient ( ) throws RemoteException {}

13

p u b l i c S t r i n g getMethod ( ) {
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( A l e g e t i v a r i a n t a a l g o r i t m u l u i l u i E u c l i d ) ;
System . out . p r i n t l n ( 1 a l g o r i t m u l ner e c u r s i v ) ;
System . out . p r i n t l n ( 2 a l g o r i t m u l r e c u r s i v ) ;
i n t x=s c a n n e r . n e x t I n t ( ) ;
S t r i n g method=n u l l ;
i f ( x==1)
method=NERECURSIV ;
else
method=RECURSIV ;
r e t u r n method ;
}

14
15
16
17
18
19
20
21
22
23
24
25

p u b l i c RemoteClient ( S t r i n g hos t , i n t p o r t ) throws RemoteException {


I F a b O b i e c t e f a b r i c a=n u l l ;
try {
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 ) ;
I F a b O b i e c t e o b j =( I F a b O b i e c t e ) r e g i s t r y . l o o k u p ( O b j e c t F a c t o r y ) ;
remote=o b j . getCmmdc ( ) ;
}
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 ( ) ) ;
}
}

27
28
29
30
31
32
33
34
35
36
37
38

si
1
2
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

package cmmdc0 ;
im po rt j a v a . u t i l . S c a n n e r ;
p u b l i c c l a s s ClientCmmdc0 {
p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) {
S t r i n g h o s t= l o c a l h o s t ;
i n t p o r t =1099;
i f ( a r g s . l e n g t h >0)
h o s t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
try {
RemoteClient c t=new RemoteClient ( ho st , p o r t ) ;
c t . remote . setMethod ( c t ) ;
System . out . p r i n t l n ( m= ) ;
l o n g m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
l o n g n=s c a n n e r . nextLong ( ) ;
l o n g x=c t . remote . compute (m, n ) ;
System . out . p r i n t l n ( Cmmdc=+x ) ;
}
catch ( Exception e ){
System . out . p r i n t l n ( C l i e n t E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;

71

72

}
System . e x i t ( 0 ) ;

25
26

27
28

ARE 5. TIPARE DE PROGRAMARE RMI


UNITATEA DE INVAT

Test de evaluare a cunostintelor


1. Ce asigur
a sablonul de programare Fabrica de obiecte n RMI?
2. Ce asigur
a sablonul de programare Callback n RMI?
3. Explicati caracterul sincron al comunicarii n RMI.

Unitatea de nv
atare 6

CORBA

Durata: 4 ore.

Introducere
6.1

CORBA

Retelele de calculatoare sunt eterogene n timp ce majoritatea interfetelor de


programare a aplicatiilor sunt orientate spre platforme omogene.
Pentru a facilita integrarea unor sisteme dezvoltate separat, ntr-un singur
mediu distribuit eterogen, OMG (Object Management Group consortiu cuprinzand
peste 800 de firme) a elaborat standardul CORBA (Common Object Request
Brocker Arhitecture): un cadru de dezvoltare a aplicatiilor distribuite n medii
eterogene.
La CORBA au aderat toate marile firme de software - cu exceptia Microsoft,
firma care a dezvoltat propriul s
au model DCOM (Distributed Component Object
73

74

ARE 6. CORBA
UNITATEA DE INVAT

Model), incompatibil CORBA.


CORBA contine programe client care utilizeaza diferite obiecte distribuite n
sistem. Deoarece n multe sisteme de operare prelucrarile trebuie sa evolueze ntrun proces, orice obiect trebuie sa evolueze ntr-un proces. In alte cazuri, obiectele
pot evolua n fire de executie sau n biblioteci dll. CORBA omogenizeaza aceste
posibilit
ati prin precizarea ca obiectele exista n servere. Fiecare obiect este
asociat cu un singur server.
Interconectarea obiectelor. Implementarea si localizarea unui obiect sunt
ascunse clientului. Comunicarea ntre client si obiect este facilitata de Object
Request Brocker (ORB) care permite obiectelor sa se regaseaca unele pe altele
n retea. El ajut
a obiectele sa faca cereri si sa primeasca raspunsuri de la alte
obiecte aflate n retea. Acestea se desfasoara transparent pentru client care nu
stie unde este localizat obiectul, care este mecanismul utilizat pentru a comunica
cu el, cum este activat sau memorat acesta.
ORB este un pachet de servicii, independent de aplicatii, dar care permit
aplicatiilor s
a interactioneze prin retea. ORB face parte din middleware un
intermediar ntre softul de retea si cel de aplicatie.
Un ORB se poate executa local pe un singur calculator sau poate fi conectat
cu oricare alt ORB din Internet, folosind protocolul IIOP -- Internet Inter
ORB Protocol, definit de CORBA 2.
CORBA face o separare ntre interfata unui obiect si implementarea sa si
foloseste un limbaj neutru pentru definirea interfetelor: IDL -- Interface Definition
Language.
IDL permite realizarea descrierii de interfete independent de limbajul de programare si de sistemul de operare folosit. O interfata IDL defineste legatura
dintre client si server.

6.1.1

Conexiunea RMI - CORBA

Firma Oracle - Sun Microsystems a dezvoltat o solutie prin care programele


RMI pot fi adaptate pentru a putea accesa obiecte CORBA. Aceasta este cunoscut
a sub numele de solutia RMI-IIOP, concretizata printr-o serie de pachete din
distributia jdk. In acest fel nu mai este necesar utilizarea limbajului IDL pentru
descrierea interfetelor la distanta.
Instrumente necesare utilizarii solutiei RMI-IIOP:
compilatorul rmic
Optiunea -iiop genereaza stub-ul si legatura (tie) din partea serverului.
Cu optiunea -d se specifica catalogul n care aceste fisiere sunt scrise.
serviciul ORB care asigura regasirea resurselor CORBA. Acest server se
lanseaz
a n executie prin

75

6.1. CORBA

start orbd -ORBInitialPort [port]


Programele orbd, rmic sunt n distributia jdk.

Transformarea unui program RMI ntr-un program RMI-IIOP


Exemplific
am prin aplicatia care implementeaza un serviciu de calcul a celui
mai mare divizor comun a dou
a numere naturale. Etapele realizarii aplicatiei
sunt:
1. Elaborarea interfetei este identica cu cea a aplicatiei RMI.
2. Implementarea interfetei
1
2
3
4
6
7
9
10
11

package cmmdciiop ;
im po rt j a v a x . rmi . P o r t a b l e R e m o t e O b j e c t ;
im po rt cmmdc . ;
im po rt j a v a . rmi . ;
// Se e x t i n d e c l a s a P o r t a b l e R e m o t e O b j e c t
// s i nu UnicastRemoteObject
p u b l i c c l a s s CmmdcImpl e x t e n d s P o r t a b l e R e m o t e O b j e c t implements ICmmdc{
// C o n s t r u c t o r u l c l a s e i
p u b l i c CmmdcImpl ( ) throws RemoteException {}
p u b l i c l o n g cmmdc( l o n g a , l o n g b ) { . . . }

13
14

3. Realizarea programului server.


1
2
3

6
7
8
9
10
11
12
13
14
15
16
18
19
20
21

package cmmdciiop ;
im po rt j a v a x . naming . I n i t i a l C o n t e x t ;
im po rt j a v a x . naming . Context ;

p u b l i c c l a s s CmmdcServer {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
S t r i n g h o s t= l o c a l h o s t ;
S t r i n g p o r t= 1050 ;
i f ( a r g s . l e n g t h >0)
h o s t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t=a r g s [ 1 ] ;
try {
// 1 : C r e a r e a u n e i i n s t a n t e CmmdcImpl
CmmdcImpl cmmdcRef = new CmmdcImpl ( ) ;
// 2 : I n r e g i s t r a r e a u n e i r e f e r i n t e a s e r v i c i u l u i
// u t i l i z a n d JNDI API
System . s e t P r o p e r t y ( j a v a . naming . f a c t o r y . i n i t i a l ,
com . sun . j n d i . cosnaming . CNCtxFactory ) ;

76

ARE 6. CORBA
UNITATEA DE INVAT

System . s e t P r o p e r t y ( j a v a . naming . p r o v i d e r . u r l ,
i i o p : // +h o s t+ : +p o r t ) ;
Context c t x = new I n i t i a l C o n t e x t ( ) ;
c t x . r e b i n d ( CmmdcService , cmmdcRef ) ;
System . out . p r i n t l n ( Cmmdc S e r v e r : Ready . . . ) ;

22
23
24
25
26

}
catch ( Exception e ) {
System . out . p r i n t l n ( CmmdcServer: + e . g e t M e s s a g e ( ) ) ;
}

27
28
29
30

31
32

4. Compilarea programelor CmmdcImpl.java si CmmdcServer.java.


5. Generarea stub-ului cmmdc. ICmmdc Stub.class corespunzator interfetei
ICmmdc si a fisierului Tie cmmdciiop. CmmdcImpl Tie.class corespunzator
clasei CmmdcImpl. Acestea se obtin ruland utilitarul rmic - din distrubutia
Java cu optiunea -iiop
rmic -iiop cmmdciiop.CmmdcImpl
6. Pornirea serverului CORBA de regasire a serviciilor
start orbd -ORBInitialPort 1050
7. Lansarea serverului n executie.
Activit
atile legate de server se obtin prin ant cu fisierul build
1
2
3
5
6
7
8
9
10
11
12
14
15
16
17
18
19
20
21
22
23
24

<project name= S e r v e r d e f a u l t= I n s t a l l b a s e d i r= . >


<description>S e r v e r a c t i o n s</ description>
< ! s e t g l o b a l p r o p e r t i e s f o r t h i s b u i l d >
<property
<property
<property
<property
<property
<property
<property
<property

name= package v a l u e= cmmdciiop />


name= i n t e r f a c e package v a l u e=cmmdc />
name= i n t e r f a c e j a r l oc a t io n= / i / p u b l i c / c l a s s e s /cmmdc />
name= j a r f i l e v a l u e=cmmdc . j a r />
name= s e r v i c e c l a s s v a l u e=CmmdcServer />
name= i m p l e m e n t a t i o n c l a s s v a l u e=CmmdcImpl />
name= h o s t v a l u e= l o c a l h o s t />
name= p o r t v a l u e= 1050 />

<target name= I n s t a l l >


< ! C r e a t e t h e time stamp >
<tstamp/>
< ! C r e a t e t h e b u i l d d i r e c t o r y s t r u c t u r e used by c o m p i l e >
<delete d i r= s r c />
<mkdir d i r= s r c />
<delete d i r= p u b l i c />
<mkdir d i r= p u b l i c />
<delete d i r= p u b l i c / c l a s s e s />
<mkdir d i r= p u b l i c / c l a s s e s />
</ target>

6.1. CORBA

26
27
28
29
30
31
32
34
35
36
37
38
39
40
41
42
43
44
46
47
48
49
50
52
53
54
55
56
57
58
59
60
61

<target name= I n i t >


<mkdir d i r= s r c /${ package } />
<mkdir d i r= p u b l i c / c l a s s e s /${ package } />
<copy f i l e = ${ i n t e r f a c e j a r }/${ j a r f i l e } t o d i r= p u b l i c / c l a s s e s />
<unjar src= p u b l i c / c l a s s e s /${ j a r f i l e } d e s t= p u b l i c / c l a s s e s />
<delete d i r= p u b l i c / c l a s s e s /METAINF />
</ target>
<target name= Compile depends= I n i t
description= c o m p i l e t h e s o u r c e >
<javac s r c d i r= s r c d e s t d i r= p u b l i c / c l a s s e s
i n c l u d e s= ${ package }\
classpath= p u b l i c \ c l a s s e s \${ j a r f i l e } />
<rmic c l a s s n a m e= ${ package }\${ i m p l e m e n t a t i o n c l a s s }
s o u r c e b a s e= s r c
i i o p= y e s
b a s e= p u b l i c / c l a s s e s
classpath= p u b l i c / c l a s s e s />
</ target>
<target name=Orb>
<exec e x e c u t a b l e= orbd >
<arg l i n e=O R B I n i t i a l P o r t ${ p o r t } O R B I n i t i a l H o s t ${ h o s t } />
</ exec>
</ target>
<target name= S e r v e r description= S t a r t t h r s e r v e r >
<java c l a s s n a m e= ${ package } . $ { s e r v i c e c l a s s } f o r k= t r u e >
<classpath>
<pathelement l oc a t io n= p u b l i c / c l a s s e s /${ j a r f i l e } />
<pathelement path= p u b l i c / c l a s s e s />
</ classpath>
<arg l i n e= ${ h o s t } ${ p o r t } />
</ java>
</ target>
</ project>

8. Editarea programului client.

1
2
3
4
5
6
7
9
10
11
12
13
14
15
16

77

package cmmdciiop ;
import j a v a . rmi . ;
import j a v a x . rmi . ;
import j a v a . n e t . MalformedURLException ;
import j a v a x . naming . ;
import j a v a . u t i l . S c a n n e r ;
import cmmdc . ;
public c l a s s CmmdcClient {
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
S t r i n g h o s t= l o c a l h o s t ;
S t r i n g p o r t= 1050 ;
i f ( a r g s . l e n g t h >0)
h o s t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
p o r t=a r g s [ 1 ] ;

78

ARE 6. CORBA
UNITATEA DE INVAT

S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( Primul numar : ) ;
long m=Long . par se Lon g ( s c a n n e r . n e x t ( ) ) ;
System . out . p r i n t l n ( Al d o i l e a numar : ) ;
long n=Long . p ars eL ong ( s c a n n e r . n e x t ( ) ) ;
try {
System . s e t P r o p e r t y ( j a v a . naming . f a c t o r y . i n i t i a l ,
com . sun . j n d i . cosnaming . CNCtxFactory ) ;
System . s e t P r o p e r t y ( j a v a . naming . p r o v i d e r . u r l ,
i i o p : / / +h o s t+ : +p o r t ) ;
Context c t x = new I n i t i a l C o n t e x t ( ) ;

18
19
20
21
22
23
24
25
26
27
28

// STEP 1 : Get t h e O b j e c t r e f e r e n c e from t h e Name S e r v c t x e


// u s i n g JNDI c a l l .
O b j e c t o b j r e f = c t x . l o o k u p ( CmmdcService ) ;
System . out . p r i n t l n ( C l i e n t : Obtained a r e f . t o Cmmdc s e r v e r . ) ;

30
31
32
33

// STEP 2 : Narrow t h e o b j e c t r e f e r e n c e t o t h e c o n c r e t e t y p e and


// i n v o k e t h e method .
ICmmdc o b j = (ICmmdc) P o r t a b l e R e m o t e O b j e c t . narrow ( o b j r e f , ICmmdc . c l a s s ) ;
long x=o b j . cmmdc(m, n ) ;
System . out . p r i n t l n ( Cmmdc=+x ) ;

35
36
37
38
39

}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( E x c e p t i o n + e . g e t M e s s a g e ( ) ) ;
}

40
41
42
43

44
45

9. Compilarea si lansarea clientului n executie. Clientul trebuie sa dispun


a
de fisierul stub (cmmdc. ICmmdc Stub.class) si binenteles de interfata
ICmmdc.jar.
Fisierul buildfile pentru executarea clientului:
1
2
3
5
6
7
8
9
10

<project name= C l i e n t d e f a u l t= I n s t a l l b a s e d i r= . >


<description>C l i e n t a c t i o n s</ description>
< ! s e t g l o b a l p r o p e r t i e s f o r t h i s b u i l d >
<property
<property
<property
<property
<property
<property

11
12
13
14
15
17
18
19
20
21
22

<property
<property
<property
<property

name= package v a l u e= cmmdciiop />


name= i n t e r f a c e j a r l oc a t io n= / i / p u b l i c / c l a s s e s /cmmdc />
name= j a r f i l e v a l u e=cmmdc . j a r />
name= s e r v e r package v a l u e= cmmdciiop />
name= i n t e r f a c e package v a l u e=cmmdc />
name= i n t e r f a c e stubl o c a t i o n
l oc a t io n= / s / p u b l i c / c l a s s e s /${ i n t e r f a c e package } />
name= stubc l a s s v a l u e= S t u b . c l a s s />
name= h o s t v a l u e= l o c a l h o s t />
name= p o r t v a l u e= 1050 />
name= c l i e n t c l a s s v a l u e= CmmdcClient />

<target name= I n s t a l l >


< ! C r e a t e t h e b u i l d d i r e c t o r y s t r u c t u r e used by c o m p i l e >
<delete d i r= s r c />
<mkdir d i r= s r c />
<delete d i r= c l a s s e s />
<mkdir d i r= c l a s s e s />

6.1. CORBA

23

</ target>

25

<target name= I n i t >


< ! C r e a t e t h e time stamp >
<tstamp/>
<mkdir d i r= s r c /${ package } />
<mkdir d i r= c l a s s e s /${ package } />
<delete d i r= c l a s s e s /${ s e r v e r package } />
<mkdir d i r= c l a s s e s /${ s e r v e r package } />
<delete d i r= c l a s s e s /${ i n t e r f a c e package } />
<mkdir d i r= c l a s s e s /${ i n t e r f a c e package } />
<copy f i l e = ${ i n t e r f a c e j a r }\${ j a r f i l e } t o d i r= c l a s s e s />
<copy t o d i r= c l a s s e s /${ i n t e r f a c e package } >
< f i l e s e t d i r= ${ i n t e r f a c e stubl o c a t i o n }
i n c l u d e s= ${ stubc l a s s } />
</copy>
<unjar src= c l a s s e s /${ j a r f i l e } d e s t= c l a s s e s />
<delete d i r= c l a s s e s /METAINF />
</ target>

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

<target name= Compile depends= I n i t


description= c o m p i l e t h e s o u r c e >
<javac s r c d i r= s r c d e s t d i r= c l a s s e s
i n c l u d e s= ${ package } \ . j a v a classpath= c l a s s e s />
</ target>

43
44
45
46
47
49
50
51
52
53
54
55
56
57
58

79

<target name=Run depends= Compile description=Run t h e c l i e n t >


<java c l a s s n a m e= ${ package } . $ { c l i e n t c l a s s } f o r k= t r u e >
<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>

6.1.2

Aplicatie Java prin CORBA

Scopul acestei sectiuni este prezentarea dezvoltarii unei aplicatii pe baza unei
interfete bazat pe IDL.
Pentru dezvoltarea aplicatiilor n limbajul de programare Java, translatarea
interfetei IDL n Java se realizeaz
a cu utilitarul idlj din distributia jdk.
Corespondenta ntre entit
atile IDL si Java este data n Tabelul 6.1
Legarea cererii unui client de codul serviciului care satisface cererea utilizeaza
componenta CORBA Portable Object Adapter (POA).

Model cu server temporal


Exemplific
am dezvoltarea unei aplicatii distribuite CORBA n cazul n care
serviciul pus la dispozitie de server este calculul celui mai mare divizor comun a
doua numere naturale.

80

ARE 6. CORBA
UNITATEA DE INVAT

Tip IDL
module
boolean
char, wchar
octet
string, wstring
short, unsigned short
long, unsigned long
long long, unsigned long long
float
double
fixed
enum, struct, union
sequence, array
interface (non-abstract)

Any

Tip Java
package
boolean
char
byte
java.lang.String
short
int
long
float
double
java.math.BigDecimal
class
array
signature interface,
operations interface,
helper class, holder class
org.omg.CORBA.Any

Table 6.1: Entitati IDL si Java

Dezvoltarea unei aplicatii distribuite CORBA cu mediul nativ Java presupune


parcurgerea urm
atoarelor pasi:
1. Realizarea interfetei IDL care nseamna
(a) Editarea programului de interfata:
1
2
3
4
5

module CmmdcApp{
i n t e r f a c e Cmmdc{
long long cmmdc( i n long long a , i n long long b ) ;
};
};

Salv
am acest text ntr-un fisier denumit Cmmdc.idl.
Cmmdc va fi numele serviciului cautat de un client si implementat de
server. Serviciul contine o singura metoda cmmdc.
(b) Translatarea n Java
idlj -fall Cmmdc.idl
Programul idlj creaza un subcatalog CmmdcApp cu un pachet Java CmmdcApp
contin
and fisierele:

81

6.1. CORBA

Cmmdc.java
CmmdcPOA.java ;
CmmdcOperations.java;
CmmdcStub.java;
CmmdcHelper.java;
CmmdcHolder.java.
2. Realizarea programelor server. Punem n evidenta programul servant CmmdcImpl.java ce implementeaza interfata Cmmdc.
1
2
4
5

im po rt CmmdcApp . ;
im po rt o r g . omg .CORBA. ;
p u b l i c c l a s s CmmdcImpl e x t e n d s CmmdcPOA {
p r i v a t e ORB orb ;
p u b l i c CmmdcImpl (ORB orb ) {
t h i s . orb = orb ;
}

7
8
9

p u b l i c l o n g cmmdc( l o n g a , l o n g b ) { . . . }

11
12

si programul CmmdcServer.java, care nscrie n registrul ORB referintele


servantului. Activit
atile ce trebuie ntreprinse sunt declarate prin comentarii n textul surs
a al programului
1
2
3
4
5
7
8
9
10
11
13
14
15
17
18
20
21
22
24
25
26

im po rt
im po rt
im po rt
im po rt
im po rt

CmmdcApp . ;
o r g . omg . CosNaming . ;
o r g . omg . CosNaming . NamingContextPackage . ;
o r g . omg .CORBA. ;
o r g . omg . P o r t a b l e S e r v e r . ;

p u b l i c c l a s s CmmdcServer {
p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) {
try {
// c r e a r e a s i i n i t i a l i z a r e a ORB
ORB orb = ORB. i n i t ( a r g s , n u l l ) ;
// o b t i n e r e a u n e i r e f e r i n t e r o o t p o a s i a c t i v a r e a m a n a g e r u l u i POAManager
POA r o o t p o a = POAHelper . narrow ( orb . r e s o l v e i n i t i a l r e f e r e n c e s ( RootPOA ) ) ;
r o o t p o a . the POAManager ( ) . a c t i v a t e ( ) ;
// c r e a r e a unui s e r v a n t
CmmdcImpl cmmdcImpl = new CmmdcImpl ( orb ) ;
// o b t i n e r e a u n e i r e f e r i n t e a s e r v a n t u l u i
o r g . omg .CORBA. O b j e c t r e f = r o o t p o a . s e r v a n t t o r e f e r e n c e ( cmmdcImpl ) ;
Cmmdc h r e f = CmmdcHelper . narrow ( r e f ) ;
// O b t i n e r e a s e r v i c i u l u i NameService
o r g . omg .CORBA. O b j e c t o b j R e f =
orb . r e s o l v e i n i t i a l r e f e r e n c e s ( NameService ) ;

82

ARE 6. CORBA
UNITATEA DE INVAT

27

NamingContextExt ncRef = NamingContextExtHelper . narrow ( o b j R e f ) ;

29

32

// l e g a r e a r e f e r i n t e i s e r v a n t u l u i i n s e r v i c i u l NameService
S t r i n g name = CmmdcService ;
NameComponent path [ ] = ncRef . to name ( name ) ;
ncRef . r e b i n d ( path , h r e f ) ;

34

System . out . p r i n t l n ( CmmdcServer r e a d y and w a i t i n g

36

// i n a s t e p t a r e a c l i e n t i l o r
orb . run ( ) ;

30
31

37

}
catch ( Exception e ) {
System . e r r . p r i n t l n ( ERROR: + e ) ;
e . p r i n t S t a c k T r a c e ( System . out ) ;
}
System . out . p r i n t l n ( CmmdcServer E x i t i n g

38
39
40
41
42
43

. . . );

44
45

. . . );

3. Realizarea programului client CmmdcClient.java:


1
2
3
4
5
7
8
10
11
12
13
15
16
17
18
19
21
22
23
25
26
27
28
29
30
31
32
33
34
35
36
37

im po rt
im po rt
im po rt
im po rt
im po rt

CmmdcApp . ;
o r g . omg . CosNaming . ;
o r g . omg . CosNaming . NamingContextPackage . ;
o r g . omg .CORBA. ;
java . u t i l . Scanner ;

p u b l i c c l a s s CmmdcClient {
s t a t i c Cmmdc cmmdcImpl ;
p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) {
try {
// c r e a r e a s i i n i t i a l i z a r e a unui r e p r e z e n t a n t ORB
ORB orb = ORB. i n i t ( a r g s , n u l l ) ;
// o b t i n e r e a u n e i r e f e r i n t e p e n t r u s e r v i c i u l d e n u m i r i l o r
// s e r v i c i i l o r i n r e g i s t r a t e
o r g . omg .CORBA. O b j e c t o b j R e f =
orb . r e s o l v e i n i t i a l r e f e r e n c e s ( NameService ) ;
NamingContextExt ncRef = NamingContextExtHelper . narrow ( o b j R e f ) ;
// o b t i n e r e a u n e i r e f e r i n t e l a s e r v i c i u l d o r i t
S t r i n g name = CmmdcService ;
cmmdcImpl = CmmdcHelper . narrow ( ncRef . r e s o l v e s t r ( name ) ) ;
System . out . p r i n t l n ( Obtained a h a n d l e on s e r v e r o b j e c t : + cmmdcImpl ) ;
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
l o n g m, n ;
System . out . p r i n t l n ( m= ) ;
m=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( n= ) ;
n=s c a n n e r . nextLong ( ) ;
System . out . p r i n t l n ( Cmmdc=+cmmdcImpl . cmmdc(m, n ) ) ;
}
catch ( Exception e ) {
System . out . p r i n t l n ( ERROR : + e ) ;
e . p r i n t S t a c k T r a c e ( System . out ) ;
}

6.1. CORBA

38
39

83

Programele se compileaz
a
javac CmmdcApp\*.java
4. Pornirea serviciului de intregistrare a numelor cu programul orbd.exe din
distributia jdk.
start orbd -ORBInitialHost localhost -ORBInitialPort 1050
5. Pornirea programului server prin
start java CmmdcServer -ORBInitialHost localhost -ORBInitialPort 1050
6. Lansarea programului client prin
java CmmdcClient -ORBInitialHost localhost -ORBInitialPort 1050

Test de evaluare a cunostintelor


1. Care sunt componentele unei aplicatii client server bazat pe CORBA?
2. C
ate si care sunt entit
atile care participa la executia unei aplicatii clientserver bazat pe CORBA?
3. Care este ideea solutiei CORBA pentru asigurarea interoperabilitatii ntre
client si server realizate n limbaje de programare diferite.
4. Explicati caracterul sincron al comunicarii n CORBA.
5. Ce ofer
a RMI-IIOP ?

Unitatea de nv
atare 7

JMS cu comunicatie punctual


a

Durata: 4 ore.

Introducere
Comunicatia prin apelul la distanta - inclusiv RMI - este sincron: programul
apelant se blocheaz
a si asteapta ca metoda apelata sa se termine si sa furnizeze
rezultatul cerut. Cu alte cuvinte apelul de procedura la distanta cere atat clientului c
at si serverului s
a fie simultan disponibile.
Comunicatiile asincrone ntre programe permit realizarea unor sisteme de programe cu un grad mult mai scazut de cuplare. Asemenea aplicatii se pot realiza
prin comunicatii de mesaje, mesaje care sunt retinute de un intermediar (serviciu
de mesagerie, server, broker, messaging middleware).
In prezent protocolul pentru realizarea aplicatiilor bazate pe comunicatii de
mesaje este Advanced Message Queue Protocol - AMQP. AMQP este un protocol
dezvoltat de mai multe firme bazat pe standardele World Wide Web Consortium
84

7.1. JAVA MESSAGE SERVICE (JMS)

85

(W3C) si Internet Engineering Task Force (IETF) pentru comunicare cu mesaje


prin intermediul unui serviciu de mesagerie si care se doreste independent de
limbajul de programare.
Modelul AMQP nglobeaz
a standardul Java Message Servuce - JMS, dezvoltat de Oracle - Sun Microsystems.
Comunicatia se realizeaz
a prin socluri TCP.

7.1

Java Message Service (JMS)

JMS defineste un cadru de programare Java (API) pentru realizarea aplicatiilor


bazate pe comunicatii asincrone. Exista mai multe implementari JMS, dintre care
semnalam:
Open Message Queue a firmei Oracle. Numele anterior al produsului a fost
Sun Java System Message Queue
ActiveMQ realizat
a de fundatia apache.
qpid realizat
a de fundatia apache.
O aplicatie JMS este alc
atuit
a 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
mpreun
a cu resursele lor.
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 coad
a, de unde este preluat de catre consumatorul care
s-a legat de coad
a. Dac
a de coada nu se leaga nici un consumator, atunci
mesajul este p
astrat n coad
a.
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.

86

ARE 7. JMS CU COMUNICAT

UNITATEA DE INVAT
IE PUNCTUALA

Structura unui mesaj Un mesaj este alcatuit din


Antet (header) : contine informatii pentru identificarea destinatiei cat si
pentru identificarea mesajului.
Propriet
ati : au caracter optional si sunt sub forma (nume, valoare). Propriet
atile ajut
a consumatorii sa selecteze mesajele.
Corpul mesajului : optional. Potrivit specificatiilor JMS exista 6 tipuri de
mesaje.
Message : mesaj fara corp;
StreamMessage : corpul mesajului contine un flux Java de date de tip
predefinit;
ByteMessage :
MapMessage : corpul mesajului contine o familie de perechi (nume,
valoare);
TextMessage : corpul mesajului contine un string;
ObjectMessage : corpul mesajului contine un obiect serializat.

7.2

Open Message Queue

Instalarea. Functie de resursa descarcata, n mediul Windows, instalarea


const
a din
Se dezarhiveaz
a fisierul openmq* *-installer-WINNT.zip si se lanseaza n
executie programul de instalare.
Se dezarhiveaz
a fisierul openmq* *-binary-WINNT.zip si se fixeaza atributele
fisierului mq\etc\imqenv.conf.
Lansarea serviciului JMS. Orice aplicatie JMS necesita functionarea serviciului JMS. Serviciul JMS se instaleaza prin
imqbrokerd -tty
Optiunea -tty are ca efect afisarea mesajelor pe ecran. Functionarea corecta este
indicat
a prin mesajul
imqbroker@hostname:7676 ready
Dac
a se doreste schimbarea portului atunci se foloseste optiunea -port port.
Pe un calculator pot coexista mai multe servicii JMS doar daca folosesc porturi distincte si au nume diferite. In acest caz, lansarea unui nou serviciu se face
prin
imqbrokerd -tty -port port -name name
Cu utilitarul imqsvcadmin putem

7.3. APACHE ACTIVEMQ

87

dezinstala : imqsvcadmin remove


verifica : imqsvcadmin query
instala : imqsvcadmin install
serviciul JMS ca serviciu Windows. Dezinstalarea si instalarea are efect odata cu
repornirea calculatorului.
Compilarea si executarea unui program necesita completarea variabilei
sistem classpath cu fisierele
JMS HOME\lib\jms.jar
JMS HOME\lib\imq.jar

7.3

Apache ActiveMQ

Instalarea se face dezarhiv


and fisierul descarcat ntr-un catalog ACTIVEMQ HOME.
Acest fisier este specific sistemului de operare utilizat, Windows sau Linux.
Lansarea serverului JMS se obtine prin
set JAVA_HOME=. . .
set ACTIVEMQ_HOME=. . .
%ACTIVEMQ_HOME%\bin\activemq

In cazul unui calculator izolat este nevoie de instalarea driver-ului Microsoft loopback Adaptor care sinuleaz
a existenta functonarii unei placi de retea active.
Distributia apache-activemq-5.*.* contine, ca exemplu, clasa EmbeddedBroker.java care lanseaz
a serverul JMS n lucru.
Compilarea unui program necesita prezenta n variabila de sistem classpath
a referintei c
atre fisierul ACTIVEMQ HOME\activemq-all-*.*.*.jar. Pentru executie,
variabila de sistem classpath nevoie sa contina referintele catre fisierele jar din
catalogul ACTIVEMQ HOME\lib.

7.4
7.4.1

Elemente de programare - JMS


Trimiterea unui mesaj

Trimiterea unui mesaj necesit


a:
1. Generarea unei fabrici de conexiuni. Fabrica de conexiuni este un obiect
administrator. Aceast
a operatie este specifica distributiei JMS.
In cazul de fata folosim obiectele create prin MessageQueue.
Se poate obtine prin

88

ARE 7. JMS CU COMUNICAT

UNITATEA DE INVAT
IE PUNCTUALA

ConnectionFactory cf=
new com.sun.messaging.ConnectionFactory();
Clasa com.sun.messaging.ConnectionFactory contine metoda
setProperty( String name, String value) prin intermediul careia
se precizeaz
a calculatorul si portul furnizorului de servicii JMS, fixand
atributele "imqBrokerHostName" si respectiv "imqBrokerHostPort".
Utiliz
and apache-activemq, fabrica de conexiuni se obtine prin
org.apache.activemq.ActiveMQConnectionFactory cf=
new org.apache.activemq.ActiveMQConnectionFactory
("tcp://host:61616");
2. Generarea conexiunii.
Se realizeaz
a prin
Connection conn=cf.createConnection();
Pentru realizarea acestui obiectiv se utilizeaza metoda createConnection,
dup
a caz, dintr-una din clasele
class ConnectionFactory{
Connection createConnection() throws JMSException;
Connection createConnection(String userName,String password)
throws JMSException;
}
class QueueConnectionFactory{
QueueConnection createQueueConnection() throws JMSException;
QueueConnection createQueueConnection(String userName,
String password) throws JMSException;
}
class TopicConnectionFactory{
TopicConnection createTopicConnection() throws JMSException;
TopicConnection createTopicConnection(String userName,
String password) throws JMSException;
}
unde Connection, QueueConnection, TopicConnection sunt interfete.
Amintim urm
atoarele metode ale unei interfete Connection
interface Connection{
Session createSession(boolean transacted,

7.4. ELEMENTE DE PROGRAMARE - JMS

89

int acknowledgeMode) throws JMSException;


void start() throws JMSException;
void close() throws JMSException;
}
interface QueueConnection{
QueueSession createQueueSession(boolean transacted,
int acknowledgeMode) throws JMSException;
void start() throws JMSException;
void close() throws JMSException;
}
interface TopicConnection{
TopicSession createTopicSession(boolean transacted,
int acknowledgeMode) throws JMSException;
void start() throws JMSException;
void close() throws JMSException;
}
Un obiect ce implementeaz
a interfata Connection asigura legatura clientului cu furnizorul JMS. Acest obiect este creat de fabrica de conexiuni.
Un client JMS trebuie s
a nchida conexiunile create.
Metoda start() asigur
a pornirea sau repornirea conexiunii n vederea
reception
arii mesajelor sosite.
3. Crearea unei sesiuni de lucru se face cu o metoda createSession().
Session session=conn.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Primul argument asigur
a (true) sau nu (false) caracterul indivizibil al
unit
atii de lucru, adic
a al unei sesiuni.
Al doilea argument indic
a modul de confirmare al receptarii mesajului.
Un obiect de tip Session defineste un context format dintr-un singur fir de
executie n care are loc producerea si consumul de mesaje.
Sunt definite
interface Session{
|
MessageProducer createProducer(Destination destination);
|
MessageConsumer createConsumer(Destination destination);
|
Message createMessage();
|
TextMessage createTextMessage();

90

ARE 7. JMS CU COMUNICAT

UNITATEA DE INVAT
IE PUNCTUALA

|
TextMessage createTextMessage(String s);
|
StreamMessage createStreamMessage();
|
MapMessage createMapMessage();
|
ObjectMessage createObjectMessage();
|
ObjectMessage createObjectMessage(Serializable object);
|
BytesMessage createBytesMessage();
|
}
|->interface QueueSession{
|
QueueSender createQueueSender(Queue queue);
|
QueueReceiver createQueueReceiver(Queue queue);
|
}
|->interface TopicSession{
TopicPublisher createPublisher(Topic topic);
TopicSubscriber createSubscriber(Topic topic);
TopicSubscriber createDurableSubscriber(Topic topic,
String name);
}
4. Generarea obiectului destinatie.
In cazul comunicatiilor punctuale obiectul destinatie este de tip Queue, iar
crearea se face prin
Destination numeDestinatie=sesssion.createQueue(String numeCoada)
iar pentru comunicatii axate pe subiect obiectul destinatie, de tip Topic se
instantiaz
a prin
Destination numeDestinatie=sesssion.createTopic(String numeSubiect)
Sunt definite arborescentele:
interface Destination
|
|->interface Queue
|
|->interface Topic
class Destination implements Destination
|
|->class Queue implements Destination, Queue, Serializable
|
|->class Topic implements Destination, Topic, Serializable

7.4. ELEMENTE DE PROGRAMARE - JMS

91

Utiliz
and Oracle-Sun Java System Message Queue obiecte de tip Queue sau
Topic se pot crea si prin
Queue q=new com.sun.messaging.Queue(String numeCoada);
Topic t=new com.sun.messaging.Topic(String numeSubiect);
5. Generarea produc
atorului de mesaje. Se realizeaza prin
MessageProducer producer=session.createProducer(obiectDestinatie);
Sunt definite interfetele
interface MessageProducer{
void send(Message mesaj);
}
interface QueueSender{
void send(Message mesaj);
}
interface TopicPublisher{
void publish(Message mesaj);
}
6. Generarea mesajelor. Un mesaj de tip TextMessage se poate crea prin
TextMessage m=session.createTextMessage();
m.setText(string);
7. Expedierea mesajelor se face cu metoda send(...) a producatorului de
mesaje.
Exemplul 7.4.1 Clasa urm
atoare genereaz
a ntr-un fir de executie, un num
ar
de mesaje de tip TextMessage ntr-o comunicatie punctual
a. Sf
arsitul expedierii mesajelor se indic
a prin generarea unui mesaj de tip Message. Num
arul
mesajelor este indicat de un parametru al constructorului.
1

import j a v a x . jms . ;

public c l a s s MsgSenderT extends Thread {


int n ;
S t r i n g queueName ;

4
5
7
8
9
10

MsgSenderT ( S t r i n g queueName , i n t n ) {
t h i s . queueName=queueName ;
t h i s . n=n ;
}

92

ARE 7. JMS CU COMUNICAT

UNITATEA DE INVAT
IE PUNCTUALA

public void run ( ) {


try {
// V a r i a n t a OracleSun Message Queue
com . sun . m e s s a g i n g . QueueConnectionFactory c f=
new com . sun . m e s s a g i n g . QueueConnectionFactory ( ) ;

12
13
14
15
16

// s e t P r o p e r t y e s t e metoda a c l a s e i
// com . sun . m e s s a g i n g . QueueConnnectionFactory
// ce i m p l e m e n t e a z a i n t e r f a t a QueueConnectionFactory
// dar nu a i n t e r f e t e i QueueConnectionFactory .
// c f . s e t P r o p e r t y ( imqBrokerHostName , h o s t ) ;
// c f . s e t P r o p e r t y ( imqBrokerHostPort , 7 6 7 6 ) ;

18
19
20
21
22
23

30

// V a r i a n t a ApacheMessageQueue
// o r g . apache . a c t i v e m q . ActiveMQConnectionFactory c f=
//new o r g . apache . a c t i v e m q .
//
ActiveMQConnectionFactory ( t c p : / / l o c a l h o s t : 6 1 6 1 6 ) ;
C o n n e c t i o n conn=c f . c r e a t e C o n n e c t i o n ( ) ;
S e s s i o n s e s s i o n=conn . c r e a t e S e s s i o n ( f a l s e , S e s s i o n .AUTO ACKNOWLEDGE) ;

32

D e s t i n a t i o n q=s e s s i o n . c r e a t e Q u e u e ( queueName ) ;

34

MessageProducer p r o d u c e r=s e s s i o n . c r e a t e P r o d u c e r ( q ) ;

36

TextMessage m=s e s s i o n . c r e a t e T e x t M e s s a g e ( ) ;
f o r ( i n t i =0; i <n ; i ++){
m. s e t T e x t ( H e l l o +i ) ;
p r o d u c e r . send (m) ;
}
// indicam s f a r s i t u l t r i m i t e r i i m e s a j e l o r
p r o d u c e r . send ( s e s s i o n . c r e a t e M e s s a g e ( ) ) ;
session . close ();
conn . c l o s e ( ) ;

25
26
27
28
29

37
38
39
40
41
42
43
44

}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( JMSException : +e . g e t M e s s a g e ( ) ) ;
}
System . out . p r i n t l n ( Sen de r f i n i s h e d ) ;

45
46
47
48
49

50
51

7.4.2

Receptia sincron
a a unui mesaj

Primele patru actiuni sunt identice cu cele de la trimiterea unui mesaj, adic
a
1. Generarea unei fabrici de conexiuni.
2. Generarea conexiunii.
3. Crearea unei sesiuni de lucru.
4. Generarea obiectului destinatie.
5. Generarea consumatorului de mesaje. Se realizeaza prin

7.4. ELEMENTE DE PROGRAMARE - JMS

93

MessageConsumer consumer=session.createConsumer(q);
q desemn
and obiectul destinatie.
Sunt definite interfetele
interface MessageConsumer{
|
Message receive();
|
Message receive(long timeout);
|
Message receiveNoWait();
|
}
|-> interface QueueReceiver
|
|-> interface TopicSubscriber
6. Receptia mesajelor se face cu una din metodele consumatorului de mesaje:
Message receive()
Message receive(long timeout)
Message receiveNoWait()
Exemplul 7.4.2 Receptia de tip sincron a mesajelor ntr-un fir de executie este
efectuat de clasa urm
atoare:
1

import j a v a x . jms . ;

public c l a s s SyncMsgReceiverT extends Thread {


S t r i n g queueName ;

4
6
7
8
10
11
12
13
14
15
16
17
18
19
21
22
23
24
25
26

SyncMsgReceiverT ( S t r i n g queueName ) {
t h i s . queueName=queueName ;
}
public void run ( ) {
try {
// V a r i a n t a OracleSun Message Queue
com . sun . m e s s a g i n g . QueueConnectionFactory c f=
new com . sun . m e s s a g i n g . QueueConnectionFactory ( ) ;
// s e t P r o p e r t y e s t e metoda a c l a s e i QueueConnnectionFactory
// ce i m p l e m e n t e a z a i n t e r f a t a QueueConnectionFactory
// dar nu e s t e a i n t e r f e t e i .
// c f . s e t P r o p e r t y ( imqBrokerHostName , h o s t ) ;
// c f . s e t P r o p e r t y ( imqBrokerHostPort , 7 6 7 6 ) ;
// V a r i a n t a ApacheMessageQueue
// o r g . apache . a c t i v e m q . ActiveMQConnectionFactory c f=
//new o r g . apache . a c t i v e m q .
//
ActiveMQConnectionFactory ( t c p : / / l o c a l h o s t : 6 1 6 1 6 ) ;
C o n n e c t i o n conn=c f . c r e a t e C o n n e c t i o n ( ) ;
S e s s i o n s e s s i o n=conn . c r e a t e S e s s i o n ( f a l s e , S e s s i o n .AUTO ACKNOWLEDGE) ;

94

ARE 7. JMS CU COMUNICAT

UNITATEA DE INVAT
IE PUNCTUALA

D e s t i n a t i o n q=s e s s i o n . c r e a t e Q u e u e ( queueName ) ;
MessageConsumer consumer=s e s s i o n . createConsumer ( q ) ;
conn . s t a r t ( ) ;
Message msg=n u l l ;
while ( ( msg=consumer . r e c e i v e ( ) ) ! = n u l l ) {
i f ( msg instanceof TextMessage ) {
TextMessage m=(TextMessage ) msg ;
System . out . p r i n t l n (m. g e t T e x t ( ) ) ;
}
else
break ;
}
session . close ();
conn . c l o s e ( ) ;

27
28
29
30
31
32
33
34
35
36
37
38
39
40

}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( JMSException : +e . g e t M e s s a g e ( ) ) ;
}
System . out . p r i n t l n ( Consumer f i n i s h e d ) ;

41
42
43
44
45

46
47

Exemplul 7.4.3 Trimiterea si receptia mesajelor se face prin aplicatia


1
2
3
4
5
6
7
8
9
10
11
12
13
14

c l a s s MsgHelloT {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
i n t n=3;
S t r i n g queueName=MyQueue ;
i f ( a r g s . l e n g t h >0)
queueName=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
n=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
MsgSenderT s e n d e r=new MsgSenderT ( queueName , n ) ;
SyncMsgReceiverT r e c e i v e r =new SyncMsgReceiverT ( queueName ) ;
receiver . start ();
sender . s t a r t ( ) ;
}
}

7.4.3

Receptia asincron
a a unui mesaj

Receptia asincron
a a mesajelor presupune implementarea interfetei
MessageListener ce contine o singura metoda
public void onMessage(Message mesaj);
care fixeaz
a prelucrarea mesajului.
Metoda MessageConsumer.setMessageListener(MessageListener obj ) fixeaz
a obiectul ce implementeaza interfata Messagelistener.
Astfel, caracterul asincron consta din faptul ca mesajele sunt preluate de
ascult
ator - adic
a obiectul ce implementeaza interfata MessageListener si nu de
clientul JMS.

7.4. ELEMENTE DE PROGRAMARE - JMS

95

ideea exemplelor anterioare, un consumator de tip asincron


Exemplul 7.4.4 In
al mesajelor este dat n clasa urm
atoare:
1
2
3

import j a v a x . jms . ;
public c l a s s AsyncMsgReceiverT extends Thread {
S t r i n g queueName ;
AsyncMsgReceiverT ( S t r i n g queueName ) {
t h i s . queueName=queueName ;
}

5
6
7

public void run ( ) {


try {
// V a r i a n t a OracleSun Message Queue
com . sun . m e s s a g i n g . QueueConnectionFactory c f=
new com . sun . m e s s a g i n g . QueueConnectionFactory ( ) ;
// s e t P r o p e r t y e s t e metoda a c l a s e i QueueConnnectionFactory
// ce i m p l e m e n t e a z a i n t e r f a t a QueueConnectionFactory
// dar nu e s t e a i n t e r f e t e i .
// c f . s e t P r o p e r t y ( imqBrokerHostName , h o s t ) ;
// c f . s e t P r o p e r t y ( imqBrokerHostPort , 7 6 7 6 ) ;

9
10
11
12
13
14
15
16
17
18

// V a r i a n t a ApacheMessageQueue
// o r g . apache . a c t i v e m q . ActiveMQConnectionFactory c f=
//new o r g . apache . a c t i v e m q .
//
ActiveMQConnectionFactory ( t c p : / / l o c a l h o s t : 6 1 6 1 6 ) ;

20
21
22
23

C o n n e c t i o n conn=c f . c r e a t e C o n n e c t i o n ( ) ;
S e s s i o n s e s s i o n=conn . c r e a t e S e s s i o n ( f a l s e , S e s s i o n .AUTO ACKNOWLEDGE) ;
D e s t i n a t i o n q==s e s s i o n . c r e a t e Q u e u e ( queueName ) ;
MessageConsumer consumer=s e s s i o n . createConsumer ( q ) ;
T e x t L i s t e n e r t e x t L i s t e n e r=new T e x t L i s t e n e r ( ) ;
consumer . s e t M e s s a g e L i s t e n e r ( t e x t L i s t e n e r ) ;
conn . s t a r t ( ) ;
t e x t L i s t e n e r . run ( ) ;
conn . c l o s e ( ) ;

25
26
27
28
29
30
31
32
33

}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}
System . out . p r i n t l n ( Consumer f i n i s h e d ) ;

34
35
36
37
38

39
40

mpreun
a cu ascult
atorul
1
2
3
4
5
6
7
8
9
10
11
12

import j a v a x . jms . ;
public c l a s s
T e x t L i s t e n e r implements M e s s a g e L i s t e n e r {
boolean s f a r s i t =f a l s e ;
public void onMessage ( Message message ) {
i f ( message instanceof TextMessage ) {
TextMessage m=(TextMessage ) message ;
try {
System . out . p r i n t l n (m. g e t T e x t ( ) ) ;
}
catch ( JMSException e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}

96

ARE 7. JMS CU COMUNICAT

UNITATEA DE INVAT
IE PUNCTUALA

}
else
s f a r s i t =true ;

13
14
15
16

18

public void run ( ) {


while ( ! s f a r s i t ) ;
}

19
20
21

Test de evaluare a cunostintelor


1. Explicati caracterul asincron din JMS.
2. Care este rolul furnizorului (provider) JMS.
3. Precizati si explicati modelele de comunicatii cu mesaje n JMS.
4. Precizati produsele JMS utilizate.
5. Precizati diferenta de utilizare dintre Sun Message Queue si Apache-activemq,
din punct de vedere al programarii aplicatiilor.

Unitatea de nv
atare 8

JMS cu comunicatie bazat


a pe
subiect

Durata: 2 ore.

8.1
8.1.1

Publicarea mesajelor
Publicarea mesajelor

Publicarea mesajelor corespunzatoare unui subiect se face asemanator cu


transmiterea mesajelor n comunicatia punctuala, dar folosind instante ale claselor
dedicate acestui tip de comunicatie.
Exemplul 8.1.1
1

import j a v a x . jms . ;

public c l a s s MsgPublisherT extends Thread {


int n ;
String subiect ;

4
5
7
8
9
10

MsgPublisherT ( S t r i n g s u b i e c t , i n t n ) {
t h i s . n=n ;
t h i s . s u b i e c t=s u b i e c t ;
}

97

98

ARE 8. JMS CU COMUNICAT


PE SUBIECT
UNITATEA DE INVAT
IE BAZATA

public void run ( ) {


try {
// V a r i a n t a OracleSun Message Queue
com . sun . m e s s a g i n g . 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 ) ;

12
13
14
15
16
17
18

// V a r i a n t a ApacheMessageQueue
// o r g . apache . a c t i v e m q . ActiveMQConnectionFactory c f=
//
new o r g . apache . a c t i v e m q .
//
ActiveMQConnectionFactory ( t c p : / / l o c a l h o s t : 6 1 6 1 6 ) ;

20
21
22
23

T o p i c C o n n e c t i o n conn=c f . c r e a t e T o p i c C o n n e c t i o n ( ) ;
TopicSession session =
conn . c r e a t e T o p i c S e s s i o n ( f a l s e , S e s s i o n .AUTO ACKNOWLEDGE) ;
Destination t = session . createTopic ( subiect ) ;
MessageProducer p r o d u c e r = s e s s i o n . c r e a t e P r o d u c e r ( t ) ;

25
26
27
28
29

// Topic t=new com . sun . m e s s a g i n g . Topic ( s u b i e c t ) ;


// T o p i c P u b l i s h e r p u b l i s h e r=s e s s i o n . c r e a t e P u b l i s h e r ( t ) ;

31
32

TextMessage m=s e s s i o n . c r e a t e T e x t M e s s a g e ( ) ;
f o r ( i n t i =0; i <n ; i ++){
m. s e t T e x t ( Despre +s u b i e c t+ +i ) ;
p r o d u c e r . send (m) ;
// p u b l i s h e r . p u b l i s h (m) ;
}
p r o d u c e r . send ( s e s s i o n . c r e a t e M e s s a g e ( ) ) ;
// p u b l i s h e r . p u b l i s h ( s e s s i o n . c r e a t e M e s s a g e ( ) ) ;
session . close ();
conn . c l o s e ( ) ;

34
35
36
37
38
39
40
41
42
43

}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( JMSException : +e . g e t M e s s a g e ( ) ) ;
}
System . out . p r i n t l n ( P u b l i s h e r f i n i s h e d ) ;

44
45
46
47
48

49
50

Varianta comentat
a este o solutie specifica implementarii Oracle Java System
Message Queue.

8.1.2

Subscrierea si receptia mesajelor

Dac
a t este obiectul de tip Destination, clientii se aboneaza - subscriu unui subiect prin
TopicSubscriber consumer=session.createSubscriber((Topic)t);
Subscrierea este este valabila atata timp cat clientul este activ. Pentru a primi
toate mesajele specifice subiectului, chiar si cand clientul este inactiv, acesta
trebuie s
a fie durabil, adica crearea consumatorului sa se faca prin

8.1. PUBLICAREA MESAJELOR

99

conn.setClientID("myID");
TopicSubscriber consumer=
session.createDurableSubscriber((Topic)t,"nameClient");
In ambele cazuri, clientul primeste doar mesajele publicate din momentul subscrierii.
Exemplul 8.1.2
1

import j a v a x . jms . ;

public c l a s s MsgSubscriberT extends Thread {


String subiect ;
String clientID ;
S t r i n g clientName ;

4
5
6
8
9
10
11
12
14
15
16
17
18
19
20
22
23
24
25
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

MsgSubscriberT ( S t r i n g s u b i e c t , S t r i n g c l i e n t I D , S t r i n g c l i e n t N a m e ) {
t h i s . s u b i e c t=s u b i e c t ;
t h i s . c l i e n t I D=c l i e n t I D ;
t h i s . c l i e n t N a m e=c l i e n t N a m e ;
}
public void run ( ) {
try {
//
V a r i a n t a O r a c l e Message Queue
com . sun . m e s s a g i n g . T o p i c C o n n e c t i o n F a c t o r y c f=
new com . sun . m e s s a g i n g . T o p i c C o n n e c t i o n F a c t o r y ( ) ;
// c f . s e t P r o p e r t y ( imqBrokerHostName , h o s t ) ;
// c f . s e t P r o p e r t y ( imqBrokerHostPort , 7 6 7 6 ) ;
//
V a r i a n t a ApacheMessageQueue
// o r g . apache . a c t i v e m q . ActiveMQConnectionFactory c f=
//new o r g . apache . a c t i v e m q .
//
ActiveMQConnectionFactory ( t c p : / / l o c a l h o s t : 6 1 6 1 6 ) ;
T o p i c C o n n e c t i o n conn=c f . c r e a t e T o p i c C o n n e c t i o n ( ) ;
conn . s e t C l i e n t I D ( c l i e n t I D ) ;
T o p i c S e s s i o n s e s s i o n=
conn . c r e a t e T o p i c S e s s i o n ( f a l s e , S e s s i o n .AUTO ACKNOWLEDGE) ;
Destination t = session . createTopic ( subiect ) ;
T o p i c S u b s c r i b e r consumer=
s e s s i o n . c r e a t e D u r a b l e S u b s c r i b e r ( ( Topic ) t , c l i e n t N a m e ) ;
conn . s t a r t ( ) ;
Message msg=n u l l ;
while ( ( msg=consumer . r e c e i v e ( ) ) ! = n u l l ) {
i f ( msg instanceof TextMessage ) {
TextMessage m=(TextMessage ) msg ;
System . out . p r i n t l n ( c l i e n t N a m e+ r e c e i v e d : +m. g e t T e x t ( ) ) ;
}
else
break ;
}
session . close ();
conn . c l o s e ( ) ;
}
catch ( E x c e p t i o n e ) {

100

ARE 8. JMS CU COMUNICAT


PE SUBIECT
UNITATEA DE INVAT
IE BAZATA

System . out . p r i n t l n ( JMSException : +e . g e t M e s s a g e ( ) ) ;

48

49

50
51

Apelarea celor dou


a activitati se face prin
Exemplul 8.1.3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

c l a s s MsgPS{
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
S t r i n g s u b i e c t=JMS ;
i n t n=3 , noAbonati =3;
i f ( a r g s . l e n g t h >0)
s u b i e c t=a r g s [ 0 ] ;
i f ( a r g s . l e n g t h >1)
n=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
MsgPublisherT p u b l i s h e r=new MsgPublisherT ( s u b i e c t , n ) ;
MsgSubscriberT [ ] abonat=new MsgSubscriberT [ noAbonati ] ;
publisher . start ( ) ;
f o r ( i n t i =0; i <noAbonati ; i ++){
abonat [ i ]=new MsgSubscriberT ( s u b i e c t , ID+i , i d +i ) ;
abonat [ i ] . s t a r t ( ) ;
}
}
}

Modulul II

Programare distribuit
a cu
comunicatii bazate pe
protocolul HTTP

101

102

Introducere
Se prezint
a tehnologiile de baza pentru aplicatiile Web
Servlet;
Java Server Pages (JSP);
Portlet.

Competente
Se descrie instalarea unui server Web container de servlet si JSP, instalarea
si utilizarea unui servlet, pagini JSP si portlet. Accentul se pune pe explicarea
arhitecturii programelor Java pentru fiecare tehnologie n parte.

Unitatea de nv
atare 9

Servlet

Durata: 3 ore.

Introducere
Printre aplicatiile distribuite de tip client-server, n care comunicatiile se
bazeaza pe protocolul http, se disting
Aplicatii Web (site): Cererea adresata serverului este lansata de o persoana
prin intermediul unui site, utilizand un program navigator: Google Chrome,
Mozilla Firefox, Microsoft InternetExplorer, Opera, Apple Safari, etc.
Servicii Web: Cererea c
atre server se face de un program. Aplicatia server
si client se programeaz
a utilizand interfete de programare specifice.
Un servlet este
un program Java care se excuta pe un server Web, compatibil;
103

104

ARE 9. SERVLET
UNITATEA DE INVAT

gestionat de serverul Web;


capabil s
a receptioneze si sa rapunda cererilor formulate de clienti.
De asemenea vom utiliza termenul servlet si pentru aplicatia Web corespunzatoare.
Pe platforma de programare Java, servlet-ul este componenta care sta la baza
dezvolt
arii aplicatiile si serviciile Web.
Programarea si utilizarea unui servlet necesita:
Cunoasterea marcajului html <form> pentru realizarea formularelor de
introducere a datelor;
Utilizarea unui server Web, container de servleti.

9.1

Marcajul <form>

Intr-un document html introducerea datelor se poate obtine utilizand marcajul <form> ...</form> .
Atribute ale marcajului <form> . Reamintim ca atributele se prezint
a
ca perechi (nume, valoare) si se scriu n antetul marcajului sub forma nume =
valoare.
Nume
action
method

Valoare
adresa tip URL
GET

POST

id
name
onSubmit

Semnificatia valorii
Resursa care prelucreaza formularul.
Mesajul trimis serverului Web contine dup
a
adresa URL numele si valorile parametrilor
introdusi. Adaugarea se face potrivit sintaxei
?numeParam1=valoare&numeParam2=valoare. . .
Lungimea mesajului nu poate depasi 255 caractere.
Transmisia datelor se face n fluxuri de date.
Permite transferul unor fisiere de pe masina
clientului pe masina serverului.
Parametru de identificare a formularului (optional).
Nume atribuit formularului (optional).
Metoda JavaScript executata naintea apelarii
serverului Web (optional).

In continutul marcajului <form> putem include elemente de control prin


marcajele
<input>
<option>

9.2. SERVER WEB - CONTAINER DE SERVLET

105

<select>
<textarea>
Atributele marcajului < input> sunt:
Nume
type

Valoare
text
password
submit
reset
file
hidden

Semnificatie
Se asteapta introducerea unui text
Se asteapta introducerea unei parole
Se marcheaza sfarsitul completarii formularului
Se reinitializeaza formularul
Permite selectarea unui fisier
Transmite mai departe un atribut fara vizualizarea lui
numele controlului
valoarea (initiala) a controlului
num
arul caracterelor atasat controlului

name
value
size
In cazul marcajului < select> utilizarea este
<select name="nume">
<option value="valoare"> Valoare
. . . . . . . . . . . . . . . .
</select>

Valoarea atributului nume este data de valoarea selectata.

9.2

Server Web - container de servlet

In prezent sunt disponibile mai multe servere Web n care poate fi instalat
un servlet si un fisier JSP Java Server Pages. Se spune ca serverul Web este
container de servlet si JSP. Dintre produsele gratuite amintim
apache-tomcat
jetty
glassfish
Acest server Web este utilizat n Glassfishv3 - o implementare JEE (Java
Enterprise Edition) de la Oracle.
JBoss
Geronimo, o alta implementare JEE dezvoltata de apache, poate utiliza containerul apache-tomcat sau jetty.

106

ARE 9. SERVLET
UNITATEA DE INVAT

Serverul Web apache-tomcat


In continuare se va folosi serverul Web apache-tomcat, pe scurt tomcat.
Serverul Web tomcat este distribuit gratuit, putand fi descarcat de la adresa
www.apache.org.
Instalarea serverului n mediul Windows revine la dezarhivarea fisierului
desc
arcat apache-tomcat-***, ntr-un catalog TOMCAT HOME. Utilizarea serverului necesit
a fixarea a doi parametri sistem:
CATALINA HOME= calea la catalogul n care s-a instalat produsul - TOMCAT HOME;
JAVA HOME=calea la distributia Java utilizata.
Pachetul contine cataloagele1 : bin, common, conf, logs, server, shared,
temp, webapps, work.
Serverul se lanseaz
a prin comanda
TOMCAT HOME\bin\startup
si se opreste cu comanda
TOMCAT HOME\bin\shutdown
Din catalogul TOMCAT HOME, lansarea se poate obtine cu ajutorul fisierului de
comenzi (*.bat)
set CATALINA_HOME=. . .
set JAVA_HOME=. . .
bin\startup
Optional se poate instala / activa managerul / administatorul serverului Web
tomcat.
Verificarea function
arii serverului Web tomcat se face apeland dintr-un navigator pagina http://host:port unde
host este numele calculatorului pe care ruleaza tomcat;
Portul implicit este 8080.

Reusita este ilustrat


a de imaginea motanului
1

Numele si num
arul cataloagelor este dependent de distributia apache-tomcat.

9.3. REALIZAREA UNUI SERVLET

9.3

107

Realizarea unui servlet

Interfata de programare (API) pentru servlet a ajuns la versiunea 3, versiune


pe care o vom utiliza n cele ce urmeaza. Aceasta interfata de programare nu face
parte din JDK, fiind implementat de fiecare producator de server Web container
de servlet.
Structura minimal
a a unui servlet este
catalogAppServlet
|--> WEB-INF
|
|--> classes
|
|
|
*.class
|
|--> lib
|
|
|
*.jar
|
index.html
Catalogul classes contine fisierele class ale aplicatiei servlet.
Catalogul lib este optional si va contine resursele jar suplimentare cerute de
clasele servlet-ului.
Prin intermediul fisierului index.html se apeleaza aplicatia servlet. Adresa de
apelare (URL - Universal Resource Locator ) a aplicatiei servlet este
http://host:port/catalogAppServlet
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/catalogAppServlet/xyz.html
host este numele calculatorului pe care ruleaza serverul Web - gazda aplicatiei
servlet. Portul implicit utilizat de un server Web container de servlet este 8080.
Catalogul aplicatiei este denumit context-ul servlet-ului.
Apelarea servlet-ului se poate face:
din meniul File/Open al unui navigator;
ca referint
a ntr-un document html
<a href="URL-servlet">...</a>
Din documentul html pomenit anterior, apelarea clasei servlet se face uzual
prin intermediul atributului action a elementului form. Valoarea atributului
este numele de apel al servlet-ului.
Legatura cu clasa servlet-ului se poate realiza
programat prin adnot
ari n codul servlet-ului;

108

ARE 9. SERVLET
UNITATEA DE INVAT

descriptiv n catalogul WEB-INF se editeaza fisierul web.xml.


In versiunile anterioare ale interfetei de programare servlet aceasta a fost
unica optiune.
Trebuie demarcat
a diferenta dintre apelarea / lansarea n executie a clasei
servlet de apelarea aplicatiei Web.
Modul programat se bazeaza pe adnotarea javax.servlet.annotation.WebServlet
cu elementele:
String
name
String[ ]
urlPatterns
@InitParams[ ] initParam
boolean
asyncSupported
long
asyncTimeout

Modul descriptiv In fisierul web.xml apar elementele


1. <servlet> leag
a numele servlet-ului definit n elementul <servlet-name>
de clasa servlet-ului dat n elementul <servlet-class> .
2. <servlet-mapping> defineste numele sub care servlet-ul identificat prin
<servlet-name> nume servlet< /servlet> se invoca din programul navigator. Acest identificator - numeApel - se fixeaza n elementul <url-pattern>
. Identificatorul are ca prefix caracterul / (slash).
Structura unui fisier web.xml este
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

<?xml version= 1 . 0 e n c o d i n g=UTF8 ?>


<webapp version= 3 . 0 xmlns= h t t p : // j a v a . sun . com/xml/ ns / j a v a e e
x m l n s : x s i= h t t p : //www. w3 . o r g /2001/XMLSchemai n s t a n c e >
< s e r v l e t>
<s e r v l e t name>n u m e s e r v l e t 1</ s e r v l e t name>
<s e r v l e t c l a s s>Nume clasa</ 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>
<s e r v l e t name>n u m e s e r v l e t 2</ s e r v l e t name>
<s e r v l e t c l a s s>Nume clasa</ 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>n u m e s e r v l e t 1</ s e r v l e t name>
<u r l p a t t e r n>/ numeApel 1</ u r l p a t t e r n>
</ s e r v l e t mapping>
<s e r v l e t mapping>
<s e r v l e t name>n u m e s e r v l e t 2</ s e r v l e t name>
<u r l p a t t e r n>/ numeApel 2</ u r l p a t t e r n>
</ s e r v l e t mapping>
. . .
</webapp>

Unui element <servlet> i pot corespunde mai multe elemente <servlet-mapping>,


prin utilizarea de numeApel diferite.
Optional web.xml poate contine elementul

9.3. REALIZAREA UNUI SERVLET

109

<welcome-file-list>
<welcome-file>
fisier.html sau jsp
</welcome-file>
</welcome-file-list>

cu precizarea fisierelor html sau jsp care apeleaza aplicatia Web. Declaratia
fisierului index.html este implicit
a.
Compilarea clasei servlet necesita completarea variabilei de mediu classpath
cu fisierul TOMCAT HOME\lib\servlet-api.jar.
Odat
a completat
a structura de cataloage si fisiere ale aplicatiei servlet aceasta
structur
a trebuie copiat
a n catalogul TOMCAT HOME\webapps. Aceasta operatie
se numeste desf
asurarea (deployment) sau instalarea servlet-ului. Copierea se
poate executa si cu serverul Web pornit.
Pentru instalarea unui servlet exista mai multe alternative:
Din catalogul catalogAppServlet se realizeaza arhiva catalogAppServlet.war
jar cfv catAppServlet.war WEB-INF\ index.html
care se copiaz
a n catalogul TOMCAT HOME\webapps.
Serverul Web tomcat va dezarhiveaza arhiva. Astfel servlet-ul este instalat.
Aceast
a instalare se numeste instalare dinamic
a - hot deployment.
Dac
a fisierul war este creat, atunci n locul copierii, instalarea se poate face
prin componenta manager a lui tomcat.
O alt
a posibilitate de instalare a unui servlet n serverul web tomcat este
prin intermediul produsului apache-tomcat-deployer. apache-tomcat-deployer
permite instalarea unui servlet de la distanta cat si instalarea comandata
dintr-un program.

9.3.1

Codul unui servlet

Un servlet implementeaz
a interfata Servlet sau extinde una din clasele GenericServlet
sau HttpServlet. GenericServlet implementeaza interfata Servlet, iar HttpServlet
extinde clasa GenericServlet. Extinzand clasa GenericServlet nu este nevoie
de rescrierea tuturor metodelor abstracte ale intrefetei Servlet.
Metodele interfetei Servlet sunt
abstract public void init(ServletConfig config)
Se apeleaz
a o singur
a dat
a la lansarea servlet-ului.
abstract public void service(ServletRequest req, ServletResponse
res)throws ServletException,IOException
Metoda este apelat
a de serverul Web pentru rezolvarea cererii unui client.

110

ARE 9. SERVLET
UNITATEA DE INVAT

abstract public void destroy()


Se apeleaz
a o singura data la distrugerea servlet-ului.
public String getServletInfo()
public ServletConfig getServletConfig()
In cele ce urmeaz
a o clasa servlet va fi o clasa care extinde clasa HttpServlet.
In locul metodei service(...), programatorul suprascrie metodele doGet(...)
sau doPost(...), n functie de metoda utilizata de client la lansarea cererii.
Practic, un servlet consta din scrierea metodelor
void init(ServletConfig config)
Aceast
a metod
a este optionala.
public void init(ServletConfig config) throws ServletException{
super.init(config);
// cod de initializare
}
Obiectul config are o metoda String getInitParameter(String numeParam)
cu ajutorul c
areia se pot recupera parametri de initializare asociati servletului si care se dau fie prin adnotarea @initParams, fie n fisierul web.xml
prin elementele
<init-param>
<param-name> NumeleParametrului </param-name>
<param-value> Valoare </param-value>
</init-param>
cuprinse n elementul <servlet>.
protected void doGet(HttpServletRequest req, HttpServletResponse
res) throws IOException, ServletException
Trateaz
a o cerere trimisa cu metoda GET (vezi marcajul <form>).
protected void doPost(HttpServletRequest req, HttpServletResponse
res) throws IOException, ServletException
Trateaz
a o cerere trimisa cu metoda POST (vezi marcajul <form>).
Activit
atile de ntreprins ntr-o metoda doGet() sau doPost() sunt

9.3. REALIZAREA UNUI SERVLET

111

1. Stabilirea naturii r
aspunsului:
res.setContentType(String tip)
unde tip specific
a tipul MIME - Multipurpose Internet Mail Extensions al
raspunsului:
"text/html" - pagin
a html;
"text/xml" - document xml;
"text/plain" - text;
"image/jpg" - imagine gif;
"image/gif" - imagine jpg.
2. Se obtine o referinta c
atre un obiect care realizeaza transmisia datelor catre
navigatorul clientului:
ServletOutputStream out = res.getOutputStream();
sau
PrintWriter out=res.getWriter();
3. Se preiau datele cererii cu una din metodele:
String getParameter(String numeParapetru)
java.util.Enumeration getParameterNames()
4. Rezolv
a cererea clientului;
5. Formeaz
a si scrie r
aspunsul;
6. Inchide conexiunea obiectului prin care s-a realizat transmisia datelor catre
navigatorul clientului prin out.close().
Un utilizator lanseaz
a o cerere catre servlet. De obicei acest lucru se realizeaza
prin completarea unui formular al unui document html. Programul navigator
trimite cererea serverului Web prin intermediul caruia este lansat servlet-ul n
actiune.
Ciclul de viat
a al unui servlet. Cand un servlet este apelat prima data
de catre serverul Web se execut
a metoda init. Dupa aceasta, fiecarei cereri
lansate de un utilizator i se asociaza un fir de executie n care se apeleaza metoda
service. Metoda service apeleaza apoi metodele doGet(), doPost().
Exemplul 9.3.1 Servlet-ul Hello: Clientul transmite numele servet-ului care i
r
aspunde cu mesajul de salut Hi + nume!.
Formularul html prin care clientul introduce numele este (index.html )

112

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

ARE 9. SERVLET
UNITATEA DE INVAT

<html>
<head>
< t i t l e> S e r v l e t u l H e l l o </ t i t l e>
</head>
<body>
<center>
<h1> Pagina de a p e l a r e a s e r v l e t u l u i H e l l o S e r v l e t </h1>
<form method= p o s t action= h e l l o >
<p>I n t r o d u c e t i numele :
<input type= t e x t name=name s i z e =20>
<p>
<input type= submit >
</form>
</ center>
</body>
</html>

In modul programat servlet-ului are codul


1
2
3
4
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

import
import
import
import

@WebServlet ( u r l P a t t e r n s = / h e l l o )
public c l a s s H e l l o S e r v l e t extends H t t p S e r v l e t {
public void doGet ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
r e s . setContentType ( t e x t / html ) ;
S e r v l e t O u t p u t S t r e a m out=r e s . getOutputStream ( ) ;
S t r i n g nume=r e q . g e t P a r a m e t e r ( name ) ;
out . p r i n t l n ( <html> ) ;
out . p r i n t l n ( <head><t i t l e >H e l l o S e r v l e t </ t i t l e ></head> ) ;
out . p r i n t l n ( <body> ) ;
out . p r i n t l n ( <h1>H e l l o S e r v l e t </h1> ) ;
out . p r i n t l n ( <p> ) ;
out . p r i n t l n ( Hi + nume+ ! ) ;
out . p r i n t l n ( </p> ) ;
out . p r i n t l n ( </body> ) ;
out . p r i n t l n ( </html> ) ;
out . c l o s e ( ) ;
}
public void doPost ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
doGet ( req , r e s ) ;
}

25
26
27
28
29

java . io . ;
javax . s e r v l e t . ;
javax . s e r v l e t . http . ;
j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;

In modul descriptiv, n locul liniilor de cod 4-6 va fi folosit fisierul web.xml


1
2
3
4
5
6
7

<?xml version= 1 . 0 e n c o d i n g=UTF8 ?>


<webapp version= 3 . 0 xmlns= h t t p : // j a v a . sun . com/xml/ ns / j a v a e e
x m l n s : x s i= h t t p : //www. w3 . o r g /2001/XMLSchemai n s t a n c e >
< s e r v l e t>
<s e r v l e t name> h e l l o</ s e r v l e t name>
<s e r v l e t c l a s s>H e l l o 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>

9.3. REALIZAREA UNUI SERVLET

9
10
11
12
13

113

<s e r v l e t mapping>
<s e r v l e t name> h e l l o</ s e r v l e t name>
<u r l p a t t e r n>/ h e l l o</ u r l p a t t e r n>
</ s e r v l e t mapping>
</webapp>

Compilarea si arhivarea servlet-ului o vom realiza prin intermediul lui apacheant. In acest scop se creaz
a structura:
hello
|
|---> src
|
|
|
HelloServlet.java
|
|---> lib
|
|---> web
|
|
|
web.xml
|
|---> web-files
|
|
|
index.html
|
build.xml

si se utilizeaz
a fisierul build.xml
1
2
3
4
5
7
8
9
10
11
12
14
15
16
17
18
19
20
21
23
24
25
26
27
28
30
31
32
33
34
35
36
37

<p r o j e c t b a s e d i r= . default= g e n e r a t e . war >


<p r o p e r t y name=TOMCAT HOME v a l u e= . . . / apachetomcat . . />
<p r o p e r t y name= d i s t . name v a l u e= a p p h e l l o />
<p r o p e r t y name= d i s t . d i r v a l u e= d i s t />
<p r o p e r t y name= b u i l d . d i r v a l u e= b u i l d />
<path i d= m y c l a s s p a t h >
< f i l e s e t d i r= l i b >
<i n c l u d e name= . j a r />
</ f i l e s e t>
<p a t h e l e m e n t path= ${TOMCAT HOME}/ l i b / s e r v l e t a p i . j a r />
</ path>
<t a r g e t name= i n i t >
<d e l e t e d i r= ${ d i s t . d i r } />
<mkdir d i r= ${ b u i l d . d i r } />
<mkdir d i r= ${ d i s t . d i r } />
<mkdir d i r= ${ b u i l d . d i r }/WEBINF />
<mkdir d i r= ${ b u i l d . d i r }/WEBINF/ c l a s s e s />
<mkdir d i r= ${ b u i l d . d i r }/WEBINF/ l i b />
</ t a r g e t>
<t a r g e t name= c o m p i l e depends= i n i t >
<j a v a c c l a s s p a t h r e f= m y c l a s s p a t h
s r c d i r= ${ b a s e d i r }/ s r c
d e s t d i r= ${ b u i l d . d i r }/WEBINF/ c l a s s e s
i n c l u d e a n t r u n t i m e= f a l s e />
</ 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 >
<copy t o d i r= ${ b u i l d . d i r } >
< f i l e s e t d i r= ${ b a s e d i r }/web f i l e s >
<i n c l u d e name= . html />
</ f i l e s e t>
</ copy>
<copy t o d i r= ${ b u i l d . d i r }/WEBINF f i l e = ${ b a s e d i r }/web/web . xml />
<copy t o d i r= ${ b u i l d . d i r }/WEBINF/ l i b >

114

38
39
40
41
42
43
44

ARE 9. SERVLET
UNITATEA DE INVAT

< f i l e s e t d i r= ${ b a s e d i r }/ l i b >
<i n c l u d e name= . j a r />
</ f i l e s e t>
</ copy>
<j a r d e s t f i l e = ${ d i s t . d i r }/${ d i s t . name } . war b a s e d i r= ${ b u i l d . d i r } />
</ t a r g e t>
</ p r o j e c t>

Observatie. Valoarea parametrului dist.name defineste parametrul catalogAppServlet.


Se lanseaz
a n executie serverul Web tomcat, se ncarca servlet-ul n serverul
Web si dintr-un navigator se deschide pagina http://localhost:8080/apphello
Exemplul 9.3.2 Servlet pentru calculul celui mai mare divizor comun a dou
a
numere.
1
2
3
4
6
7

import
import
import
import

@WebServlet ( u r l P a t t e r n s = /cmmdc )
public c l a s s CmmdcServlet extends H t t p S e r v l e t {
public long cmmdc( long m, long n ) { . . . }

public void doGet ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )


throws S e r v l e t E x c e p t i o n , IOException {
S t r i n g 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 t i p=r e q . g e t P a r a m e t e r ( t i p ) ;
long m=Long . par se Lon g ( sm ) , n=Long . par se Lon g ( sn ) ;
long x=cmmdc(m, n ) ;
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 = 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 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 ( ) ;
}

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

public void doPost ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )


throws S e r v l e t E x c e p t i o n , IOException {
doGet ( req , r e s ) ;
}

35
36
37
38
39

java . io . ;
javax . s e r v l e t . ;
javax . s e r v l e t . http . ;
j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;

apelabil prin documentul html (index.html )

9.3. REALIZAREA UNUI SERVLET

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

<html>
<head>
<s c r i p t l a n g u a g e= J a v a S c r i p t >
< !
function checkIt (){
var sm=document . cmmdc .m. value ;
var sn=document . cmmdc . n . value ;
i f (sm== ) {
a l e r t ( L i p s e s t e p r i m u l numar ! ) ;
return f a l s e ;
}
i f ( sn== ) {
a l e r t ( L i p s e s t e a l d o i l e a numar ! ) ;
return f a l s e ;
}
i f ( ! IsNumeric (sm ) ) {
a l e r t ( Primul numar e s t e g r e s i t i n t r o d u s ! ) ;
return f a l s e ;
}
i f ( ! IsNumeric ( sn ) ) {
a l e r t ( Al d o i l e a numar e s t e g r e s i t i n t r o d u s ! ) ;
return f a l s e ;
}
return true ;
}
f u n c t i o n IsNumeric ( s T e x t ) {
// J e f f Anderson
// A j a v a s c r i p t v a l i d a t i o n f u n c t i o n t o c h e c k w h e t h e r t h e d e t a i l s
// e n t e r e d by a u s e r a r e numeric ( 2 0 0 2 )
var V a l i d C h a r s = 0 1 2 3 4 5 6 7 8 9 . ;
var IsNumber=t r u e ;
var Char ;
f o r ( i = 0 ; i < sText . l e n g t h && IsNumber == t r u e ; i ++){
Char = sText . charAt ( i ) ;
i f ( V a l i d C h a r s . i n d e x O f ( Char ) == 1){
IsNumber = f a l s e ;
}
}
r e t u r n IsNumber ;
}
//>
</ s c r i p t>
< t i t l e>Cmmdc S e r v l e t</ t i t l e>
</head>
<body bgcolor=#c c b b c c >
<center>
<h1> Cmmdc S e r v l e t </h1>
<form method= g e t
action= h t t p : / / l o c a l h o s t : 8 0 8 0 / m y s e r v l e t /cmmdc
name=cmmdc onSubmit= r e t u r n c h e c k I t ( ) >
<p>Primul numar e s t e <input type= t e x t name=m s i z e=5>
<p>Al d o i l e a numar e s t e <input type= t e x t name=n s i z e=5>
<p><input type= submit value= C a l c u l e a z a >
<input type= h id de n name= t i p value= t e x t / html >
</form>
</ center>
</body>
</html>

115

116

ARE 9. SERVLET
UNITATEA DE INVAT

Pentru fixarea naturii r


aspunsului text/html sau text/plain s-a introdus variabila tip, care n fisierul de invocare index.html primeste pe ascuns valoarea
text/html. In cazul n care vom apela servlet-ul dintr-un program, va fi avantajos s
a primim r
aspunsul ca text/plain.

9.4

Procesare asincron
a n Java Servlet 3.0

Rezolvarea unei cereri adresat de un client unui servlet se executa de catre


serverul Web ntr-un fir de executie. Aceasta executie este sincrona n sensul
n care trecerea la instructiunea urmatoare are loc doar la incheierea executiei
instructiunii curente.
Interfata de programare Servlet 3.0 ofera posibilitatea unui executii asincrone.
Acest mod de executie se indica prin adnotarea
@WebServlet(url="/numeApel " ,asyncSupported=true)
Suportul asincron necesita un context, obiect de tip AsyncContext
AsyncContext asyncCtx=req.startAsync(req,res);
Activit
atile ce trebuie ndeplinite pentru satisfacerea cererii clientului se lanseaz
a
ntr-un fir de executie, obiect care este parte a unei familii gestionate de o clas
a
ce implementeaz
a interfata Executor
public ScheduledThreadPoolExecutor(int corePoolSize)
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long
keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)
Interfata AsyncListener permite notificarea evenimentelor
void onComplete(AsyncEvent ae)
void onTimeout(AsyncEvent ae)
void onError(AsyncEvent ae)
void onStartAsync(AsyncEvent ae)
Obiectul de tip AsyncEvent este creat n momentul satisfacerii cererii clientului,
dep
asirii timpului alocat sau producerii unei erori.
Exemplul 9.4.1 Varianta asincrona a servlet-ului de calcul a celui mare divizor
comun.

IN JAVA SERVLET 3.0


9.4. PROCESARE ASINCRONA

1
2
3
4
5
6
7
9
10
11
12
13
14
15
16
17
18
19

package m y s e r v l e t ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;
import j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
import j a v a . u t i l . c o n c u r r e n t . ;
import j a v a . i o . IOException ;
import l i s t e n e r s . ;
@WebServlet ( u r l P a t t e r n s= /cmmdc , a s y n c S u p p o r t e d=true )
public c l a s s A s y n c S e r v l e t extends H t t p S e r v l e t {
public void doGet ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
AsyncContext asyncCtx=r e q . s t a r t A s y n c ( req , r e s ) ;
asyncCtx . a d d L i s t e n e r (new MyAsyncListener ( ) ) ;
E x e c u t o r e x e c u t o r=new ThreadPoolExecutor ( 1 0 , 1 0 , 5 0 0 0 0 ,
TimeUnit . MILLISECONDS,
new LinkedBlockingQueue<Runnable > ( 1 0 0 ) ) ;
e x e c u t o r . e x e c u t e (new AsyncWebService ( asyncCtx ) ) ;
}
public void doPost ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
doGet ( req , r e s ) ;
}

21
22
23
24
25

Firul de executie responsabil cu ndeplinirea cererii clientului este


1
2
3
4
6
7

package m y s e r v l e t ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;
import j a v a . i o . ;
public c l a s s AsyncWebService implements Runnable {
AsyncContext asyncCtx ;
public AsyncWebService ( AsyncContext asyncCtx ) {
t h i s . asyncCtx=asyncCtx ;

9
10
11

13

public void run ( ) {


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=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 ( ) ;
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 ( ) ;
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 ( ) ;

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

117

118

}
catch ( IOException e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}

32
33
34
35

36

public long cmmdc( long m, long n ) { . . . }

38
39

ARE 9. SERVLET
UNITATEA DE INVAT

Clasa care implementeaza interfata AsyncListener

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 ;

public c l a s s MyAsyncListener implements A s y n c L i s t e n e r {

1
2
3

public MyAsyncListener ( ) { }

public void onComplete ( AsyncEvent ae ) {


S e r v l e t R e q u e s t r e q=ae . getAsyncContext ( ) . g e t R e q u e s t ( ) ;
S t r i n g r=r e q . g e t P a r a m e t e r ( m)+ <> +r e q . g e t P a r a m e t e r ( n ) ;
System . out . p r i n t l n ( A s y n c L i s t e n e r : onComplete f o r r e q u e s t : +r ) ;
}

10
11
12
13
14

public void onTimeout ( AsyncEvent ae ) {


S e r v l e t R e q u e s t r e q=ae . getAsyncContext ( ) . g e t R e q u e s t ( ) ;
S t r i n g r=r e q . g e t P a r a m e t e r ( m)+ <> +r e q . g e t P a r a m e t e r ( n ) ;
System . out . p r i n t l n ( A s y n c L i s t e n e r : onTimeout f o r r e q u e s t : +r ) ;
}

16
17
18
19
20

public void o n E r r o r ( AsyncEvent ae ) {


S e r v l e t R e q u e s t r e q=ae . getAsyncContext ( ) . g e t R e q u e s t ( ) ;
S t r i n g r=r e q . g e t P a r a m e t e r ( m)+ <> +r e q . g e t P a r a m e t e r ( n ) ;
System . out . p r i n t l n ( A s y n c L i s t e n e r : o n E r r o r f o r r e q u e s t : +r ) ;
}

22
23
24
25
26

public void o n S t a r t A s y n c ( AsyncEvent ae ) {


S e r v l e t R e q u e s t r e q=ae . getAsyncContext ( ) . g e t R e q u e s t ( ) ;
S t r i n g r=r e q . g e t P a r a m e t e r ( m)+ <> +r e q . g e t P a r a m e t e r ( n ) ;
System . out . p r i n t l n ( A s y n c L i s t e n e r : o n S t a r t A s y n c f o r r e q u e s t : +r ) ;
}

28
29
30
31
32
33

Test de evaluare a cunostintelor


1. Care este rolul unui servlet?

IN JAVA SERVLET 3.0


9.4. PROCESARE ASINCRONA

2. Unde se instaleaz
a o aplicatie cu servlet?
3. Cum se poate apela un servlet?
4. Extinz
and clasa HttpServlet, ce trebuie sa faca programatorul?

119

Unitatea de nv
atare 10

Facilit
ati de programare cu
servlet

Durata: 4 ore.

10.1

Program client al unui servlet

Apelarea unui servlet dintr-un program Java adica lansarea unei cereri
si receptionarea r
aspunsului furnizat de servlet se poate realiza cu produsul
commons-httpclient dezvoltat de apache.
Intr-un asemenea caz, din punctul de vedere al clientului este mai avantajos
ca r
aspunsul servlet-ului fie text/plain, n loc de text/html.
Pe l
ang
a commons-httpclient este nevoie de urmatoarele produse soft:
commons-codec de la apache;
commons-logging de la apache;
Pentru compilare trebuie declarata n variabila de sistem classpath referinta
c
atre commons-httpclient, dar pentru executie este nevoie si de referintele catre
celelalte dou
a produse.
Dezvoltarea unui client presupune:
120

10.1. PROGRAM CLIENT AL UNUI SERVLET

121

1. Resursele utilizate se declar


a prin
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.httpclient.params.HttpMethodParams;
2. Crearea unui obiect de tip HttpClient:
HttpClient client=new HttpClient();
3. Declararea metodei de transmitere a datelor get, post.
GetMethod method = new GetMethod(url);
unde url este String-ul de apelare a servlet-ului, de forma
http://host:port/catalog/numeApel?numeParam=valParam&. . . ,
PostMethod method = new PostMethod(url);
cu url=http://host:port/catalog/numeApel.
Datele se adaug
a cu metoda
method.addParameter(String paramName, String paramValue);
Dac
a se transmit at
at parametri cat si fisiere atunci datele se adauga
prin sablonul
Part[] parts = {
new StringPart(paramName, paramValue),
. . .
new FilePart(file.getName(), file)
. . .
};
method.setRequestEntity(
new MultipartRequestEntity(parts, method.getParams())
);
unde o variabil
a file corespunde unui fisier care este ncarcat.
4. Specificarea modului de reluare a cererii.
DefaultHttpMethodRetryHandler retryhandler=
new DefaultHttpMethodRetryHandler(int numarReluari,
boolean seFacReluari);
method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
retryhandler);

122

ARE 10. FACILITAT


I DE PROGRAMARE CU SERVLET
UNITATEA DE INVAT

5. Lansarea cererii.
int statusCode = client.executeMethod(method);
6. Preluarea r
aspunsului. Exista trei cai de realizare a acestui obiectiv:
Ca sir de octeti:
byte[] method.getResponseBody();
Ca String:
String method.getResponseBodyAsString();
Prin intermediul unui flux:
InputStream method.getResponseBodyAsStream();
7. Inchiderea conexiunii cu servlet-ul.
method.releaseConnection();
Exemplul 10.1.1 Dezvolt
am un program client pentru servlet-ul CmmdcServlet.
java . u t i l . ;
o r g . apache . commons . h t t p c l i e n t . ;
o r g . apache . commons . h t t p c l i e n t . methods . ;
o r g . apache . commons . h t t p c l i e n t . params . HttpMethodParams ;

import
import
import
import

import j a v a . i o . ;

public c l a s s ClientCmmdcServlet {
private s t a t i c S t r i n g u r l = h t t p : / / l o c a l h o s t : 8 0 8 0 / m y s e r v l e t /cmmdc ;

1
2
3

9
11
12
13
14
15
16
18
19
21
22
23
25
26
27
28
29
30

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 ( ) ;
H t t p C l i e n t c l i e n t = new H t t p C l i e n t ( ) ;
PostMethod method = new PostMethod ( u r l ) ;
method . addParameter ( m ,m) ;
method . addParameter ( n , n ) ;
method . addParameter ( t i p , t e x t / p l a i n ) ;
DefaultHttpMethodRetryHandler r e t r y h a n d l e r=
new DefaultHttpMethodRetryHandler ( 3 , true ) ;
method . getParams ( ) . s e t P a r a m e t e r ( HttpMethodParams .RETRY HANDLER,
retryhandler ) ;
try {
i n t s t a t u s C o d e = c l i e n t . executeMethod ( method ) ;

UITE
10.2. SERVLETE INLANT

i f ( s t a t u s C o d e != H t t p S t a t u s . SC OK) {
System . e r r . p r i n t l n ( Method f a i l e d : + method . g e t S t a t u s L i n e ( ) ) ;
System . e x i t ( 0 ) ;
}
byte [ ] r e s p o n s e B o d y = method . getResponseBody ( ) ;
System . out . p r i n t l n ( Cmmdc = +(new S t r i n g ( r e s p o n s e B o d y ) ) ) ;

32
33
34
35
36
37

}
catch ( H t t p E x c e p t i o n e ) {
System . e r r . p r i n t l n ( Http e r r o r : + e . g e t M e s s a g e ( ) ) ;
}
catch ( IOException e ) {
System . e r r . p r i n t l n ( I /O e r r o r : + e . g e t M e s s a g e ( ) ) ;
}
finally {
method . r e l e a s e C o n n e c t i o n ( ) ;
}

38
39
40
41
42
43
44
45
46
47

48
49

123

10.2

Servlete nl
antuite

Un servlet apeleaz
a la un moment dat alt servlet. Sablonul de lucru este
RequestDispatcher dispatcher=
getServletContext().getRequestDispatcher("/url_pattern_servlet_apelat");
if(dispatcher!=null)
dispatcher.include(request,response);
Exemplul 10.2.1 Un servlet VerifServlet verific
a parametri cererii. Pentru problema calculului celui mai mare divizor comun a dou
a numere, dac
a cei doi parametri
sunt numere ntregi, atunci se apeleaz
a servletul ComputeServlet, altfel se formeaz
a
un mesaj de eroare.
Codurile celor dou
a servlete sunt:
VerifServlet.java

package cmmdc ;
import j a v a . i o . ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;

public c l a s s V e r i f S e r v l e t extends H t t p S e r v l e t {

1
2
3

8
9
10
11
12
13
14
15

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 ( ) ) ) {

124

ARE 10. FACILITAT


I DE PROGRAMARE CU SERVLET
UNITATEA DE INVAT

message=Numar a b s e n t ;
}
else {
try {
m=Long . par se Lon g ( sm ) ;
}
catch ( NumberFormatException e ) {
message=Nu e s t e numar ;
}
}
i f ( ( sn==n u l l ) | | ( sn . e q u a l s ( ) ) ) {
message=Numar a b s e n t ;
}
else {
try {
n=Long . p ars eL ong ( sn ) ;
}
catch ( NumberFormatException e ) {
message=Nu e s t e numar ;
}
}
out . p r i n t l n ( <html><body> ) ;
i f ( message . e q u a l s ( ) ) {
out . p r i n t l n ( <h3> R e z u l t a t u l ob&#355; i n u t </h3> ) ;
R e q u e s t D i s p a t c h e r d i s p a t c h e r=
getServletContext ( ) . getRequestDispatcher ( / c a l c u l ) ;
i f ( d i s p a t c h e r != n u l l )
d i s p a t c h e r . i n c l u d e ( req , r e s ) ;
}
else {
out . p r i n t l n ( <h3> Date e r o n a t e </h3> ) ;
out . p r i n t l n ( message ) ;
}
out . p r i n t l n ( </body></html> ) ;
out . c l o s e ( ) ;

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

53

public void doPost ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )


throws S e r v l e t E x c e p t i o n , IOException {
doGet ( req , r e s ) ;
}

54
55
56
57

ComputeServlet.java

package cmmdc ;
import j a v a . i o . ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;

public c l a s s ComputeServlet extends H t t p S e r v l e t {

1
2
3

8
10
11
12
13
14
15

public long cmmdc( long m, long n ) { . . . }


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 {
long m=Long . par se Lon g ( r e q . g e t P a r a m e t e r ( m ) ) ;
long n=Long . p ars eL ong ( r e q . g e t P a r a m e t e r ( n ) ) ;
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 ( <H1> Cmmdc = +cmmdc(m, n)+</H1> ) ;

10.3. SESIUNE DE LUCRU

16

18

public void doPost ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )


throws S e r v l e t E x c e p t i o n , IOException {
doGet ( req , r e s ) ;
}

19
20
21
22

125

10.3

Sesiune de lucru

In cazul protocolului HTTP, de fiecare data cand un client deschide sau revine
la o pagin
a Web se deschide o nou
a conexiune cu serverul Web iar acesta nu retine
informatiile referitoare la client pe perioada conexiunii respective. Perioada de
timp cat un client este n conexiune cu o pagina Web se numeste sesiune.
Exist
a posibilitatea p
astr
arii unor informatii pe durata unei sesiuni (prin
mecanismul denumit Session Tracking).
Inaintea satisfacerii unei cereri, servletul verifica existenta unui obiect HttpSession.
Acest obiect se creaz
a la prima apelare de catre un client a servletului prin
HttpSession sesiune=request.getSession(true);
Un obiect HttpSession poate retine atribute, adica perechi de forma (nume,
valoare). Introducerea unui atribut se realizeaza prin
void setAttribute(String nume, Object valoare)
iar extragerea valorii unui atribut se obtine prin
Object getAttribute(String nume)
Metoda String nume[ ] getValueNames() returneaza numele tuturor
atributelor definite.
Un atribut se elimin
a cu metoda void removeAttribute(String nume).
Exemplul 10.3.1 Exemplul urm
ator num
ar
a de c
ate ori se apeleaz
a servletul ntr-o sesiune. Se defineste un atribut noAcces, care la prima apelare este
initializat iar apoi este m
arit cu c
ate o unitate la fiecare nou
a apelare a servletului.

import j a v a . i o . ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;

public c l a s s S e s i u n e extends H t t p S e r v l e t {

1
2

7
8

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 {

126

ARE 10. FACILITAT


I DE PROGRAMARE CU SERVLET
UNITATEA DE INVAT

r e s . setContentType ( t e x t / html ) ;
S t r i n g mesaj ;
P r i n t W r i t e r out=r e s . g e t W r i t e r ( ) ;
H t t p S e s s i o n s e s s i o n=r e q . g e t S e s s i o n ( true ) ;
I n t e g e r c o n t o r =( I n t e g e r ) s e s s i o n . g e t A t t r i b u t e ( noAcces ) ;
i f ( c o n t o r==n u l l ) {
c o n t o r=new I n t e g e r ( 1 ) ;
mesaj= S a l u t ! ;
}
else {
c o n t o r=new I n t e g e r ( c o n t o r . i n t V a l u e ( ) + 1 ) ;
mesaj= Bine a t i r e v e n i t ! ;
}
s e s s i o n . s e t A t t r i b u t e ( noAcces , c o n t o r ) ;
out . p r i n t l n ( <html><body> ) ;
out . p r i n t l n ( <h1>+mesaj+</h1> ) ;
out . p r i n t l n ( Numarul de a c c e s a r i a l a c e a s t e i p a g i n i e s t e +
contor . intValue ( ) ) ;
out . p r i n t l n ( </body></html> ) ;
out . c l o s e ( ) ;

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

31

public void doPost ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )


throws S e r v l e t E x c e p t i o n , IOException {
doGet ( req , r e s ) ;
}

32
33
34
35

Apelarea servletului se face din


1
2
3
4
5
6
7
8
9
10
11
12
13

<html>
<head>
< t i t l e> S e s i u n e </ t i t l e>
</head>
<body>
<h1> Formular de a c c e s </h1>
<form method= g e t
action= h t t p : / / l o c a l h o s t : 8 0 8 0 / m y s e r v l e t / s e s i u n e >
<p>
<input type= submit value= A c c e s e a z a >
</form>
</body>
</html>

10.4

Cookie

Un Cookie este un fisier de mica dimensiune trimis de catre programul server


clientului ca parte a header-ului Http.
Acesta contine informatii despre sesiunea curenta care salvate pe disc vor
putea fi accesate n sesiuni ulterioare. Cand un navigator emite o cerere catre un
server, cookie-urile anterioare primite de catre client de la serverul respectiv sunt
trimise din nou serverului ca parte a cererii formulata de client.
Cookie-urile sunt sterse automat n momentul expirarii.

10.4. COOKIE

127

Unii clienti nu permit memorarea cookie-urilor. In acest caz, clientul este


informat c
a acest fapt ar putea duce la imposibilitatea satisfacerii cereri sale
/ acces
arii paginii Web. Implicit, durata de viata a unui cookie este sesiunea
curenta a navigatorului (p
an
a se nchide navigatorul).
Clasa Cookie
Contructor
Cookie(String nume, String valoare)
Metode
void setDomain(String model )
Domeniul este o adres
a URL ce restrictioneaza accesul cookie-urilor la acel
domeniu. model trebuie s
a contina cel putin doua caractere ..
void setMaxAge(int durat
a ) Fixeaza durata de existenta a cookie-ului - n
secunde. Valoarea implicit
a este -1, adica cookie-ul exista pana la nchiderea
programului navigator.
void setComment(String comentariu)
void setSecure(boolean flag)
Valoarea implicit
a este false.
Trimiterea unui cookie clientului:
public void HttpServletResponse.addCookie(Cookie cookie)
Recunoasterea cookie-urilor de catre servlet:
Cookie [ ] cookies=request.getCookies();
if(cookies!=null){
for(int i=0;i<cookies.length;i++){
String name=cookies[i].getName();
String valoare=cookies[i].getValue();
. . .
}
exemplul urm
Exemplul 10.4.1 In
ator se num
ar
a de c
ate ori se apeleaz
a servletul pe durata de viat
a a cookie-ului.

1
2
3

import j a v a . i o . ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;

128

public c l a s s A p e l a r i extends H t t p S e r v l e t {
public void doGet ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
r e s . setContentType ( t e x t / html ) ;
S t r i n g mesaj= ;
P r i n t W r i t e r out=r e s . g e t W r i t e r ( ) ;
Cookie myCookie=n u l l ;
i n t c o n t o r =1;
Cookie [ ] c o o k i e s=r e q . g e t C o o k i e s ( ) ;
i f ( c o o k i e s != n u l l ) {
f o r ( i n t i =0; i <c o o k i e s . l e n g t h ; i ++){
S t r i n g name=c o o k i e s [ i ] . getName ( ) ;
i f ( name . e q u a l s ( u r m a r i r e ) ) {
c o n t o r=I n t e g e r . p a r s e I n t ( c o o k i e s [ i ] . g e t V a l u e ( ) ) ;
c o n t o r ++;
mesaj= Bine a t i r e v e n i t ! ;
}
}
}
else {
mesaj= S a l u t ! ;
}
myCookie=new Cookie ( u r m a r i r e , (new I n t e g e r ( c o n t o r ) ) . t o S t r i n g ( ) ) ;
myCookie . setMaxAge ( 1 0 0 0 0 0 0 ) ;
r e s . addCookie ( myCookie ) ;
out . p r i n t l n ( <html><body> ) ;
out . p r i n t l n ( <h1>+mesaj+</h1> ) ;
out . p r i n t l n ( Numarul de a c c e s a r i a l a c e a s t e i p a g i n i e s t e +c o n t o r ) ;
out . p r i n t l n ( </body></html> ) ;
out . c l o s e ( ) ;
}

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

public void doPost ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )


throws S e r v l e t E x c e p t i o n , IOException {
doGet ( req , r e s ) ;
}

38
39
40
41
42

ARE 10. FACILITAT


I DE PROGRAMARE CU SERVLET
UNITATEA DE INVAT

10.5

Servlet cu conexiune la o baz


a de date

Presupunem cunoscuta accesul din Java ntr-un SGBD consideram aplicatia:


Exemplul 10.5.1 Consultarea unei agende de adrese e-mail. Se utilizeaz
a o
baz
a de date AgendaEMail alc
atuit
a dintr-un singur tabel adrese (id int, nume
varchar(20), numar varchar(30)).
Utiliz
and SGBD derby servletul este
1
2
3
4
5

import
import
import
import
import

java . io . ;
javax . s e r v l e t . ;
javax . s e r v l e t . http . ;
java . s q l . ;
java . net . ;

DE DATE
10.5. SERVLET CU CONEXIUNE LA O BAZA

7
8
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
32
33
34
35
36

public c l a s s A g e n d a E M a i l S e r v l e t extends H t t p S e r v l e t {
Statement i n s t r u c t i u n e=n u l l ;
public void i n i t ( S e r v l e t C o n f i g c o n f i g ) throws S e r v l e t E x c e p t i o n {
super . i n i t ( c o n f i g ) ;
// SGBD Derby
S t r i n g j d b c D r i v e r= o r g . apache . derby . j d b c . C l i e n t D r i v e r ;
S t r i n g URLBazaDate= j d b c : derby : / / l o c a l h o s t : 1 5 2 7 / AgendaEMail ;
C o n n e c t i o n con=n u l l ;
try {
C l a s s . forName ( j d b c D r i v e r ) . n e w I n s t a n c e ( ) ;
con=DriverManager . g e t C o n n e c t i o n ( URLBazaDate ) ;
i n s t r u c t i u n e=con . c r e a t e S t a t e m e n t ( ) ;
}
catch ( ClassNotFoundException e ) {
System . out . p r i n t l n ( D r i v e r i n e x i s t e n t JDBC : +j d b c D r i v e r ) ;
}
catch ( SQLException e ) {
System . out . p r i n t l n ( Baza de d a t e i n e x i s t e n t a +URLBazaDate ) ;
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( E r o a r e : +e . g e t M e s s a g e ( ) ) ;
}
}
public void doGet ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
S t r i n g myAtribut , myVal ;
r e s . setContentType ( t e x t / html ) ;
S e r v l e t O u t p u t S t r e a m out = r e s . getOutputStream ( ) ;
myAtribut=r e q . g e t P a r a m e t e r ( c r i t e r i u ) ;
myVal=r e q . g e t P a r a m e t e r ( termen ) ;
myVal= \ +myVal+ \ ;
try {
S t r i n g s q l= s e l e c t from a d r e s e where + myAtribut+ = +myVal ;
R e s u l t S e t r s=i n s t r u c t i u n e . e x e c u t e Q u e r y ( s q l ) ;
out . p r i n t l n ( <html> ) ;
out . p r i n t l n ( <head><t i t l e >AgendaEMail</ t i t l e ></head> ) ;
out . p r i n t l n ( <body> ) ;
out . p r i n t l n ( <h1>Agenda de Adrese em a i l </h1> ) ;
out . p r i n t l n ( <p/> ) ;
out . p r i n t l n ( <b>
Nume
<>
Adresa em a i l </b> ) ;
out . p r i n t l n ( <br/> ) ;
while ( r s . n e x t ( ) ) {
out . p r i n t ( r s . g e t S t r i n g ( nume)+ <> +r s . g e t S t r i n g ( e m a i l ) ) ;
out . p r i n t l n ( <br/> ) ;
}
out . p r i n t l n ( </body> ) ;
out . p r i n t l n ( </html> ) ;
out . c l o s e ( ) ;
}
catch ( SQLException e ) {
System . out . p r i n t l n ( SQLException : +e . g e t M e s s a g e ( ) ) ;
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( E r o a r e : +e . g e t M e s s a g e ( ) ) ;
}

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

129

130

public void doPost ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )


throws S e r v l e t E x c e p t i o n , IOException {
doGet ( req , r e s ) ;
}

67
68
69
70
71

ARE 10. FACILITAT


I DE PROGRAMARE CU SERVLET
UNITATEA DE INVAT

Apelarea servlet-ului se face din


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

<html>
<body>
<h1> Cautare i n baza de d a t e AgendaEMail</h1>
<form method= g e t
action= h t t p : / / l o c a l h o s t : 8 0 8 0 / agendae / a d r e s e >
<p>C r i t e r i u de c a u t a r e :
<s e l e c t name= c r i t e r i u >
<option value=nume>dupa Nume
<option value= e m a i l >dupa Email
</ s e l e c t>
<br>
<p>E n t i t a t e a c a u t a t a
<input type= t e x t name= termen s i z e =30>
<p><input type= submit value= Cauta >
</form>
</body>
</html>

Testarea aplicatiei presupune:


1. Realizarea bazei de date:
2. Testarea servlet-ului:
(a) Pornirea serverului bazei de date.
(b) Se verific
a prezenta n catalogul servlet-ului ...\WEB-INF\lib a fisierului
derbyclient.jar sau mysql-connector-java-*.*.*-bin.jar.
(c) Pornirea serverului tomcat sau rencarcarea servlet-ului.
(d) Apelarea servlet-ului din pagina Web.

10.6

Imagini furnizate de servlet

Indic
am dou
a modalitati prin care un client obtine o imagine furnizata de
un servlet. Imaginea poate proveni dintr-un fisier extern sau poate fi creata de
servlet.
Imaginea este transmisa direct clientului n fluxul de iesire de tip
ServletOutputStream, tipul MIME al raspunsului fiind
response.setContentType("image/ext");

10.6. IMAGINI FURNIZATE DE SERVLET

131

ext {gif, jpg, png, . . .}.


Textul surs
a al servlet-ului este:

1
2
3
5
6
7
8
9

import j a v a . i o . ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;
public c l a s s MyGraphG extends H t t p S e r v l e t {
public void doGet ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
r e s . setContentType ( image / g i f ) ;
S e r v l e t O u t p u t S t r e a m out = r e s . getOutputStream ( ) ;
// R e f e r i n t a l a f i s i e r u l g r a f i c
String f =
d : \ \ apachetomcat 6 . 0 . 2 0 \ \ webapps \\ m y s e r v l e t \\WEBINF\\ +
c l a s s e s \\ w a l k i n g s a n t a . g i f ;
// T r a n f e r a r e a f i s i e r u l u i g r a f i c
F i l e I n p u t S t r e a m f i s = new F i l e I n p u t S t r e a m ( f ) ;
B u f f e r e d I n p u t S t r e a m b i s = new B u f f e r e d I n p u t S t r e a m ( f i s ) ;
byte [ ] b y t e s = new byte [ b i s . a v a i l a b l e ( ) ] ;
i n t nread = 0 ;
while (1 != ( nread = b i s . r e a d ( b y t e s ) ) ) {
out . w r i t e ( b y t e s , 0 , nread ) ;
}

11
12
13
14
15
16
17
18
19
20
21
22

23
24

Pe calculatorul serverului Web, imaginea se salveaza ntr-un fisier grafic,


dup
a care servlet-ul scrie n fluxul de iesire un document html cu o legatura
(link) c
atre fisierul cu imaginea creata anterior. Navigatorul clientului va
desc
arca si vizualiza imaginea.
Dac
a tipul fisierului grafic este jpg sau png atunci textul sursa al servlet-ului
este:

1
2
3
4
5
6
7
8
10
11
12
13
14
15

mport j a v a . i o . ;
import j a v a . awt . ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;
import j a v a x . i m a g e i o . ;
import j a v a . awt . image . ;
import j a v a x . i m a g e i o . stream . ;
import j a v a . u t i l . ;
public c l a s s MyGraphP extends H t t p S e r v l e t {
public void doGet ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
r e s . setContentType ( t e x t / html ) ;
P r i n t W r i t e r out=r e s . g e t W r i t e r ( ) ;
S t r i n g f i l e R e f=d : \ \ apachetomcat 6 . 0 . 2 0 \ \ webapps \\ m y s e r v l e t \\ ;

132

ARE 10. FACILITAT


I DE PROGRAMARE CU SERVLET
UNITATEA DE INVAT

S t r i n g numeFis= d e s e n ;
S t r i n g e x t= j p g ;
// sau png
// Formarea i m a g i n i i
Frame frame = n u l l ;
Graphics g = null ;
B u f f e r e d I m a g e image=n u l l ;
try {
frame = new Frame ( ) ;
frame . a d d N o t i f y ( ) ;
image = ( B u f f e r e d I m a g e ) frame . c r e a t e I m a g e ( 8 0 0 , 6 0 ) ;
g = image . g e t G r a p h i c s ( ) ;
// F i x a r e a f o n t u l u i
g . s e t F o n t (new Font ( S e r i f , Font . ITALIC , 4 8 ) ) ;
// E d i t a r e a unui t e x t
g . d r a w S t r i n g ( T e h n o l o g i i d i s t r i b u i t e i n Java , 1 0 , 5 0 ) ;

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

// S a l v a r e a i m a g i n i i i n t r un f i s i e r j p g sau png
F i l e f=new F i l e ( f i l e R e f+numeFis+ . +e x t ) ;
ImageIO . w r i t e ( image , j p g , f ) ;

32
33
34

// Raspunsul c a t r e c l i e n t
out . p r i n t l n ( <HTML><BODY> ) ;
out . p r i n t l n ( <h2>Imagine p r e l u a t a de pe s e r v e r </h2> ) ;
out . p r i n t l n ( <p><a h r e f =\ h t t p : / / l o c a l h o s t : 8 0 8 0 / m y s e r v l e t / +
numeFis+ . +e x t+\> ) ;
out . p r i n t l n ( V i z u a l i z a r e a i m a g i n i i </a> ) ;
out . p r i n t l n ( </BODY></HTML> ) ;
out . c l o s e ( ) ;

36
37
38
39
40
41
42
43

}
finally {
// E l i b e r a r e a r e s u r s e l o r
i f ( g != n u l l ) g . d i s p o s e ( ) ;
i f ( frame != n u l l ) frame . r e m o v e N o t i f y ( ) ;
}

44
45
46
47
48
49

50
51

Dac
a tipul fisierului grafic va fi gif atunci linia 34 se nlocuieste cu
FileOutputStream fos=new FileOutputStream(f);
GifEncoder encoder = new GifEncoder(image,fos);
encoder.encode();

Clasa GifEncoder care realizeaza codarea, face parte din pachetul Acme.JPM.Encoders,
disponibil gratuit la adresa web http://www.acme.com.

10.7

Filtru

Un filtru se asemeana unui servlet, dar activitatea ntreprinsa vizeaza uzual


contex ul, adic
a ansamblul servletilor care fac parte din aplicatia Web.
Un filtru se declar
a n fisierul web.xml prin
<web-app>
. . .

10.7. FILTRU

133

<filter>
<filter-name>nume_filtru</filter-name>
<filter-class>clasa_filtrului</filter-class>
</filter>
<filter-mapping>
<filter-name>nume_filtru</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
. . .
</web-app>
Clasa filtrului implementeaz
a interfata Filter, adica metodele
public void init(FilterConfig filterConfig) throws ServletException
public void destroy()
public void doFilter(ServletRequest request,
ServletResponse response, FilterChain filterChain)
throws IOException, ServletException
Exemplul 10.7.1 Contextul myservlet contine doi servleti HelloServlet si CmmdcServlet, apelabili respectiv din hello.html, cmmdc.html. S
a se programeze un
filtru care
Redirecteaz
a solicitarea /myservlet/hello c
atre /cmmdc.html.
Dac
a se cere ca natura r
aspunsului s
a fie text/xml atunci invalideaz
a
cererea.
Servletii HelloServlet si CmmdcServlet sunt cei dezvoltati la nceputul acestui
capitol. Filtrul are codul
1
2
3
5
6
8
9
10

import j a v a . i o . IOException ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;
public c l a s s M y F i l t e r D i s p a t c h e r implements F i l t e r {
private F i l t e r C o n f i g f i l t e r C o n f i g ;
public void i n i t ( F i l t e r C o n f i g f i l t e r C o n f i g ) throws S e r v l e t E x c e p t i o n {
this . f i l t e r C o n f i g = f i l t e r C o n f i g ;
}

14

public void d e s t r o y ( ) {
this . f i l t e r C o n f i g = null ;
}

16

public void d o F i l t e r ( S e r v l e t R e q u e s t r e q u e s t , S e r v l e t R e s p o n s e r e s p o n s e ,

12
13

134

F i l t e r C h a i n f i l t e r C h a i n ) throws IOException , S e r v l e t E x c e p t i o n {
HttpServletRequest req = ( HttpServletRequest ) request ;
HttpServletResponse res = ( HttpServletResponse ) response ;
S t r i n g u r i = r e q . getRequestURI ( ) ;
i f ( u r i . equals ( / myservlet ) | | u r i . equals ( / myservlet / ) )
f i l t e r C h a i n . doFilter ( request , response ) ;
else {
i f ( u r i . equals ( / myservlet / h e l l o )){
S t r i n g d i s p a t c h e r U r i= /cmmdc . html ;
R e q u e s t D i s p a t c h e r rd=r e q u e s t . g e t R e q u e s t D i s p a t c h e r ( d i s p a t c h e r U r i ) ;
rd . f o r w a r d ( r e q u e s t , r e s p o n s e ) ;
}
else {
i n t i n d e x=u r i . l a s t I n d e x O f ( . ) ;
i f ( i n d e x==1){
S t r i n g t i p=r e q . g e t P a r a m e t e r ( t i p ) ;
i f ( t i p . e q u a l s ( t e x t /xml ) ) {
r e s . s e n d E r r o r ( H t t p S e r v l e t R e s p o n s e . SC FORBIDDEN ) ;
}
}
f i l t e r C h a i n . doFilter ( request , response ) ;
}
}

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

40
41

ARE 10. FACILITAT


I DE PROGRAMARE CU SERVLET
UNITATEA DE INVAT

Fisierul web.xml este


1
2
3
4
6
7
8
9
10
12
13
14
15
17
18
19
20
22
23
24
25

<?xml version= 1 . 0 e n c o d i n g=ISO88591 ?>


< !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>
< 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>
< s e r v l e t>
<s e r v l e t name>cmmdc</ s e r v l e t name>
<s e r v l e t c l a s s>CmmdcServlet</ s e r v l e t c l a s s>
</ s e r v l e t>
< s e r v l e t>
<s e r v l e t name> h e l l o</ s e r v l e t name>
<s e r v l e t c l a s s>H e l l o 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>

30

<s e r v l e t mapping>
<s e r v l e t name> h e l l o</ s e r v l e t name>
<u r l p a t t e r n>/ h e l l o</ u r l p a t t e r n>
</ s e r v l e t mapping>

32

<s e r v l e t mapping>

27
28
29

10.7. FILTRU

33
34
35
37

<s e r v l e t name>cmmdc</ s e r v l e t name>


<u r l p a t t e r n>/cmmdc</ u r l p a t t e r n>
</ s e r v l e t mapping>
</webapp>

Pentru ntelegerea aplicatiei prezentam si codul fisierului cmmdc.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
35
36
37

<html>
<head>
< t i t l e>
Cmmdc S e r v l e t
</ t i t l e>
</head>
<body bgcolor=#c c b b c c >
<center>
<h1> Cmmdc S e r v l e t </h1>
<form method= g e t
action= h t t p : / / l o c a l h o s t : 8 0 8 0 / m y s e r v l e t /cmmdc>
<table border= 1 >
<tr>
<td> Primul numar </td>
<td> <input type= t e x t name=m s i z e =10> </td>
</ tr>
<tr>
<td> Al d o i l e a numar </td>
<td> <input type= t e x t name=n s i z e =10> </td>
</ tr>
<tr>
<td> Natura r a s p u n s u l u i </td>
<td> <s e l e c t name= t i p >
<option value= t e x t / html > t e x t / html
<option value= t e x t / p l a i n > t e x t / p l a i n
<option value= t e x t /xml> t e x t /xml
</ s e l e c t> </td>
</ tr>
<tr>
<td> <input type= submit value= C a l c u l e a z a > </td>
<td></td>
</ tr>
</ table>
</form>
</ center>
</body>
</html>

135

Unitatea de nv
atare 11

Java Server Page JSP

Durata: 4 ore.

Introducere
11.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 depoziteaz
a 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
136

137

11.1. TEHNOLOGIA JSP

http://host:port/cale/doc.jsp
referint
a html
<a href="http://host:port/cale/doc.jsp">
valoare a atributului action ntr-un marcaj form
<form action="http://host:port/cale/doc.jsp" ...

>

Prin cale se ntelege calea de la catalogul webapps pana la catalogul ce contine


fisierul jsp.
Vom depozita fisierele JSP ntr-un catalog jsp din arborele
webapps
|--> JSPApp
|
|--> WEB-INF
|
|
|--> classes
|
|
|
web.xml
|
|--> jsp
|
|
|
doc.jsp
caz n care cale=JSPApp/jsp.
Astfel, schimb
and numele fisierului Hello.html
1
2
3
4
5

<html>
<body>
Hello
</body>
</html>

n Hello.jsp si plas
andu-l n catalogul jsp se obtine acelasi efect, dar prelucrarea
paginilor / documentelor este diferita. Fisierul html este prelucrat doar de programul navigator si poate fi deschis ca fisier, n timp ce fisierul JSP este prelucrat de
serverul Web cu afisarea prin intermediul navigatorului. Prelucrarea efectuata
de serverul Web const
a din transformarea paginii / documentului JSP ntr-un
servlet, care este compilat si lansat n executie. Din aceastra cauza prima invocare a paginii / documentului JSP dureaza mai mult decat apelarile ulterioare.
Apelarea paginii / documentului JSP se face prin
http://localhost:8080/JSPApp/jsp/Hello.jsp
Exist
a dou
a moduri de a include elemente JSP ntr-un text html:
prin elemente specifice JSP.
Fisierul are extensia jsp si se numeste pagin
a JSP.
prin marcaje xml apartin
and spatiului de nume
http://java.sun.com/JSP/Page

138

ARE 11. JAVA SERVER PAGE JSP


UNITATEA DE INVAT

Fisierul poate avea extensia jsp sau jspx si se numeste document JSP.
Comentariile JSP se scriu de forma
<%-- Comentariu --%>
Consider
am urm
atorul exemplu introductiv:
Exemplul 11.1.1 Putem afisa valoarea unei variabile Java (de exemplu data
calendaristic
a) prin
Varianta paginii JSP
1
2
3
4
5
7
8
9
10
12
13
14
15
16
17

<html>
<body>
<p>
Data c a l e n d a r i s t i c a 1 :
<%= new j a v a . u t i l . Date ( ) %>
<p>
<% j a v a . u t i l . Date data1=new j a v a . u t i l . Date ( ) ; %>
Data c a l e n d a r i s t i c a 2 :
<%= data1 %>
<p>
<% j a v a . u t i l . Date data2=new j a v a . u t i l . Date ( ) ; %>
Data c a l e n d a r i s t i c a 3 :
<% out . p r i n t ( data2 ) ; %>
</body>
</html>

Dac
a se utilizeaz
a operatorul de afisare = atunci dupa expresia de afisat nu
se pune ;.
Variabila predefinita out este de tip javax.servlet.jsp.JspWriter.
Varianta documentului JSP
1
2
3
4
5
6
7
8
9

<? xml v e r s i o n= 1 . 0 e n c o d i n g=UTF8 ?>


<html xmlns : j s p= h t t p : / / j a v a . sun . com/JSP/ Page >
<body>
<j s p : d e c l a r a t i o n>
j a v a . u t i l . Date d=new j a v a . u t i l . Date ( ) ;
</ j s p : d e c l a r a t i o n>
<j s p : e x p r e s s i o n> d </ j s p : e x p r e s s i o n>
</body>
</html>

Codul Java inglobat ntr-un text html se numeste scriptlet. Sintaxa utilizat
a
este
Varianta paginii JSP

139

11.1. TEHNOLOGIA JSP

<% cod Java %>


Varianta documentului JSP
<jsp:scriptlet> codJava </jsp:scriptlet>
Domeniul de valabilitate. Domeniul de valabilitate defineste intervalul de
timp, de existent
a al unui obiect, fiind definit prin valorile:
Valoare
page
request

Domeniu de valabilitate
pagina curent
a
n pagina curenta,
n paginile incluse si
n paginile c
atre care se face o redirectare
session
n sesiunea curenta
application pe durata rul
arii aplicatiei
In orice pagin
a
Variabila
out
request
response
session
page
pageContext
application
exception

/ document JSP sunt predefinite obiectele:


Tip/Clasa
javax.servlet.jsp.JspWriter
javax.servlet.ServletRequest
javax.servlet.ServletResponse
javax.servlet.http.HttpSession
java.lang.Object, this
javax.servlet.jsp.PageContext
javax.servlet.ServletContext
ServletContext.getServletConfig().getContext()
java.lang.Throwable

Astfel
String request.getParameter(String numeParametru)
furnizeaz
a valoarea parametrului numeParametru dintr-un formular html.
Exemplul 11.1.2 Pagina JSP Hello: Clientul transmite numele paginii care i
r
aspunde cu mesajul de salut Hi + nume + !.
Codul paginii JPS (hello.jsp) este
1
2
3
4
5
6

<html>
<head>
< t i t l e> j s p h e l l o </ t i t l e>
</head>
<body>
<center>

140

7
8
9
10
11
12
13
14

ARE 11. JAVA SERVER PAGE JSP


UNITATEA DE INVAT

<h1> Pagina de r &#259; 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>

apelat din (index.html )


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

<html>
<head>
< t i t l e> JSP H e l l o </ t i t l e>
</head>
<body bgcolor=#bbeebb >
<center>
<h1> Pagina de a p e l a r e JSP </h1>
<form method= p o s t
action= h t t p : / / l o c a l h o s t : 8 0 8 0 / j s p h e l l o / j s p / h e l l o . j s p >
<p> Numele :
<input type= t e x t name=name s i z e =20>
<p>
<input type= submit >
</form>
</ center>
</body>
</html>

Compilarea si arhivarea servlet-ului o vom realiza prin intermediul lui apacheant. In acest scop se creaza structura:
jsphello
|
|--> jsp
|
|
|
hello.jsp
|
|--> lib
|
|--> src
|
|--> web
|
|
|
web.xml
|
|--> web-files
|
|
|
index.html
|
build.xml

Fisierul web.xml este simplu


1

<?xml version= 1 . 0 e n c o d i n g=ISO88591 ?>

< !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 >

4
5
7
8
9
10
11
12

<webapp>
<welcomef i l e l i s t>
<welcome f i l e >i n d e x . html</ welcome f i l e >
<welcome f i l e >i n d e x . j s p</ welcome f i l e >
</ welcomef i l e l i s t>
</webapp>

Fisierul build.xml prelucrat de apache-ant este

11.1. TEHNOLOGIA JSP

1
3
4
5
6
8
9
10
11
12
13
15
16
17
18
19
20
21
22
23
25
26
27
28
29
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

141

<project b a s e d i r= . d e f a u l t= g e n e r a t e . war >


<property
<property
<property
<property

name=TOMCAT HOME v a l u e= d : / apachetomcat 5 . 5 . 2 6 />


name= d i s t . name v a l u e= j s p h e l l o />
name= d i s t . d i r v a l u e= d i s t />
name= b u i l d . d i r v a l u e= b u i l d />

<path i d= m y c l a s s p a t h >
< f i l e s e t d i r= l i b >
<include name= . j a r />
</ f i l e s e t>
<pathelement path= ${TOMCAT HOME}/ l i b / s e r v l e t a p i . j a r />
</path>
<target name= i n i t >
<delete d i r= ${ d i s t . d i r } />
<mkdir d i r= ${ b u i l d . d i r } />
<mkdir d i r= ${ d i s t . d i r } />
<mkdir d i r= ${ b u i l d . d i r }/ j s p />
<mkdir d i r= ${ b u i l d . d i r }/WEBINF />
<mkdir d i r= ${ b u i l d . d i r }/WEBINF/ c l a s s e s />
<mkdir d i r= ${ b u i l d . d i r }/WEBINF/ l i b />
</ target>
<target name= c o m p i l e depends= i n i t >
<javac c l a s s p a t h r e f= m y c l a s s p a t h
s r c d i r= ${ b a s e d i r }/ s r c
d e s t d i r= ${ b u i l d . d i r }/WEBINF/ c l a s s e s />
</ target>
<target name= g e n e r a t e . war depends= c o m p i l e >
<copy t o d i r= ${ b u i l d . d i r } >
< f i l e s e t d i r= ${ b a s e d i r }/web f i l e s >
<include name= . html />
</ f i l e s e t>
</copy>
<copy t o d i r= ${ b u i l d . d i r }/ j s p >
< f i l e s e t d i r= ${ b a s e d i r }/ j s p >
<include name= . j s p />
<include name= . j s p x />
</ f i l e s e t>
</copy>
<copy t o d i r= ${ b u i l d . d i r }/WEBINF >
< f i l e s e t d i r= ${ b a s e d i r }/web >
<include name= . xml />
</ f i l e s e t>
</copy>
<copy t o d i r= ${ b u i l d . d i r }/WEBINF/ l i b >
< f i l e s e t d i r= ${ b a s e d i r }/ l i b >
<include name= . j a r />
</ f i l e s e t>
</copy>
<copy t o d i r= ${ b u i l d . d i r } >
< f i l e s e t d i r= ${ b a s e d i r } >
<include name= . p r o p e r t i e s />
</ f i l e s e t>
</copy>
<j a r d e s t f i l e = ${ d i s t . d i r }/${ d i s t . name } . war b a s e d i r= ${ b u i l d . d i r } />
</ target>

142

60

ARE 11. JAVA SERVER PAGE JSP


UNITATEA DE INVAT

</ project>

11.1.1

Declaratii JSP

Printr-o declaratie JSP, putem defini campuri(variabile) si metode Java ce


pot fi apoi folosite, respectiv apelate n documentul respectiv. O declaratie JSP
se defineste printr-un marcaj
<%! . . . %>
sau, n format XML
<jsp:declaration> . . . </jsp:declaration>
Exemplul 11.1.3 Calculul celui mai mare divizor comun a dou
a numere naturale cu metoda de calcul este definit
a ntr-o declaratie JSP.
Pagina JSP a aplicatiei cmmdc.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

<html>
<body>
<H1> CMMDC </H1>
<%!
l o n g cmmdc( l o n g m, l o n g n ) {
long c , r ;
do {
c=n ;
r=m%n ;
m=n ;
n=r ;
} while ( r !=0);
return c ;
}
%>
Rezultatul este
<%
String sm=r e q u e s t . g e t P a r a m e t e r ( m ) ;
String sn=r e q u e s t . g e t P a r a m e t e r ( n ) ;
l o n g m=Long . pa rse Lo ng ( sm ) , n=Long . pa rse Lo ng ( sn ) ;
out . p r i n t l n (cmmdc(m, n ) ) ;
%>
</body>
</html>

apelat din documentul cmmdc.html


1
2
3
4
5
6
7
8

<html>
<body>
<h1> C a l c u l u l Cmmdc </h1>
<form method= p o s t
action= h t t p : / / l o c a l h o s t : 8 0 8 0 / JSPApp/ j s p /cmmdc . j s p >
<p>
Primul numar e s t e
<input type= t e x t name=m value= s i z e=5>

143

11.1. TEHNOLOGIA JSP

9
10
11
12
13
14
15
16
17

<p>
Al d o i l e a numar e s t e
<input type= t e x t name=n value= s i z e=5>
<p>
<input type= submit value= C a l c u l e a z a >
<input type= r e s e t value=Abandon>
</form>
</body>
</html>

Exist
a dou
a metode jspInit() - utilizata pentru initializarea datelor -, si
jspDestroy() - utilizat
a pentru eliberarea resurselor -, care daca sunt declarate
de programator atunci sunt executate la nceputul si la sfarsitul ciclului de executie
a paginii / documentului JSP.

11.1.2

Directive JSP

Directivele JSP fixeaz


a informatii pentru tot documentul jsp. O directiva jsp
se indic
a prin marcajul
<%@ directiv
a atribut1 atribut2 . . . %>
sau n format XML
<jsp:directive.directiva atribut1 atribut2 . . . />
unde fiecare atribut are sintaxa nume=valoare.
Directivele pot fi: page, include, taglib.
Directiva page. Mention
am atributele
import=
info=
errorPage=
isErrorPage=

list
a de pachete separate prin ,
text Informatia se poate regasi apeland metoda
getServletInfo()
adresa url a paginii ce trateaz
a exceptia
"true | false"

Directiva include permite includerea unor fisiere .html sau .jsp n document
<%@ include file=fisier html, jsp %>
Includerea are loc n locul n care apare directiva.
Referinta la fisierul html sau jsp se face relativ la catalogul paginii JSP
initiale (adic
a cea n care apare directiva).
Directiva taglib indic
a bibliotecile de marcaje utilizate n documentul jsp,
av
and atributele
uri=
uri - Universal Resource Identifier - a bibliotecii de marcaje
prefix= prefixul marcajului

144

ARE 11. JAVA SERVER PAGE JSP


UNITATEA DE INVAT

11.1.3

Marcaje JSP predefinite

Un marcaj JSP defineste o actiune care se executa n timpul procesarii paginii


jsp. Sintaxa marcajelor JSP seamana cu cea a marcajelor html sau xml
<prefix :

marcaj atribute />

Dintre marcajele JSP predefinite adica cu prefixul JSP amintim:


<jsp :

include page=numeFisier jsp sau html />

<jsp :

forward page=numeFisier jsp sau html />

Prelucrarea care urmeaza va fi cea din fisierul mentional. Diferenta dintre


cele dou
a elemente consta n faptul ca include prevede revenirea n pagina
JSP initial
a iar forward nu.
Referinta la fisierul html sau jsp se face relativ la catalogul paginii JSP
initiale.
In cazul marcajelor <jsp: include>, <jsp: forward> se pot transmite parametri prin marcajele incluse
<jsp:param name="nume" value=valoare "/>
sau
<jsp:params>
<jsp:param name="nume" value=valoare "/>
. . . . . .
</jsp:params>
<jsp :

useBean id=numeComponent
aJava
class=numeClasa
scope=domeniu />

unde domeniu precizeaza domeniul de valabilitate al componentei Java,


adic
a page, request, session, application.
Creaz
a un obiect numeComponent
aJava de tip numeClasa avand domeniul de valabilitate data de domeniu.
<jsp :

setProperty name=numeComponent
aJava
property=numeProp
value=valoare/>

Acest marcaj este echivalent cu codul Java


numeComponent
aJava.setNumeProp(valoare).
<jsp : setProperty name=numeComponent
aJava property="*" />
vizeaz
a toate proprietatile componentei Java, fixarea valorilor facandu-se cu

11.1. TEHNOLOGIA JSP

145

datele unui formular. Numele parametrilor din formularele de introducere


a datelor trebuie s
a coincid
a cu identificatorii campurilor din componenta
Java corespunz
atoare.
<jsp :

getProperty name=numeComponent
aJava
property=numeProp/>

Preia si afiseaz
a valoarea c
ampului numeComponent
aJava.numeProp.

11.1.4

Component
a Java (Java Bean)

O component
a Java este o clasa care poate interactiona cu alte componente
Java, cu un document jsp, etc.
O componenta Java contine cel putin
Un constructor f
ar
a nici un argument;
O multime de c
ampuri declarate private;
Pentru fiecare asemenea c
amp
private Tip xyz;
trebuie definite metodele
public void setXyz(Tip xyz){
this.xyz=xyz;
}
public Tip getXyz(){
return xyz;
}

11.1.5

Pagini JSP cu componente Java

Clasa componentei Java care se va utiliza ntr-o pagina JSP trebuie inclusa
ntr-un pachet.
Relu
am exemplul 11.1.2 cu o componenta Java corespunzatoare numelui din
formularul index.html.
Exemplul 11.1.4

146

1
2
3
4
5
6
7
8
9
10

ARE 11. JAVA SERVER PAGE JSP


UNITATEA DE INVAT

package j s p ;
public c l a s s H e l l o B e a n {
private S t r i n g name= ;
public S t r i n g getName ( ) {
return name ;
}
public void setName ( S t r i n g name ) {
t h i s . name=name ;
}
}

In acest caz, pagina JSP este (hello.jsp)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

<j s p : useBean id= o b j c l a s s= j s p . H e l l o B e a n scope= r e q u e s t />


<j s p : s e t P r o p e r t y name= o b j p r o p e r t y= />
<html>
<head>
< t i t l e> j s p h e l l o </ t i t l e>
</head>
<body>
<h1> Pagina de r &#259; spuns </h1>
<center>
<%
out . p r i n t l n ( Hi +o b j . getName ()+ ! ) ;
%>
</ center>
</body>
</html>

Mai mult, se poate include formularul n pagina JSP, binenteles stergandu-l


din fisierul html:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

<j s p : useBean id= o b j c l a s s= j s p . H e l l o B e a n scope= r e q u e s t />


<j s p : s e t P r o p e r t y name= o b j p r o p e r t y= />
<html>
<head>
< t i t l e> j s p h e l l o </ t i t l e>
</head>
<body>
<center>
<h1> Pagina JSP a p l i c a &#355; i a H e l l o </h1>
<form method= p o s t >
<p> <h3> I n t r o d u c e t i numele : </h3>
<input type= t e x t name=name s i z e =20>
<p>
<input type= submit >
</form>
<p>
<%
out . p r i n t l n ( Hi +o b j . getName ()+ ! ) ;
%>
</ center>
</body>
</html>

In vederea gener
arii arhivei war, desfasurarea aplicatiei va fi
jsphello

11.1. TEHNOLOGIA JSP

|
|
|
|
|
|
|
|
|
|
|

147

|---> jsp
|
|
hello.jsp
|---> lib
|---> src
|
|---> jsp
|
|
|
HelloBean.java
|---> web
|
|
web.xml
|---> web-files
|
|
index.html
build.xml

Exemplul 11.1.5 Pagin


a JSP pentru calculul celui mai mare divizor comun cu
metoda de calcul definit
a ntr-o component
a Java.
Utiliz
and documentului html din Exemplul 11.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 ;
public void setM ( S t r i n g m) {
t h i s .m=m;
}
public void setN ( S t r i n g n ) {
t h i s . n=n ;
}
public S t r i n g getM ( ) {
return m;
}
public S t r i n g getN ( ) {
return n ;
}

7
8
9
10
11
12
13
14
15
16
17
18

24

public S t r i n g getCmmdc ( ) {
long m=Long . par se Lo ng ( getM ( ) ) ;
long n=Long . pa rs eL ong ( getN ( ) ) ;
return (new Long (cmmdc(m, n ) ) ) . t o S t r i n g ( ) ;
}

26

long cmmdc( long m, long n ) { . . . }

20
21
22
23

28

Instantiem o componenta Java si i fixam proprietatile (adica i transmitem


parametri problemei) dup
a care apelam metoda ce calculeaza rezultatul dorit n
pagina JSP:
1
2
3
4
5
6

<j s p : useBean id= o b j c l a s s=cmmdc . CmmdcBean scope= a p p l i c a t i o n />


<j s p : s e t P r o p e r t y name= o b j p r o p e r t y= />
<html>
<body>
Cel mai mare d i v i z o r comun a l n u m e r e l o r
<p>

148

7
8
9
10

ARE 11. JAVA SERVER PAGE JSP


UNITATEA DE INVAT

<%=o b j . getM ( ) %> s i <%=o b j . getN ( ) %>


e s t e <%=o b j . getCmmdc ( ) %>
</body>
</html>

Exemplul 11.1.6 Generarea unei exceptii (errhandler.jsp):

1
2
3
4
5
6
7
8
9
10
11
12
13
14

<%@ page e r r o r P a g e= e r r o r p a g e . j s p %>


<html>
<body>
<%
String m a t e r i a=r e q u e s t . g e t P a r a m e t e r ( m a t e r i a ) . t r i m ( ) ;
i f ( m a t e r i a . e q u a l s ( AN ) ) {
out . p r i n t l n ( <hr><f o n t c o l o r=red>A l e g e r e c o r e c t a ! </ f o n t > ) ;
}
else{
throw new E x c e p t i o n ( Na t i f a c u t a l e g e r e a c o r e c t a ) ;
}
%>
</body>
</html>

cu pagina de tratare a exceptiei (errorpage.jsp)

1
2
3
4
5
7
8
10
11
13
14
15
16
17
18
20
21

< !
Aceste comentarii sunt f o a r t e importante in c a z u l u t i l i z a r i i
n a v i g a t o r u l u i IE s i a l u i apachetomcat 5 . . . / 6 . . . In l i p s a
l o r nu s e g e n e r e a z a s a l t u l l a e x c e p t i e p r i n p a g i n a j s p .
R o l u l c o m e n t a r i i l o r e s t e marirea l u n g i m i i f i s i e r u l u i de f a t a .
O a l t e r n a t i v a e s t e ca d i n IE6 . . . O p t i o n s sa s e d e z a c t i v e z e
o p t i u n e a Show f r i e n d l y HTTP e r r o r message
Cu n a v i g a t o r u l F i r e f o x nu e x i s t a a c e a s t a problema .
>
<%@ page i s E r r o r P a g e= t r u e %>
<html>
<body>
<div a l i g n= c e n t e r >
<%= e x c e p t i o n . g e t M e s s a g e ( ) %>
</ div>
</body>
</html>

apelate prin

1
2
3

<html>
<body>
<form method=p o s t

11.2. JSP STANDARD TAG LIBRARY JSTL

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

149

action= h t t p : / / l o c a l h o s t : 8 0 8 0 / m y s e r v l e t / j s p / e r r h a n d l e r . j s p >
Care e s t e m a t e r i a p r e f e r a t a d i n a n i i de s t u d i u u n i v e r s i t a r ?
<p>
A l g o r i t m i c a s i programare
<input type= r a d i o name= m a t e r i a value=AP checked>
<p>
A n a l i z a numerica
<input type= r a d i o name= m a t e r i a value=AN>
<p>
Inteligenta artificiala
<input type= r a d i o name= m a t e r i a value=IA>
<p>
<input type=submit>
</form>
</body>
</html>

11.2

JSP Standard Tag Library JSTL

JSTL este o familie de biblioteci de marcaje ce ofera o serie de facilitati


activitatii de realizare a paginilor Web. JSTL ajuta la separarea activitatii de
programare de aceea a proiectare (design) a paginii Web.
JSTL este alc
atuit
a din 5 biblioteci:
URI
Descriere
http://java.sun.com/jsp/jstl/core
Biblioteca de baza
http://java.sun.com/jsp/jstl/xml
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 jstl.jar si standard.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 printr-o
directiv
a taglib.

11.2.1

Biblioteca de baz
a

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>


Marcaje din biblioteca de baz
a:

150

ARE 11. JAVA SERVER PAGE JSP


UNITATEA DE INVAT

c:set Fixeaz
a o valoare ntr-o variabila.
Atribute ale marcajului:
Atribut
var

Fel
obligatoriu

value

optional

scope

optional

Descriere
Numele variabilei ce va stoca valoarea
expresiei.
Expresia care va fi evaluata si atribuita
variabilei
Domeniul de valabilitate al variabilei.
Unul din valorile:
page, request, session, application.

Referirea la o variabila se face prin sintaxa ${numeVariabil


a}
Referirea la valoarea unui camp dintr-un formular se face prin
${param.numeC
amp}
Al
aturi de obiectul param, alte obiecte predefinite sunt cookie, header,
initParam, pageContext.
Se pot defini variabile cu acelasi nume dar avand domenii de valabilitate
diferit
a. Referirea se face prin ${pageScope.numeVariabil
a },
${requestScope.numeVariabil
a }, ${sessionScope.numeVariabil
a },
${applicationScope.numeVariabil
a }.
Plas
and clauza empty naintea unei variabile, ${empty numeVariabil
a }, se
obtine false sau true dupa cum variabila are sau nu atribuita o valoare.
c:remove S
terge o variabila.
Atribute ale marcajului:
Atribut
var
scope

Fel
obligatoriu
optional

Descriere
Numele variabilei ce se sterge.
Domeniul de valabilitate al variabilei.
Unul din valorile:
page, request, session, application.

c:out Afiseaz
a o valoare.
Atribute ale marcajului:

11.2. JSP STANDARD TAG LIBRARY JSTL

Atribut
value
default

Fel
obligatoriu
optional

escapeXml

optional

151

Descriere
Valoarea ce se evalueaza si se afiseaza.
Cea ce se afiseaza n cazul n care
expresia nu poate fi evaluata.
true / false. Valoarea implicita este true.
Pe false interpreteaza caracterele din value
ca si cod html.

c:if Test, verificarea unei conditii.


Atribute ale marcajului:
Atribut
test
var

Fel
obligatoriu
optional

scope

optional

Descriere
Conditia de test.
Numele variabilei ce va stoca valoarea
testului.
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.
Exemplul 11.2.1 Preluarea datelor unui formular cu c
ampurile 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>

152

ARE 11. JAVA SERVER PAGE JSP


UNITATEA DE INVAT

c:choose Marcajul de selectie poate contine oricate marcaje c:when si cel


mult un marcaj c:otherwise. Fiecare marcaj c:when contine obligatoriu
atributul test. Daca ntr-un marcaj c:when conditia are valoarea true,
atunci se prelucreaza corpul acelui marcaj. In cazul n care toate marcajele c:when au fost evaluate cu false atunci se va prelucra marcajul
c:otherwise (marcaj fara atribute).
c:forEach Ciclu.
Atribute ale marcajului:
Atribut
items
var

Fel
optional
optional

begin
end
step
varStatus

optional
optional
optional
optional

Descriere
Colectia care se parcurge.
Numele variabilei n care se stocheaza
valoarea elementului curent.
Valoarea initiala a variabilei var.
Valoarea finala a variabilei var.
Valoarea pasului de iterare. Implicit este 1.
Informatii despre elementul curent.

Variabila varStatus are campurile:


index valoarea curenta a elementului dupa care se realizeaza ciclarea;
count num
arul iteratiei curente;
first are valoarea true daca este primul element al ciclului;
last are valoarea true daca este ultimul element al ciclului;
Exemplul 11.2.2 Lista parametrilor formularului de apelare a exemplului
anterior se afiseaz
a prin:
<h2> Lista parametrilor din formular </h2>
<ul>
<c:forEach items="${param}" var="p">
<li>
<c:out value="${p}" />
</li>
</c:forEach>
</ul>

Exemplul 11.2.3 Lista parametrilor unui header se afiseaz


a prin:
<h2> Lista campurilor din antet </h2>
<ul>
<c:forEach items="${header}" var="h">
<li>
<c:out value="${h}" />
</li>
</c:forEach>
</ul>

11.2. JSP STANDARD TAG LIBRARY JSTL

153

Exemplul 11.2.4 Evidentierea fontului cu care se scriu titlurile ntr-un


document html:

<c:forEach begin="1" end="6" var="i" >


<c:out value="<h${i}> Heading ${i} </h${i}>" escapeXml="false" />
</c:forEach>

c:forTokens Asigur
a aceasi functionalitate ca si clasei java.util.String
Tokenizer.
Atribute ale marcajului:
Atribut
value

Fel
obligatoriu

default

optional

escapeXml

optional

Descriere
Valoarea ce se evalueaza si se afiseaza.
expresiei.
Cea ce se afiseaza n cazul n care
expresia nu poate fi evaluata.
true / false. Valoarea implicita este true.
Pe false interpreteaza caracterele din value
ca si cod html.

c:import Permite includerea altor pagini JSP n pagina curenta.


Atribute ale marcajului:
Atribut
url
context

Fel
obligatoriu
optional

var

optional

scope

optional

Descriere
Adresa documentului importat.
Context-ul paginii / documentului importat.
Simbolul /, urmat de numele unei aplicatii
de pe acelasi server.
Numele variabilei n care va fi stocat
documentul importat.
Domeniul de valabilitate al variabilei var.
Unul din valorile:
page, request, session, application.

Cu marcajul c:param se pot fixa parametri pentru pagina importata. Acest


marcaj are dou
a atribute name si value. Acesti parametri se transmit cu
metoda get.
c:redirect Redirectarea activitatea catre o alta pagina.
Atribute ale marcajului:

154

ARE 11. JAVA SERVER PAGE JSP


UNITATEA DE INVAT

Atribut
url
context

Fel
obligatoriu
optional

Descriere
Adresa paginii catre care se face redirectarea.
Context-ul paginii catre care se face redirectarea.
Simbolul /, urmat de numele unei aplicatii
de pe acelasi server.

Prin redirectare, parametrii nu sunt retransmisi automat mai departe.


c:url Retine adrese URL.
Atribute ale marcajului:
Atribut
value
context

Fel
obligatoriu
optional

var

optional

scope

optional

11.2.2

Descriere
Adresa documentului de retinut.
Context-ul documentului.
Simbolul /, urmat de numele unei aplicatii
de pe acelasi server.
Numele variabilei n care va fi stocata
adresa documentului.
Domeniul de valabilitate al variabilei var.
Unul din valorile:
page, request, session, application.

Biblioteca de lucru cu baze de date

<%@taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>


Marcaje din biblioteca de baza:
sql:setDataSource Fixeaza referinta la baza de date.
Atribute ale marcajului:
Atribut
dataSource
driver
url
username
password
var
scope

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.

sql:query O interogare a bazei de date.


Atribute ale marcajului:

11.2. JSP STANDARD TAG LIBRARY JSTL

Atribut
sql
dataSource
startRow
maxRows
var

Fel
obligatoriu
optional
optional
optional
obligatoriu

scope

optional

155

Descriere
Fraza sql
Referinta la baza de date
Linia de la care se ncepe interogarea
Numarul maxim de rezultate acceptate
Variabila cu rezultatele interogarii
bazei de date
Domeniul de valabilitate al variabilei var.

sql:update Actualizarea a bazei de date.


Atribute ale marcajului:
Atribut
sql
dataSource

Fel
obligatoriu
optional

Descriere
Fraza sql
Referinta la baza de date

Exemplul 11.2.5 S
a se afiseze lista din agenda telefonic
a creat
a n exemplul
din Cap. Servlet.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

<HTML>
<%@ t a g l i b u r i= h t t p : / / j a v a . sun . com/ j s p / j s t l / c o r e p r e f i x= c %>
<%@ t a g l i b u r i= h t t p : / / j a v a . sun . com/ j s p / j s t l / s q l p r e f i x= s q l %>
<BODY>
<p>
<s q l : s e t D a t a S o u r c e
d r i v e r= o r g . apache . derby . j d b c . C l i e n t D r i v e r
u r l= j d b c : derby : / / l o c a l h o s t : 1 5 2 7 / A g e n d a T e l e f o n i c a
var=db />
<s q l : query
d a t a S o u r c e= $ {db}
var= r e z u l t
s q l= s e l e c t from t e l e f />
<c : i f t e s t= $ { r e z u l t . rowCount g t 0} >
<table>
<tr>
<c : f o r E a c h i t e m s= $ { r e z u l t . columnNames} var= c o l >
<th>
<c : out value= $ { c o l } />
</th>
</ c : f o r E a c h>
</ tr>
<c : f o r E a c h i t e m s= $ { r e z u l t . rowsByIndex } var= l i n e >
<tr>
<c : f o r E a c h i t e m s= $ { l i n e } var= elem >
<td>
<c : out value= $ { elem } />
</td>
</ c : f o r E a c h>
</ tr>
</ c : f o r E a c h>
</ table>

156

33
34
35

ARE 11. JAVA SERVER PAGE JSP


UNITATEA DE INVAT

</ c : i f>
</BODY>
</HTML>

Test de evaluare a cunostintelor


1. Care este rolul unei pagini JSP ?
2. Precizati diferenta dintre o pagina JSP si un document JSP.
3. Unde se instaleaz
a o pagina JSP?
4. Care este rolul unei declaratii JSP ?
5. Care este rolul unei directive JSP ?
6. Cum se poate apela o pagina JSP ?
7. Cum prelucreaz
a un server Web o pagina / document JSP ?

Unitatea de nv
atare 12

Portlet

Durata: 3 ore.

Introducere
Prezentarea termenului de portlet se face mpreuna cu cea de portal. Portalul
ca si portletul sunt aplicatii Web. Practic, un portal accesat afiseaza portlete
n ferestre distincte, portletele fiind aplicatii pe care clientul le poate folosi (Fig.
12.1, Fig. 12.2).
O aplicatie portlet ndeplineste standardele JSR (Java Specification Request)
168 si JSR 286.
Portalul este o aplicatie Web cu functionalitatile:
Container de portleti. Containerul este responsabil de initializarea si distrugerea portletilor, de transmiterea cererilor catre portleti si de colectarea
raspunsurilor.
157

158

ARE 12. PORTLET


UNITATEA DE INVAT

Figure 12.1: Portal - Portlet.

Figure 12.2: Aparitia portlet-etelor ntr-o pagina a unui portal.

159

12.1. APACHE-PLUTO

Agregarea continuturilor (Content aggregator). Permite afisarea si gestionarea mai multor portlete.
Asigur
a servicii dintre care amintim:
acces la portal pe baz
a de autentificare si autorizare. Odata autorizat,
un client are acces la orice portlet.
posibilitatea personaliz
arii portletelor de catre clienti.
Varietatea serviciilor variaz
a de la un portal la altul.
Portletul este o aplicatie Web care se aseamana cu servletul prin:
Se instaleaz
a ntr-un container.
Genereaz
a continut dinamic.
Ciclul de viat
a este gestionat de container.
Interactioneaz
a cu clientul prin modelul request/reply.
Deosebirile unui portlet fat
a de un servlet sunt:
Portletul posed
a mai multe variante de tratare a cererilor.
Prin conceptul de mod (mode) se specifica variante distincte prin care
portletul reactioneaz
a. Sunt definite modurile VIEW, EDIT, HELP. Actiunile
corespunz
atoare sunt definite n metodele doView, doEdit, doHelp.
Prin WindowState se fixeaz
a spatiul utilizat de portlet. Valorile variabilei
WindowState sunt NORMAL, MAXIMIZED, MINIMIZED. In varianta MAXIMIZED portletul ocup
a ntreaga fereastra, n timp ce n varianta MINIMIZED portletul apare ntr-o bara de titluri.

12.1

Apache-pluto

Pentru dezvoltarea unui portlet vom folosi produsul Apache-pluto care genereaza
un portal n care se pot instala / dezinstala usor portlete.
Instalarea produsului. Daca se descarca varianta ncorporata n serverul
Web apache-tomcat, denumit
a pluto-bundle, atunci instalarea la dezarhivarea
fisierului desc
arcat.
Utilizarea produsului. Dintr-un navigator, portalul se apeleaza prin
http://host:8080/pluto/portal
Accesul se face cu User name = password = pluto.
Instalarea unui portlet se face n 2 pasi:

160

ARE 12. PORTLET


UNITATEA DE INVAT

1. Desf
asurarea portlet-ului: Fisierul arhivat al portletului, avand extensia
war, se depune n catalogul PlutoDomain. Apeland managerul lui apachetomcat din componenta Pluto admin se obtine instalarea portletului.
Alternativ, desf
asurarea portlet-lui se va obtine cu apache-ant cu utilizarea
unui fisier build.xml dedicat.
2. Publicarea portlet-ului se face prin componenta Pluto admin.

12.2

Dezvoltarea unui portlet

Compilarea si arhivarea unui portlet n vederea desfasurarii se va face ruland


ant cu fisierul build.xml:
1
2
4
5
6
7
8
9
10
12
13
14
15
16
17
18
19
20
21
22
23
25
26
27
28
29
31
32
33
34
35
36
37
39
40
41
42

<?xml version= 1 . 0 e n c o d i n g=UTF8 ?>


<p r o j e c t name= p o r t l e t b u i l d default= d e p l o y b a s e d i r= . >
<p r o p e r t y e n v i ro n m en t= env />
< !
S e t CATALINA HOME or u s e D p l u t o . home=/p a t h / t o / tomcatw i t h p l u t o
on command l i n e
>
<p r o p e r t y name= p l u t o . home v a l u e= ${ env .CATALINA HOME} />
<p r o p e r t y f i l e = b u i l d . p r o p e r t i e s />
< !
A l l j a r s used by your p o r t l e t need t o be i n l i b i n a d d i t i o n t o t h e
p l u t o antt a s k s j a r
>
<path i d= p r o j e c t . c l a s s p a t h >
< f i l e s e t d i r= l i b >
<i n c l u d e name= . j a r />
</ f i l e s e t>
< f i l e s e t d i r= ${ p l u t o . home}/ l i b >
<i n c l u d e name= . j a r />
</ f i l e s e t>
</ path>
<t a s k d e f
name= a s s e m b l e
c l a s s n a m e= o r g . apache . p l u t o . ant . AssembleTask
c l a s s p a t h r e f= p r o j e c t . c l a s s p a t h
/>
<t a r g e t name= a s s e m b l e >
<a s s e m b l e
webxml= ${webi n f . d i r }/web . xml
p o r t l e t x m l= ${webi n f . d i r }/ p o r t l e t . xml
d e s t f i l e = ${ b u i l d . d i r }/web . xml
/>
</ t a r g e t>
<t a r g e t name= i n i t d e s c r i p t i o n= C r e a t e s b u i l d d i r s >
<echo message=Ant v e r s i o n = ${ ant . v e r s i o n } />
<mkdir d e s c r i p t i o n= C r e a t e s b u i l d d i r e c t o r y i f needed
d i r= ${ b u i l d . d i r } />

12.2. DEZVOLTAREA UNUI PORTLET

43
44
45
46
47
48
49
50
51
53
54
55
56
57
58
59
60
62
63
64
65
66

<mkdir d e s c r i p t i o n= C r e a t e s war d i r e c t o r y i f needed


d i r= ${ w e b b u i l d . d i r } />
<mkdir d e s c r i p t i o n= C r e a t e s WEBINF d i r e c t o r y i f needed
d i r= ${ w e b b u i l d . d i r }/WEBINF />
<mkdir d e s c r i p t i o n= C r e a t e s WEBINF/ c l a s s e s d i r e c t o r y i f needed
d i r= ${ c l a s s b u i l d . d i r } />
<mkdir d e s c r i p t i o n= C r e a t e s WEBINF/ l i b d i r e c t o r y i f needed
d i r= ${ w e b b u i l d . d i r }/WEBINF/ l i b />
</ t a r g e t>
<t a r g e t name= c o m p i l e depends= i n i t d e s c r i p t i o n= Compiles s o u r c e >
<j a v a c c l a s s p a t h r e f= p r o j e c t . c l a s s p a t h
f o r k= y e s
debug= t r u e
d e b u g l e v e l= l i n e s , v a r s , s o u r c e
d e s t d i r= ${ c l a s s b u i l d . d i r }
s r c d i r= ${ j a v a . s r c . d i r } />
</ t a r g e t>
<t a r g e t name= war depends= c o m p i l e >
< ! Move web f i l e s e x c l u d i n g web . xml >
<copy t o d i r= ${ w e b b u i l d . d i r }/ >
< f i l e s e t d i r= ${web . d i r } e x c l u d e s= / web . xml />
</ copy>

78

< ! Move o t h e r n e c c e s s a r y l i b r a r i e s >


<copy t o d i r= ${ w e b b u i l d . d i r }/WEBINF/ l i b / >
< f i l e s e t d i r= ${ l i b . d i r } >
<i n c l u d e name= / . j a r />
<e x c l u d e name= c a s t o r . j a r />
<e x c l u d e name= p l u t o . j a r />
<e x c l u d e name= p o r t l e t . j a r />
<e x c l u d e name= s e r v l e t . j a r />
<e x c l u d e name= j u n i t . j a r />
</ f i l e s e t>
</ copy>

80

< a n t c a l l t a r g e t= a s s e m b l e />

68
69
70
71
72
73
74
75
76
77

86

< ! C r e a t e war i n d e p l o y m e n t d i r e c t o r y >


<war b a s e d i r= ${ w e b b u i l d . d i r } update= f a l s e
w a r f i l e= ${ app . name } . war
webxml= ${ b u i l d . d i r }/web . xml />
</ t a r g e t>

88

<t a r g e t name= b u i l d depends= c l e a n , war />

90

<t a r g e t name= d e p l o y depends= b u i l d >


<echo message= D e p l o y i n g t o p l u t o . home=${ p l u t o . home} />
< !
Remove former d e p l o y m e n t b e c a u s e sometimes
tomcat d o e s n o t f u l l y r e d e p l o y a war
>
<d e l e t e
d i r= ${ p l u t o . home}/ webapps /${ app . name}
f a i l o n e r r o r= t r u e
/>
< ! Deploy war f i l e >
<copy

82
83
84
85

91
92
93
94
95
96
97
98
99
100
101

161

162

102
103
104
105
106
107
108
109
110
111

ARE 12. PORTLET


UNITATEA DE INVAT

f i l e = ${ app . name } . war


t o d i r= ${ p l u t o . home}/ PlutoDomain
o v e r w r i t e= t r u e
/>
< ! Deploy c o n t e x t d e p l o y m e n t d e s c r i p t o r f o r Tomcat >
<copy
f i l e = ${ c o n f . d i r }/${ app . name } . xml
t o d i r= ${ p l u t o . home}/ c o n f / C a t a l i n a / l o c a l h o s t
o v e r w r i t e= f a l s e
/>

113

</ t a r g e t>

115

<t a r g e t name= c l e a n d e s c r i p t i o n= C l e a n s b u i l d >


<d e l e t e d i r= ${ b u i l d . d i r } f a i l o n e r r o r= f a l s e />
</ t a r g e t>

116
117
119

</ p r o j e c t>

Fisierul de propriet
ati build.properties este
1
2
4
5
7
8
9
11
12
14
15
16
17
19
20
22
23
25
26
28
29

32
33

#b u i l d . p r o p e r t i e s
#Standard p r o p e r t i e s f o r Ant b u i l d o f a P l u t o 1 . 1 p o r t l e t
#module name
app . name=NumePortlet
#D i r e c t o r y t h a t h o l d s s o u r c e code
s r c . d i r = s r c / main
j a v a . s r c . d i r = ${ s r c . d i r }/ j a v a
#D i r e c t o r y t h a t h o l d s documentation
doc . d i r = d o c s
#D i r e c t o r y t h a t h o l d s f i l e s t o be b u i l t i n t o a j a r , war o r e a r
build . dir = build
w e b b u i l d . d i r = ${ b u i l d . d i r }/ webapp
c l a s s b u i l d . d i r = ${ w e b b u i l d . d i r }/WEBINF/ c l a s s e s
#D i r e c t o r y t h a t h o l d s c o n f i g u r a t i o n
c o n f . d i r = ${ s r c . d i r }/ r e s o u r c e

files

#D i r e c t o r y t h a t h o l d s l i b r a r i e s r e q u i r e d t o b u i l d and run t h e c l a s s e s
lib . dir = lib
#D i r e c t o r y t h a t h o l d s webapp f i l e s
web . d i r = ${ s r c . d i r }/ webapp
#WEBINF d i r e c t o r y
webi n f . d i r = ${web . d i r }/WEBINF

#D i r e c t o r y t h a t h o l d s f i l e s t o b u i l d d i s t r i b u t i o n
d i s t . d i r = ${ b u i l d . d i r }/ d i s t

Pentru utilizarea acestui build.xml este nevoie de structura urmatoare de cataloage


NumePortlet

12.2. DEZVOLTAREA UNUI PORTLET

|-->
|
|
|
|
|
|
|
|
|
|-->
|
|
|
|
|
|
|
|
|
|
|

163

lib
| castor-1.1.1.jar
| commons-logging-1.0.4.jar
| pluto-ant-tasks-2.0.*.jar
| pluto-descriptor-api-1.1.6.jar
| pluto-descriptor-impl-1.1.6.jar
| pluto-util-2.0.*.jar
| pluto-container-2.0.0.jar
| jaxb-api-2.1.jar
| jaxb-impl-2.1.9.jar
src
|--> main
|
|--> java
|
|
|--> pachetul portletului
|
|--> resource
|
|
|
NumePortlet.xml
|
|--> webapp
|
|
|--> jsp
|
|
|
|
fisierele jsp ale portletului
|
|
|--> WEB-INF
|
|
|
|
portlet.xml
|
|
|
|
web.xml

Fisierele castor.1.1.1.jar, pluto-descriptor-api-*.jar, pluto-descriptor-impl-*.jar,


portlet-container-*.jar se copiaz
a din catalogul PLUTO HOME\shared\lib.
Fisierul web.xml de mai sus este
2

<?xml version= 1 . 0 e n c o d i n g=UTF8 ?>

<webapp xmlns= h t t p : // j a v a . sun . com/xml/ ns / j 2 e e


x m l n s : 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 2 e e
h t t p : // j a v a . sun . com/xml/ ns / j 2 e e /weba p p 2 4 . xsd
version= 2 . 4 >

5
6
7
8
10

</webapp>

Continutul final al acestui fisier rezulta n urma obiectivului ant assemple,


n care se preiau date din fisierul de configurare al portletului portlet.xml.
Editarea fisierului portlet.xml este sarcina programatorului.
Fisierul NumePortlet.xml este utilizat la desfasurarea aplicatie, fiind copiat
n catalogul conf\Catalina\localhost al lui apache-tomcat sau Apache-pluto.
Acest fisier are continutul:
1
2

<Context path= NumePortlet docBase= . . \ PlutoDomain \ NumePortlet . war


c r o s s C o n t e x t= t r u e />

164

ARE 12. PORTLET


UNITATEA DE INVAT

12.3

Elemente de programare

Orice portlet implementeaza interfata Portlet. Interfata Portlet declara 4


metode
public interface Portlet{
public void init(PortletConfig config) throws PortletException;
public void processAction(ActionRequest request, ActionResponse
response) throws PortletException, java.io.IOException;
public void render(RenderRequest request, RenderResponse
response) throws PortletException, java.io.IOException;
public void destroy();
}
Metoda processAction prelucreaza cererea emisa de containerul de portlete.
La solicitarea containerului, metoda render regenereaza continutul unui portlet.
Clasa GenericPortlet este implementarea initiala a interfetei Portlet. Extinz
and clasa GenericPortlet, sarcina programatorului este sa suprascrie metodele
doView pentru tratarea modului VIEW;
protected void doView(RenderRequest req,RenderResponse res)
throws PortletException, IOException
doEdit pentru tratarea modului EDIT;
protected void doEdit(RenderRequest req,RenderResponse res)
throws PortletException, IOException
doHelp pentru tratarea modului HELP;
protected void doHelp(RenderRequest req,RenderResponse res)
throws PortletException, IOException
init, destroy pentru initializarea, respectiv oprirea portletului.
void init() throws PortletException
void init(PortletConfig config) throws PortletException
void destroy()
si eventual, s
a defineasc
a continutul metodei
public void processAction(ActionRequest request,ActionResponse
response) throws PortletException, java.io.IOException;

12.3. ELEMENTE DE PROGRAMARE

165

Metoda processAction este apelata de metoda include(request, response) a


clasei PortletRequestDispatcher.
Exemplul 12.3.1 Portletul HelloWorld.
1
2
3
5
6
7
8
9
10

package h e l l o ;
import j a v a . i o . ;
import j a v a x . p o r t l e t . ;
public c l a s s H e l l o W o r l d P o r t l e t extends G e n e r i c P o r t l e t {
protected void doView ( RenderRequest r e q u e s t , RenderResponse r e s p o n s e )
throws P o r t l e t E x c e p t i o n , IOException {
r e s p o n s e . setContentType ( t e x t / html ) ;
r e s p o n s e . g e t W r i t e r ( ) . p r i n t l n ( H e l l o World ! ) ;
}
// A l t a v a r i a n t a de programare
/
p u b l i c v o i d doView ( RenderRequest req , RenderResponse r e s )
t h r o w s P o r t l e t E x c e p t i o n , IOException {
r e s . s e t C o n t e n t T y p e ( t e x t / html ) ;
P r i n t W r i t e r o u t=r e s . g e t W r i t e r ( ) ;
o u t . p r i n t l n (<h2 >);
o u t . p r i n t l n ( H e l l o World ! ) ;
o u t . p r i n t l n (</h2 >);
}
/

12
13
14
15
16
17
18
19
20
21
22
23

Fisierul portlet.xml este


1
2
3
4
5
6
8
9
10
11
12
13
14
15
16
17
18
19
20
21

<?xml version= 1 . 0 e n c o d i n g=UTF8 ?>


<p o r t l e t app xmlns= h t t p : // j a v a . sun . com/xml/ ns / p o r t l e t / p o r t l e t a p p 2 0 . xsd
x m l n s : x s i= h t t p : //www. w3 . o r g /2001/XMLSchemai n s t a n c e
x s i : s c h e m a L o c a t i o n= h t t p : // j a v a . sun . com/xml/ ns / p o r t l e t / p o r t l e t a p p 2 0 . xsd
h t t p : // j a v a . sun . com/xml/ ns / p o r t l e t / p o r t l e t a p p 2 0 . xsd
i d= myPortletApp version= 2 . 0 >
< p o r t l e t>
<d e s c r i p t i o n>H e l l o World a s a p o r t l e t app</ d e s c r i p t i o n>
<p o r t l e t name>H e l l o W o r l d 1 P o r t l e t</ p o r t l e t name>
<d i s p l a y name>H e l l o World P o r t l e t</ d i s p l a y name>
<p o r t l e t c l a s s> h e l l o . H e l l o W o r l d 1 P o r t l e t</ p o r t l e t c l a s s>
<s u p p o r t s>
<mimet y p e>t e x t / html</mimet y p e>
<p o r t l e t mode>VIEW</ p o r t l e t mode>
</ s u p p o r t s>
<p o r t l e t i n f o>
< t i t l e>H e l l o World P o r t l e t</ t i t l e>
</ p o r t l e t i n f o>
</ p o r t l e t>
</ p o r t l e t app>

Exemplul 12.3.2 Evidentierea modurilor VIEW, EDIT si HELP.

166

1
2
3
5
6
7
8
9
10
11

package h e l l o p l u t o ;
import j a v a . i o . ;
import j a v a x . p o r t l e t . ;
public c l a s s H e l l o P l u t o P o r t l e t extends G e n e r i c P o r t l e t {
public void doView ( RenderRequest req , RenderResponse r e s )
throws P o r t l e t E x c e p t i o n , IOException {
r e s . setContentType ( t e x t / html ) ;
W r i t e r out=r e s . g e t W r i t e r ( ) ;
out . w r i t e ( <s t r o n g >H e l l o P l u t o i n view mode</s t r o n g > ) ;
}
public void doEdit ( RenderRequest req , RenderResponse r e s )
throws P o r t l e t E x c e p t i o n , IOException {
r e s . setContentType ( t e x t / html ) ;
W r i t e r out=r e s . g e t W r i t e r ( ) ;
out . w r i t e ( <i >H e l l o P l u t o i n e d i t mode</i > ) ;
}

13
14
15
16
17
18

public void doHelp ( RenderRequest req , RenderResponse r e s )


throws P o r t l e t E x c e p t i o n , IOException {
r e s . setContentType ( t e x t / html ) ;
W r i t e r out=r e s . g e t W r i t e r ( ) ;
out . w r i t e ( <u>H e l l o P l u t o i n h e l p mode</u> ) ;
}

20
21
22
23
24
25
26

ARE 12. PORTLET


UNITATEA DE INVAT

Fisierul portlet.xml este


1
2
3
4
5
6
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

<?xml v e r s i o n= 1 . 0 e n c o d i n g=UTF8?>
<p o r t l e t app xmlns= h t t p : / / j a v a . sun . com/xml/ ns / p o r t l e t / p o r t l e t a p p 2 0 . xsd
xmlns : x s i= h t t p : / /www. w3 . o r g /2001/XMLSchemai n s t a n c e
x s i : s c h e m a L o c a t i o n= h t t p : / / j a v a . sun . com/xml/ ns / p o r t l e t / p o r t l e t a p p 2 0 . xsd
h t t p : / / j a v a . sun . com/xml/ ns / p o r t l e t / p o r t l e t a p p 2 0 . xsd
i d= myPortletApp v e r s i o n= 2 . 0 >
<p o r t l e t >
<d e s c r i p t i o n >H e l l o P l u t o a s a p o r t l e t app</ d e s c r i p t i o n >
<p o r t l e t name>H e l l o P l u t o P o r t l e t </ p o r t l e t name>
<d i s p l a y name>H e l l o Pluto </ d i s p l a y name>
<p o r t l e t c l a s s >h e l l o p l u t o . H e l l o P l u t o P o r t l e t </ p o r t l e t c l a s s >
<s u p p o r t s >
<mimetype>t e x t / html</mimetype>
<p o r t l e t mode>VIEW</ p o r t l e t mode>
<p o r t l e t mode>EDIT</ p o r t l e t mode>
<p o r t l e t mode>HELP</ p o r t l e t mode>
</s u p p o r t s >
<p o r t l e t i n f o >
< t i t l e >H e l l o P l u t o P o r t l e t </ t i t l e >
</ p o r t l e t i n f o >
</ p o r t l e t >
</ p o r t l e t app>

Exemplul 12.3.3 Portletul Hello. Portletul afiseaz


a o zon
a text de introducere a
unui nume si un buton. Odat
a introdus numele, la ap
asarea butonului se afisaez
a
textul Hello nume si un buton de reluare.

12.3. ELEMENTE DE PROGRAMARE

package h e l l o n a m e ;

3
5

import j a v a . i o . ;
import j a v a x . p o r t l e t . ;
import j a v a . u t i l . Enumeration ;

public c l a s s H e l l o N a m e P o r t l e t extends G e n e r i c P o r t l e t {

public void doView ( RenderRequest req , RenderResponse r e s )


throws P o r t l e t E x c e p t i o n , IOException {
r e s . setContentType ( t e x t / html ) ;
S t r i n g nume=( S t r i n g ) r e q . g e t P a r a m e t e r ( name ) ;
P o r t l e t R e q u e s t D i s p a t c h e r prd=n u l l ;
i f ( nume==n u l l ) {
prd=g e t P o r t l e t C o n t e x t ( ) . g e t R e q u e s t D i s p a t c h e r ( / j s p / i n p u t . j s p ) ;
prd . i n c l u d e ( req , r e s ) ;
}
else {
// V a r i a n t a cu a f i s a r e p r i n View
/
Writer o u t=r e s . g e t W r i t e r ( ) ;
o u t . w r i t e ( H e l l o + nume ) ;
PortletURL renderURL=r e s . createRenderURL ( ) ;
renderURL . s e t P o r t l e t M o d e ( P o r t l e t M o d e .VIEW) ;
renderURL . setWindowState ( WindowState .NORMAL) ;
o u t . w r i t e (<p><a h r e f =\+renderURL . t o S t r i n g ()+\> R e l u a r e </a >);
/
// V a r i a n t a cu a f i s a r e p r i n t r un f i s i e r j s p
prd=g e t P o r t l e t C o n t e x t ( ) . g e t R e q u e s t D i s p a t c h e r ( / j s p / ou tp ut . j s p ) ;
prd . i n c l u d e ( req , r e s ) ;
}
}

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

public void p r o c e s s A c t i o n ( A c t i o n R e q u e s t req , A c t i o n R e s p o n s e r e s )


throws IOException , P o r t l e t E x c e p t i o n {
// P r e i a p a r a m e t r i i s i l e t r i m i t e c e l u i c a r e a emis c e r e r e a
Enumeration params=r e q . getParameterNames ( ) ;
while ( params . hasMoreElements ( ) ) {
S t r i n g parameterName = ( S t r i n g ) params . nextElement ( ) ;
S t r i n g p a r a m e t e r V a l u e=r e q . g e t P a r a m e t e r ( parameterName ) ;
r e s . s e t R e n d e r P a r a m e t e r ( parameterName , p a r a m e t e r V a l u e ) ;
}
}

34
35
36
37
38
39
40
41
42
43
44

Fisierele input.jsp si putput.jsp au codurile


1
2
3
4
5
6
7
8
9
10
11
12

167

<%@ t a g l i b u r i= h t t p : / / j a v a . sun . com/ p o r t l e t p r e f i x= p o r t l e t %>


< p o r t l e t : d e f i n e O b j e c t s />
<div a l i g n= c e n t e r >
I n t r o d u c e &#355; i numele :
<br/>
<form action=< p o r t l e t : actionURL />
method=POST>
<br>
<input type= t e x t name=name />
<br>
<input type= submit name= submitButton value=Apasama />
</form>

168

13

ARE 12. PORTLET


UNITATEA DE INVAT

</ div>

si respectiv
1
2
3
4
5
6
7
8
9
10

<%@ t a g l i b u r i= h t t p : // j a v a . sun . com/ p o r t l e t p r e f i x= p o r t l e t %>


< p o r t l e t : d e f i n e O b j e c t s />
<p>
<%
S t r i n g r e s u l t= H e l l o +r e n d e r R e q u e s t . g e t P a r a m e t e r ( name)+ ! ;
out . p r i n t l n ( r e s u l t ) ;
%>
<p><a h r e f=<p o r t l e t : r e n d e r U R L p o r t l e t M o d e= view windowState= normal />>
Reluare
</ a> .

Exemplul 12.3.4 Cel mai mare divizor comun a dou


a numere naturale ntr-un
portlet.
Variant
a n care calculul este programat n portlet.
1

package cmmdc ;

3
5

import j a v a . i o . ;
import j a v a x . p o r t l e t . ;
import j a v a . u t i l . Enumeration ;

public c l a s s CmmdcPortlet extends G e n e r i c P o r t l e t {

public void doView ( RenderRequest req , RenderResponse r e s )


throws P o r t l e t E x c e p t i o n , IOException {
r e s . setContentType ( t e x t / html ) ;
P o r t l e t R e q u e s t D i s p a t c h e r prd=n u l l ;
S t r i n g r e z=r e q . g e t P a r a m e t e r ( r e z ) ;
i f ( r e z==n u l l ) {
prd=g e t P o r t l e t C o n t e x t ( ) . g e t R e q u e s t D i s p a t c h e r ( / j s p / i n p u t . j s p ) ;
prd . i n c l u d e ( req , r e s ) ;
}
else {
prd=g e t P o r t l e t C o n t e x t ( ) . g e t R e q u e s t D i s p a t c h e r ( / j s p / ou tp ut . j s p ) ;
prd . i n c l u d e ( req , r e s ) ;
}
}

9
10
11
12
13
14
15
16
17
18
19
20
21
22

33

public void p r o c e s s A c t i o n ( A c t i o n R e q u e s t req , A c t i o n R e s p o n s e r e s )


throws IOException , P o r t l e t E x c e p t i o n {
// P r e i a p a r a m e t r i i s i l e t r i m i t e c e l u i c a r e a emis c e r e r e a
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 Lon g ( sm ) ;
long n=Long . p ars eL ong ( sn ) ;
long c=cmmdc(m, n ) ;
r e s . s e t R e n d e r P a r a m e t e r ( r e z , (new Long ( c ) ) . t o S t r i n g ( ) ) ;
}

35

private long cmmdc( long m, long n ) { . . . }

24
25
26
27
28
29
30
31
32

37

12.3. ELEMENTE DE PROGRAMARE

169

Fisierele inputCmmdc.jsp si outputCmmdc.jsp au codurile

21

<%@ t a g l i b u r i= h t t p : / / j a v a . sun . com/ p o r t l e t p r e f i x= p o r t l e t %>


< p o r t l e t : d e f i n e O b j e c t s />
<div a l i g n= c e n t e r >
<form action=< p o r t l e t : actionURL />
method=POST>
<table border= 1 >
<tr>
<td> Primul num&#259; r </td>
<td> <input type= t e x t name=m /> </td>
</ tr>
<tr>
<td> Al d o i l e a num&#259; r </td>
<td> <input type= t e x t name=n /> </td>
</ tr>
<tr>
<td>
<input type= submit name= submitButton value= C a l c u l e a z a />
</td>
</ tr>
</ table>
</form>

23

</ div>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

si respectiv
1
2
4
5
6
7
8
10
11
12
13

<%@ t a g l i b u r i= h t t p : / / j a v a . sun . com/ p o r t l e t p r e f i x= p o r t l e t %>


< p o r t l e t : d e f i n e O b j e c t s />
<P>
<%
String r e s u l t=Cmmdc +r e n d e r R e q u e s t . g e t P a r a m e t e r ( r e z )+ ! ;
out . p r i n t l n ( r e s u l t ) ;
%>
<P>
<a href=< p o r t l e t : renderURL p o r t l e t M o d e= view windowState= normal />>
Reluare
</a>

Variant
a n care calculul este programat ntr-o component
a Java (bean)
si care este apelat n pagina jsp de afisare a rezultatului.
1

package cmmdc ;

3
5

import j a v a . i o . ;
import j a v a x . p o r t l e t . ;
import j a v a . u t i l . Enumeration ;

public c l a s s CmmdcPortlet extends G e n e r i c P o r t l e t {

9
10
11
12
13
14
15

public void doView ( RenderRequest req , RenderResponse r e s )


throws P o r t l e t E x c e p t i o n , IOException {
r e s . setContentType ( t e x t / html ) ;
P o r t l e t R e q u e s t D i s p a t c h e r prd=n u l l ;
S t r i n g sb=r e q . g e t P a r a m e t e r ( submitButton ) ;
i f ( sb==n u l l ) {
prd=g e t P o r t l e t C o n t e x t ( ) . g e t R e q u e s t D i s p a t c h e r ( / j s p /inputCmmdc . j s p ) ;

170

ARE 12. PORTLET


UNITATEA DE INVAT

prd . i n c l u d e ( req , r e s ) ;
}
else {
prd=g e t P o r t l e t C o n t e x t ( ) . g e t R e q u e s t D i s p a t c h e r ( / j s p /outputCmmdc . j s p ) ;
prd . i n c l u d e ( req , r e s ) ;
}

16
17
18
19
20
21
22

24

public void p r o c e s s A c t i o n ( A c t i o n R e q u e s t req , A c t i o n R e s p o n s e r e s )


throws IOException , P o r t l e t E x c e p t i o n {
// P r e i a p a r a m e t r i i s i l e t r i m i t e c e l u i c a r e a emis c e r e r e a
Enumeration params=r e q . getParameterNames ( ) ;
while ( params . hasMoreElements ( ) ) {
S t r i n g parameterName = ( S t r i n g ) params . nextElement ( ) ;
S t r i n g p a r a m e t e r V a l u e=r e q . g e t P a r a m e t e r ( parameterName ) ;
System . out . p r i n t l n ( >> parameterName = + parameterName +
<=> p a r a m e t e r V a l u e = + p a r a m e t e r V a l u e ) ;
r e s . s e t R e n d e r P a r a m e t e r ( parameterName , p a r a m e t e r V a l u e ) ;
}
}

25
26
27
28
29
30
31
32
33
34
35
36

Codul componentei Java


1

public c l a s s CmmdcBean{
private S t r i n g m= ;
private S t r i n g n= ;

3
4

public void setM ( S t r i n g m) {


t h i s .m=m;
}
public void setN ( S t r i n g n ) {
t h i s . n=n ;
}
public S t r i n g getM ( ) {
return m;
}
public S t r i n g getN ( ) {
return n ;
}
public S t r i n g cmmdc ( ) {
long m0=Long . pa rs eL ong (m) ;
long n0=Long . pa rse Lo ng ( n ) ;
long c , r ;
do{
c=n0 ;
r=m0%n0 ;
m0=n0 ;
n0=r ;
}
while ( r ! = 0 ) ;
return (new Long ( c ) ) . t o S t r i n g ( ) ;
}

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

Pagina outputCmmdc.jsp
1
2

<%@ t a g l i b u r i= h t t p : / / j a v a . sun . com/ p o r t l e t p r e f i x= p o r t l e t %>


<j s p : useBean id=myCmmdcBean c l a s s=cmmdc . CmmdcBean scope= s e s s i o n />

12.3. ELEMENTE DE PROGRAMARE

171

<j s p : s e t P r o p e r t y name=myCmmdcBean p r o p e r t y= />

< p o r t l e t : d e f i n e O b j e c t s />

<P>
<%
String r e s u l t=Cmmdc +myCmmdcBean . cmmdc ( ) ;
out . p r i n t l n ( r e s u l t ) ;
%>
<P>
<a href=< p o r t l e t : renderURL p o r t l e t M o d e= view windowState= normal />>
Reluare
</a>

8
9
10
11
12
13
14
15

Variant
a n care care calculul este programat ntr-un servlet. Servletul
utilizat este cel prezentat n capitolul Servlet, (9.3.2), dar inclus n pachetul
portlet-ului. Fisierul inputCmmdc.jsp are n plus linia
<input type="hidden" name="tip" value="text/html"/>

iar n codul clasei CmmdcPortlet, n locul liniei


prd=getPortletContext().getRequestDispatcher("/jsp/outputCmmdc.jsp");

apare
prd=getPortletContext().getRequestDispatcher("/cmmdc");

adica n locul invoc


arii paginii JSP, dispecerul apeleaza servletul. In servlet este
esential
a furnizarea rezultatului n format html. Pagina html generata se ncarca
n fereastra portlet-ului.
Fisierul web.xml, naintea completarii prin ant, este
1

<?xml version= 1 . 0 e n c o d i n g=UTF8 ?>

<webapp xmlns= h t t p : // j a v a . sun . com/xml/ ns / j 2 e e


x m l n s : 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 2 e e
h t t p : // j a v a . sun . com/xml/ ns / j 2 e e /weba p p 2 4 . xsd
version= 2 . 4 >

4
5
6
7
9
10
11
12
14
15
16
17
18

< s e r v l e t>
<s e r v l e t name>CmmdcServlet</ s e r v l e t name>
<s e r v l e t c l a s s>cmmdc . CmmdcServlet</ s e r v l e t c l a s s>
</ s e r v l e t>
<s e r v l e t mapping>
<s e r v l e t name>CmmdcServlet</ s e r v l e t name>
<u r l p a t t e r n>/cmmdc</ u r l p a t t e r n>
</ s e r v l e t mapping>
</webapp>

Interfata PortletPreferences
Atribute, adic
a perechi de tip String (nume,valoare) definite n fisierul portlet.xml
prin

172

ARE 12. PORTLET


UNITATEA DE INVAT

<portlet-preferences>
<preference>
<name>nume_atribut</name>
<value>valoare_atribut</value>
<read-only>true|false</read-only>
</preference>
. . .
</portlet-preferences>
Atributele se transmit metodelor doView, doEdit si doHelp. Suportul este
oferit prin interfata PortletPreferences.
Metode
String getValue(String key, String def )
Returneaz
a valoarea primului atribut avand numele key. In lipsa atributului
sau a valorii returneaza valoarea def.
String[] getValues(String key, String[] def )
Returneaz
a toate valorile atributului key.
Enumeration<String> getNames()
Suport pentru acces la numele atributelor care au valoare.
Map<String,String[]> getMap()
Suport pentru acces la atribute.
Un obiect care implementeaza interfata PortletPreferences se obtine prin
metoda getPreferences() a clasei RenderRequest.
Exemplul 12.3.5 Portlet n care se preiau si se afiseaz
a valori ale atributelor.
Codul portletului este
1

package p r e f ;

3
4

import j a v a . i o . ;
import j a v a x . p o r t l e t . ;

public c l a s s P r e f P o r t l e t extends G e n e r i c P o r t l e t {
public void doView ( RenderRequest req , RenderResponse r e s )
throws P o r t l e t E x c e p t i o n , IOException {
P o r t l e t P r e f e r e n c e s p r e f s = req . g e tP r e f e re n c e s ( ) ;
S t r i n g a t t r 1 = p r e f s . g e t V a l u e ( ATTR1 , a t t r 1 ) ;
S t r i n g a t t r 2 = p r e f s . g e t V a l u e ( ATTR2 , a t t r 2 ) ;
r e s . setContentType ( t e x t / html ) ;
W r i t e r out=r e s . g e t W r i t e r ( ) ;
out . w r i t e ( <s t r o n g >+a t t r 1+ <> +a t t r 2+</s t r o n g > ) ;
}

8
9
10
11
12
13
14
15
16
17

12.4. PRODUSE PORTAL

173

iar atributele din fisierul portlet.xml sunt


<portlet-preferences>
<preference>
<name>ATTR1</name>
<value>Programare distribuita</value>
<read-only>true</read-only>
</preference>
<preference>
<name>ATTR2</name>
<!-<value>Analiza numerica</value>
-->
<read-only>true</read-only>
</preference>
</portlet-preferences>

Al doilea atribut nu are valoare.Portletul afiseaza textul Programare distribuita


<> attr2.

12.4

Produse Portal

Termenul portal va desemna


aplicatia informatic
a prin care o institutie comunica cu lumea exterioara
produsul informatic care realizeaza aplicatia amintita la pct. anterior
In cele ce urmeaz
a ne vom referi doar la produse portal care sunt containere
de portlete.
Dezvoltarea unui portal al unei organizatii se face pe produse specializate
acestui scop. Dintre asemenea produsele gratuite amintim:
uPortal;
jetspeed-2;
care vor fi prezentate n continuare. apache-pluto este ideal pentru testarea
portlet-elor.

12.4.1

uPortal

uPortal este un portal cadru, dezvoltat de JA-SIG (Java Architecture Special


Interest Group) si a fost utilizat de mai multe universitati ca suport n constructia
portalului specific.
Instalarea produsului. Distributia produsului se face n doua variante
uPortal-*.*.* - uPortal-only;

174

ARE 12. PORTLET


UNITATEA DE INVAT

uPortal-*.*.*-quick-start care nglobeaza toate resursele necesare function


arii
(apache-ant, apache-tomcat, apache-maven, HypersonicSQLDB).
In cele ce urmeaz
a utilizam varianta uPortal-quick-start. Instalarea produsului
revine la dezarhivarea fisierului descarcat.
Lansarea portalului. In urma dezarhivarii, n catalogul uPortal HOME se
g
aseste un fisier build.xml, ale carei obiective asigura lansarea portalului1 .
Se completeaz
a fisierul ant.bat cu referinta set JAVA HOME=...
Lansarea portalului consta n executarea comenzii
ant start
De fapt se porneste SGBD HypersonicSQLDB si serverul Web apache-tomcat.
Oprirea portalului se face prin executarea comenzii
ant stop
Dintr-un navigator, portalul se acceseaza prin
http://host:8080/uPortal
Accesarea portalului se poate face doar de detinatorii unui cont (UserName,
Password). Administratorul (UserName=Password=admin) poate crea conturi
noi.
Instalarea unui portlet consta n desfasurarea si publicarea lui.
Compilarea si arhivarea portletului se poate face cu apache-ant In acest scop
se creaz
a structura
|-->
|
|-->
|
|
|
|
|
|
|
|

lib
|
portlet-api-1.0.jar
pachetul portlet-ului
|--> jsp
|
|
*.jsp
|--> WEB-INF
|
|--> classes
|
|
|
*.java
|
|
web.xml
|
|
portlet.xml
build.xml

cu fisierele *.java, *.jsp si portlet.xml corespunzatoare portletului iar web.xml


este generic
1
2
3
4
5
6

<?xml version= 1 . 0 e n c o d i n g=ISO88591 ?>


< !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>
</webapp>
1

La prima executare a unei operatii asupra portalului, calculatorul trebuie s


a fie conectat
la internet, deoarece mai multe resurse sunt desc
arcate prin apache-maven. Aceste resurse se
depun n c:\Documents and Settings\adminName\.m2\repository.

12.4. PRODUSE PORTAL

175

Fisierul build.xml, compilare si arhivare este


1
3
4
5
7
8
9
10
11
13
14
15
16
17
18
19
21
22
23
24
25
27
28
29
30
31
32
33
34

<p r o j e c t name= p o r t l e t b u i l d default= war b a s e d i r= . >


<p r o p e r t y name= package v a l u e= h e l l o />
<p r o p e r t y name= p o r t l e t . name v a l u e= H e l l o N a m e P o r t l e t />
<p r o p e r t y name= b u i l d . d i r v a l u e= b u i l d />
<path i d= p r o j e c t . c l a s s p a t h >
< f i l e s e t d i r= l i b >
<i n c l u d e name= . j a r />
</ f i l e s e t>
</ path>
<t a r g e t name= i n i t >
<d e l e t e d i r= ${ package }/${ b u i l d . d i r } />
<mkdir d i r= ${ package }/${ b u i l d . d i r } />
<mkdir d i r= ${ package }/${ b u i l d . d i r }/ j s p />
<mkdir d i r= ${ package }/${ b u i l d . d i r }/WEBINF />
<mkdir d i r= ${ package }/${ b u i l d . d i r }/WEBINF/ c l a s s e s />
</ t a r g e t>
<t a r g e t name= c o m p i l e depends= i n i t d e s c r i p t i o n= Compiles s o u r c e >
<j a v a c c l a s s p a t h r e f= p r o j e c t . c l a s s p a t h
d e s t d i r= ${ package }/${ b u i l d . d i r }/WEBINF/ c l a s s e s
s r c d i r= ${ package }/WEBINF/ c l a s s e s />
</ t a r g e t>
<t a r g e t name= war depends= c o m p i l e >
<copy t o d i r= ${ package }/${ b u i l d . d i r }/WEBINF/
f i l e = ${ package }/WEBINF/ p o r t l e t . xml />
<copy t o d i r= ${ package }/${ b u i l d . d i r }/ j s p >
< f i l e s e t d i r= ${ package }/ j s p >
<i n c l u d e name= . j s p />
</ f i l e s e t>
</ copy>

39

<war b a s e d i r= ${ package }/${ b u i l d . d i r } update= f a l s e


w a r f i l e= ${ p o r t l e t . name } . war
webxml= ${ package }/WEBINF/web . xml />
</ t a r g e t>

41

<t a r g e t name= b u i l d depends= c l e a n , war />

43

<t a r g e t name= c l e a n d e s c r i p t i o n= C l e a n s b u i l d >


<d e l e t e d i r= ${ b u i l d . d i r } f a i l o n e r r o r= f a l s e />
</ t a r g e t>

36
37
38

44
45
47

</ p r o j e c t>

Desf
asurarea portlet-ului se face cu apache-ant utilizand fisierul build.xml
din uPortal HOME\uPortal-*.*.* prin
ant deployPortletApp -DportletApp=arhiva portlet-ului.war
In urma acestei operatii, portlet-ul se dezarhiveaza n uPortal HOME\apachetomcat-*.*.*\webapps iar fisierul web.xml este actualizat.

176

ARE 12. PORTLET


UNITATEA DE INVAT

Publicarea portlet-ului se face cu rolul de administrator. Dupa conectare la


uPortal
1. AdminTools Portlet Manager Publish a new channel
2. Se parcurg meniurile Channel Manager
(a) Din meniul Channel Type se selecteaza optiunea Portlet. Clic Next.
(b) In meniul General Settings se fixeaza toti parametrii indicati. Clic
Next.
(c) In meniul Portlet Descriptor se fixeaza
Contextul portlet-ului, adica catalogul din webapps care contine
portlet-ul. In mod obligatoriu primul caracter este / (slash) Pentru fixarea acestui parametru se va consulta fisierul web.xml.
Numele portlet-ului asa cum este definit n fisierul portlet.xml.
Clic Next.
(d) In meniul Portlet Preferences, clic Next.
(e) In meniul Display Settings, clic Next.
(f) In meniul Channel Controls, clic Next.
(g) In meniul Categories se fixeaza categoria canalului si cel putin un
membru.
Select Marked Next.

(h) In meniul Groups se fixeaza grupul si cel putin un membru.


Select Marked Next
Grupul desemneaza clientii care pot publica portlet-ul.

(i) In meniul Review, clic Finish.


Canalul portlet-ului apare n lista afisata.
3. Fiecare client care poate utiliza portlet-ul - adica cei din grupul selectat, l
public
a prin componenta Add Content.
Pentru administrator: AdminTools Customize urmat de
(a) Clic pe un buton Add Channel corespunzator locului unde vrem sa fie
pozitionat portlet-ul.

(b) In User Preferences,


i. se alege categoria portlet-ului, clic go;
ii. se alege numele portlet-ului, clic Add Channel.
(c) Clic pe numele canalului corespunzator portlet-ului.
afisat n meniul Welcome.

Canalul este

12.4. PRODUSE PORTAL

177

(d) Clic pe numele canalului din meniul Welcome lanseaza portlet-ul.


Un client elimin
a un portlet prin clic pe butonul Remove din fereastra
portlet-ului.
Administratorul portalului sterge un portlet prin clic pe butonul de nchidere
n lista portlet-elor publicate din AdminTools Portlet Manager Modify
a currently published channel.
Asem
an
ator, se pot publica n uPortal aplicatii Web. Deosebirea esentiala
este ca tipul canalului (Channel Type) este WebProxy sau Inline Frame.

12.4.2

Jetspeed-2

Jetspeed-2 este un portal cadru dezvoltat de apache.


Instalarea se execut
a rul
and distributia jetspeed-2.*.*-installer.jar.
Versiunea instalat
a a platformei jetspeed este construita peste o distributie
apache-tomcat-*. Astfel, lansarea se face apeland bin\startup.bat.
Portalul se acceseaz
a, dintr-un navigator, prin
http://localhost:8080/jetspeed
Desf
asurarea unui portlet consta n copierea arhivei war corespunzatoare,
realizat n 12.4.1, n catalogul
Jetspeed HOME \webapps\jetspeed\WEB-INF\deploy
Pe rol de admin (acces cu valorile initiale username=password=admin), publicarea portlet-ului presupune
1. Clic pe icon-ul butonului Edit - aflat sub butonul logout.
2. Clic pe butonul Add Portlet, aflat sub butonul Edit.
3. Clic pe butonul Add al portlet-ului care se doreste publicat.
4. Clic pe s
ageata de rentoarcere, urmat de clic pe iconul butonului View aflat pe pozitia butonului Edit.
Pentru a sterge un portlet, dupa primul pas anterior, se apasa butonul de
nchidere din zona portlet-ului.

178

ARE 12. PORTLET


UNITATEA DE INVAT

Test de evaluare a cunostintelor


1. Care sunt produsele portal exemplificate n curs si laborator ?
2. In ce const
a instalarea unui portlet ?
3. Ce este un portlet ?
4. Ce este un portal (relativ la portlet) ?

Bibliografie

[1] ATHANASIU I., COSTINESCU B., DRAGOI


O.A., POPOVICI F.I., 1998,
Limbajul Java. O perspectiv
a pragmatic
a. Ed. Computer Libris Agora, ClujNapoca.
[2] BOIAN F.M., BOIAN R. F., 2004, Tehnologii fundamentale Java pentru
aplicatii Web. Ed. Albastr
a, Cluj-Napoca.
[3] BURAGA S.C., 2001, Tehnologii Web. Ed. Matrix Rom,Bucuresti.
[4] BURAGA S. (ed), 2007, Programarea n Web 2.0., Ed. Polirom, Iasi.
I., 2000, Programarea retelelor de calculatoare. Ed. de Vest,
[5] JURCA
Timisoara.
[6] HUNTER J., CRAWFORD W., 1998, Java Servlet Programming. OReilly.
[7] ALBOAIE L., BURAGA S., 2006, Servicii Web. Ed. Polirom, Iasi.
[8] SCHEIBER E., 2007, Programare concurent
a si paralel distribuit
a n Java.
Ed. Albastr
a, Cluj-Napoca.
S
[9] TANASA
., OLARU C., 2005, Dezvoltarea aplicatiilor Web folosind Java.
Ed. Polirom, Bucuresti.
Toate produsele utilizate sunt nsotite de documentatie, care se consulta ori
de cate ori este nevoie.

179

S-ar putea să vă placă și