Documente Academic
Documente Profesional
Documente Cultură
Facultatea de Matematică–Informatică
Catedra de Informatică Teoretică
ERNEST SCHEIBER
Braşov
2
Introducere
3
4
5
6 CUPRINS
6 Servlet 123
6.1 Marcajul <form> . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
6.2 Server Web - container de servlet . . . . . . . . . . . . . . . . . . . . 125
6.3 Realizarea unui servlet . . . . . . . . . . . . . . . . . . . . . . . . . . 126
6.3.1 Instalarea unui servlet . . . . . . . . . . . . . . . . . . . . . . 126
6.3.2 Compilarea şi apelarea unui servlet . . . . . . . . . . . . . . . 128
6.3.3 Codul unui servlet . . . . . . . . . . . . . . . . . . . . . . . . 129
6.4 Facilităţi de programare cu servlet . . . . . . . . . . . . . . . . . . . 135
6.4.1 Program client al unui servlet . . . . . . . . . . . . . . . . . . 135
6.4.2 Servlete ı̂nlănţuite . . . . . . . . . . . . . . . . . . . . . . . . 138
6.4.3 Sesiune de lucru . . . . . . . . . . . . . . . . . . . . . . . . . 139
6.4.4 Cookie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
6.4.5 Autorizarea accesului prin parola . . . . . . . . . . . . . . . . 143
6.4.6 Servlet cu conexiune la o bază de date . . . . . . . . . . . . . 145
6.4.7 Imagini furnizate de servlet . . . . . . . . . . . . . . . . . . . 147
6.4.8 Servlet cu RMI . . . . . . . . . . . . . . . . . . . . . . . . . . 149
6.4.9 Servlet cu JMS . . . . . . . . . . . . . . . . . . . . . . . . . . 150
6.5 FileUpload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
CUPRINS 7
8 Portlet 187
8.1 Apache-pluto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
8.2 Portlet container JSR 286 . . . . . . . . . . . . . . . . . . . . . . . . 189
8.3 Dezvoltarea unui portlet . . . . . . . . . . . . . . . . . . . . . . . . . 190
8.4 Elemente de programare . . . . . . . . . . . . . . . . . . . . . . . . . 193
8.5 Produse Portal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
8.5.1 uPortal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
8.5.2 Jetspeed-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
A XML 249
B Apache-ant 253
8 CUPRINS
Bibliografie 273
Capitolul 1
import java.applet.*;
import java.awt.*;
9
10 CAPITOLUL 1. APPLET - MINIAPLICAŢIE JAVA
<BODY>
. . .
<script src="http://java.com/js/deployJava.js"></script>
<script>
var attributes={ code:’numele_arhivei_jar’,width:...,height:...};
var parameters={jnlp_href:’numele_fisierului_de_configurare_jnlp’};
deployJava.runApplet(attributes, parameters, ’1.6’);
</script>
. . .
</BODY>
4. Cele trei fişiere se depun ı̂ntr-un catalog al unui server Web, asigurând visibil-
itatea aplicaţiei in internet.
Verificarea aplicaţiei se poate face, dintr-un program navigator, prin simpla
apelare a fişierului html, aflat ı̂n catalogul de lucru. În acest caz, calculatorul
trebuie să fie conectat la internet.
7 public void p a i n t ( G r a p h i c s g ) {
8 g . d r a w S t r i n g ( ” H e l l o World ! ! ” , 5 0 , 60 ) ;
12 CAPITOLUL 1. APPLET - MINIAPLICAŢIE JAVA
9 }
10 }
Exemplul 1.2.1 Calculul celui mai mare divizor comun a două naturale.
Într-un applet, introducerea datelor din exterior se poate face doar prin inter-
mediul unei interfeţe grafice. Codul sursă este:
1 import j a v a . awt . ∗ ;
2 import j a v a . a p p l e t . ∗ ;
3 import j a v a . awt . e v e n t . ∗ ;
8 public void i n i t ( ) {
9 setBackground ( Color . yellow ) ;
10 GridLayout g l=new GridLayout ( 3 , 2 , 3 0 , 2 0 ) ;
11 setLayout ( g l ) ;
12 L a b e l lm=new L a b e l ( ” Primul numar : ” ) ;
13 add ( lm ) ;
14 tm=new T e x t F i e l d ( ” 1 ” , 5 ) ;
15 add ( tm ) ;
16 L a b e l l n=new L a b e l ( ” Al d o i l e a numar : ” ) ;
17 add ( l n ) ;
18 tn=new T e x t F i e l d ( ” 1 ” , 5 ) ;
19 add ( tn ) ;
20 Button compute=new Button ( ” C a l c u l e a z a ” ) ;
21 compute . a d d A c t i o n L i s t e n e r ( t h i s ) ;
22 add ( compute ) ;
23 r e z=new T e x t F i e l d ( ” 1 ” , 5 ) ;
24 rez . setEditable ( false ) ;
25 add ( r e z ) ;
26 }
28 public void p a i n t ( G r a p h i c s g ) {
29 S t r i n g sm=tm . g e t T e x t ( ) ;
30 long m=Long . parseLong ( sm ) ;
31 S t r i n g sn=tn . g e t T e x t ( ) ;
32 long n=Long . parseLong ( sn ) ;
33 long c=cmmdc(m, n ) ;
34 r e z . s e t T e x t ( (new Long ( c ) ) . t o S t r i n g ( ) ) ;
35 }
• code
Valoarea atributului este numele clasei applet-ului.
• width
Valoarea atributului este lăţimea ferestrei atribuită de navigator applet-ului la
afişarea documentului html.
• height
Valoarea atributului este ı̂nălţimea ferestrei atribuită de navigator applet-ului
la afişarea documentului html.
• codebase
Valoarea atributului este adresa URL ( Universal Resource Locator) sau calea
la fişierul cu clasa applet-ului. În lipsa acestui parametru, căutarea clasei are
loc ı̂n catalogul din care a fost ı̂ncărcată sursa html.
• vspace
Valoarea atributului este lungimea, exprimată ı̂n pixeli, care se lasă liberă
deasupra şi dedesuptul ferestrei miniaplicaţiei.
• hspace
Valoarea parametrului este lungimea, exprimată ı̂n pixeli, care se lasă liberă
la stânga şi la dreapta ferestrei applet-ului.
În marcajul <applet> prin intermediul elementului <param> pot fi incluşi parametri
ce pot fi preluaţi de applet. Un parametru se defineşte prin atributele:
• name
Valoarea atributului este numele variabilei recunoscut ı̂n applet.
• value
Valoarea atributului este valoarea recepţionat de applet şi este de tip String.
Preluarea se realizează cu metoda
Dacă fişierul class al applet-ului nu se află ı̂n acelaşi catalog cu documentul html
atunci localizarea clasei se face cu valoarea atributului codebase =
"file://host/calea către catalogul clasei applet-ului"
Pentru testare, ı̂n locul navigatorului se poate folosi programul appletviewer.exe
din distribuţia jdk.
Elementul applet activează maşina virtuală Java utilizată de programul navi-
gator. Această maşină virtuală s-ar putea să nu fie compatibilă cu maşina virtuală
1.2. DESFĂŞURAREA UNUI APPLET 15
Java de la Sun. Dacă pe calculatorul clientului este instalată distribuţia jdk atunci
documentul html se poate converti astfel ı̂ncât execuţia applet-ului să fie execu-
tată de maşina virtuală Java a distribuţiei jdk. Convertirea se face cu utilitarul
HtmlConverter, din distribuţia jdk.
16 CAPITOLUL 1. APPLET - MINIAPLICAŢIE JAVA
Capitolul 2
Limbajul de programare Java oferă facilităţi de elaborare ale unor programe care
utilizează şi interacţionează cu resurse din Internet şi din World Wide Web.
În plus limbajul Java permite utilizarea URL-ului (Universal Resource Locator
– adresa resurselor ı̂n Internet), a soclurilor (socket) şi a datagramelor.
• componenta server - alcătuită din programe / clase ce asigură una sau mai
multe funcţiuni (servicii), care pot fi apelate de către clienţi.
• componenta client - alcătuită din programe / clase care permit accesul la server
şi apelarea serviciilor acestuia.
17
18 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA
TCP Când două aplicaţii comunică ı̂ntre ele se stabileşte o conexiune prin in-
termediul căreia se schimbă date. Folosind protocolul TCP, comunicaţia garantează
că datele trimise dintr-un capăt ajung ı̂n celălalt capăt cu păstrarea ordinii ı̂n care
au fost trimise. Acest tip de comunicaţie seamănă cu o convorbire telefonică. TCP
furnizează un canal sigur de comunicaţie ı̂ntre aplicaţii.
Metode
Exemplul 2.4.1 Sistem client - server pentru calculul celui mai mare divizor comun
a două numere naturale. Portul obiectului de tip ServerSocket este 7999.
1. Deschide/crează un soclu.
5. Închiderea soclului.
1 import j a v a . i o . ∗ ;
2 import j a v a . n e t . ∗ ;
3 import j a v a . u t i l . Sca nner ;
5 public c l a s s CmmdcClient {
6 public s t a t i c void main ( S t r i n g [ ] a r g s ) throws IOException {
7 S t r i n g h o s t=” l o c a l h o s t ” ;
8 i n t p o r t =7999;
9 i f ( a r g s . l e n g t h >0)
10 h o s t=a r g s [ 0 ] ;
11 i f ( a r g s . l e n g t h >1)
12 p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
13 S o c k e t cmmdcSocket = n u l l ;
14 DataInputStream i n=n u l l ;
15 DataOutputStream out=n u l l ;
17 try {
18 cmmdcSocket = new S o c k e t ( hos t , p o r t ) ;
19 out=new DataOutputStream ( cmmdcSocket . getOutputStream ( ) ) ;
20 i n=new DataInputStream ( cmmdcSocket . g e t I n p u t S t r e a m ( ) ) ;
21 }
22 catch ( E x c e p t i o n e ) {
23 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 ( ) ) ;
24 System . e x i t ( 1 ) ;
25 }
34 try {
35 out . w r i t e L o n g (m) ;
36 out . w r i t e L o n g ( n ) ;
37 r=i n . readLong ( ) ;
38 System . out . p r i n t l n ( ”Cmmdc : ”+r ) ;
39 }
40 catch ( IOException e ) {
41 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 ( ) ) ;
42 }
44 out . c l o s e ( ) ;
45 in . close ( ) ;
46 cmmdcSocket . c l o s e ( ) ;
47 }
48 }
Se presupune că programul server rulează pe calculatorul local şi utilizează portul
7999. Dacă aceşti parametri se modifică - de exemplu serverul rulează ı̂n reţea pe
calculatorul atlantis la portul 8200 - atunci la apelare transmitem aceşti parametri
prin java CmmdcClient atlantis 8200
Partea server este alcătuită din mai multe clase:
22 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA
4 public c l a s s MyMServer {
5 public s t a t i c void main ( S t r i n g [ ] a r g s ) throws IOException {
6 i n t p o r t =7999;
7 boolean l i s t e n i n g=true ;
8 ServerSocket s e r v e r S o c k e t = null ;
9 try {
10 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 ) ;
11 }
12 catch ( IOException e ) {
13 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 ) ;
14 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
15 System . e x i t ( 1 ) ;
16 }
18 while ( l i s t e n i n g )
19 // v a r i a n t a 1
20 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 ( ) ;
21 // v a r i a n t a 2
22 /∗
23 {
24 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 ( ) ;
25 try {
26 DataOutputStream o u t=
27 new DataOutputStream ( s o c k e t . g e t O u t p u t S t r e a m ( ) ) ;
28 DataInputStream i n=
29 new DataInputStream ( s o c k e t . g e t I n p u t S t r e a m ( ) ) ;
30 l o n g m=0,n=0, r ;
31 App app=new App ( ) ;
32 m=i n . readLong ( ) ;
33 n=i n . readLong ( ) ;
34 r=app . cmmdc(m, n ) ;
35 out . writeLong ( r ) ;
36 out . c l o s e ( ) ;
37 in . c l o s e ( ) ;
38 socket . close ();
39 }
40 c a t c h ( IOException e ) {
41 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 : ”+
42 e . getMessage ( ) ) ;
43 }
44 }
45 ∗/
46 serverSocket . close ( ) ;
47 }
48 }
În ciclul while, la recepţia unei solicitări de conexiune se crează şi se lansează
un fir de execuţie a cărei metodă run conţine acţiunile ce răspund solicitării.
O soluţie mai eficientă este utilizarea unui bazin de fire de execuţie:
7 public AppThread ( S o c k e t s o c k e t ) {
8 t h i s . s o c k e t=s o c k e t ;
9 }
• Clasa App corespunzătoare calcului celui mai mare divizor comul a două nu-
mere naturale.
1 public c l a s s App{
2 public long cmmdc( long m, long n ) { . . . }
3 }
2.5 Datagrame
Pentru utilizarea datagramelor pachetul java.net pune la dispoziţie clasele
• DatagramSocket
• DatagramPacket
• MulticastSocket
O aplicaţie trimite şi recepţionează pachete DatagramPacket prin intermediul
unui DatagramSocket. Un pachet DatagramPacket poate fi trimis la mai mulţi
destinatari prin intermediul unui MulticastSocket.
Reamintim că o datagramă este un mesaj trimis prin reţea a cărei sosire nu este
garantat iar momentul de sosire este neprecizat.
• int getPort()
returnează portul.
• byte[] getData()
returnează conţinutul pachetului.
• int getLength()
returnează lungimea pachetului.
Metode
Clasa DatagramSocket conţine metode pentru trimiterea şi primirea de obiecte
DatagramPacket, ı̂nchiderea soclului, determinarea informaţiilor adresei locale şi
setarea timpului de primire.
• void disconnect()
Deconectează soclul conectat.
• InetAddress getInetAddress()
Returnează obiectul InetAddress către care este conectat soclul sau null dacă
acesta nu este conectat.
• int getPort()
Returnează portul la care este conectat soclul sau -1 dacă acesta nu este conec-
tat.
• byte [ ] getAddress()
Returnează şirul de octeţi corespunzător obiectului InetAddress de referinţă.
28 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA
• String getHostName()
Returnează numele maşinii gazdă.
• String getHostAddress()
Returnează adresa IP a maşinii gazdă.
• boolean isMulticastAddress()
Returnează true dacă obiectul InetAddress reprezintă o adresă IP multicast
(primul octet cuprins ı̂ntre 224 şi 239).
Exemplul următor afişează numele şi adresa calculatorului gazdă cât şi acela al
calculatoarelor ale căror nume este transmis programului ca parametru.
Exemplul 2.5.1
1 import j a v a . n e t . ∗ ;
3 public c l a s s AdreseIP {
4 public s t a t i c void main ( S t r i n g a r g [ ] ) {
5 I n e t A d d r e s s a d r e s a=n u l l ;
6 try {
7 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 ( ) ;
8 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 : ” ) ;
9 System . out . p r i n t l n ( ” numele : ”+a d r e s a . getHostName ( ) ) ;
10 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 ( ) ) ;
11 }
12 catch ( UnknownHostException e ) {
13 System . out . p r i n t l n ( ” UnknownHostException : ”+e . g e t M e s s a g e ( ) ) ;
14 }
15 i f ( a r g . l e n g t h >0){
16 f o r ( i n t i =0; i <a r g . l e n g t h ; i ++){
17 try {
18 a d r e s a=I n e t A d d r e s s . getByName ( a r g [ i ] ) ;
19 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 : ” ) ;
20 System . out . p r i n t l n ( ” a d r e s a IP \” getByName \” : ”+a d r e s a ) ;
21 byte [ ] b=a d r e s a . g e t A d d r e s s ( ) ;
22 f o r ( i n t j =0; j <b . l e n g t h ; j ++)
23 i f ( b [ j ] <0)
24 System . out . p r i n t (256+b [ j ]+ ” . ” ) ;
25 else
26 System . out . p r i n t ( b [ j ]+ ” . ” ) ;
27 System . out . p r i n t l n ( ) ;
28 }
29 catch ( UnknownHostException e ) {
30 System . out . p r i n t l n ( ” UnknownHostException : ”+
31 e . getMessage ( ) ) ;
32 }
33 }
34 }
35 }
36 }
2.5. DATAGRAME 29
unde address şi port sunt adresa şi portul utilizat de expeditorul mesajului. Dacă
packet este un obiect DatagramPacket recepţionat atunci metodele getAddress()
şi getPort() furnizează adresa şi portul expeditorului
Recepţionarea şi transformarea inversă este
Dacă mesajul este un obiect String atunci el se transformă ı̂ntr-un şir de octeţi
cu metoda byte[] String.getByte() şi invers, el se obţine prin new String(bin)
sau new String(packet.getData()).
Exemplul 2.5.2 Programăm serviciul calculului celui mai mare divizor comun a
două numere.
1 import j a v a . i o . ∗ ;
3 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 {
4 long x , y ;
5 P r o t o c o l ( long x , long y ) {
6 t h i s . x=x ;
7 t h i s . y=y ;
8 }
9 }
1 import j a v a . n e t . ∗ ;
2 import j a v a . i o . ∗ ;
3 import j a v a . u t i l . Sca nne r ;
5 public c l a s s ClientCmmdc {
6 public s t a t i c void main ( S t r i n g [ ] args ){
8 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 ” ;
9 i n t p o r t S e r v e r =7999;
10 i f ( a r g s . l e n g t h >0)
11 h o s t S e r v e r=a r g s [ 0 ] ;
12 i f ( a r g s . l e n g t h >1)
13 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 ] ) ;
14 try {
15 // Crearea unui s o c l u Datagramsocket
16 DatagramSocket s o c k e t=new DatagramSocket ( ) ;
18 // Formarea m e s a j u l u i
19 P r o t o c o l p=new P r o t o c o l ( 0 , 0 ) ;
20 Sca nner s c a n n e r=new S c a n n e r ( System . i n ) ;
21 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 : ” ) ;
22 p . x=s c a n n e r . nextLong ( ) ;
23 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 : ” ) ;
24 p . y=s c a n n e r . nextLong ( ) ;
26 // Transformarea m e s a j u l u i i n t r −un s i r de o c t e t i
33 // E x p e d i e r e a m e s a j u l u i
35 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 ) ;
36 DatagramPacket p a c k e t=new
37 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 ) ;
38 s o c k e t . send ( p a c k e t ) ;
40 // A s t e p t a r e a r a s p u n s u l u i
46 // P r e l u c r a r e a r a s p u n s u l u i
53 socket . close ( ) ;
54 }
55 catch ( E x c e p t i o n e ) {
56 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
57 }
58 }
59 }
1 import j a v a . n e t . ∗ ;
2 import j a v a . i o . ∗ ;
4 public c l a s s ServerCmmdc{
5 public s t a t i c void main ( S t r i n g [ ] args ){
7 DatagramSocket s o c k e t=n u l l ;
8 i n t s e r v e r P o r t =7999;
9 try {
10 // Crearea unui s o c l u DatagramSocket
12 s o c k e t=new DatagramSocket ( s e r v e r P o r t ) ;
14 }
15 catch ( E x c e p t i o n e ) {
16 System . out . p r i n t l n ( ” DatagramSocket−e r r o r −”+e . g e t M e s s a g e ( ) ) ;
17 System . e x i t ( 0 ) ;
18 }
20 // A c t i v i t a t e a s e r v e r u l u i
22 boolean l i s t e n i n g=true ;
23 DatagramPacket p a c k e t=n u l l ;
24 App app=new App ( ) ;
25 P r o t o c o l p=n u l l ;
27 while ( l i s t e n i n g ) {
32 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA
28 try {
30 // R e c e p t i o n a r e a unui mesaj
36 // P r e l u c r a r e a d a t e l o r
42 // R e z o l v a r e a c e r e r i i clientului
44 p . x=app . cmmdc( p . x , p . y ) ;
45 p . y =0;
47 // Transformarea m e s a j u l u i de r a s p u n s i n t r −un s i r de o c t e t i
54 // E x p e d i e r e a m e s a j u l u i n e c e s i t a c u n o a s t e r e a e x p e d i t o r u l u i
56 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 ( ) ;
57 i n t p o r t=p a c k e t . g e t P o r t ( ) ;
58 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 ) ;
59 s o c k e t . send ( p a c k e t ) ;
60 }
61 catch ( E x c e p t i o n e ) {
62 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
63 }
64 }
65 socket . close ( ) ;
66 }
67 }
Constructori
Metode
• void close()
socket.leaveGroup(adresa);
socket.close();
DatagramSocket.setBroadcast(true)
Orice client care ı̂şi crează un soclu la portul la care emite serverul recepţionează
datagramele trimise de server. Adresa utilizată de server la crearea datagramelor
trebuie să identifice reţeaua.
Observaţie. În cazul unui calculator ”izolat” este nevoie de instalarea driverului
Microsoft Loopback Adapter, care simulează existenţa unei plăci de reţea active.
Exemplul 2.5.3 Multicast şi Broadcast: programele server emit din cinci ı̂n
cinci secunde ora exactă. Un client va recepţiona câte cinci datagrame.
Codurile sunt date ı̂n Fig. 2.1 şi Fig. 2.2, respectiv pentru partea de server şi
cea de client.
34 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA
MulticastServer BroadcastServer
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
import java.util.*; import java.util.*;
import java.text.DateFormat; import java.text.DateFormat;
MulticastClient BroadcastClient
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
public static void main(String[] args) public static void main(String[] args)
throws IOException { throws IOException {
DatagramPacket packet; DatagramPacket packet;
byte[] buf = new byte[256]; byte[] buf = new byte[256];
int clientPort=7001; int clientPort=7001;
MulticastSocket socket= DatagramSocket socket=
new MulticastSocket(clientPort); new DatagramSocket(clientPort);
InetAddress address=
InetAddress.getByName("230.0.0.1");
socket.joinGroup(address);
int i=-1; int i=-1;
do{ do{
i++; i++;
packet=new DatagramPacket(buf, buf.length); packet=new DatagramPacket(buf, buf.length);
socket.receive(packet); socket.receive(packet);
String received=new String(packet.getData()); String received=new String(packet.getData());
System.out.println("Am primit: "+received); System.out.println("Am primit: "+received);
} }
while(i<5); while(i<5);
socket.leaveGroup(address);
socket.close(); socket.close();
} }
} }
abstract Buffer
ByteBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
CharBuffer
Metode generale
• clear() permite unui obiect de tip Buffer să fie reı̂ncărcat. Fixează limita =
capacitate şi indice = 0.
Metode
Introducerea datelor ı̂n mod relativ:
• ByteBuffer put(byte b)
• ByteBuffer putTip(tip x )
• byte get()
• tip getTip()
ByteBuffer bb=ByteBuffer.allocate(10);
LongBuffer lb=bb.asLongBuffer();
DoubleBuffer db=bb.asDoubleBuffer();
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 să genereze un obiect de tip Socket
Channel prin care se vor derula comunicaţiile cu clientul. Acest canal de comunicaţie
se obţine cu metoda accept().
2.6. CANALE DE COMUNICAŢIE 39
Exemplul 2.6.1 Calculul celui mai mare divizor comun a două numere naturale.
7 public c l a s s SocketChannelCmmdcServer {
9 private s t a t i c void s e r v i c i u ( S e r v e r S o c k e t C h a n n e l s s c ) {
10 S o ck e t Ch a n ne l s c = n u l l ;
11 try {
12 s c=s s c . a c c e p t ( ) ;
13 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 ) ;
14 // 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 ( ) ;
15 s c . r e a d ( bb ) ;
16 // V a r i a n t a 1
17 long m=bb . getLong ( 0 ) ;
18 long n=bb . getLong ( 8 ) ;
19 // V a r i a n t a 2
20 // l o n g m=l b . g e t ( 0 ) ;
21 // l o n g n=l b . g e t ( 1 ) ;
22 App app=new App ( ) ;
23 long r=app . cmmdc(m, n ) ;
24 bb . c l e a r ( ) ;
40 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA
25 // V a r i a n t a 1
26 bb . putLong ( 0 , r ) ;
27 // V a r i a n t a 2
28 // l b . p u t ( r ) ;
29 s c . w r i t e ( bb ) ;
30 sc . clos e ( ) ;
31 }
32 catch ( E x c e p t i o n e ) {
33 System . out . p r i n t l n ( ” S e r v e r e r r o r : ”+e . g e t M e s s a g e ( ) ) ;
34 }
35 }
şi clientul
1 import java . io . ∗ ;
2 import java . net . ∗ ;
3 import java . nio . ∗ ;
4 import java . nio . channels . ∗ ;
5 import j a v a . u t i l . Sca nne r ;
7 public c l a s s SocketChannelCmmdcClient {
8 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
9 S t r i n g h o s t=” l o c a l h o s t ” ;
10 i n t p o r t =7999;
11 i f ( a r g s . l e n g t h >0)
12 h o s t=a r g s [ 0 ] ;
13 i f ( a r g s . l e n g t h >1)
14 p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
15 S oc k e t Ch a n ne l s c=n u l l ;
16 try {
17 I n e t S o c k e t A d d r e s s i s a=new I n e t S o c k e t A d d r e s s ( hos t , p o r t ) ;
18 s c=S oc k e tC h a nn e l . open ( ) ;
19 sc . connect ( i s a ) ;
20 }
21 catch ( UnknownHostException e ) {
22 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 ( ) ) ;
23 System . e x i t ( 1 ) ;
24 }
25 catch ( IOException e ) {
26 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 : ”+
2.6. CANALE DE COMUNICAŢIE 41
37 B y t e B u f f e r bb=B y t e B u f f e r . a l l o c a t e ( 1 6 ) ;
38 // V a r i a n t a 1
39 bb . putLong ( 0 ,m) . putLong ( 8 , n ) ;
40 // V a r i a n t a 2
41 // 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 ( ) ;
42 // l b . p u t ( 0 ,m) . p u t ( 1 , n ) ;
43 try {
44 s c . w r i t e ( bb ) ;
45 bb . c l e a r ( ) ;
46 s c . r e a d ( bb ) ;
47 // V a r i a n t a 1
48 r=bb . getLong ( 0 ) ;
49 // V a r i a n t a 2
50 // r=l b . g e t ( 0 ) ;
51 System . out . p r i n t l n ( ”Cmmdc : ”+r ) ;
52 sc . c los e ( ) ;
53 }
54 catch ( E x c e p t i o n e ) {
55 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 ( ) ) ;
56 }
57 }
58 }
Varianta comentată corespunde cazului ı̂n care se utilizeară clasa acoperitoare LongBuffer.
DatagramChannel dc=null;
InetSocketAddress isa=new InetSocketAddress(port);
try{
dc=DatagramChannel.open();
DatagramSocket datagramSocket=dc.socket();
datagramSocket.bind(isa);
}
catch(Exception e){. . .}
unde port este portul folosit de DatagramChannel. Dacă port=0 atunci se alege
aleator un port disponibil.
Transmiterea unui obiect ByteBuffer se face cu metoda
42 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA
Exemplul 2.6.2 Calculul celui mai mare divizor comun a două numere naturale.
1 import java . io . ∗ ;
2 import java . net . ∗ ;
3 import java . nio . ∗ ;
4 import java . nio . channels . ∗ ;
5 import java . u t i l . ∗ ;
7 public c l a s s DatagramChannelCmmdcServer {
8 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
9 i n t p o r t =7999;
10 DatagramChannel dc=n u l l ;
11 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 ) ;
12 try {
13 dc=DatagramChannel . open ( ) ;
14 }
15 catch ( IOException e ) {
16 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
17 }
18 DatagramSocket datagramSocket=dc . s o c k e t ( ) ;
19 try {
20 datagramSocket . bind ( i s a ) ;
21 }
22 catch ( S o c k e t E x c e p t i o n e ) {
23 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
24 }
25 System . out . p r i n t l n ( ” S e r v e r r e a d y . . . ” ) ;
26 boolean l i s t e n i n g=true ;
28 while ( l i s t e n i n g ) {
29 try {
30 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 ) ;
31 // 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 ( ) ;
32 S o c k e t A d d r e s s c l i e n t=dc . r e c e i v e ( bb ) ;
33 // V a r i a n t a 1
34 long m=bb . getLong ( 0 ) ;
35 long n=bb . getLong ( 8 ) ;
36 // V a r i a n t a 2
37 // l o n g m=l b . g e t ( 0 ) ;
38 // l o n g n=l b . g e t ( 1 ) ;
39 App app=new App ( ) ;
40 long r=app . cmmdc(m, n ) ;
41 bb . c l e a r ( ) ;
42 // V a r i a n t a 1
43 bb . putLong ( 0 , r ) ;
44 // V a r i a n t a 2
2.6. CANALE DE COMUNICAŢIE 43
45 // l b . p u t ( 0 , r ) ;
46 dc . send ( bb , c l i e n t ) ;
47 }
48 catch ( E x c e p t i o n e ) {
49 System . out . p r i n t l n ( ” E r o a r e s e r v e r : ”+e . g e t M e s s a g e ( ) ) ;
50 System . e x i t ( 1 ) ;
51 }
52 }
53 }
54 }
1 import java . io . ∗ ;
2 import java . net . ∗ ;
3 import java . nio . ∗ ;
4 import java . nio . channels . ∗ ;
5 import j a v a . u t i l . Sca nner ;
7 public c l a s s DatagramChannelCmmdcClient {
8 public s t a t i c void main ( S t r i n g [ ] a r g s ) throws IOException {
9 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 ” ;
10 i n t p o r t =7999;
11 i f ( a r g s . l e n g t h >0)
12 s e r v e r H o s t=a r g s [ 0 ] ;
13 i f ( a r g s . l e n g t h >1)
14 p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
15 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 ;
16 try {
17 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 ) ;
18 }
19 catch ( UnknownHostException e ) {
20 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 ( ) ) ;
21 System . e x i t ( 1 ) ;
22 }
23 i s a=new I n e t S o c k e t A d d r e s s ( 0 ) ;
24 DatagramChannel dc=n u l l ;
25 try {
26 dc=DatagramChannel . open ( ) ;
27 DatagramSocket s o c k e t = dc . s o c k e t ( ) ;
28 s o c k e t . bind ( i s a ) ;
29 }
30 catch ( IOException e ) {
31 System . e r r . p r i n t l n ( ” Couldn ’ t open t h e DatagramChannel ”+ e . g e t M e s s a g e ( ) ) ;
32 System . e x i t ( 1 ) ;
33 }
34 long m, n , r ;
35 Sc anner s c a n n e r=new Sc anner ( System . i n ) ;
36 System . out . p r i n t l n ( ”m=” ) ;
37 m=s c a n n e r . nextLong ( ) ;
38 System . out . p r i n t l n ( ”n=” ) ;
39 n=s c a n n e r . nextLong ( ) ;
40 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 ) ;
41 // V a r i a n t a 1
42 bb . putLong ( 0 ,m) . putLong ( 8 , n ) ;
43 // V a r i a n t a 2
44 // 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 ( ) ;
45 // l b . p u t ( 0 ,m) . p u t ( 1 , n ) ;
46 try {
47 dc . send ( bb , s e r v e r ) ;
48 bb . c l e a r ( ) ;
44 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA
49 dc . r e c e i v e ( bb ) ;
50 // V a r i a n t a 1
51 r=bb . getLong ( 0 ) ;
52 // V a r i a n t a 2
53 // r=l b . g e t ( 0 ) ;
54 System . out . p r i n t l n ( ”Cmmdc = ”+r ) ;
55 }
56 catch ( E x c e p t i o n e ) {
57 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 ( ) ) ;
58 }
59 finally {
60 i f ( dc != n u l l ) dc . d i s c o n n e c t ( ) ;
61 }
62 }
63 }
Metode
Exemplul 2.7.1 Pe baza referinţei către un fişier html dintr-un catalog vizibil al
unui server Web, să se afişeze conţinutul fişierului.
În codul reprodus mai jos, fişierul Hello.html se află pe un server apache-tomcat,
ı̂n catalogul webapps\myservlet.
1 import j a v a . n e t . ∗ ;
2 import j a v a . i o . ∗ ;
4 public c l a s s ReadHTTP{
5 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
6 try {
7 S t r i n g adr=” 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 / H e l l o . html ” ;
8 URL u r l=new URL( adr ) ;
9 InputStream i n=u r l . openStream ( ) ;
1
apache-tomcat, apache, Micrsoft IIS (Internet Information Services), etc.
2.7. CONEXIUNI HTTP 45
Oricărui obiect ı̂i sunt asociate un nume şi o referinţă. Regăsirea / căutarea
obiectului se face pornind de la numele obiectului, prin referinţă se ajunge la obiect.
Exemple date prin şablonul (Nume ⇒ Referinţă ⇒ Obiect)
Un serviciu de nume conţine asocieri dintre nume de obiecte şi obiecte şi poate
oferi facilităţi de regăsire a obiectelor.
• Filesystem are ca obiect asocierea dintre numele de fişier sau catalog cu obiec-
tul corespunzător.
47
48 CAPITOLUL 3. REGĂSIREA OBIECTELOR PRIN SERVICII DE NUME
• DNS - Domain Name System are ca obiect asocierea dintre adresa Internet cu
adresa IP.
• RMI registry utilizat ı̂n aplicaţii RMI, din Java. Are ca obiect asocierea ı̂ntre
un nume de serviciu de invocare ale obiectelor la distanţă cu un delegat al
serviciului (stub).
• COS - Common Object Service Naming utilizat ı̂n aplicaţii CORBA. Are ca
obiect asocierea ı̂ntre numele unui serviciu de invocare ale obiectelor la distanţă
cu referinţa la serviciu.
Interfaţa Context
Printr-un context se va ı̂nţelege o mulţime de asocieri nume - obiect. Core-
spunzător unui context, JNDI defineşte interfaţa Context, cu metodele
Specificaţiile JNDI prevăd definirea unui context iniţial, implementat prin clasa
InitialContext, clasă ce implementează interfaţa Context.
Constructori.
Pentru crearea contextului iniţial trebuie specificaţa clasa care crează contextul
iniţial prin parametrul java.naming.factory.initial sau constanta
Contect.INITIAL CONTEXT FACTORY.
Acest parametru se poate da ı̂n mai multe moduri:
3.1. JAVA NAMING AND DIRECTORY INTERFACE 49
• Includerea ı̂n obiectul Hashtable care apare ı̂n constructorul clasei InitalContext.
sau
System.setProperty("java.naming.factory.initial",...);
sau
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,...);
Funcţie de serviciul de nume, clasa care crează contextul iniţial este dat ı̂n tabelul
Exemplul 3.1.1 Utilizând serviciul JNDI Filesystem se crează un context prin in-
termediul căreia se afişează conţinutul unui catalog indicat de client.
50 CAPITOLUL 3. REGĂSIREA OBIECTELOR PRIN SERVICII DE NUME
1 import j a v a x . naming . ∗ ;
2 import java . io . F i l e ;
3 import java . u t i l . Hashtable ;
4 import j a v a . u t i l . Sca nne r ;
6 c l a s s Lookup {
7 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
8 Context c t x=n u l l ;
9 /∗
10 // V a r i a n t a 1
11 H a s h t a b l e env = new H a s h t a b l e ( 1 1 ) ;
12 env . p u t ( C o n t e x t . INITIAL CONTEXT FACTORY,
13 ”com . sun . j n d i . f s c o n t e x t . RefFSContextFactory ” ) ;
14 try {
15 c t x = new I n i t i a l C o n t e x t ( env ) ;
16 }
17 c a t c h ( NamingException e ) {
18 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 ( ) ) ;
19 }
20 ∗/
21 /∗
22 // V a r i a n t a 2
23 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 ” ,
24 ”com . sun . j n d i . f s c o n t e x t . RefFSContextFactory ” ) ;
25 try {
26 c t x = new I n i t i a l C o n t e x t ( ) ;
27 }
28 c a t c h ( NamingException e ) {
29 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 ( ) ) ;
30 }
31 ∗/
33 // V a r i a n t a 3
34 try {
35 c t x = new I n i t i a l C o n t e x t ( ) ;
36 }
37 catch ( NamingException e ) {
38 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 ( ) ) ;
39 }
60 System . out . p r i n t l n ( bd ) ;
61 // System . o u t . p r i n t l n ( bd . getName ( ) + ” : ” + bd . g e t O b j e c t ( ) ) ;
62 }
63 ctx . c l o s e ( ) ;
64 }
65 catch ( NamingException e ) {
66 System . out . p r i n t l n ( ” Lookup f a i l e d : ” + e . g e t M e s s a g e ( ) ) ;
67 }
68 }
69 }
Invocarea procedurilor la
distanţă
• Invocarea procedurilor la distanţă ı̂n cazul medii neomogene. Soluţia ı̂n acest
caz este dat de Common Object Request Brocker Arhitecture (CORBA).
unde valoarea implicită a portului este 1099. Comanda start aparţine sistemului
de operare. rmiregistry este un serviciu de nume JNDI.
Un client obţine din registry stub-ul serverului, prin intermediul căruia realizează
comunicaţia cu programul server.
53
54 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANŢĂ
2. Aplicaţia server care poate implementa serviciile interfeţei la distanţă şi ı̂nscrie
ı̂n registry stub-ul corespunzător;
3. Aplicaţia client ce apelează unul sau mai multe servicii ale serverului.
Nici o clipă nu trebuie scăpat din vedere faptul că cele trei componente evoluează
pe calculatoare diferite.
Registrul rmiregistry implementează interfaţa Registry. Metodele oferite sunt:
• calculatorul pe care se găseşte obiectul registry şi portul la care ascultă servi-
ciul;
1 package cmmdc ;
2 public i n t e r f a c e ICmmdc extends j a v a . rmi . Remote{
3 long cmmdc( long a , long b ) throws j a v a . rmi . RemoteException ;
4 }
1
Sistemul de operare utilizat este Windows
4.1. REMOTE METHOD INVOCATION 57
1 package s e r v e r ;
3 import cmmdc . ∗ ;
4 import j a v a . rmi . ∗ ;
5 import j a v a . rmi . s e r v e r . ∗ ;
6 // V a r i a n t a d i r e c t a
7 import j a v a . rmi . r e g i s t r y . ∗ ;
8 // V a r i a n t a JNDI
9 /∗
10 i m p o r t j a v a x . naming . ∗ ;
11 ∗/
28 // V a r i a n t a d i r e c t a
29 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 ) ;
30 r e g i s t r y . bind ( ”CmmdcServer” , s t u b ) ;
32 // V a r i a n t a JNDI
33 /∗
34 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 ( ) ;
35 System . s e t P r o p e r t y ( C o n t e x t . INITIAL CONTEXT FACTORY,
36 ”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 ” ) ;
37 System . s e t P r o p e r t y ( C o n t e x t .PROVIDER URL, ” rmi ://”+ h o s t +”:”+ s P o r t ) ;
38 C o n t e x t c t x=new I n i t i a l C o n t e x t ( ) ;
39 c t x . b i n d (” CmmdcServer ” , s t u b ) ;
40 ∗/
41 System . out . p r i n t l n ( ”CmmdcServer r e a d y ” ) ;
42 }
43 catch ( E x c e p t i o n e ) {
44 System . out . p r i n t l n ( ”CmmdcImpl e r r : ” + e . g e t M e s s a g e ( ) ) ;
45 }
46 }
47 }
5. Crearea obiectului registry şi lansarea serverului ı̂n lucru se obţine cu fişierul
de comenzi bat
cd \s\public\classes
start rmiregistry
cd \s\public\classes
start java -cp /s/public/classes -Djava.rmi.server.codebase=
file:/s/public/classes/ server.CmmdcImpl
1 package c l i e n t ;
3 import cmmdc . ∗ ;
4 import j a v a . u t i l . Sca nner ;
5 // V a r i a n t a d i r e c t a
6 import j a v a . rmi . r e g i s t r y . ∗ ;
7 // V a r i a n t a JNDI
8 /∗
9 i m p o r t j a v a x . naming . ∗ ;
10 ∗/
12 public c l a s s CmmdcClient {
13 public s t a t i c void main ( S t r i n g a r g s [ ] ) {
14 S t r i n g h o s t=” l o c a l h o s t ” ;
15 i n t p o r t =1099;
16 i f ( a r g s . l e n g t h >0)
17 h o s t=a r g s [ 0 ] ;
18 i f ( a r g s . l e n g t h >1)
19 p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
20 Sca nner s c a n n e r=new Sca n n e r ( System . i n ) ;
21 System . out . p r i n t l n ( ” Primul numar : ” ) ;
22 long m=Long . parseLong ( s c a n n e r . n e x t ( ) ) ;
60 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANŢĂ
29 description=” c o m p i l e t h e s o u r c e ”>
30 <javac s r c d i r=” s r c ”
31 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 ”
32 classpath=” c l a s s e s \${ j a r − f i l e } ” />
33 </ target>
Pentru exemplificarea tehnicii de lucru reluăm aplicaţia pentru calculul celui mai
mare divizor comun a două numere naturale, considerând interfaţa
1 package cmmdc0 ;
2 import j a v a . rmi . ∗ ;
3 p u b l i c i n t e r f a c e ICmmdc0 e x t e n d s Remote{
4 p u b l i c l o n g compute ( l o n g m, l o n g n ) throws RemoteException ;
5 }
3 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{
4 p u b l i c ICmmdc0 getCmmdc ( ) throws RemoteException ;
5 }
respectiv
1 package cmmdc0 ;
2 import j a v a . rmi . ∗ ;
3 import j a v a . rmi . s e r v e r . ∗ ;
4 import j a v a . rmi . r e g i s t r y . ∗ ;
6 p u b l i c c l a s s FabObiecte implements I F a b O b i e c t e {
13 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 [ ] ) {
14 S t r i n g h o s t=” l o c a l h o s t ” ;
15 i n t p o r t =1099;
16 i f ( a r g s . l e n g t h >0)
17 h o s t=a r g s [ 0 ] ;
18 i f ( a r g s . l e n g t h >1)
19 p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
20 try {
21 FabObiecte o b j=new FabObiecte ( ) ;
22 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 ) ;
23 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 ) ;
24 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 ) ;
25 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 ” ) ;
26 }
27 catch ( Exception e ){
28 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 ( ) ) ;
29 }
30 }
31 }
1. RemoteClient
4.1. REMOTE METHOD INVOCATION 63
6 p u b l i c c l a s s RemoteClient e x t e n d s UnicastRemoteObject {
8 ICmmdc0 remote=n u l l ;
2. ClientCmmdc0
Apelează metoda compute a obiectului remote.
1 package cmmdc0 ;
2 import j a v a . u t i l . Sc anne r ;
4 p u b l i c c l a s s ClientCmmdc0 {
6 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 [ ] ) {
7 S t r i n g h o s t=” l o c a l h o s t ” ;
8 i n t p o r t =1099;
9 i f ( a r g s . l e n g t h >0)
10 h o s t=a r g s [ 0 ] ;
11 i f ( a r g s . l e n g t h >1)
12 p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
13 Sca nner s c a n n e r=new Sca n n e r ( System . i n ) ;
14 try {
15 RemoteClient c t=new RemoteClient ( ho st , p o r t ) ;
16 System . out . p r i n t l n ( ”m=” ) ;
17 l o n g m=s c a n n e r . nextLong ( ) ;
18 System . out . p r i n t l n ( ”n=” ) ;
19 l o n g n=s c a n n e r . nextLong ( ) ;
20 l o n g x=c t . remote . compute (m, n ) ;
21 System . out . p r i n t l n ( ”Cmmdc=”+x ) ;
22 }
23 catch ( Exception e ){
24 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 ( ) ) ;
25 }
26 System . e x i t ( 0 ) ;
64 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANŢĂ
27 }
28 }
1 package cmmdc0 ;
2 import j a v a . rmi . ∗ ;
3 p u b l i c i n t e r f a c e ICmmdc0 e x t e n d s Remote{
4 p u b l i c l o n g compute ( l o n g m, l o n g n ) throws RemoteException ;
5 p u b l i c v o i d setMethod ( ICallbackCmmdc o b j ) throws RemoteException ;
6 }
6 p u b l i c c l a s s ServerCmmdc e x t e n d s UnicastRemoteObject
7 implements ICmmdc0{
8 p r i v a t e S t r i n g method=n u l l ;
12 p u b l i c l o n g compute ( l o n g m, l o n g n ) {
13 l o n g x =0;
14 i f ( method . e q u a l s ( ”NERECURSIV” ) )
4.1. REMOTE METHOD INVOCATION 65
15 x=n e r e c u r s i v (m, n ) ;
16 i f ( method . e q u a l s ( ”RECURSIV” ) )
17 x=r e c u r s i v (m, n ) ;
18 return x ;
19 }
35 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 ) {
36 long r , c ;
37 do {
38 c=n ;
39 r=m%n ;
40 m=n ;
41 n=r ;
42 }
43 while ( r !=0);
44 return c ;
45 }
46 }
7 p u b l i c c l a s s RemoteClient e x t e n d s UnicastRemoteObject
8 implements ICallbackCmmdc {
9 ICmmdc0 remote=n u l l ;
13 p u b l i c S t r i n g getMethod ( ) {
14 Sc anner s c a n n e r=new Scan ner ( System . i n ) ;
15 System . out . p r i n t l n ( ” A l e g e t i una d i n v a r i a n t e l e a l g o r i t m u l u i l u i E u c l i d ” ) ;
16 System . out . p r i n t l n ( ” 1 − a l g o r i t m u l ne−r e c u r s i v ” ) ;
17 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 ” ) ;
18 i n t x=s c a n n e r . n e x t I n t ( ) ;
19 S t r i n g method=n u l l ;
20 i f ( x==1)
66 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANŢĂ
21 method=”NERECURSIV” ;
22 else
23 method=”RECURSIV” ;
24 r e t u r n method ;
25 }
şi
1 package cmmdc0 ;
2 import j a v a . u t i l . Sc anne r ;
4 p u b l i c c l a s s ClientCmmdc0 {
5 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 [ ] ) {
6 S t r i n g h o s t=” l o c a l h o s t ” ;
7 i n t p o r t =1099;
8 i f ( a r g s . l e n g t h >0)
9 h o s t=a r g s [ 0 ] ;
10 i f ( a r g s . l e n g t h >1)
11 p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
12 Sca nner s c a n n e r=new S c a n n e r ( System . i n ) ;
13 try {
14 RemoteClient c t=new RemoteClient ( ho st , p o r t ) ;
15 c t . remote . setMethod ( c t ) ;
16 System . out . p r i n t l n ( ”m=” ) ;
17 l o n g m=s c a n n e r . nextLong ( ) ;
18 System . out . p r i n t l n ( ”n=” ) ;
19 l o n g n=s c a n n e r . nextLong ( ) ;
20 l o n g x=c t . remote . compute (m, n ) ;
21 System . out . p r i n t l n ( ”Cmmdc=”+x ) ;
22 }
23 catch ( Exception e ){
24 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 ( ) ) ;
25 }
26 System . e x i t ( 0 ) ;
27 }
28 }
grame care ı̂nregistrează informaţii despre obiecte la distanţă ce vor fi create şi
executate la cerere.
Invocarea de la distanţă a unei metode aparţinând unui asemenea obiect are ca
efect activarea obiectului.
Pe fiecare maşină virtuală Java există un grup de activare (activation group),
care realizează activarea. Activarea este făcută de un activator. Un activator conţine
o tabelă care face legătura dintre clasa obiectului cu URL-ul acestuia şi eventual, cu
date necesare iniţializării obiectului. Atunci când activatorul constată că nu există
un obiect referit, face apel la grupul de activare care va produce activarea obiectului.
Din punctul de vedere al clientului utilizarea mecanismului de activare la distanţă
nu implică modificări. Modificările intervin numai din punctul de vedere al serverului
şi al ı̂nregistrării sale.
Reluăm aplicaţia dezvoltată la ı̂nceputul capitolului, privind calculul celui mai
mare divizor comun a două numere naturale.
Aplicaţia server este compusă din două clase
1. o clasa ce implementează interfaţa ICmmdc : CmmdcActivabil;
2. clasa Setup, cu metoda main, care face posibilă mecanismul de activare şi
ı̂nscrie serviciul ı̂n registry. Această clasă este preluată din tutorialul dedicat
activării a documentaţiei ce ı̂nsoţeşte distribuţia Java.
Clasa ce implementează interfaţa la distanţă trebuie
1. să extindă clasa Activatable;
2. să aibă un constructor ce are doi parametrii
(a) un identificator al grupului de activare, de tip ActivationID, utilizat de
demonul de activare rmid;
(b) un obiect de tip MarchalledObject cu date de iniţializare a obiectului
activabil. În cazul nostru, acest parametru nu va fi folosit.
Codul sursă al clasei CmmdcActivabil este
1 package acmmdc ;
2 import j a v a . rmi . ∗ ;
3 import j a v a . rmi . a c t i v a t i o n . ∗ ;
4 import cmmdc . ∗ ;
6 p u b l i c c l a s s CmmdcActivabil e x t e n d s A c t i v a t a b l e
7 implements ICmmdc{
9 p u b l i c CmmdcActivabil ( A c t i v a t i o n I D id , M a r s h a l l e d O b j e c t data )
10 throws RemoteException {
11 s u p e r ( id , 0 ) ;
12 }
14 p u b l i c l o n g cmmdc( l o n g m, l o n g n ) { . . . }
15 }
68 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANŢĂ
2. java.class.path=no.classpath
ceea ce previne grupul de activare să ı̂ncarce o clasă din classpath-ul local;
1 package acmmdc ;
3 import j a v a . rmi . ∗ ;
4 import j a v a . rmi . a c t i v a t i o n . ∗ ;
5 import j a v a . rmi . r e g i s t r y . ∗ ;
6 import java . u t i l . Properties ;
8 p u b l i c c l a s s Setup {
10 p r i v a t e Setup ( ) {}
12 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) throws E x c e p t i o n {
14 // Argumentul l i n i e i de comanda
15 S t r i n g implClass = ”” ;
16 i f ( args . length < 1) {
17 System . e r r . p r i n t l n ( ” u s a g e : j a v a [ o p t i o n s ] examples . a c t i v a t i o n . Setup <i m p l C l a s s >” ) ;
18 System . e x i t ( 1 ) ;
19 }
20 else {
21 implClass = args [ 0 ] ;
22 }
24 // C o n s t r u i r e a d e s c r i p t o r u l u i g r u p u l u i de a c t i v a r e
25 S t r i n g p o l i c y=System . g e t P r o p e r t y ( ” m y a c t i v a t i o n . p o l i c y ” , ” group . p o l i c y ” ) ;
26 S t r i n g implCodbase=System . g e t P r o p e r t y ( ” m y a c t i v a t i o n . impl . c o d e b a s e ” ) ;
27 S t r i n g filename=System . g e t P r o p e r t y ( ” m y a c t i v a t i o n . f i l e ” , ” ” ) ;
28 P r o p e r t i e s p r o p s = new P r o p e r t i e s ( ) ;
29 p r o p s . put ( ” j a v a . s e c u r i t y . p o l i c y ” , p o l i c y ) ;
30 p r o p s . put ( ” j a v a . c l a s s . path ” , ” n o c l a s s p a t h ” ) ;
31 p r o p s . put ( ” m y a c t i v a t i o n . impl . c o d e b a s e ” , implCodebase ) ;
32 i f ( filename != n u l l && ! filename . equals ( ” ” ) ) {
33 p r o p s . put ( ” m y a c t i v a t i o n . f i l e ” , filename ) ;
34 }
35 A c t i v a t i o n G r o u p D e s c groupDesc = new A c t i v a t i o n G r o u p D e s c ( props , n u l l ) ;
37 // I n r e g i s t r a r e a g r u p u l u i de a c t i v a r e p e n t r o b t i n e r e a
38 // i d e n t i f i c a t o r u l u i de a c t i v a r e
39 ActivationGroupID groupID=A c t i v a t i o n G r o u p . getSystem ( ) . r e g i s t e r G r o u p ( groupDesc ) ;
40 System . e r r . p r i n t l n ( ” A c t i v a t i o n group d e s c r i p t o r r e g i s t e r e d . ” ) ;
42 // C o n s t r u i r e a d e s c r i p t o r u l u i de a c t i v a r e
43 M a r s h a l l e d O b j e c t data = n u l l ;
44 i f ( filename != n u l l && ! filename . equals ( ” ” ) ) {
45 data = new M a r s h a l l e d O b j e c t ( filename ) ;
46 }
50 // I n r e g i s t r a r e a d e s c r i p t o r u l u i de a c t i v a r e
51 Remote s t u b = A c t i v a t a b l e . r e g i s t e r ( d e s c ) ;
52 System . e r r . p r i n t l n ( ” A c t i v a t i o n d e s c r i p t o r r e g i s t e r e d . ” ) ;
54 // I n r e g i s t r a r e a s e r v i c i u l u i i n r e g i s t r y
55 S t r i n g name = System . g e t P r o p e r t y ( ” m y a c t i v a t i o n . name” ) ;
70 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANŢĂ
56 L o c a t e R e g i s t r y . g e t R e g i s t r y ( ) . r e b i n d ( name , s t u b ) ;
57 System . e r r . p r i n t l n ( ” Stub bound i n r e g i s t r y . ” ) ;
58 }
59 }
grant {
// allow activation groups to use certain system properties
permission com.sun.rmi.rmid.ExecOptionPermission
"-Djava.security.policy=${myactivation.policy}";
permission com.sun.rmi.rmid.ExecOptionPermission
"-Djava.class.path=no_classpath";
permission com.sun.rmi.rmid.ExecOptionPermission
"-Dmyactivation.impl.codebase=*";
permission com.sun.rmi.rmid.ExecOptionPermission
"-Dmyactivation.file=*";};
2. Pornirea registry-ului
start rmiregistry
set classpath=\s\public\classes\cmmdc.jar;\s\public\classes
java -Djava.rmi.server.codebase=file:/s/public/classes/
-Dmyactivation.impl.codebase=file:/s/public/classes/
-Dmyactivation.name=CmmdcServer
-Dmyactivation.file=""
-Dmyactivation.policy=group.policy
acmmdc.Setup acmmdc.CmmdcActivabil
4.2. CORBA 71
4.2 CORBA
Reţelele de calculatoare sunt eterogene ı̂n timp ce majoritatea interfeţelor de
programare a aplicaţiilor sunt orientate spre platforme omogene.
Pentru a facilita integrarea unor sisteme dezvoltate separat, ı̂ntr-un singur mediu
distribuit eterogen, OMG (Object Management Group – consorţiu cuprinzând peste
800 de firme) a elaborat standardul CORBA (Common Object Request Brocker
Arhitecture): un cadru de dezvoltare a aplicaţiilor distribuite ı̂n medii eterogene.
La CORBA au aderat toate marile firme de software - cu exceptia Microsoft,
firmă care a dezvoltat propriul său model DCOM (Distributed Component Object
Model), incompatibil CORBA.
CORBA conţine programe client care utilizează diferite obiecte distribuite ı̂n
sistem. Deoarece ı̂n multe sisteme de operare prelucrările trebuie să evolueze ı̂ntr-
un proces, orice obiect trebuie să evolueze ı̂ntr-un proces. În alte cazuri, obiectele
pot evolua ı̂n fire de execuţie sau ı̂n biblioteci dll. CORBA omogenizează aceste
posibilităţi prin precizarea că obiectele există ı̂n servere. Fiecare obiect este asociat
cu un singur server.
Interconectarea obiectelor. Implementarea şi localizarea unui obiect sunt as-
cunse clientului. Comunicarea ı̂ntre client şi obiect este facilitată de Object Request
Brocker (ORB) – care permite obiectelor să se regăseacă unele pe altele ı̂n reţea.
El ajută obiectele să facă cereri şi să primească răspunsuri de la alte obiecte aflate
ı̂n reţea. Acestea se desfăşoară transparent pentru client – care nu ştie 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 aplicaţii, dar care permit aplicaţiilor
să interacţioneze prin reţea. ORB face parte din middleware – un intermediar ı̂ntre
softul de reţea şi cel de aplicaţie.
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 interfaţa unui obiect şi implementarea sa şi foloseşte
un limbaj neutru pentru definirea interfeţelor: IDL -- Interface Defi- nition
Language.
IDL permite realizarea descrierii de interfeţe independent de limbajul de pro-
gramare şi de sistemul de operare folosit. O interfaţă IDL defineşte legătura dintre
client şi server.
72 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANŢĂ
• serverul care asigură regăsirea resurselor CORBA. Acest server se lansează ı̂n
execuţie prin
start orbd -ORBInitialPort [port]
2. Implementarea interfeţei
1 package cmmdciiop ;
2 import j a v a x . rmi . P o r t a b l e R e m o t e O b j e c t ;
3 import cmmdc . ∗ ;
4 import j a v a . rmi . ∗ ;
6 // 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
7 // s i nu UnicastRemoteObject
13 p u b l i c l o n g cmmdc( l o n g a , l o n g b ) { . . . }
14 }
1 package cmmdciiop ;
2 import j a v a x . naming . I n i t i a l C o n t e x t ;
3 import j a v a x . naming . Context ;
5 p u b l i c c l a s s CmmdcServer {
6 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 ) {
4.2. CORBA 73
7 try {
8 // 1 : C r e a r e a u n e i i n s t a n t e CmmdcImpl
9 CmmdcImpl cmmdcRef = new CmmdcImpl ( ) ;
11 // 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
12 // u t i l i z a n d JNDI API
13 Context i n i t i a l N a m i n g C o n t e x t = new I n i t i a l C o n t e x t ( ) ;
14 i n i t i a l N a m i n g C o n t e x t . r e b i n d ( ” CmmdcService ” , cmmdcRef ) ;
java.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
java.naming.provider.url=iiop://localhost:1050
1 package cmmdciiop ;
2 import j a v a . rmi . ∗ ;
3 import j a v a . n e t . MalformedURLException ;
4 import j a v a x . rmi . ∗ ;
5 import j a v a x . naming . ∗ ;
6 import cmmdc . ∗ ;
7 import j a v a . u t i l . S c a n n e r ;
9 public c l a s s CmmdcClient {
10 public s t a t i c void main ( S t r i n g a r g s [ ] ) {
4.2. CORBA 75
11 S t r i n g h o s t=” l o c a l h o s t ” ;
12 i n t p o r t =1099;
13 i f ( a r g s . l e n g t h >0)
14 h o s t=a r g s [ 0 ] ;
15 i f ( a r g s . l e n g t h >1)
16 p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
24 long x =0;
25 Context i c ;
26 Object o b j r e f ;
27 ICmmdc o b j ;
28 try {
29 i c = new I n i t i a l C o n t e x t ( ) ;
31 // 1 . O b t i n e r e a u n e i r e f e r i n t e de l a s e r v i c i u l CORBA
32 // p r i n a p e l JNDI .
33 o b j r e f = i c . l o o k u p ( ” CmmdcService ” ) ;
34 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 . ” ) ;
36 // 2 . A s o c i e r e a r e f e r i n t e i l a s e r v i c i u cu i n t e r f a t a
37 // s i i n v o c a r e a m e t o d e i
38 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 ) ;
39 x=o b j . cmmdc(m, n ) ;
40 System . out . p r i n t l n ( ”Cmmdc=”+x ) ;
41 }
42 catch ( E x c e p t i o n e ) {
43 System . e r r . p r i n t l n ( ” E x c e p t i o n ” + e . g e t M e s s a g e ( ) ) ;
44 }
45 }
46 }
9. Compilarea şi lansarea clientului ı̂n execuţie. Clientul trebuie să dispună de
fişierul stub (cmmdc. ICmmdc Stub.class) şi bineı̂nţeles de interfaţa ICmmdc.jar.
La apelarea clientului trebuie fixate proprietăţile
java.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
java.naming.provider.url=iiop://localhost:1050
Legarea cererii unui client de codul serviciului care satisface cererea utilizează
componenta CORBA Portable Object Adapter (POA).
1 module CmmdcApp{
2 i n t e r f a c e Cmmdc{
3 long long cmmdc( i n long long a , i n long long b ) ;
4 };
5 };
• Cmmdc.java
• CmmdcPOA.java ;
• CmmdcOperations.java;
• CmmdcStub.java;
• CmmdcHelper.java;
• CmmdcHolder.java.
4 p u b l i c c l a s s CmmdcImpl e x t e n d s CmmdcPOA {
5 p r i v a t e ORB orb ;
11 p u b l i c l o n g cmmdc( l o n g a , l o n g b ) { . . . }
12 }
şi programul CmmdcServer.java, care ı̂nscrie ı̂n registrul ORB referinţele ser-
vantului. Activităţile ce trebuie ı̂ntreprinse sunt declarate prin comentarii ı̂n
textul sursă al programului
1 import CmmdcApp . ∗ ;
2 import o r g . omg . CosNaming . ∗ ;
3 import o r g . omg . CosNaming . NamingContextPackage . ∗ ;
4 import o r g . omg .CORBA. ∗ ;
4.2. CORBA 79
5 import o r g . omg . P o r t a b l e S e r v e r . ∗ ;
7 p u b l i c c l a s s CmmdcServer {
8 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 [ ] ) {
9 try {
10 // c r e a r e a s i i n i t i a l i z a r e a ORB
11 ORB orb = ORB. i n i t ( a r g s , n u l l ) ;
13 // 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
14 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” ) ) ;
15 r o o t p o a . the POAManager ( ) . a c t i v a t e ( ) ;
17 // c r e a r e a unui s e r v a n t
18 CmmdcImpl cmmdcImpl = new CmmdcImpl ( orb ) ;
20 // 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
21 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 ) ;
22 Cmmdc h r e f = CmmdcHelper . narrow ( r e f ) ;
24 // O b t i n e r e a s e r v i c i u l u i NameService
25 o r g . omg .CORBA. O b j e c t o b j R e f =
26 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 ” ) ;
27 NamingContextExt ncRef = NamingContextExtHelper . narrow ( o b j R e f ) ;
29 // 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
30 S t r i n g name = ” CmmdcService ” ;
31 NameComponent path [ ] = ncRef . to name ( name ) ;
32 ncRef . r e b i n d ( path , h r e f ) ;
36 // i n a s t e p t a r e a c l i e n t i l o r
37 orb . run ( ) ;
38 }
39 catch ( Exception e ) {
40 System . e r r . p r i n t l n ( ”ERROR: ” + e ) ;
41 e . p r i n t S t a c k T r a c e ( System . out ) ;
42 }
43 System . out . p r i n t l n ( ”CmmdcServer E x i t i n g . . . ”);
44 }
45 }
7 p u b l i c c l a s s CmmdcClient {
8 s t a t i c Cmmdc cmmdcImpl ;
10 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 [ ] ) {
11 try {
12 // 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
13 ORB orb = ORB. i n i t ( a r g s , n u l l ) ;
15 // 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
80 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANŢĂ
16 // s e r v i c i i l o r i n r e g i s t r a t e
17 o r g . omg .CORBA. O b j e c t o b j R e f =
18 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 ” ) ;
19 NamingContextExt ncRef = NamingContextExtHelper . narrow ( o b j R e f ) ;
21 // 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
22 S t r i n g name = ” CmmdcService ” ;
23 cmmdcImpl = CmmdcHelper . narrow ( ncRef . r e s o l v e s t r ( name ) ) ;
Programele se compilează
javac CmmdcApp\*.java
Partea de server este alcătuită din clasa servant CmmdcImpl.java care imple-
mentează interfaţa Cmmdc -prezentat ı̂n secţiunea anterioară şi clasa PersistentServer
care asigură
15 // Pas 2 : I n s t a n t i e r e a s e r v a n t u l u i
16 CmmdcImpl s e r v a n t = new CmmdcImpl ( orb ) ;
32 // Pas 4 : A s o c i e r e a s e r v a n t u l u i cu PersistentPOA
33 persistentPOA . a c t i v a t e o b j e c t ( servant ) ;
50 }
51 }
Programul client
1 import java . u t i l . Properties ;
2 import o r g . omg .CORBA. ∗ ;
3 import o r g . omg . CosNaming . ∗ ;
4 import o r g . omg . P o r t a b l e S e r v e r .POA;
22 // Pas 2 : R e z o l v a r e a p e r s i s t e n t e i
23 // S e r v i c i u l NameService r u l e a z a pe h o s t cu p o r t u l p o r t
24 // Numele s e r v i c i u l u i c e r u t l u i NameService e s t e
25 // ” P e r s i s t e n t C m m d c S e r v e r ”
26 o r g . omg .CORBA. O b j e c t o b j = orb . s t r i n g t o o b j e c t (
27 ” c o r b a n a m e : : ”+h o s t+” : ”+p o r t+”#P e r s i s t e n t C m m d c S e r v e r ” ) ;
28 Cmmdc cmmdc=CmmdcHelper . narrow ( o b j ) ;
30 // Pas 3 : U t i l i z a r e a s e r v i c i u l u i
31 Sca nner s c a n n e r=new S c a n n e r ( System . i n ) ;
32 System . out . p r i n t l n ( ” C a l l i n g P e r s i s t e n t S e r v e r . . ” ) ;
33 i n t m, n , r ;
34 System . out . p r i n t l n ( ”m=” ) ;
35 m=s c a n n e r . n e x t I n t ( ) ;
36 System . out . p r i n t l n ( ”n=” ) ;
37 n=s c a n n e r . n e x t I n t ( ) ;
38 System . out . p r i n t l n (cmmdc . cmmdc(m, n ) ) ;
39 }
40 catch ( Exception e ) {
41 System . e r r . p r i n t l n ( ” E x c e p t i o n i n P e r s i s t e n t C l i e n t . j a v a . . . ” + e ) ;
42 e . printStackTrace ( ) ;
43 }
44 }
45 }
Serverul trebuie să fie pe acelaşi calculator pe care rulează orbd. Executarea
aplicaţiei presupune:
1. Pornirea serviciului de intregistrare a numelor cu programul orbd.exe din
distribuţia jdk.
2. Activarea serverului:
3. Executarea clientului
java PersistentClient [hostORB [portORB]]
84 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANŢĂ
Capitolul 5
• Sun Java System Message Queue a firmei Sun. Versiunea Platform Edition
este gratuită.
85
86 CAPITOLUL 5. MESAJE ÎN JAVA
Modele de comunicaţie:
• Comunicaţii punctuale : Un mesaj este generat de un producător (expeditor)
şi la care va avea acces un singur consumator (destinatar). Mesajul este depus
ı̂ntr-o coadă, de unde este preluat de către consumatorul care s-a legat de
coadă. Dacă de coadă nu se leagă nici un consumator, atunci mesajul este
păstrat ı̂n coadă.
• Proprietăţi : au caracter opţional şi sunt sub forma (nume, valoare). Pro-
prietăţile ajută consumatorii să selecteze mesajele.
În cazul unui calculator izolat este nevoie de instalarea driver-ului Microsoft loopback
Adaptor care sinulează existenţa funcţonării unei plăci de reţea active.
Distribuţia apache-activemq-5.*.* conţine, ca exemplu, clasa EmbeddedBroker.java
care lansează serverul JMS ı̂n lucru.
Compilarea unui program necesită prezenţa ı̂n variabila de sistem classpath a
referinţei către fişierul ACTIVEMQ HOME\activemq-all-*.*.*.jar. Pentru execuţie,
variabila de sistem classpath nevoie să conţină referinţele către fişierele jar din
catalogul ACTIVEMQ HOME\lib.
88 CAPITOLUL 5. MESAJE ÎN JAVA
2. Generarea conexiunii.
Se realizează prin
Connection conn=cf.createConnection();
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{
5.4. ELEMENTE DE PROGRAMARE - JMS 89
interface Connection{
Session createSession(boolean transacted,
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;
}
Session session=conn.createSession(false,
Session.AUTO_ACKNOWLEDGE);
interface Session{
| MessageProducer createProducer(Destination destination);
| MessageConsumer createConsumer(Destination destination);
| Message createMessage();
| TextMessage createTextMessage();
| 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);
}
interface Destination
5.4. ELEMENTE DE PROGRAMARE - JMS 91
|
|->interface Queue
|
|->interface Topic
Utilizând Sun Java System Message Queue obiecte de tip Queue sau Topic se
pot crea şi prin
MessageProducer producer=session.createProducer(obiectDestinatie);
interface MessageProducer{
void send(Message mesaj);
}
interface QueueSender{
void send(Message mesaj);
}
interface TopicPublisher{
void publish(Message mesaj);
}
TextMessage m=session.createTextMessage();
m.setText(string);
1 import j a v a x . jms . ∗ ;
7 MsgSenderT ( S t r i n g queueName , i n t n ) {
8 t h i s . queueName=queueName ;
9 t h i s . n=n ;
10 }
18 // s e t P r o p e r t y e s t e metoda a c l a s e i
19 // com . sun . m e s s a g i n g . QueueConnnectionFactory
20 // ce im plemen tea z a i n t e r f a t a QueueConnectionFactory
21 // dar nu a i n t e r f e t e i QueueConnectionFactory .
22 // c f . s e t P r o p e r t y (” imqBrokerHostName ” ,” h o s t ” ) ;
23 // c f . s e t P r o p e r t y (” imqBrokerHostPort ” , ” 7 6 7 6 ” ) ;
25 // V a r i a n t a Apache−MessageQueue
26 // o r g . apache . a c t i v e m q . ActiveMQConnectionFactory c f=
27 //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 ” ) ;
28 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 ( ) ;
29 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) ;
31 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 ) ;
33 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 ) ;
35 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 ( ) ;
36 f o r ( i n t i =0; i <n ; i ++){
37 m. s e t T e x t ( ” H e l l o ”+i ) ;
38 p r o d u c e r . send (m) ;
39 }
40 // 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
41 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 ( ) ) ;
42 session . close ();
43 conn . c l o s e ( ) ;
44 }
45 catch ( E x c e p t i o n e ) {
46 System . out . p r i n t l n ( ” JMSException : ”+e . g e t M e s s a g e ( ) ) ;
47 }
48 System . out . p r i n t l n ( ” Sen de r f i n i s h e d ” ) ;
49 }
50 }
5.4. ELEMENTE DE PROGRAMARE - JMS 93
2. Generarea conexiunii.
MessageConsumer consumer=session.createConsumer(q);
interface MessageConsumer{
| Message receive();
| Message receive(long timeout);
| Message receiveNoWait();
| }
|-> interface QueueReceiver
|
|-> interface TopicSubscriber
• Message receive()
• Message receive(long timeout)
• Message receiveNoWait()
Exemplul 5.4.2 Recepţia de tip sincron a mesajelor ı̂ntr-un fir de execuţie este
efectuat de clasa următoare:
1 import j a v a x . jms . ∗ ;
6 SyncMsgReceiverT ( S t r i n g queueName ) {
7 t h i s . queueName=queueName ;
8 }
21 // V a r i a n t a Apache−MessageQueue
22 // o r g . apache . a c t i v e m q . ActiveMQConnectionFactory c f=
23 //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 ” ) ;
24 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 ( ) ;
25 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) ;
26 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 ) ;
27 MessageConsumer consumer=s e s s i o n . createConsumer ( q ) ;
28 conn . s t a r t ( ) ;
29 Message msg=n u l l ;
30 while ( ( msg=consumer . r e c e i v e ( ) ) ! = n u l l ) {
31 i f ( msg instanceof TextMessage ) {
32 TextMessage m=(TextMessage ) msg ;
33 System . out . p r i n t l n (m. g e t T e x t ( ) ) ;
34 }
35 else
36 break ;
37 }
38 session . close ();
39 conn . c l o s e ( ) ;
40 }
41 catch ( E x c e p t i o n e ) {
42 System . out . p r i n t l n ( ” JMSException : ”+e . g e t M e s s a g e ( ) ) ;
43 }
44 System . out . p r i n t l n ( ” Consumer f i n i s h e d ” ) ;
45 }
46 }
1 c l a s s MsgHelloT {
2 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
3 i n t n=3;
4 S t r i n g queueName=”MyQueue” ;
5 i f ( a r g s . l e n g t h >0)
6 queueName=a r g s [ 0 ] ;
7 i f ( a r g s . l e n g t h >1)
8 n=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
9 MsgSenderT s e n d e r=new MsgSenderT ( queueName , n ) ;
10 SyncMsgReceiverT r e c e i v e r =new SyncMsgReceiverT ( queueName ) ;
11 receiver . start ();
12 sender . s t a r t ( ) ;
13 }
14 }
5.4. ELEMENTE DE PROGRAMARE - JMS 95
1 import j a v a x . jms . ∗ ;
2 public c l a s s AsyncMsgReceiverT extends Thread {
3 S t r i n g queueName ;
5 AsyncMsgReceiverT ( S t r i n g queueName ) {
6 t h i s . queueName=queueName ;
7 }
20 // V a r i a n t a Apache−MessageQueue
21 // o r g . apache . a c t i v e m q . ActiveMQConnectionFactory c f=
22 // 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 ” ) ;
24 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 ( ) ;
25 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) ;
26 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 ) ;
27 MessageConsumer consumer=s e s s i o n . createConsumer ( q ) ;
28 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 ( ) ;
29 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 ) ;
30 conn . s t a r t ( ) ;
31 t e x t L i s t e n e r . run ( ) ;
32 conn . c l o s e ( ) ;
33 }
34 catch ( E x c e p t i o n e ) {
35 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
36 }
37 System . out . p r i n t l n ( ” Consumer f i n i s h e d ” ) ;
38 }
39 }
41 import j a v a x . jms . ∗ ;
96 CAPITOLUL 5. MESAJE ÎN JAVA
42 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 {
43 boolean s f a r s i t =f a l s e ;
44 public void onMessage ( Message message ) {
45 i f ( message instanceof TextMessage ) {
46 TextMessage m=(TextMessage ) message ;
47 try {
48 System . out . p r i n t l n (m. g e t T e x t ( ) ) ;
49 }
50 catch ( JMSException e ) {
51 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
52 }
53 }
54 else
55 s f a r s i t =true ;
56 }
Exemplul 5.4.5
1 import j a v a x . jms . ∗ ;
7 MsgPublisherT ( S t r i n g s u b i e c t , i n t n ) {
8 t h i s . n=n ;
9 t h i s . s u b i e c t=s u b i e c t ;
10 }
20 // V a r i a n t a Apache−MessageQueue
21 // o r g . apache . a c t i v e m q . ActiveMQConnectionFactory c f=
22 // 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 ” ) ;
24 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 ( ) ;
25 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) ;
26 Destination t = session . createTopic ( subiect ) ;
5.4. ELEMENTE DE PROGRAMARE - JMS 97
27 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 ) ;
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 ( ) ;
33 f o r ( i n t i =0; i <n ; i ++){
34 m. s e t T e x t ( ” Despre ”+s u b i e c t+” ”+i ) ;
35 p r o d u c e r . send (m) ;
36 // p u b l i s h e r . p u b l i s h (m) ;
37 }
38 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 ( ) ) ;
39 // 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 ( ) ) ;
40 session . close ();
41 conn . c l o s e ( ) ;
42 }
43 catch ( E x c e p t i o n e ) {
44 System . out . p r i n t l n ( ” JMSException : ”+e . g e t M e s s a g e ( ) ) ;
45 }
46 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 ” ) ;
47 }
48 }
Varianta comentată este o soluţie specifică implementării Sun Java System Mes-
sage Queue.
TopicSubscriber consumer=session.createSubscriber((Topic)t);
Subscrierea este este valabilă atâta timp cât clientul este activ. Pentru a primi toate
mesajele specifice subiectului, chiar şi când clientul este inactiv, acesta trebuie să fie
durabil, adică crearea consumatorului să se facă prin
conn.setClientID("myID");
TopicSubscriber consumer=
session.createDurableSubscriber((Topic)t,"nameClient");
În ambele cazuri, clientul primeşte doar mesajele publicate din momentul subscrierii.
Exemplul 5.4.6
1 import j a v a x . jms . ∗ ;
8 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 ) {
9 t h i s . s u b i e c t=s u b i e c t ;
10 t h i s . c l i e n t I D=c l i e n t I D ;
11 t h i s . c l i e n t N a m e=c l i e n t N a m e ;
12 }
22 // V a r i a n t a Apache−MessageQueue
23 // o r g . apache . a c t i v e m q . ActiveMQConnectionFactory c f=
24 //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 ” ) ;
26 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 ( ) ;
27 conn . s e t C l i e n t I D ( c l i e n t I D ) ;
28 T o p i c S e s s i o n s e s s i o n=
29 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) ;
30 Destination t = session . createTopic ( subiect ) ;
31 T o p i c S u b s c r i b e r consumer=
32 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 ) ;
33 conn . s t a r t ( ) ;
34 Message msg=n u l l ;
35 while ( ( msg=consumer . r e c e i v e ( ) ) ! = n u l l ) {
36 i f ( msg instanceof TextMessage ) {
37 TextMessage m=(TextMessage ) msg ;
38 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 ( ) ) ;
39 }
40 else
41 break ;
42 }
43 session . close ();
44 conn . c l o s e ( ) ;
45 }
46 catch ( E x c e p t i o n e ) {
47 System . out . p r i n t l n ( ” JMSException : ”+e . g e t M e s s a g e ( ) ) ;
48 }
49 }
50 }
Exemplul 5.4.7
1 c l a s s MsgPS{
2 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
3 S t r i n g s u b i e c t=”JMS” ;
4 i n t n=3 , noAbonati =3;
5 i f ( a r g s . l e n g t h >0)
6 s u b i e c t=a r g s [ 0 ] ;
7 i f ( a r g s . l e n g t h >1)
8 n=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
9 MsgPublisherT p u b l i s h e r=new MsgPublisherT ( s u b i e c t , n ) ;
10 MsgSubscriberT [ ] abonat=new MsgSubscriberT [ noAbonati ] ;
5.5. MESAJE SOAP PRIN JAVA MESSAGE SERVICE 99
11 publisher . start ( ) ;
12 f o r ( i n t i =0; i <noAbonati ; i ++){
13 abonat [ i ]=new MsgSubscriberT ( s u b i e c t , ”ID”+i , ” i d ”+i ) ;
14 abonat [ i ] . s t a r t ( ) ;
15 }
16 }
17 }
5.5.1 SOAP
SOAP - Simple Object Access Protocol - este un protocol de comunicaţii ı̂ntre
aplicaţii. În prezent SOAP este protocolul standard pentru servicii Web prin Inter-
net. SOAP este independent de platforma de calcul şi de limbajul de programare.
SOAP se bazează pe XML (eXtended Markup Language) şi este un standard
W3C (World Wide Web Consortium).
• un corp (body);
SOAPPart part=soapMsg.getSOAPPart();
SOAPEnvelope envelope=part.getEnvelope();
SOAPHeader header=envelope.getHeader();
SOAPBody body=envelope.getBody();
Name n1=envelope.createName("e1");
SOAPElement e1=body.addBodyElement(n1);
În general, un element se include ı̂n elementul părinte, care pote fi chiar şi body, prin
metoda clasei SOAPElement
e1.addTextNode("primul");
se obţine cu programul
4 public c l a s s MsgSOAP{
5 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
6 Name name=n u l l ;
7 try {
8 MessageFactory mf=MessageFac to ry . n e w I n s t a n c e ( ) ;
9 SOAPMessage soapMsg=mf . c r e a t e M e s s a g e ( ) ;
10 SOAPPart p a r t=soapMsg . getSOAPPart ( ) ;
102 CAPITOLUL 5. MESAJE ÎN JAVA
11 SOAPEnvelope e n v e l o p e=p a r t . g e t E n v e l o p e ( ) ;
12 SOAPBody body=e n v e l o p e . getBody ( ) ;
13 Name n1=e n v e l o p e . createName ( ” e1 ” ) ;
14 SOAPElement e1=body . addBodyElement ( n1 ) ;
15 e1 . addTextNode ( ” p r i m u l ” ) ;
16 Name n2=e n v e l o p e . createName ( ” e2 ” ) ;
17 SOAPElement e2=body . addBodyElement ( n2 ) ;
18 e2 . addTextNode ( ” a l d o i l e a ” ) ;
19 Name n11 =e n v e l o p e . createName ( ” e11 ” ) ;
20 SOAPElement e11=e1 . addChildElement ( n11 ) ;
21 e11 . addTextNode ( ” a l t r e i l e a ” ) ;
22 F i l eO u t p u t St r e a m f=new F i l e O u t p u t S t r e a m ( ”MySOAPMessage . xml” ) ;
23 soapMsg . writ eTo ( f ) ;
24 }
25 catch ( E x c e p t i o n e ) {
26 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 ( ) ) ;
27 }
28 }
29 }
}
}
Exemplul 5.5.2 Un client introduce ı̂ntr-un mesaj SOAP două numere ı̂ntregi,
transmite mesajul altui program care calculează cel mai mare divizor comun al celor
două numere şi transmite clientului rezultatul tot sub forma unui mesaj SOAP.
6 public c l a s s MsgSOAPClientSender {
8 long a , b ;
9 String topicResult ;
10 S t r i n g c l i e n t I D , clientName ;
12 MsgSOAPClientSender ( 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 ) {
13 t h i s . c l i e n t I D=c l i e n t I D ;
14 t h i s . c l i e n t N a m e=c l i e n t N a m e ;
15 Sca nner s c a n n e r=new Sca n n e r ( System . i n ) ;
16 System . out . p r i n t l n ( ” I n t r o d u c e t i m : ” ) ;
17 a=s c a n n e r . nextLong ( ) ;
18 System . out . p r i n t l n ( ” I n t r o d u c e t i n : ” ) ;
19 b=s c a n n e r . nextLong ( ) ;
20 System . out . p r i n t l n ( ” I n t r o d u c e t i ’ Topic ’− u l r a s p u n s u l u i ” ) ;
21 t o p i c R e s u l t=s c a n n e r . n e x t ( ) ;
22 }
24 public void s e r v i c e ( ) {
25 MessageFactory mf=n u l l ;
26 SOAPMessage soapMsg=n u l l ;
27 SOAPPart p a r t=n u l l ;
28 SOAPEnvelope e n v e l o p e=n u l l ;
29 SOAPBody body=n u l l ;
30 SOAPElement elem=n u l l ;
31 Name name=n u l l ;
32 try {
33 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=
34 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 ( ) ;
35 // c f . s e t P r o p e r t y (” imqBrokerHostName ” ,” a t l a n t i s ” ) ;
36 // c f . s e t P r o p e r t y (” imqBrokerHostPort ” , ” 7 6 7 6 ” ) ;
37 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 ( ) ;
38 conn . s e t C l i e n t I D ( c l i e n t I D ) ;
39 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) ;
40 D e s t i n a t i o n tDate=s e s s i o n . c r e a t e T o p i c ( ”Cmmdc” ) ;
41 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 ( tDate ) ;
42 mf=MessageFactory . n e w I n s t a n c e ( ) ;
43 soapMsg=mf . c r e a t e M e s s a g e ( ) ;
44 p a r t=soapMsg . getSOAPPart ( ) ;
45 e n v e l o p e=p a r t . g e t E n v e l o p e ( ) ;
104 CAPITOLUL 5. MESAJE ÎN JAVA
46 body=e n v e l o p e . getBody ( ) ;
47 name=e n v e l o p e . createName ( ” n1 ” ) ;
48 elem=body . addChildElement ( name ) ;
49 elem . addTextNode ( (new Long ( a ) ) . t o S t r i n g ( ) ) ;
50 name=e n v e l o p e . createName ( ” n2 ” ) ;
51 elem=body . addChildElement ( name ) ;
52 elem . addTextNode ( (new Long ( b ) ) . t o S t r i n g ( ) ) ;
53 name=e n v e l o p e . createName ( ” t o p i c ” ) ;
54 elem=body . addChildElement ( name ) ;
55 elem . addTextNode ( t o p i c R e s u l t ) ;
56 D e s t i n a t i o n t R e s u l t=s e s s i o n . c r e a t e T o p i c ( t o p i c R e s u l t ) ;
57 T o p i c S u b s c r i b e r consumer=
58 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 R e s u l t , c l i e n t N a m e ) ;
59 Message m=
60 MessageTr an s fo r me r . SOAPMessageIntoJMSMessage ( soapMsg , s e s s i o n ) ;
61 p r o d u c e r . send (m) ;
62 F i l e Ou t p u t St r e a m f=new F i l e O u t p u t S t r e a m ( ”MySOAPMessage . xml” ) ;
63 soapMsg . writ e T o ( f ) ;
64 conn . c l o s e ( ) ;
65 }
66 catch ( E x c e p t i o n e ) {
67 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 ( ) ) ;
68 }
69 System . out . p r i n t l n ( ” Sen de r f i n i s h e d ” ) ;
70 }
• Recepţionarea răspunsului.
1 import j a v a x . jms . ∗ ;
2 import j a v a x . xml . soap . ∗ ;
3 import com . sun . m e s s a g i n g . xml . Me s sa g eT ra n sf o rm e r ;
4 import java . u t i l . ∗ ;
6 public c l a s s MsgSOAPClientReceiver {
8 String topicResult ;
9 S t r i n g c l i e n t I D , clientName ;
11 MsgSOAPClientReceiver ( 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 ) {
12 t h i s . c l i e n t I D=c l i e n t I D ;
13 t h i s . c l i e n t N a m e=c l i e n t N a m e ;
14 Sc anne r s c a n n e r=new S c a n n e r ( System . i n ) ;
15 System . out . p r i n t l n ( ” I n t r o d u c e t i ’ Topic ’− u l r a s p u n s u l u i ” ) ;
16 t o p i c R e s u l t=s c a n n e r . n e x t ( ) ;
17 }
19 public void s e r v i c e ( ) {
20 MessageFactory mf=n u l l ;
5.5. MESAJE SOAP PRIN JAVA MESSAGE SERVICE 105
21 SOAPMessage soapMsg=n u l l ;
22 SOAPPart p a r t=n u l l ;
23 SOAPEnvelope e n v e l o p e=n u l l ;
24 SOAPBody body=n u l l ;
25 SOAPBodyElement e l e m e n t=n u l l ;
26 Name name=n u l l ;
27 try {
28 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=
29 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 ( ) ;
30 // c f . s e t P r o p e r t y (” imqBrokerHostName ” ,” a t l a n t i s ” ) ;
31 // c f . s e t P r o p e r t y (” imqBrokerHostPort ” , ” 7 6 7 6 ” ) ;
32 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 ( ) ;
33 conn . s e t C l i e n t I D ( c l i e n t I D ) ;
34 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 ,
35 S e s s i o n .AUTO ACKNOWLEDGE) ;
36 D e s t i n a t i o n t R e s u l t=s e s s i o n . c r e a t e T o p i c ( t o p i c R e s u l t ) ;
37 T o p i c S u b s c r i b e r consumer=
38 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 R e s u l t , c l i e n t N a m e ) ;
39 mf=MessageFactory . n e w I n s t a n c e ( ) ;
40 conn . s t a r t ( ) ;
41 Message msg=consumer . r e c e i v e ( ) ;
42 soapMsg=MessageTransf or m er . SOAPMessageFromJMSMessage ( msg , mf ) ;
43 System . out . p r i n t l n ( ” C l i e n t Mesaj SOAP r e c e p t i o n a t ” ) ;
44 p a r t=soapMsg . getSOAPPart ( ) ;
45 e n v e l o p e=p a r t . g e t E n v e l o p e ( ) ;
46 body=e n v e l o p e . getBody ( ) ;
47 I t e r a t o r i t e r a t o r=body . g e t C h i l d E l e m e n t s ( ) ;
48 S t r i n g s=” ” ;
49 while ( i t e r a t o r . hasNext ( ) ) {
50 e l e m e n t =(SOAPBodyElement ) i t e r a t o r . n e x t ( ) ;
51 name=e l e m e n t . getElementName ( ) ;
52 i f ( name . getLocalName ( ) . e q u a l s ( ”cmmdc” ) )
53 s=e l e m e n t . g e t V a l u e ( ) ;
54 }
55 System . out . p r i n t l n ( ”Cmmdc : ”+s ) ;
56 conn . c l o s e ( ) ;
57 }
58 catch ( E x c e p t i o n e ) {
59 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 ( ) ) ;
60 }
61 System . out . p r i n t l n ( ” R e c e i v e r f i n i s h e d ” ) ;
62 }
4 import j a v a . u t i l . I t e r a t o r ;
6 public c l a s s MsgSOAPCmmdcServer{
10 public void s e r v i c e ( ) {
11 MessageFactory mf=n u l l ;
12 SOAPMessage soapMsg=n u l l ;
13 SOAPPart p a r t=n u l l ;
14 SOAPEnvelope e n v e l o p e=n u l l ;
15 SOAPBody body=n u l l ;
16 SOAPBodyElement e l e m e n t=n u l l ;
17 SOAPElement elem=n u l l ;
18 Name name=n u l l ;
19 try {
20 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
21 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 ( ) ;
22 // c f . s e t P r o p e r t y (” imqBrokerHostName ” ,” a t l a n t i s ” ) ;
23 // c f . s e t P r o p e r t y (” imqBrokerHostPort ” , ” 7 6 7 6 ” ) ;
24 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 ( ) ;
25 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 ,
26 S e s s i o n .AUTO ACKNOWLEDGE) ;
27 D e s t i n a t i o n tDate=s e s s i o n . c r e a t e T o p i c ( ”Cmmdc” ) ;
28 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 S u b s c r i b e r ( ( Topic ) tDate ) ;
29 conn . s t a r t ( ) ;
30 Message msg=n u l l ;
31 mf=MessageFactory . n e w I n s t a n c e ( ) ;
32 while ( true ) {
33 msg=consumer . r e c e i v e ( ) ;
34 soapMsg=Message T ra n sf o rm er . SOAPMessageFromJMSMessage ( msg , mf ) ;
35 System . out . p r i n t l n ( ” S e r v e r Mesaj SOAP r e c e p t i o n a t ” ) ;
36 p a r t=soapMsg . getSOAPPart ( ) ;
37 e n v e l o p e=p a r t . g e t E n v e l o p e ( ) ;
38 body=e n v e l o p e . getBody ( ) ;
39 I t e r a t o r i t e r a t o r=body . g e t C h i l d E l e m e n t s ( ) ;
40 S t r i n g sn1=” ” , sn2=” ” , t o p i c R e s u l t=” ” ;
41 while ( i t e r a t o r . hasNext ( ) ) {
42 e l e m e n t =(SOAPBodyElement ) i t e r a t o r . n e x t ( ) ;
43 name=e l e m e n t . getElementName ( ) ;
44 i f ( name . getLocalName ( ) . e q u a l s ( ” n1 ” ) )
45 sn1=e l e m e n t . g e t V a l u e ( ) ;
46 i f ( name . getLocalName ( ) . e q u a l s ( ” n2 ” ) )
47 sn2=e l e m e n t . g e t V a l u e ( ) ;
48 i f ( name . getLocalName ( ) . e q u a l s ( ” t o p i c ” ) )
49 t o p i c R e s u l t=e l e m e n t . g e t V a l u e ( ) ;
50 }
51 System . out . p r i n t l n ( sn1+” : ”+sn2+” : ”+t o p i c R e s u l t ) ;
52 long a=Long . par se Lon g ( sn1 ) ;
53 long b=Long . pars eL ong ( sn2 ) ;
54 long c=cmmdc( a , b ) ;
55 soapMsg=mf . c r e a t e M e s s a g e ( ) ;
56 p a r t=soapMsg . getSOAPPart ( ) ;
57 e n v e l o p e=p a r t . g e t E n v e l o p e ( ) ;
58 body=e n v e l o p e . getBody ( ) ;
59 name=e n v e l o p e . createName ( ”cmmdc” ) ;
60 elem=body . addChildElement ( name ) ;
61 elem . addTextNode ( (new Long ( c ) ) . t o S t r i n g ( ) ) ;
62 Message m=
5.5. MESAJE SOAP PRIN JAVA MESSAGE SERVICE 107
Mesajul SOAP utilizat de client, pentru n1 = 45, n2 = 35 şi topic = nume este
<soap-env:Envelope
xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header/>
<soap-env:Body>
<n1>45</n1>
<n2>35</n2>
<topic>nume</topic>
</soap-env:Body>
</soap-env:Envelope>
MessageFactory mf=MessageFactory.newInstance();
SOAPMessage soapMsg=mf.createMessage();
2. • Ataşament text
(a) Crearea unui obiect de tip AttachmentPart
AttachmentPart attachment=soapMsg.createAttachmentPart();
(b) Completarea conţinutului
String stringContent=. . .
attachment.setContent(stringContent, "text/plain");
Conţinutului i se poate ataşa un cod de identificare
attachment.setContentId("Text1");
108 CAPITOLUL 5. MESAJE ÎN JAVA
Extragerea ataşamentelor
Tipul unui ataşament se poate deduce din rezultatul metodei getContentId sau
getContentType a clasei AttachmentPart.
Image image=(Image)attached.getContent();
. . .
}
Exemplul 5.5.3 Crearea unui mesaj SOAP cu ataşamente text, imagine şi muzică
mp3. Textul, imaginea şi muzica mp3 sunt conţinute ı̂n fişiere. Căile către aceste
fişiere se vor da ca proprietăţi.
1 import j a v a x . jms . ∗ ;
2 import j a v a x . xml . soap . ∗ ;
3 import com . sun . m e s s a g i n g . xml . Mes sa g eT ra n sf o rm e r ;
4 import java . io . ∗ ;
5 import j a v a x . a c t i v a t i o n . DataHandler ;
6 import j a v a . n e t .URL;
11 MsgSOAPPublisher ( S t r i n g f i l e l o c a t i o n , S t r i n g i m a g e l o c a t i o n , S t r i n g m p 3 l o c a t i o n ) {
12 this . f i l e l o c a t i o n=f i l e l o c a t i o n ;
13 t h i s . i m a g e l o c a t i o n=i m a g e l o c a t i o n ;
14 t h i s . m p 3 l o c a t i o n=m p 3 l o c a t i o n ;
15 }
38 // Se c o m p l e t e a z a c a l e a l a f i s i e r u l myText . t x t
39 F i l e R e a d e r f r = new F i l e R e a d e r ( f i l e l o c a t i o n ) ) ;
40 B u f f e r e d R e a d e r br = new B u f f e r e d R e a d e r ( f r ) ;
42 S t r i n g stringContent = ”” ;
43 S t r i n g l i n e = br . r e a d L i n e ( ) ;
44 while ( l i n e != n u l l ) {
45 stringContent = stringContent . concat ( l i n e ) ;
46 s t r i n g C o n t e n t = s t r i n g C o n t e n t . c o n c a t ( ” \n” ) ;
47 l i n e = br . r e a d L i n e ( ) ;
48 }
50 attachment1 . s e t C o n t e n t ( s t r i n g C o n t e n t , ” t e x t / p l a i n ” ) ;
51 attachment1 . s e t C o n t e n t I d ( ” a t t a c h e d t e x t ” ) ;
52 soapMsg . addAttachmentPart ( attachment1 ) ;
1 import j a v a x . jms . ∗ ;
2 import j a v a x . xml . soap . ∗ ;
3 import com . sun . m e s s a g i n g . xml . Me s sa g eT ra n sf o rm e r ;
4 import java . u t i l . I t e r a t o r ;
5 import java . io . ∗ ;
6 import j a v a . awt . ∗ ;
12 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=
13 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 ( ) ;
14 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 ( ) ;
15 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) ;
16 D e s t i n a t i o n t=s e s s i o n . c r e a t e T o p i c ( ” Date ” ) ;
17 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 S u b s c r i b e r ( ( Topic ) t ) ;
18 conn . s t a r t ( ) ;
19 Message msg=n u l l ;
20 MessageFactory mf=MessageFac to ry . n e w I n s t a n c e ( ) ;
21 while ( ( msg=consumer . r e c e i v e ( ) ) ! = n u l l ) {
22 SOAPMessage soapMsg=
23 MessageTransformer . SOAPMessageFromJMSMessage ( msg , mf ) ;
24 // E x t r a g e r e a a t a s a m e n t e l o r
25 I t e r a t o r i t e r a t o r = soapMsg . g e t A t t a c h m e n t s ( ) ;
26 while ( i t e r a t o r . hasNext ( ) ) {
27 AttachmentPart a t t a c h e d =(AttachmentPart ) i t e r a t o r . n e x t ( ) ;
28 String id = attached . getContentId ( ) ;
29 S t r i n g t y p e = a t t a c h e d . getContentType ( ) ;
30 System . out . p r i n t l n ( ” Attachment ” + i d +
31 ” has c o n t e n t t y p e ” + t y p e ) ;
32 i f ( type . e q u a l s ( ” t e x t / p l a i n ” ) ) {
33 Object content = attached . getContent ( ) ;
34 System . out . p r i n t l n ( ” Attachment c o n t a i n s : \ n” + c o n t e n t ) ;
35 }
36 i f ( t y p e . e q u a l s ( ” image / j p e g ” ) ) {
37 Image image=(Image ) a t t a c h e d . g e t C o n t e n t ( ) ;
38 ShowImage s=new ShowImage ( image ) ;
39 s . show ( ) ;
40 }
41 i f ( t y p e . e q u a l s ( ” a u d i o /x−wav” ) ) {
42 MP3Player mp3Player=new MP3Player ( a t t a c h e d . getRawContent ( ) ) ;
43 mp3Player . s t a r t ( ) ;
44 }
45 }
46 }
47 conn . c l o s e ( ) ;
48 }
49 catch ( E x c e p t i o n e ) {
50 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 ( ) ) ;
51 }
52 System . out . p r i n t l n ( ” S u b s c r i b e r f i n i s h e d ” ) ;
53 }
54 }
15 public void p a i n t ( G r a p h i c s g ) {
16 g . drawImage ( image , 0 , 0 , t h i s ) ;
17 }
18 }
20 public c l a s s ShowImage{
21 MyCanvas mc=n u l l ;
Programul pentru redarea conţinutului unui fişier mp3 necesită prezenţa resursei
jl1.0.jar din pachetul JLayer1.0, descărcabil din internet. Un program de redare este
1 public c l a s s MP3Player extends Thread {
2 private P l a y e r p l a y e r ;
8 @REM C r e a t e Broker K e y s t o r e :
9 k e y t o o l −genkey − a l i a s q p i d B r o k e r −k e y a l g RSA − v a l i d i t y 365
10 −k e y s t o r e q p i d . k e y s t o r e −s t o r e p a s s password −k e y p a s s password
11 −dname ”CN=unitbv , OU=cs , O=Org , L=Bv , C=R”
13 @REM Export S e l f S i g n e d C e r t :
14 k e y t o o l −e x p o r t − a l i a s q p i d B r o k e r −k e y s t o r e q p i d . k e y s t o r e
15 − f i l e q p i d B r o k e r . c e r −s t o r e p a s s password
114 CAPITOLUL 5. MESAJE ÎN JAVA
21 @REM D e l e t e t h e c e r t
22 del qpidBroker . cer
13 MsgSenderT ( S t r i n g queueName , i n t n ) {
14 t h i s . queueName=queueName ;
15 t h i s . n=n ;
16 }
29 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 ( ) ;
30 f o r ( i n t i =0; i <n ; i ++){
31 m. s e t T e x t ( ” H e l l o ”+i ) ;
32 p r o d u c e r . send (m) ;
33 }
34 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 ( ) ) ;
35 session . close ();
36 conn . c l o s e ( ) ;
37 }
38 catch ( E x c e p t i o n e ) {
39 System . out . p r i n t l n ( ” JMSException : ”+e . g e t M e s s a g e ( ) ) ;
40 }
41 System . out . p r i n t l n ( ” Sender f i n i s h e d ” ) ;
42 }
61 private void c l o s e J N D I ( ) {
62 try {
63 ctx . c l o s e ( ) ;
64 }
65 catch ( NamingException e ) {
66 System . e r r . p r i n t l n ( ” Unable t o c l o s e JNDI Context : ” + e ) ;
67 }
68 }
Clasa SyncMsgReceiverT
1 import j a v a x . jms . ∗ ;
2 import j a v a x . naming . ∗ ;
3 import java . u t i l . Properties ;
4 import java . io . ∗ ;
12 SyncMsgReceiverT ( S t r i n g queueName ) {
13 t h i s . queueName=queueName ;
14 }
63 private void c l o s e J N D I ( ) {
64 try {
65 ctx . c l o s e ( ) ;
66 }
67 catch ( NamingException e ) {
68 System . e r r . p r i n t l n ( ” Unable t o c l o s e JNDI Context : ” + e ) ;
69 }
70 }
12 MsgPublisherT ( S t r i n g s u b i e c t , i n t n ) {
13 t h i s . n=n ;
14 t h i s . s u b i e c t=s u b i e c t ;
15 }
26 D e s t i n a t i o n t =( D e s t i n a t i o n ) c t x . l o o k u p ( s u b i e c t ) ;
27 closeJNDI ( ) ;
28 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 ) ;
29 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 ( ) ;
30 f o r ( i n t i =0; i <n ; i ++){
31 m. s e t T e x t ( ” Despre ”+s u b i e c t+” ”+i ) ;
32 p r o d u c e r . send (m) ;
33 }
34 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 ( ) ) ;
35 session . close ();
36 conn . c l o s e ( ) ;
37 }
38 catch ( E x c e p t i o n e ) {
39 System . out . p r i n t l n ( ” JMSException : ”+e . g e t M e s s a g e ( ) ) ;
40 }
41 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 ” ) ;
42 }
61 private void c l o s e J N D I ( ) {
62 try {
63 ctx . c l o s e ( ) ;
64 }
65 catch ( NamingException e ) {
66 System . e r r . p r i n t l n ( ” Unable t o c l o s e JNDI Context : ” + e ) ;
67 }
68 }
Clasa MsgSubscriberT
1 import j a v a x . jms . ∗ ;
2 import j a v a x . naming . ∗ ;
5.6. ADVANCED MESSAGE QUEUE PROTOCOL - QPID 119
3 import j a v a . u t i l . P r o p e r t i e s ;
4 import j a v a . i o . ∗ ;
13 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 ) {
14 t h i s . s u b i e c t=s u b i e c t ;
15 t h i s . c l i e n t I D=c l i e n t I D ;
16 t h i s . c l i e n t N a m e=c l i e n t N a m e ;
17 }
35 conn . s t a r t ( ) ;
36 Message msg=n u l l ;
37 while ( ( msg=consumer . r e c e i v e ( ) ) ! = n u l l ) {
38 i f ( msg instanceof TextMessage ) {
39 TextMessage m=(TextMessage ) msg ;
40 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 ( ) ) ;
41 }
42 else
43 break ;
44 }
45 session . close ();
46 conn . c l o s e ( ) ;
47 }
48 catch ( E x c e p t i o n e ) {
49 System . out . p r i n t l n ( ” JMSException : ”+e . g e t M e s s a g e ( ) ) ;
50 }
51 System . out . p r i n t l n ( ” S u b s c r i b e r f i n i s h e d ” ) ;
52 }
72 private void c l o s e J N D I ( ) {
73 try {
74 ctx . c l o s e ( ) ;
75 }
76 catch ( NamingException e ) {
77 System . e r r . p r i n t l n ( ” Unable t o c l o s e JNDI Context : ” + e ) ;
78 }
79 }
4 # r e g i s t e r some c o n n e c t i o n f a c t o r i e s
5 # c o n n e c t i o n f a c t o r y . [ jndiname ] = [ ConnectionURL ]
6 c o n n e c t i o n f a c t o r y . ConnectionFactory =
7 amqp: // g u e s t : g u e s t @ c l i e n t i d / t e s t ? b r o k e r l i s t= ’ t c p : // l o c a l h o s t : 5 6 7 2 ’
13 # t o p i c . [ jndiName ] = [ physicalName ]
14 t o p i c . JMS = mytopic
Varianta ActiveMQ
1 j a v a . naming . f a c t o r y . i n i t i a l =
2 o r g . apache . a c t i v e m q . j n d i . A c t i v e M Q I n i t i a l C o n t e x t F a c t o r y
În acest caz este nevoie de crearea ı̂n prealabil a obiectelor corespunzătoare conexi-
unii, a cozii (queue) şi a subiectului (topic). Aceaste obiecte se crează cu utilitarul
imqobjmgr din distribuţia Sun Java System Message Queue.
Obiectele se pot crea cu fişierul de comenzi:
1 s e t PATH=d : \mq\ b i n ;%PATH%
2 imqobjmgr add −t q f − l ” C o n n e c t i o n F a c t o r y ”
3 −j j a v a . naming . p r o v i d e r . u r l= f i l e : /// c : /Temp
4 −j 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
5 imqobjmgr add −t q − l ” queue ”
6 −j j a v a . naming . p r o v i d e r . u r l= f i l e : /// c : /Temp
7 −j 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
8 imqobjmgr add −t t − l ” t o p i c ”
9 −j j a v a . naming . p r o v i d e r . u r l= f i l e : /// c : /Temp
10 −j 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
Servlet
Un servlet este un program Java care se excută pe un server Web, compatibil, şi
este capabil să răpundă cererilor formulate de clienţi.
Scrierea şi utilizarea unui servlet necesită
123
124 CAPITOLUL 6. SERVLET
• <input>
• <option>
• <select>
• <textarea>
<select name="nume">
<option value="valoare"> Valoare
6.2. SERVER WEB - CONTAINER DE SERVLET 125
. . . . . . . . . . . . . . . .
</select>
Valoarea atributului nume este dată de valoarea selectată.
• jetty
set CATALINA_HOME=. . .
set JAVA_HOME=. . .
bin\startup
apphello
| |---> WEB-INF
| | |---> classes
| | | web.xml
Catalogul classes conţine fişierele .class ale servletului iar fişierul web.xml
furnizează serverului web informaţii de acces la servlet. Astfel
cu precizarea fişierelor html sau jsp care lansează servletul. Declaraţia fişierului
index.html este implicită.
Dacă servlet-ul necesă alte resurse - fişiere jar, atunci acestea se depun ı̂ntr-un
subcatalog lib ı̂n WEB-INF.
apphello
| |---> WEB-INF
| | |---> classes
| | | | HelloServlet.class
| | | web.xml
3. Se porneşte serverul tomcat, operaţie ı̂n urma căreie arhiva este dezarhivată.
Astfel servlet-ul este instalat.
Dacă serverul tomcat este pornit atunci arhiva se dezarhivează automat şi
servlet-ul este gata de utilizare. Această instalare se numeşte instalare di-
namică - hot deployment.
Dacă fişierul war este creat, atunci ı̂n locul copierii, instalarea se poate face prin
componenta manager a lui tomcat.
O altă posibilitate de instalare a unui servlet ı̂n serverul web tomcat este prin
intermediul produsului apache-tomcat-deployer. apache-tomcat-deployer permite in-
stalarea unui servlet de la distanţă cât şi instalarea comandată dintr-un program.
apache-tomcat-*.*.*-deployer se instalează prin dezarhivarea fişierului apache-tomcat-*.*.*-deployer.
Posibilităţile oferite de apache-tomcat-*.*.*-deployer se obţin rulând ant cu un fişierul build.xml din
distribuţia produsului. Obiectivele care pot fi atinse sunt
• path=/catalog-ul servlet-ului.
http://host:port/catalog/numeApel
6.3. REALIZAREA UNUI SERVLET 129
unde
<init-param>
<param-name> NumeleParametrului </param-name>
<param-value> Valoare </param-value>
</init-param>
• "text/plain" - text;
• "image/jpg" - imagine gif;
• "image/gif" - imagine jpg.
6. Închide conexiunea obiectului prin care s-a realizat transmisia datelor către
navigatorul clientului prin out.close().
Exemplul 6.3.1 Servletul Hello: Clientul transmite numele servet-ului care ı̂i răspunde
cu mesajul de salut ”Hi nume!”.
14 </form>
15 </ center>
16 </body>
17 </html>
5 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 {
6 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 )
7 throws S e r v l e t E x c e p t i o n , IOException {
8 r e s . setContentType ( ” t e x t / html ” ) ;
9 S e r v l e t O u t p u t S t r e a m out=r e s . getOutputStream ( ) ;
10 S t r i n g nume=r e q . g e t P a r a m e t e r ( ”name” ) ;
11 out . p r i n t l n ( ”<html>” ) ;
12 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>” ) ;
13 out . p r i n t l n ( ”<body>” ) ;
14 out . p r i n t l n ( ”<h1>H e l l o S e r v l e t </h1>” ) ;
15 out . p r i n t l n ( ”<p>” ) ;
16 out . p r i n t l n ( ” Hi ”+ nume+” ! ” ) ;
17 out . p r i n t l n ( ”</p>” ) ;
18 out . p r i n t l n ( ”</body>” ) ;
19 out . p r i n t l n ( ”</html>” ) ;
20 out . c l o s e ( ) ;
21 }
7 <web−app>
8 < s e r v l e t>
9 <s e r v l e t −name> h e l l o</ s e r v l e t −name>
10 <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>
11 </ s e r v l e t>
12 <s e r v l e t −mapping>
13 <s e r v l e t −name> h e l l o</ s e r v l e t −name>
14 <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>
15 </ s e r v l e t −mapping>
16 <welcome−f i l e − l i s t>
17 <welcome− f i l e >i n d e x . html</ welcome− f i l e >
18 </ welcome−f i l e − l i s t>
19 </web−app>
Compilarea şi arhivarea servlet-ului o vom realiza prin intermediul lui apache-
ant. În acest scop se crează structura:
6.3. REALIZAREA UNUI SERVLET 133
hello
| |---> src
| | | HelloServlet.java
| |---> lib
| |---> web
| | | web.xml
| |---> web-files
| | | index.html
| build.xml
cu fişierul build.xml
1 <p r o j e c t b a s e d i r=” . ” default=” g e n e r a t e . war ”>
49 </ f i l e s e t>
50 </ copy>
51 <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 } ” />
52 </ t a r g e t>
53 </ p r o j e c t>
Exemplul 6.3.2 Servlet pentru calculul celui mai mare divizor comun a două nu-
mere.
1 import j a v a . i o . ∗ ;
2 import j a v a x . s e r v l e t . ∗ ;
3 import j a v a x . s e r v l e t . h t t p . ∗ ;
1 <html>
2 <body>
3 <form method=” g e t ”
4 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”>
5 <p>Primul numar e s t e <input type=” t e x t ” name=”m” s i z e=5>
6 <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>
7 <p><input type=” submit ” value=” C a l c u l e a z a ”>
8 <input type=” hidden ” name=” t i p ” value=” t e x t / html ” >
9 </form>
10 </body>
11 </html>
Pentru fixarea naturii răspunsului text/html sau text/plain s-a introdus variabila
tip, care ı̂n fişierul de invocare index.html primeşte pe ascuns valoarea text/html.
În cazul ı̂n care vom apela servlet-ul dintr-un program, va fi avantajos să primim
răspunsul ca text/plain.
• commons-codec de la apache;
• commons-logging de la apache;
Pentru compilare trebuie declarată ı̂n variabila de sistem classpath referinţa către
commons-httpclient, dar pentru execuţie este nevoie şi de referintele către celelalte
două produse.
Dezvoltarea unui client presupune:
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.httpclient.params.HttpMethodParams;
DefaultHttpMethodRetryHandler retryhandler=
new DefaultHttpMethodRetryHandler(int numarReluari,
boolean seFacReluari);
method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
retryhandler);
5. Lansarea cererii.
• Ca şir de octeţi:
byte[] method.getResponseBody();
• Ca String:
6.4. FACILITĂŢI DE PROGRAMARE CU SERVLET 137
String method.getResponseBodyAsString();
• Prin intermediul unui flux:
InputStream method.getResponseBodyAsStream();
method.releaseConnection();
1 import java . u t i l . ∗ ;
2 import o r g . apache . commons . h t t p c l i e n t . ∗ ;
3 import o r g . apache . commons . h t t p c l i e n t . methods . ∗ ;
4 import o r g . apache . commons . h t t p c l i e n t . params . HttpMethodParams ;
6 import j a v a . i o . ∗ ;
8 public c l a s s ClientCmmdcServlet {
9 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” ;
18 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 ( ) ;
19 PostMethod method = new PostMethod ( u r l ) ;
25 DefaultHttpMethodRetryHandler r e t r y h a n d l e r=
26 new DefaultHttpMethodRetryHandler ( 3 , true ) ;
27 method . getParams ( ) . s e t P a r a m e t e r ( HttpMethodParams .RETRY HANDLER,
28 retryhandler );
29 try {
30 i n t s t a t u s C o d e = c l i e n t . executeMethod ( method ) ;
32 i f ( s t a t u s C o d e != H t t p S t a t u s . SC OK) {
33 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 ( ) ) ;
34 System . e x i t ( 0 ) ;
35 }
36 byte [ ] re sp on se B od y = method . getResponseBody ( ) ;
37 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 ) ) ) ;
38 }
39 catch ( H t t p E x c e p t i o n e ) {
40 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 ( ) ) ;
41 }
42 catch ( IOException e ) {
43 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 ( ) ) ;
44 }
138 CAPITOLUL 6. SERVLET
45 finally {
46 method . r e l e a s e C o n n e c t i o n ( ) ;
47 }
48 }
49 }
RequestDispatcher dispatcher=
getServletContext().getRequestDispatcher("/url_pattern_servlet_apelat");
if(dispatcher!=null)
dispatcher.include(request,response);
6 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 {
31 n=Long . parseLong ( sn ) ;
32 }
33 catch ( NumberFormatException e ) {
34 message=”Nu e s t e numar” ;
35 }
36 }
37 out . p r i n t l n ( ”<html><body>” ) ;
38 i f ( message . e q u a l s ( ” ” ) ) {
39 out . p r i n t l n ( ”<h3> R e z u l t a t u l obţ i n u t </h3>” ) ;
40 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=
41 getServletContext ( ) . getRequestDispatcher ( ”/ c a l c u l ” ) ;
42 i f ( d i s p a t c h e r != n u l l )
43 d i s p a t c h e r . i n c l u d e ( req , r e s ) ;
44 }
45 else {
46 out . p r i n t l n ( ”<h3> Date e r o n a t e </h3>” ) ;
47 out . p r i n t l n ( message ) ;
48 }
49 out . p r i n t l n ( ”</body></html>” ) ;
50 out . c l o s e ( ) ;
51 }
ComputeServlet.java
1 package cmmdc ;
2 import j a v a . i o . ∗ ;
3 import j a v a x . s e r v l e t . ∗ ;
4 import j a v a x . s e r v l e t . h t t p . ∗ ;
HttpSession sesiune=request.getSession(true);
Un obiect HttpSession poate reţine atribute, adică perechi de forma (nume, val-
oare). Introducerea unui atribut se realizează prin
Exemplul 6.4.3 Exemplul următor numără de câte ori se apelează servlet-ul ı̂ntr-o
sesiune. Se defineşte un atribut noAcces, care la prima apelare este iniţializat iar
apoi este mărit cu câte o unitate la fiecare nouă apelare a servlet-ului.
1 import j a v a . i o . ∗ ;
2 import j a v a x . s e r v l e t . ∗ ;
3 import j a v a x . s e r v l e t . h t t p . ∗ ;
5 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 {
27 out . p r i n t l n ( ”</body></html>” ) ;
28 out . c l o s e ( ) ;
29 }
6.4.4 Cookie
Un Cookie este un fişier de mică dimensiune trimis de către programul server
clientului ca parte a header-ului Http.
Acesta conţine informaţii despre sesiunea curentă care salvate pe disc vor putea
fi accesate ı̂n sesiuni ulterioare. Când un navigator emite o cerere către un server,
cookie-urile anterioare primite de către client de la serverul respectiv sunt trimise
din nou serverului ca parte a cererii formulată de client.
Cookie-urile sunt sterse automat ı̂n momentul expirării.
Unii clienţi nu permit memorarea cookie-urilor. În acest caz, clientul este infor-
mat că acest fapt ar putea duce la imposibilitatea satisfacerii cereri sale / accesării
paginii Web. Implicit, durata de viaţă a unui cookie este sesiunea curentă a naviga-
torului (până se ı̂nchide navigatorul).
Clasa Cookie
Contructor
Cookie(String nume, String valoare)
Metode
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 6.4.4 În exemplul următor se numără de câte ori se apelează servlet-ul
pe durata de viaţă a cookie-ului.
1 import j a v a . i o . ∗ ;
2 import j a v a x . s e r v l e t . ∗ ;
3 import j a v a x . s e r v l e t . h t t p . ∗ ;
5 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 {
26 mesaj=” S a l u t ! ” ;
27 }
28 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 ( ) ) ;
29 myCookie . setMaxAge ( 1 0 0 0 0 0 0 ) ;
30 r e s . addCookie ( myCookie ) ;
31 out . p r i n t l n ( ”<html><body>” ) ;
32 out . p r i n t l n ( ”<h1>”+mesaj+”</h1>” ) ;
33 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 ) ;
34 out . p r i n t l n ( ”</body></html>” ) ;
35 out . c l o s e ( ) ;
36 }
Exemplul 6.4.5
1 import java . io . ∗ ;
2 import javax . s e r v l e t . ∗ ;
3 import javax . s e r v l e t . http . ∗ ;
4 import java . u t i l . Properties ;
6 public c l a s s P r o t e c t e d P a g e extends H t t p S e r v l e t {
7 private P r o p e r t i e s p a s s w o r d s ;
8 private S t r i n g p a s s w o r d F i l e ;
10 // P a r o l e l e s u n t i n t r −un f i s i e r ” p a r o l e ”
11 // s u b forma nume=p a r o l a .
12 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 {
13 super . i n i t ( c o n f i g ) ;
14 try {
15 passwordFile = config . getInitParameter ( ” passwordFile ” ) ;
16 p a s s w o r d s = new P r o p e r t i e s ( ) ;
17 p a s s w o r d s . l o a d (new F i l e I n p u t S t r e a m ( p a s s w o r d F i l e ) ) ;
18 }
19 catch ( IOException i o e ) {}
20 }
144 CAPITOLUL 6. SERVLET
52 // Cererea a f o s t f a r a a u t o r i z a r e
53 private void c e r P a r o l a ( H t t p S e r v l e t R e s p o n s e r e s p o n s e ) {
54 r e s p o n s e . s e t S t a t u s ( r e s p o n s e . SC UNAUTHORIZED ) ; // I e 401
55 r e s p o n s e . s e t H e a d e r ( ”WWW −A u t h e n t i c a t e ” ,
56 ”BASIC realm =\” p r i v i l e g e d −few \” ” ) ;
57 }
<init-param>
<param-name>passwordFile</param-name>
<param-value>d:\\apache-tomcat-*.*.*\\. . .\\parole.properties</param-value>
</init-param>
Acest element apare ı̂n corpul elementului <servlet> ataşat servlet-ului. Servletul
se apelează prin http://host:port/context/numeApel.
6.4. FACILITĂŢI DE PROGRAMARE CU SERVLET 145
6 public c l a s s T e l e f extends H t t p S e r v l e t {
7 Statement i n s t r u c t i u n e=n u l l ;
45 // P r e l u a r e a v a l o r i i unui parametru
47 myAtribut=r e q . g e t P a r a m e t e r ( ” c r i t e r i u ” ) ;
48 myVal=r e q . g e t P a r a m e t e r ( ” termen ” ) ;
146 CAPITOLUL 6. SERVLET
49 myVal= ’ \ ’ ’+myVal+ ’ \ ’ ’ ;
50 try {
51 S t r i n g s q l=” s e l e c t ∗ from t e l e f where ”+ myAtribut+” = ”
52 +myVal ;
53 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 ) ;
54 out . p r i n t l n ( ”<html>” ) ;
55 out . p r i n t l n ( ”<head><t i t l e >A g e n d a T e l e f o n i c a </ t i t l e ></head>” ) ;
56 out . p r i n t l n ( ”<body>” ) ;
57 out . p r i n t l n ( ”<h1>Agenda T e l e f o n i c a </h1>” ) ;
58 while ( r s . n e x t ( ) ) {
59 out . p r i n t ( r s . g e t S t r i n g ( ”nume”)+” a r e numarul de t e l e f o n : ”+
60 r s . g e t S t r i n g ( ”numar” ) ) ;
61 }
62 out . p r i n t l n ( ”</body>” ) ;
63 out . p r i n t l n ( ”</html>” ) ;
64 out . c l o s e ( ) ;
65 }
66 catch ( SQLException e ) {
67 System . out . p r i n t l n ( ” SQLException : ”+e . g e t M e s s a g e ( ) ) ;
68 }
69 catch ( E x c e p t i o n e ) {
70 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 ( ) ) ;
71 }
72 }
2. Testarea servlet-ului:
response.setContentType("image/gif");
În cazul unui fişier extern imaginea este refăcută ı̂n memorie şi ı̂n fluxul de ieşire
de tip ServletOutputStream se transmite recodarea imaginii ı̂n format gif.
Această recodare se poate face cu pachetul Acme.JPM.Encoders, disponibil
gratuit la adresa web http://www.acme.com.
Preluarea imaginii dintr-un fişier se programează
Image image=Toolkit.getDefaultToolkit().getImage(String
referinţăFişier );
1 import java . io . ∗ ;
2 import j a v a . awt . ∗ ;
3 import javax . s e r v l e t . ∗ ;
4 import javax . s e r v l e t . http . ∗ ;
5 import Acme .JPM. Encoders . G i f E n c o d e r ;
15 // 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
16 S t r i n g f=”d : \ \ apache−tomcat − ∗ . ∗ . ∗ \ \ webapps \\ m y s e r v l e t \\
17 WEB−INF\\ c l a s s e s \\ w a l k i n g s a n t a . g i f ” ;
18 // P r e l u a r e a i m a g i n i i g r a f i c e
19 Image image=T o o l k i t . g e t D e f a u l t T o o l k i t ( ) . getImage ( f ) ;
20 // Transmiterea i m a g i n i i u t i l i z a n d p a c h e t u l
21 G i f E n c o d e r e n c o d e r = new G i f E n c o d e r ( image , out ) ;
22 e n c o d e r . encode ( ) ;
23 }
24 }
• Pe calculatorul serverului Web, imaginea se salvează ı̂ntr-un fişier jpg sau png,
după care servlet-ul scrie ı̂n fluxul de ieşire un document html cu o legătură
(link) către fişierul cu imaginea creată anterior. Navigatorul clientului va
descărca şi vizualiza imaginea.
Textul sursă al servlet-ului este:
1 import java . io . ∗ ;
2 import j a v a . awt . ∗ ;
3 import javax . s e r v l e t . ∗ ;
4 import javax . s e r v l e t . http . ∗ ;
5 import javax . imageio . ∗ ;
6 import j a v a . awt . image . ∗ ;
7 import j a v a x . i m a g e i o . stream . ∗ ;
8 import java . u t i l . ∗ ;
19 // Formarea i m a g i n i i
20 Frame frame = n u l l ;
21 Graphics g = null ;
22 B u f f e r e d I m a g e image=n u l l ;
23 try {
24 frame = new Frame ( ) ;
25 // a d d N o t i f y : Cadrul Frame d e v i n e a f i s a b i l p r i n
26 // l e g a r e a l u i l a o r e s u r s a n a t i v a a e c r a n u l u i .
27 // P r o p r i e t a t e a s e m o s t e n e s t e de t o t i d e s c e n d e n t i i
28 // c a d r u l u i
29 frame . a d d N o t i f y ( ) ;
30 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 ) ;
31 g = image . g e t G r a p h i c s ( ) ;
33 // F i x a r e a f o n t u l u i
34 g . s e t F o n t (new Font ( ” S e r i f ” , Font . ITALIC , 4 8 ) ) ;
36 // E d i t a r e a unui t e x t
6.4. FACILITĂŢI DE PROGRAMARE CU SERVLET 149
37 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 ) ;
43 // Raspunsul c a t r e c l i e n t
44 out . p r i n t l n ( ”<HTML><BODY>” ) ;
45 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>” ) ;
46 out . p r i n t l n ( ”<p><a h r e f =\”d : \ \ apache−tomcat − ∗ . ∗ . ∗ \ \ ”
47 +numeFis+” . ”+e x t+”\”>” ) ;
48 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>” ) ;
49 out . p r i n t l n ( ”</BODY></HTML>” ) ;
50 out . c l o s e ( ) ;
51 }
52 finally {
53 // E l i b e r a r e a r e s u r s e l o r
54 i f ( g != n u l l ) g . d i s p o s e ( ) ;
55 i f ( frame != n u l l ) frame . r e m o v e N o t i f y ( ) ;
56 }
57 }
58 }
InterfataDistanta obj=(InterfataDistanta)
Naming.lookup("//"+host+":"+port+"/NumeServiciuRMI");
Exemplul 6.4.7 Client servlet pentru aplicaţia RMI de calcul al celui mai mare
divizor comun a două numere naturale.
1 import java . io . ∗ ;
2 import j a v a . rmi . ∗ ;
3 import j a v a . rmi . r e g i s t r y . ∗ ;
4 import javax . s e r v l e t . ∗ ;
5 import javax . s e r v l e t . http . ∗ ;
6 import cmmdc . ∗ ;
19 S t r i n g h o s t=r e q . g e t P a r a m e t e r ( ” h o s t ” ) . t r i m ( ) ;
20 S t r i n g s P o r t=r e q . g e t P a r a m e t e r ( ” p o r t ” ) ;
21 i n t p o r t=I n t e g e r . p a r s e I n t ( s P o r t ) ;
23 try {
24 ICmmdc o b j =(ICmmdc) Naming . l o o k u p ( ” // ”+h o s t+” : ”+p o r t+” /CmmdcServer” ) ;
25 x=o b j . cmmdc(m, n ) ;
26 }
27 catch ( E x c e p t i o n e ) {
28 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 ( ) ) ;
29 }
30 S t r i n g t i t l e =” CmmdcServlet ” ;
31 r e s . setContentType ( ” t e x t / html ” ) ;
32 out . p r i n t l n ( ”<HTML><HEAD><TITLE>” ) ;
33 out . p r i n t l n ( t i t l e ) ;
34 out . p r i n t l n ( ”</TITLE></HEAD><BODY>” ) ;
35 out . p r i n t l n ( ”<H1>”+ t i t l e +”</H1>” ) ;
36 out . p r i n t l n ( ”<P>Cmmdc : ”+x ) ;
37 out . p r i n t l n ( ”</BODY></HTML>” ) ;
38 out . c l o s e ( ) ;
39 }
• In prima fază se apelează un servlet care apelează un server JMS. Soluţia este
reţinută de furnizorul serviciului de mesagerie pe o destinaţie cu un subiect
furnizat de client. Pentru regăsirea rezultatului, servlet-ul crează clientului un
abonament durabil, funcţie de numele subiectului.
• În faza a doua, clientul apelează un alt servlet, a cărei funcţie este preluarea
rezultatului. Clientul trebuie sa furnizeze subiectul destinaţiei rezultatului.
Exemplul 6.4.8
5 public c l a s s MsgCmmdcServer{
9 public void s e r v i c e ( ) {
10 try {
6.4. FACILITĂŢI DE PROGRAMARE CU SERVLET 151
11 // V a r i a n t a Apache−MessageQueue
12 // o r g . apache . a c t i v e m q . ActiveMQConnectionFactory c f=
13 // new o r g . apache . a c t i v e m q . ActiveMQConnectionFactory (
14 // ” tcp :// l o c a l h o s t :61616”);
16 // V a r i a n t a Sun MessageQueue
17 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=
18 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 ( ) ;
19 // c f . s e t P r o p e r t y (” imqBrokerHostName ” ,” h o s t ” ) ;
20 // c f . s e t P r o p e r t y (” imqBrokerHostPort ” , ” 7 6 7 6 ” ) ;
21 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 ( ) ;
22 T o p i c S e s s i o n s e s s i o n=
23 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) ;
24 D e s t i n a t i o n tDate=s e s s i o n . c r e a t e T o p i c ( ”Cmmdc” ) ;
25 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 S u b s c r i b e r ( ( Topic ) tDate ) ;
26 conn . s t a r t ( ) ;
27 TextMessage txtMsg=n u l l ;
28 S t r i n g sm=” ” , sn=” ” , t o p i c=” ” ;
29 while ( true ) {
30 txtMsg=(TextMessage ) consumer . r e c e i v e ( ) ;
31 S t r i n g msg=txtMsg . g e t T e x t ( ) ;
32 S t r i n g T o k e n i z e r s t=new S t r i n g T o k e n i z e r ( msg , ” ” ) ;
33 i n t i =0;
34 while ( s t . hasMoreElements ( ) ) {
35 i ++;
36 i f ( i ==1) sm=s t . nextToken ( ) ;
37 i f ( i ==2) sn=s t . nextToken ( ) ;
38 i f ( i ==3) t o p i c=s t . nextToken ( ) ;
39 }
40 System . out . p r i n t l n ( sm+” : ”+sn+” : ”+t o p i c ) ;
41 long a=Long . parseLong ( sm ) ;
42 long b=Long . parseLong ( sn ) ;
43 long c=cmmdc( a , b ) ;
44 D e s t i n a t i o n t R e s u l t=s e s s i o n . c r e a t e T o p i c ( t o p i c ) ;
45 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 R e s u l t ) ;
46 txtMsg=s e s s i o n . c r e a t e T e x t M e s s a g e ( (new Long ( c ) ) . t o S t r i n g ( ) ) ;
47 p r o d u c e r . send ( txtMsg ) ;
48 System . out . p r i n t l n ( ” E x p e d i a t r a s p u n s ” ) ;
49 }
50 }
51 catch ( E x c e p t i o n e ) {
52 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 ( ) ) ;
53 }
54 System . out . p r i n t l n ( ” S e r v e r f i n i s h e d ” ) ;
55 }
7 public c l a s s J M S S e n d e r S e r v l e t extends H t t p S e r v l e t {
24 // V a r i a n t a Sun MessageQueue
25 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=
26 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 ( ) ;
27 // c f . s e t P r o p e r t y (” imqBrokerHostName ” ,” h o s t ” ) ;
28 // c f . s e t P r o p e r t y (” imqBrokerHostPort ” , ” 7 6 7 6 ” ) ;
29 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 ( ) ;
30 conn . s e t C l i e n t I D ( c l i e n t I D ) ;
31 T o p i c S e s s i o n s e s s i o n=
32 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) ;
33 D e s t i n a t i o n t R e s u l t=s e s s i o n . c r e a t e T o p i c ( t o p i c ) ;
34 T o p i c S u b s c r i b e r consumer=
35 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 R e s u l t , c l i e n t N a m e ) ;
36 D e s t i n a t i o n t = s e s s i o n . c r e a t e T o p i c ( ”Cmmdc” ) ;
37 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 ) ;
38 TextMessage txtMsg=s e s s i o n . c r e a t e T e x t M e s s a g e ( ) ;
39 S t r i n g mesaj=m+” ”+n+” ”+t o p i c ;
40 txtMsg . s e t T e x t ( mesaj ) ;
41 p r o d u c e r . send ( txtMsg ) ;
42 session . close ();
43 conn . c l o s e ( ) ;
44 out . p r i n t l n ( ”<html><body b g c o l o r=\”#c c b b c c\”>< c e n t e r >” ) ;
45 out . p r i n t l n ( ”<h1> JSP Cmmdc </h1>” ) ;
46 out . p r i n t l n ( ”<p>” ) ;
47 out . p r i n t l n ( ” D a t e l e au f o s t e x p e d i a t e s e r v e r u l u i ” ) ;
48 out . p r i n t l n ( ”</ c e n t e r ></body></html>” ) ;
49 }
50 catch ( E x c e p t i o n e ) {
51 out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
52 }
53 out . c l o s e ( ) ;
54 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 ” ) ;
55 }
3 import j a v a . i o . ∗ ;
4 import j a v a x . s e r v l e t . ∗ ;
5 import j a v a x . s e r v l e t . h t t p . ∗ ;
7 public c l a s s J M S R e c e i v e r S e r v l e t extends H t t p S e r v l e t {
22 // V a r i a n t a Sun MessageQueue
23 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=
24 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 ( ) ;
25 // c f . s e t P r o p e r t y (” imqBrokerHostName ” ,” h o s t ” ) ;
26 // c f . s e t P r o p e r t y (” imqBrokerHostPort ” , ” 7 6 7 6 ” ) ;
27 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 ( ) ;
28 conn . s e t C l i e n t I D ( c l i e n t I D ) ;
29 T o p i c S e s s i o n s e s s i o n=
30 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) ;
31 Destination tResult = session . createTopic ( topic ) ;
32 T o p i c S u b s c r i b e r consumer=
33 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 R e s u l t , c l i e n t N a m e ) ;
34 conn . s t a r t ( ) ;
35 TextMessage txtMsg=(TextMessage ) consumer . r e c e i v e ( ) ;
36 S t r i n g cmmdc=txtMsg . g e t T e x t ( ) ;
37 session . close ();
38 conn . c l o s e ( ) ;
39 out . p r i n t l n ( ”<html><body b g c o l o r=\”#c c b b c c\”>< c e n t e r >” ) ;
40 out . p r i n t l n ( ”<h1> JSP Cmmdc </h1>” ) ;
41 out . p r i n t l n ( ”<p>” ) ;
42 out . p r i n t l n ( ” R e z u l t a t u l o b t i n u t : ”+cmmdc ) ;
43 out . p r i n t l n ( ”</ c e n t e r ></body></html>” ) ;
44 }
45 catch ( E x c e p t i o n e ) {
46 out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
47 }
48 out . c l o s e ( ) ;
49 System . out . p r i n t l n ( ” S u b s c r i b e r f i n i s h e d ” ) ;
50 }
6.5 FileUpload
Deseori clientul trebuie să furnizeze unui servlet un volum mare de date, de-
pozitate ı̂ntr-un fişier. Un produs care ne ajută să ı̂ndeplinim acest obiectiv este
commons-fileupload - dezvoltat de apache.
Commons-FileUpload - dezvoltat ı̂n cadrul apache - este un produs care simplifică
transferul unui fişier de la un client la programul server (file upload). Interfaţa de
programare a produsului se referă la partea de server - ı̂n cazul de faţă reprezentat
prin servlet.
Instalarea produsului constă din dezarhivarea fişierului descărcat din Internet.
În plus este nevoie de
• commons-io
Fişierele
• commons-fileupload-*.*.jar
• commons-io-*.*.jar
<form
action=. . .
enctype="multipart/form-data"
method="post">
Iterator iter=fileItems.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (item.isFormField()) {
// Prelucrarea elementului item care corespunde unei
// date din formularul html care nu este de tip fisier
}
else{
// Prelucrarea elementului item de tip fisier
}
}
5. În cazul unui element care nu este de tip fişier putem obţine numele şi valoarea
atributului furnizat de client
6. În cazul unui fişier putem afla numele câmpului input, numele fişierului, di-
mensiunea fişierului
156 CAPITOLUL 6. SERVLET
7. Dacă dorim să salvăm fişierul pe calculatorul server atunci prelucrarea este
InputStream in = item.getInputStream();
//preluarea datelor din fluxul in
. . .
in.close();
Exemplul 6.5.1 Să se obţină ı̂n memoria serverului matricea conţinută ı̂ntr-un
fişier text. În fişierul text, fiecare linie conţine o linie a matricei, iar elementele
sunt separate prin spaţii.
10 public c l a s s F i l e U p l o a d S e r v l e t extends H t t p S e r v l e t {
24 F i l e I t e m item = ( F i l e I t e m ) i t e r . n e x t ( ) ;
25 i f ( ! item . i s F o r m F i e l d ( ) ) {
26 S t r i n g f i l e N a m e = item . getName ( ) ;
27 out . p r i n t l n ( f i l e N a m e ) ;
28 long s i z e I n B y t e s = item . g e t S i z e ( ) ;
29 out . p r i n t l n ( s i z e I n B y t e s ) ;
30 InputStream i n=item . g e t I n p u t S t r e a m ( ) ;
31 InputStreamReader i s r =new InputStreamReader ( i n ) ;
32 B u f f e r e d R e a d e r br=new B u f f e r e d R e a d e r ( i s r ) ;
33 double [ ] [ ] m a t r i x=g e t M a t r i x ( br ) ;
34 i n t m=m a t r i x . l e n g t h ;
35 i n t n=m a t r i x [ 0 ] . l e n g t h ;
36 f o r ( i n t i =0; i <m; i ++){
37 f o r ( i n t j =0; j <n ; j ++)
38 out . p r i n t ( m a t r i x [ i ] [ j ]+ ” ” ) ;
39 out . p r i n t l n ( ) ;
40 }
41 br . c l o s e ( ) ;
42 isr . close ();
43 in . close ( ) ;
44 out . c l o s e ( ) ;
45 }
46 }
47 }
48 catch ( E x c e p t i o n e ) {
49 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 ( ) ) ;
50 }
51 }
83 }
84 catch ( E x c e p t i o n e ) {
85 throw new E x c e p t i o n ( e . g e t M e s s a g e ( ) ) ;
86 }
87 return m a t r i x ;
88 }
89 }
• referinţă html
<a href="http://host:port/context/doc.jsp">
webapps
|--> JSPApp
|--> WEB-INF
|--> classes
|--> web.xml
|--> jsp
|--> doc.jsp
159
160 CAPITOLUL 7. JAVA SERVER PAGE – JSP
ı̂n Hello.jsp şi plasându-l ı̂n catalogul jsp se obţine acelaşi efect, dar prelucrarea
paginilor / documentelor este diferită. Fişierul html este prelucrat doar de progra-
mul navigator şi poate fi deschis ca fişier, ı̂n timp ce fişierul JSP este prelucrat de
serverul Web cu afişarea prin intermediul navigatorului. Prelucrarea efectuată de
serverul Web constă din transformarea paginii / documentului JSP ı̂ntr-un servlet,
care este compilat şi lansat ı̂n execuţie. Din aceastră cauză prima invocare a paginii
/ documentului JSP durează mai mult decât apelările ulterioare.
Apelarea paginii / documentului JSP se face prin
http://localhost:8080/JSPApp/jsp/Hello.jsp
Există două moduri de a include elemente JSP ı̂ntr-un text html:
http://java.sun.com/JSP/Page
Fişierul poate avea extensia jsp sau jspx şi se numeşte document JSP.
Exemplul 7.1.1 Putem afişa valoarea unei variabile Java (de exemplu data calen-
daristică) prin
1 <html>
2 <body>
3 <p>
4 Data c a l e n d a r i s t i c a 1 :
5 <%= new j a v a . u t i l . Date ( ) %>
7 <p>
8 <% j a v a . u t i l . Date data1=new j a v a . u t i l . Date ( ) ; %>
9 Data c a l e n d a r i s t i c a 2 :
7.1. TEHNOLOGIA JSP 161
12 <p>
13 <% j a v a . u t i l . Date data2=new j a v a . u t i l . Date ( ) ; %>
14 Data c a l e n d a r i s t i c a 3 :
15 <% out . p r i n t ( data2 ) ; %>
16 </body>
17 </html>
Codul Java inglobat ı̂ntr-un text html se numeşte scriptlet. Sintaxa utilizată este
Astfel
Exemplul 7.1.2 Pagina JSP Hello: Clientul transmite numele paginii care ı̂i răspunde
cu mesajul de salut ”Hi nume!”.
1 <html>
2 <head>
3 < t i t l e> JSP H e l l o </ t i t l e>
4 </head>
5 <body bgcolor=”#bbeebb ”>
6 <center>
7 <h1> Pagina de a p e l a r e JSP </h1>
8 <form method=” p o s t ”
9 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 ”>
10 <p> Numele :
7.1. TEHNOLOGIA JSP 163
Compilarea şi arhivarea servlet-ului o vom realiza prin intermediul lui apache-
ant. În acest scop se crează structura:
jsphello
| |---> jsp
| | | hello.jsp
| |---> lib
| |---> src
| |---> web
| | | web.xml
| |---> web-files
| | | index.html
| build.xml
7 <web−app>
8 <welcome−f i l e − l i s t>
9 <welcome− f i l e >i n d e x . html</ welcome− f i l e >
10 <welcome− f i l e >i n d e x . j s p</ welcome− f i l e >
11 </ welcome−f i l e − l i s t>
12 </web−app>
Exemplul 7.1.3 Calculul celui mai mare divizor comun a două numere naturale
cu metoda de calcul este definită ı̂ntr-o declaraţie JSP.
7.1. TEHNOLOGIA JSP 165
1 <html>
2 <body>
3 <H1> CMMDC </H1>
4 <%!
5 l o n g cmmdc( l o n g m, l o n g n ) {
6 long c , r ;
7 do {
8 c=n ;
9 r=m%n ;
10 m=n ;
11 n=r ;
12 } while ( r !=0);
13 return c ;
14 }
15 %>
16 Rezultatul este
17 <%
18 String sm=r e q u e s t . g e t P a r a m e t e r ( ”m” ) ;
19 String sn=r e q u e s t . g e t P a r a m e t e r ( ”n” ) ;
20 l o n g m=Long . parseLong ( sm ) , n=Long . pa rse Lo ng ( sn ) ;
21 out . p r i n t l n (cmmdc(m, n ) ) ;
22 %>
23 </body>
24 </html>
Există două metode jspInit() - utilizată pentru iniţializarea datelor -, şi jspDestroy()
- utilizată pentru eliberarea resurselor -, care dacă sunt declarate de programator
atunci sunt executate la ı̂nceputul şi la sfârşitul ciclului de execuţie a paginii /
documentului JSP.
. . . . . .
</jsp:params>
Exemplul 7.1.4
1 package j s p ;
2 public c l a s s Hel loBe an {
3 private S t r i n g name=” ” ;
4 public S t r i n g getName ( ) {
5 return name ;
6 }
7 public void setName ( S t r i n g name ) {
8 t h i s . name=name ;
9 }
10 }
Mai mult, se poate include formularul ı̂n pagina JSP, bineı̂nţeles ştergându-l din
fişierul html:
1 <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 ” />
2 <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=” ∗ ” />
3 <html>
4 <head>
5 < t i t l e> j s p h e l l o </ t i t l e>
6 </head>
7 <body>
8 <center>
9 <h1> Pagina JSP − a p l i c a ţ i a H e l l o </h1>
10 <form method=” p o s t ”>
11 <p> <h3> I n t r o d u c e t i numele : </h3>
12 <input type=” t e x t ” name=”name” s i z e =20>
7.1. TEHNOLOGIA JSP 169
13 <p>
14 <input type=” submit ”>
15 </form>
16 <p>
17 <%
18 out . p r i n t l n ( ” Hi ”+o b j . getName ()+ ” ! ” ) ;
19 %>
20 </ center>
21 </body>
22 </html>
Exemplul 7.1.5 Pagină JSP pentru calculul celui mai mare divizor comun cu metoda
de calcul definită ı̂ntr-o componentă Java.
Utilizând documentului html din Exemplul 7.1.3 se defineşte componenta Java
1 package cmmdc ;
2 public c l a s s CmmdcBean{
3 private S t r i n g m=” ” ;
4 private S t r i n g n=” ” ;
5 private S t r i n g cmmdc ;
20 public S t r i n g getCmmdc ( ) {
21 long m=Long . parseLong ( getM ( ) ) ;
22 long n=Long . parseLong ( getN ( ) ) ;
23 return (new Long (cmmdc(m, n ) ) ) . t o S t r i n g ( ) ;
24 }
28 }
170 CAPITOLUL 7. JAVA SERVER PAGE – JSP
Instanţiem o componenta Java şi ı̂i fixăm proprietăţile (adică ı̂i transmitem
parametri problemei) după care apelăm metoda ce calculează rezultatul dorit ı̂n
pagina JSP:
1 <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 ” />
2 <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=” ∗ ” />
3 <html>
4 <body>
5 Cel mai mare d i v i z o r comun a l n u m e r e l o r
6 <p>
7 <%=o b j . getM ( ) %> s i <%=o b j . getN ( ) %>
8 e s t e <%=o b j . getCmmdc ( ) %>
9 </body>
10 </html>
1 < !−−
2 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
3 n a v i g a t o r u l u i IE s i a l u i apache−tomcat − 5 . ∗ . ∗ . / 6 . ∗ . ∗ . In l i p s a
4 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 .
5 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 .
7 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
8 o p t i u n e a ”Show f r i e n d l y HTTP e r r o r message ”
10 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 .
11 −−>
20 </body>
21 </html>
apelate prin
1 <html>
2 <body>
3 <form method=p o s t
4 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 ”>
5 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 ?
6 <p>
7 A l g o r i t m i c a s i programare
8 <input type=” r a d i o ” name=” m a t e r i a ” value=”AP” checked>
9 <p>
10 A n a l i z a numerica
11 <input type=” r a d i o ” name=” m a t e r i a ” value=”AN”>
12 <p>
13 Inteligenta artificiala
14 <input type=” r a d i o ” name=” m a t e r i a ” value=”IA”>
15 <p>
16 <input type=submit>
17 </form>
18 </body>
19 </html>
Utilizarea bibliotecilor. În vederea utilizării, cele două fişiere trebuie copiate
ı̂n catalogul apache-tomcat-*.*\lib sau ı̂n catalogul lib al aplicaţiei care uti-
lizează bibliotecile.
172 CAPITOLUL 7. JAVA SERVER PAGE – JSP
În cazul ı̂n care condiţia are valoarea true se prelucrează corpul marcajului,
ı̂n caz contrar, acesta este ignorat.
1 <HTML>
2 <%@ 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 ” %>
3 <BODY>
4 <p>
5 <c : i f t e s t=” $ {empty param . nume} ” var=” testNume ” >
6 <c : out value=”Numele l i p s e s t e ! ” />
7 </ c : i f>
8 <c : i f t e s t=” $ { not testNume } ” >
9 Nume :<c : out value=” $ {param . nume} ” />
10 </ c : i f>
11 <p>
12 <c : i f t e s t=” $ {empty param . prenume } ” var=” testPrenume ” >
13 <c : out value=” Prenumele l i p s e s t e ! ” />
14 </ c : i f>
15 <c : i f t e s t=” $ { not testPrenume } ” >
16 Prenume :<c : out value=” $ {param . prenume } ” />
17 </ c : i f>
18 <p>
19 <c : i f t e s t=” $ {empty param . e m a i l } ” var=” t e s t E m a i l ”>
20 <c : out value=” Adresa E−Mail l i p s e s t e ! ” />
21 </ c : i f>
22 <c : i f t e s t=” $ { not t e s t E m a i l } ” >
174 CAPITOLUL 7. JAVA SERVER PAGE – JSP
• c:choose Marcajul de selecţie poate conţine oricâte marcaje c:when şi cel mult
un marcaj c:otherwise. Fiecare marcaj c:when conţine obligatoriu atributul
test. Dacă ı̂ntr-un marcaj c:when condiţia are valoarea true, atunci se
prelucrează corpul acelui marcaj. În cazul ı̂n care toate marcajele c:when au
fost evaluate cu false atunci se va prelucra marcajul c:otherwise (marcaj
fără atribute).
• c:forEach Ciclu.
Atribute ale marcajului:
Atribut Fel Descriere
items opţional Colecţia care se parcurge.
var opţional Numele variabilei ı̂n care se stochează
valoarea elementului curent.
begin opţional Valoarea iniţială a variabilei var.
end opţional Valoarea finală a variabilei var.
step opţional Valoarea pasului de iterare. Implicit este 1.
varStatus opţional Informaţii despre elementul curent.
Variabila varStatus are câmpurile:
Exemplul 7.2.5 Să se afişeze lista din agenda telefonică creată ı̂n exemplul din
Cap. Servlet.
1 <HTML>
2 <%@ 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 ” %>
3 <%@ 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 ” %>
4 <BODY>
5 <p>
6 <s q l : s e t D a t a S o u r c e
7 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 ”
8 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 ”
9 var=”db” />
10 <s q l : query
11 d a t a S o u r c e=” $ {db} ”
12 var=” r e z u l t ”
13 s q l=” s e l e c t ∗ from t e l e f ” />
14 <c : i f t e s t=” $ { r e z u l t . rowCount g t 0} ” >
15 <table>
16 <tr>
17 <c : f o r E a c h i t e m s=” $ { r e z u l t . columnNames} ” var=” c o l ”>
18 <th>
19 <c : out value=” $ { c o l } ” />
20 </th>
21 </ c : f o r E a c h>
22 </ tr>
23 <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 ” >
24 <tr>
25 <c : f o r E a c h i t e m s=” $ { l i n e } ” var=” elem ” >
26 <td>
27 <c : out value=” $ { elem } ” />
28 </td>
29 </ c : f o r E a c h>
178 CAPITOLUL 7. JAVA SERVER PAGE – JSP
30 </ tr>
31 </ c : f o r E a c h>
32 </ table>
33 </ c : i f>
34 </BODY>
35 </HTML>
Exemplul 7.3.1 Să se realizeze un marcaj dateTag, a cărui efect să fie afişarea
datei calendaristice.
(c) Scrierea ı̂n fluxul de ieşire se face cu un obiect JspWriter, care se obţine
cu pageContext.getOut(). Metoda print a clasei JspWriter poate
genera o excepţie IOException.
1 package j s p ;
2 import j a v a x . s e r v l e t . j s p . ∗ ;
3 import j a v a x . s e r v l e t . j s p . t a g e x t . ∗ ;
4 import j a v a . i o . ∗ ;
5 import j a v a . u t i l . ∗ ;
14 <t a g>
15 <name> dateTag </name>
16 <tag−c l a s s> j s p . DateTag </ tag−c l a s s>
17 <body−c o n t e n t> EMPTY </body−c o n t e n t>
18 <d e s c r i p t i o n> f u r n i z e a z a data c u r e n t a </ d e s c r i p t i o n>
19 </ t a g>
20 </ t a g l i b>
<taglib>
<taglib-uri>
http://java.apache.org/tomcat/mytaglib
</taglib-uri>
<taglib-location>
/WEB-INF/jsp/mylibtag.tld
</taglib-location>
</taglib>
webapps
|--> mytag
| |--> WEB-INF
| | |--> classes
| | | |--> jsp
| | | | |--> DateTag.class
7.3. MARCAJE JSP PERSONALE 181
| | | web.xml
| | |--> jsp
| | | |--> mylibtag.tld
| |--> jsp
| | | dateTag.jsp
1 <html>
2 <head>
3 < t i t l e>
4 Tag p e n t r u data c a l e n d a r i s t i c a c u r e n t a
5 </ t i t l e>
6 </head>
7 <body>
8 <%@ t a g l i b u r i=” h t t p : / / j a v a . apache . o r g / tomcat / m y t a g l i b ”
9 p r e f i x=”mk” %>
10 <p>
11 Data c u r e n t a e s t e :
12 <mk : dateTag />
13 </body>
14 </html>
1. Pentru fiecare atribut clasa ce defineşte acţiunea marcajului trebuie să conţină
o metodă
Exemplul 7.3.2
1 package j s p ;
2 import j a v a x . s e r v l e t . j s p . ∗ ;
3 import j a v a x . s e r v l e t . j s p . t a g e x t . ∗ ;
4 import j a v a . i o . ∗ ;
9 public void s e t Z i u a ( S t r i n g v a l u e ) {
10 z i u a=v a l u e ;
11 }
13 public i n t doStartTag ( ) {
14 try {
15 J s p W r i t e r out=pageContext . getOut ( ) ;
16 out . p r i n t l n ( z i u a ) ;
17 }
18 catch ( IOException e ) {
19 System . out . p r i n t l n ( ” ZiuaTagException ”+e . g e t M e s s a g e ( ) ) ;
20 }
21 return SKIP BODY ;
22 }
23 }
<tag>
<name> ziuaTag </name>
<tag-class> jsp.ZiuaTag </tag-class>
<body-content> EMPTY </body-content>
<description> furnizeaza argumentul ziua curenta </description>
<attribute>
<name> ziua </name>
<required> true </required>
<rtexprvalue> true </rtexprvalue>
</attribute>
</tag>
1 <html>
2 <body>
3 <form method=” g e t ”
4 action=” h t t p : / / l o c a l h o s t : 8 0 8 0 / mytag/ j s p / ziuaTag . j s p ”>
5 <p>A s t a z i , e s t e
6 <s e l e c t name=” z i u a ”>
7 <option value=” l u n i ”> Luni
8 <option value=” m a r t i ”> Marti
9 <option value=” m i e r c u r i ”> M i e r c u r i
10 <option value=” j o i ”> J o i
11 <option value=” v i n e r i ”> V i n e r i
12 <option value=” simb at a ”> Simbata
13 <option value=” duminica ”> Duminica
14 </ s e l e c t>
15 <p><input type=” submit ” value=” A f i s e a z a ”>
16 </form>
17 </body>
18 </html>
1 <html>
2 <head>
3 < t i t l e> Tag cu marcaj </ t i t l e>
4 </head>
5 <body>
6 <%@ t a g l i b u r i=” h t t p : / / j a v a . apache . o r g / tomcat / m y t a g l i b ”
7 p r e f i x=”mk” %>
8 <p>
9 <%
10 String z i=r e q u e s t . g e t P a r a m e t e r ( ” z i u a ” ) ;
11 %>
12 Ziua e s t e :
13 <mk : ziuaTag z i u a=”<%= z i %>” />
14 </body>
15 </html>
Exemplul 7.3.3 Fie marcajul modTag care modifica un text ı̂n caractere mari sau
mici după valoarea atributului trans. Acest marcaj poate include ale elemente.
1 package j s p ;
2 import j a v a x . s e r v l e t . j s p . ∗ ;
3 import j a v a x . s e r v l e t . j s p . t a g e x t . ∗ ;
4 import j a v a . i o . ∗ ;
10 public void s e t T e x t ( S t r i n g v a l u e ) {
11 t e x t=v a l u e ;
12 }
14 public void s e t T r a n s ( S t r i n g v a l u e ) {
15 toUpperCase=(new Boolean ( v a l u e ) ) . b o o l e a n V a l u e ( ) ;
16 }
18 public i n t doStartTag ( ) {
19 try {
20 J s p W r i t e r out=pageContext . getOut ( ) ;
21 i f ( toUpperCase )
22 out . p r i n t l n ( t e x t . toUpperCase ( ) ) ;
23 else
24 out . p r i n t l n ( t e x t . toLowerCase ( ) ) ;
25 }
26 catch ( IOException e ) {
27 System . out . p r i n t l n ( ” ModTagException ”+e . g e t M e s s a g e ( ) ) ;
28 }
29 return EVAL BODY INCLUDE ;
30 }
31 }
<tag>
<name> modTag </name>
<tag-class> jsp.ModTag </tag-class>
<body-content> JSP </body-content>
<description> modifica caracterele </description>
<attribute>
<name> text </name>
<required> true </required>
<rtexprvalue> true </rtexprvalue>
</attribute>
<attribute>
<name> trans </name>
<required> true </required>
<rtexprvalue> true </rtexprvalue>
</attribute>
</tag>
1 <html>
2 <body>
3 <form method=” g e t ”
4 action=” h t t p : / / l o c a l h o s t : 8 0 8 0 / mytag/ j s p / modtextTag . j s p ”>
5 I n t r o d u c e o f r a z ă
6 <input type=” t e x t ” name=” t e x t ” s i z e=” 40 ” >
7 <p>
8 Se t r a n s f o r m ă în l i t e r e
9 <s e l e c t name=” t r a n s ”>
10 <option value=” upperCase ”> mari
11 <option value=” l o w e r C a s e ”> m i c i
12 </ s e l e c t>
13 <p><input type=” submit ” value=” A f i s e a z a ”>
14 </form>
15 </body>
16 </html>
ı̂mpreună cu modtextTag.jsp
1 <html>
2 <body>
3 <%@ t a g l i b u r i=” h t t p : / / j a v a . apache . o r g / tomcat / m y t a g l i b ” p r e f i x=”mk” %>
4 <%
5 String text=r e q u e s t . g e t P a r a m e t e r ( ” t e x t ” ) ;
6 String t r a n s=r e q u e s t . g e t P a r a m e t e r ( ” t r a n s ” ) ;
7 String t ;
8 i f ( t r a n s . e q u a l s ( ” upperCase ” ) )
9 t=” t r u e ” ;
10 else
11 t=” f a l s e ” ;
12 %>
13 <p>
14 <mk : modTag text=”<%= t e x t %>” t r a n s=”<%=t%>”>
15 <mk : dateTag />
16 </mk : modTag>
17 </body>
18 </html>
186 CAPITOLUL 7. JAVA SERVER PAGE – JSP
Capitolul 8
Portlet
187
188 CAPITOLUL 8. PORTLET
• Prin conceptul de mod (mode) se specifică variante distincte prin care portle-
tul reacţionează. Sunt definite modurile VIEW, EDIT, HELP. Acţiunile core-
spunzătoare sunt definite ı̂n metodele doView, doEdit, doHelp.
8.1. APACHE-PLUTO 189
8.1 Apache-pluto
Pentru dezvoltarea unui portlet vom folosi produsul Apache-pluto care generează
un portal ı̂n care se pot instala / dezinstala uşor portlete.
Instalarea produsului. Dacă se descarcă varianta ı̂ncorporată ı̂n serverul Web
apache-tomcat, denumită pluto-bundle, atunci instalarea la dezarhivarea fişierului
descărcat.
Utilizarea produsului. Dintr-un navigator, portalul se apelează prin
http://host:8080/pluto/portal
Accesul se face cu User name = password = pluto.
Instalarea unui portlet se face ı̂n 2 paşi:
1. Desfăşurarea portlet-ului: Fişierul arhivat al portletului, având estensia war,
se depune ı̂n catalogul PlutoDomain. Apelând managerul lui apache-tomcat
din componenta Pluto admin se obţine instalarea portletului.
Alternativ, desfăşurarea portlet-lui se va obţine cu apache-ant cu utilizarea
unui fişier build.xml dedicat.
2. Publicarea portlet-ului se face prin componenta Pluto admin.
12 < !−−
13 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
14 p l u t o −ant−t a s k s j a r
15 −−>
16 <path i d=” p r o j e c t . c l a s s p a t h ”>
17 < f i l e s e t d i r=” l i b ”>
18 <i n c l u d e name=” ∗ . j a r ” />
19 </ f i l e s e t>
20 </ path>
22 <t a s k d e f
23 name=” a s s e m b l e ”
24 c l a s s n a m e=” o r g . apache . p l u t o . ant . AssembleTask ”
25 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 ”
26 />
55 d e s t d i r=” ${ c l a s s b u i l d . d i r } ”
56 s r c d i r=” ${ j a v a . s r c . d i r } ” />
57 </ t a r g e t>
4 #module name
5 app . name=NumePortlet
7 #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
8 s r c . d i r = s r c / main
9 j a v a . s r c . d i r = ${ s r c . d i r }/ j a v a
11 #D i r e c t o r y t h a t h o l d s documentation
12 doc . d i r = d o c s
14 #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
15 build . dir = build
16 w e b b u i l d . d i r = ${ b u i l d . d i r }/ webapp
17 c l a s s b u i l d . d i r = ${ w e b b u i l d . d i r }/WEB−INF/ c l a s s e s
19 #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 files
20 c o n f . d i r = ${ s r c . d i r }/ r e s o u r c e
22 #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
23 lib . dir = lib
25 #D i r e c t o r y t h a t h o l d s webapp f i l e s
26 web . d i r = ${ s r c . d i r }/ webapp
28 #WEB−INF d i r e c t o r y
29 web−i n f . d i r = ${web . d i r }/WEB−INF
32 #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
33 d i s t . d i r = ${ b u i l d . d i r }/ d i s t
NumePortlet
|--> lib
| | castor-1.1.1.jar
| | commons-logging-*.jar
| | pluto-ant-tasks-*.jar
| | pluto-descriptor-api-*-dev.jar
| | pluto-descriptor-impl-*-dev.jar
| | pluto-util-*-dev.jar
| | portlet-api-*.jar
| | servlet-api-*.jar
|--> src
8.4. ELEMENTE DE PROGRAMARE 193
| |--> main
| | |--> java
| | | |--> pachetul portletului
| | |--> resource
| | | | NumePortlet.xml
| | |--> webapp
| | | |--> jsp
| | | | | fisierele jsp ale portletului
| | | |--> WEB-INF
| | | | | portlet.xml
| | | | | web.xml
Fişierele castor.1.1.1.jar, pluto-descriptor-api-*.jar, pluto-descriptor-impl-*.jar, portlet-
api.jar se copiază din catalogul PLUTO HOME\shared\lib, iar fişierul servlet-api-
*.jar se ia din PLUTO HOME\common\lib.
Fişierul web.xml de mai sus este
10 </web−app>
Conţinutul final al acestui fişier rezultă ı̂n urma obiectivului ant assemple, ı̂n
care se preiau date din fişierul de configurare al portletului portlet.xml. Editarea
fişierului portlet.xml este sarcina programatorului.
Fişierul NumePortlet.xml este utilizat la desfăşurarea aplicaţie, fiind copiat ı̂n
catalogul conf\Catalina\localhost al lui apache-tomcat sau Apache-pluto. Acest
fişier are conţinutul:
1 <Context path=” NumePortlet ” docBase=” . . \ PlutoDomain \ NumePortlet . war ”
2 c r o s s C o n t e x t=” t r u e ” />
1 package h e l l o ;
2 import j a v a . i o . ∗ ;
3 import j a v a x . p o r t l e t . ∗ ;
5 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 {
6 protected void doView ( RenderRequest r e q u e s t , RenderResponse r e s p o n s e )
7 throws P o r t l e t E x c e p t i o n , IOException {
8 r e s p o n s e . setContentType ( ” t e x t / html ” ) ;
9 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 ! ” ) ;
8.4. ELEMENTE DE PROGRAMARE 195
10 }
12 // A l t a v a r i a n t a de programare
13 /∗
14 p u b l i c v o i d doView ( RenderRequest req , RenderResponse r e s )
15 t h r o w s P o r t l e t E x c e p t i o n , IOException {
16 r e s . s e t C o n t e n t T y p e (” t e x t / html ” ) ;
17 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 ( ) ;
18 o u t . p r i n t l n (”<h2 >”);
19 o u t . p r i n t l n (” H e l l o World ! ” ) ;
20 o u t . p r i n t l n (”</h2 >”);
21 }
22 ∗/
23 }
8 < p o r t l e t>
9 <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>
10 <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>
11 <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>
12 <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>
13 <s u p p o r t s>
14 <mime−t y p e>t e x t / html</mime−t y p e>
15 <p o r t l e t −mode>VIEW</ p o r t l e t −mode>
16 </ s u p p o r t s>
17 <p o r t l e t −i n f o>
18 < t i t l e>H e l l o World P o r t l e t</ t i t l e>
19 </ p o r t l e t −i n f o>
20 </ p o r t l e t>
21 </ p o r t l e t −app>
1 package h e l l o p l u t o ;
2 import j a v a . i o . ∗ ;
3 import j a v a x . p o r t l e t . ∗ ;
5 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 {
6 public void doView ( RenderRequest req , RenderResponse r e s )
7 throws P o r t l e t E x c e p t i o n , IOException {
8 r e s . setContentType ( ” t e x t / html ” ) ;
9 W r i t e r out=r e s . g e t W r i t e r ( ) ;
10 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 >” ) ;
11 }
8 <p o r t l e t >
9 <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 >
10 <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>
11 <d i s p l a y −name>H e l l o Pluto </ d i s p l a y −name>
12 <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 >
13 <s u p p o r t s >
14 <mime−type>t e x t / html</mime−type>
15 <p o r t l e t −mode>VIEW</ p o r t l e t −mode>
16 <p o r t l e t −mode>EDIT</ p o r t l e t −mode>
17 <p o r t l e t −mode>HELP</ p o r t l e t −mode>
18 </s u p p o r t s >
19 <p o r t l e t −i n f o >
20 < 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 >
21 </ p o r t l e t −i n f o >
22 </ p o r t l e t >
23 </ p o r t l e t −app>
1 package h e l l o n a m e ;
3 import j a v a . i o . ∗ ;
4 import j a v a x . p o r t l e t . ∗ ;
5 import j a v a . u t i l . Enumeration ;
7 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 {
16 prd . i n c l u d e ( req , r e s ) ;
17 }
18 else {
19 // V a r i a n t a cu a f i s a r e p r i n View
20 /∗
21 Writer o u t=r e s . g e t W r i t e r ( ) ;
22 o u t . w r i t e (” H e l l o ”+ nume ) ;
23 PortletURL renderURL=r e s . createRenderURL ( ) ;
24 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) ;
25 renderURL . setWindowState ( WindowState .NORMAL) ;
26 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 >”);
27 ∗/
28 // 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
29 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 ” ) ;
30 prd . i n c l u d e ( req , r e s ) ;
31 }
32 }
şi respectiv
1 <%@ 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 ” %>
2 < p o r t l e t : d e f i n e O b j e c t s />
3 <p>
4 <%
5 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”)+” ! ” ;
6 out . p r i n t l n ( r e s u l t ) ;
7 %>
8 <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 ” />”>
9 Reluare
10 </ a> .
198 CAPITOLUL 8. PORTLET
Exemplul 8.4.4 Cel mai mare divizor comun a două numere naturale ı̂ntr-un port-
let.
3 import j a v a . i o . ∗ ;
4 import j a v a x . p o r t l e t . ∗ ;
5 import j a v a . u t i l . Enumeration ;
37 }
15 <tr>
16 <td>
17 <input type=” submit ” name=” submitButton ” value=” C a l c u l e a z a ” />
18 </td>
19 </ tr>
20 </ table>
21 </form>
23 </ div>
şi respectiv
1 <%@ 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 ” %>
2 < p o r t l e t : d e f i n e O b j e c t s />
4 <P>
5 <%
6 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 ”)+” ! ” ;
7 out . p r i n t l n ( r e s u l t ) ;
8 %>
10 <P>
11 <a href=”< p o r t l e t : renderURL p o r t l e t M o d e=” view ” windowState=” normal ” />”>
12 Reluare
13 </a>
Variantă ı̂n care calculul este programat ı̂ntr-o componentă Java (bean)
şi care este apelat ı̂n pagina jsp de afişare a rezultatului.
1 package cmmdc ;
3 import j a v a . i o . ∗ ;
4 import j a v a x . p o r t l e t . ∗ ;
5 import j a v a . u t i l . Enumeration ;
3 private S t r i n g m=” ” ;
4 private S t r i n g n=” ” ;
Pagina outputCmmdc.jsp
1 <%@ 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 ” %>
2 <j s p : useBean id=”myCmmdcBean” c l a s s=”cmmdc . CmmdcBean” scope=” s e s s i o n ” />
3 <j s p : s e t P r o p e r t y name=”myCmmdcBean” p r o p e r t y=” ∗ ” />
5 < p o r t l e t : d e f i n e O b j e c t s />
7 <P>
8 <%
9 String r e s u l t=”Cmmdc ”+myCmmdcBean . cmmdc ( ) ;
10 out . p r i n t l n ( r e s u l t ) ;
11 %>
12 <P>
13 <a href=”< p o r t l e t : renderURL p o r t l e t M o d e=” view ” windowState=” normal ” />”>
14 Reluare
15 </a>
8.4. ELEMENTE DE PROGRAMARE 201
Variantă ı̂n care care calculul este programat ı̂ntr-un servlet. Servletul
utilizat este cel prezentat ı̂n capitolul Servlet, (6.3.2), dar inclus ı̂n pachetul portlet-
ului. Fişierul inputCmmdc.jsp are ı̂n plus linia
<input type="hidden" name="tip" value="text/html"/>
apare
prd=getPortletContext().getRequestDispatcher("/cmmdc");
adică ı̂n locul invocării paginii JSP, dispecerul apelează servletul. În servlet este
esenţială furnizarea rezultatului ı̂n format html. Pagina html generată se ı̂ncarcă ı̂n
fereastra portlet-ului.
Fişierul web.xml, ı̂naintea completării prin ant, este
1 <?xml version=” 1 . 0 ” e n c o d i n g=”UTF−8” ?>
9 < s e r v l e t>
10 <s e r v l e t −name>CmmdcServlet</ s e r v l e t −name>
11 <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>
12 </ s e r v l e t>
14 <s e r v l e t −mapping>
15 <s e r v l e t −name>CmmdcServlet</ s e r v l e t −name>
16 <u r l −p a t t e r n>/cmmdc</ u r l −p a t t e r n>
17 </ s e r v l e t −mapping>
18 </web−app>
Interfaţa PortletPreferences
Atribute, adică perechi de tip String (nume,valoare) definite ı̂n fişierul portlet.xml
prin
<portlet-preferences>
<preference>
<name>nume_atribut</name>
<value>valoare_atribut</value>
<read-only>true|false</read-only>
</preference>
. . .
</portlet-preferences>
202 CAPITOLUL 8. PORTLET
Metode
• Enumeration<String> getNames()
Suport pentru acces la numele atributelor care au valoare.
• Map<String,String[]> getMap()
Suport pentru acces la atribute.
Exemplul 8.4.5 Portlet ı̂n care se preiau şi se afişează valori ale atributelor.
3 import j a v a . i o . ∗ ;
4 import j a v a x . p o r t l e t . ∗ ;
6 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 {
<name>ATTR2</name>
<!--
<value>Analiza numerica</value>
-->
<read-only>true</read-only>
</preference>
</portlet-preferences>
În cele ce urmează ne vom referi doar la produse portal care sunt containere de
portlete.
Dezvoltarea unui portal al unei organizaţii 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.
8.5.1 uPortal
uPortal este un portal cadru, dezvoltat de JA-SIG (Java Architecture Special
Interest Group) şi a fost utilizat de mai multe universităţi ca suport ı̂n construcţia
portalului specific.
Instalarea produsului. Distribuţia produsului se face ı̂n două variante
• uPortal-*.*.* - uPortal-only;
ant start
ant stop
http://host:8080/uPortal
cu fişierele *.java, *.jsp şi portlet.xml corespunzătoare portletului iar web.xml este
generic
1 <?xml version=” 1 . 0 ” e n c o d i n g=”ISO−8859−1” ?>
2 < !DOCTYPE web−app PUBLIC
3 ”−//Sun Microsystems , I n c . / /DTD Web A p p l i c a t i o n 2 . 3 / /EN”
4 ” h t t p : // j a v a . sun . com/ dtd /web−a p p 2 3 . dtd ”>
5 <web−app>
6 </web−app>
1
La prima executare a unei operaţii asupra portalului, calculatorul trebuie să fie conectat la
internet, deoarece mai multe resurse sunt descărcate prin apache-maven. Aceste resurse se depun
ı̂n c:\Documents and Settings\adminName\.m2\repository.
8.5. PRODUSE PORTAL 205
47 </ p r o j e c t>
(a) Din meniul Channel Type se selectează opţiunea Portlet. Clic Next.
(b) În meniul General Settings se fixează toţi parametrii indicaţi. Clic Next.
(c) În meniul Portlet Descriptor se fixează
• Contextul portlet-ului, adică catalogul din webapps care conţine portlet-
ul. În mod obligatoriu primul caracter este / (slash);
• Numele portlet-ului aşa cum este definit ı̂n fişierul portlet.xml.
Clic Next.
(d) În meniul Portlet Preferences, clic Next.
(e) În meniul Channel Controls, clic Next.
(f) În meniul Categories se fixează categoria canalului şi cel putin un mem-
bru.
Select Marked → Next.
(g) În meniul Groups se fixează grupul şi cel putin un membru.
Select Marked → Next
Grupul desemnează clienţii care pot publica portlet-ul.
(h) În meniul Review, clic Finish.
3. Fiecare client care poate utiliza portlet-ul, ı̂l publică prin componenta Cus-
tomize.
Pentru administrator: AdminTools → Customize urmat de
(a) Clic pe un buton Add Channel corespunzător locului unde vrem să fie
poziţionat portlet-ul.
(b) În User Preferences,
i. se alege categoria portlet-ului, clic go;
ii. se alege numele portlet-ului, clic Add Channel.
(c) Clic pe numele canalului corespunzător portlet-ului. Canalul este afişat
ı̂n meniul Welcome.
(d) Clic pe numele canalului din meniul Welcome lansează portlet-ul.
8.5.2 Jetspeed-2
Jetspeed-2 este un portal cadru dezvoltat de apache.
Instalarea se execută rulând distribuţia jetspeed-2.*.*-installer.jar.
Versiunea instalată a platformei jetspeed este construită peste o distribuţie apache-tomcat-5.5.*.
Astfel, lansarea se face apelând bin\startup.bat.
Portalul se accesează, dintr-un navigator, prin
http://localhost:8080/jetspeed
Desfăşurarea unui portlet constă ı̂n copierea arhivei war corespunzătoare, re-
alizat ı̂n 8.5.1, ı̂n catalogul
2. Clic pe un buton Add Portlet, stabilind astfel şi poziţia ı̂n care va fi afişată
fereastra portlet-ului.
<security>
<all-permissions/>
</security>
209
210 CAPITOLUL 9. JAVA WEB START
8 private void i n i t C o m p o n e n t s ( ) {
9 // cod g e n e r a t de Netbeans
10 }
1. Arhivarea aplicaţiei
jar cfv cmmdc.jar *.class
app
|--- cmmdc.jar
|--- launch.jnlp
WEB-INF
|--- lib
| |--- jnlp-servlet.jar
|--- web.xml
Dacă interfaţa grafică a aplicaţiei utilizează imagini grafice acestea trebuie arhi-
vate ı̂mpreună cu aplicaţia, de exemplu ı̂ntr-un catalog images.
Încărcarea şi afişarea unei imagini programându-se prin
ClassLoader cl=this.getClass().getClassLoader();
URL file=cl.getResource("images/pic1.jpg");
Image img=Toolkit.getDefaultToolkit().getImage(file);
graphics.drawImage(img,x,y,this);
Pentru utilizarea unor pachete arhivate jar, fişierele respective se includ ı̂ntr-un
catalog app\lib şi ı̂n fişierul jnlp-servlet ı̂n elementul jnlp se introduc declaraţiile
9.1. JAVA WEB START 213
<resources>
<jar href="lib/NumeFisier.jar"/>
. . .
</resources>
Dacă aplicaţia foloseşte resurse suplimentare, date prin fişiere jar ı̂n catalogul
lib, atunci fiecare arhivă jar trebuie certificată.
Certificarea resurselor se realizează rulând succesiv
<security>
<all-permissions />
</security>
214 CAPITOLUL 9. JAVA WEB START
Capitolul 10
Java Management Extensions (JMX) face posibilă ca un obiect Java să permită
gestionarea metodelor şi a anumitor câmpuri de către alte obiecte. Obiectele Java
care ı̂şi expun astfel resursele se numesc MBean - uri şi formează temelia cadrului
de lucru JMX.
Există mai multe tipuri de MBean-uri:
• Standard MBean;
• Dynamic MBean;
• Open MBean;
• Model MBean;
• MXBean;
Un obiect care gestionează resursele unui MBean se numeşte agent sau server MBean.
Agentul dispune de mijloace care interacţionează cu un MBean, permiţându-i:
• accesul la valorile unui câmp şi la modificarea lor;
• invocarea metodelor.
În general, un agent poate fi definit ca
• autorul unei acţiuni;
• factor care provoacă acţiuni;
• reprezentant al unei instituţii ı̂nsărcinat cu ı̂ndeplinirea unor acţiuni.
Terminologia server MBean se justifică prin faptul că poate fi invocat de un
program client. În această ipostază, serverul MBean are rolul unui container de
MBean-uri şi de gestionare şi execuţie a apelurilor clienţilor.
Structura unei aplicaţii JMX conţine două nivele:
215
216 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS
• componentele MBean;
1. interfaţa are numele clasei care o implementează având ı̂n plus sufixul MBean;
În continuare câmpurile şi metodele destinate expunerii se vor denumi atribute,
respectiv operaţii. Fiecărui atribut xxx i se ataşează cel puţin una din metodele
şi / sau
Un atribut se precizează doar prin aceste metode, fără definirea / declararea câmpului
corespunzător. Câmpul se defineşte ı̂n clasa ce implementează interfaţa MBean-ului.
Astfel, un MBean este caracterizat de
• atribute
care pot fi consultate (citite), modificate (scrise) sau cu ambele opţiuni.
• operaţii
• notificări
cu evidenţa modificărilor suferite de atribute.
Exemplul 10.1.1
Construim un MBean cu
10.1. STANDARD MBEAN 217
• atributele
– label
ce poate fi numai citit;
– cursEuro
care poate fi consultat şi modificat;
• operaţiile
3 public i n t e r f a c e IntroMBean {
4 // O p e r a t i i
5 public S t r i n g s a y H e l l o ( ) ;
6 public long cmmdc( long m, long n ) ;
8 // A t r i b u t e
9 // read−o n l y
10 public S t r i n g g e t L a b e l ( ) ;
11 // read−w r i t e
12 public double getCursEuro ( ) ;
13 public void s e t C u r s E u r o ( double c u r s E u r o ) ;
14 }
6 // A t r i b u t e
7 private f i n a l S t r i n g l a b e l = ” Fac . Matematica s i I n f o r m a t i c a ” ;
8 private double c u r s E u r o = 3 . 5 0 ;
10 public S t r i n g g e t L a b e l ( ) {
11 return l a b e l ;
12 }
22 // O p e r a t i i
23 public S t r i n g s a y H e l l o ( ) {
24 S t r i n g message=” H e l l o World ! ” ;
25 System . out . p r i n t l n ( message ) ;
26 return message ;
27 }
unde
• domeniu
este un nume simbolic (String). Dacă domeniul este stringul vid atunci se
consideră valoarea implicită DefaultDomain.
• atribute uzuale:
– type=numele MBean-ului
– index=număr de identificare a MBean-ului
Clasa ObjectName
Constructori
• ObjectName(String nume)
Parametrul nume are structura descrisă mai sus.
10.1. STANDARD MBEAN 219
Metode
ObjectInstance
Un obiect de tip ObjectInstance este folosit pentru reprezentarea ansamblu-
lui alcătuit de un obiect ObjectName asociat unui MBean şi numele clasei core-
spunzătoare.
Interfaţa MBeanServer
Metode
• String getDefaultDomain()
Exemplul 10.1.2 Se crează două componente MBean de tip Intro care vor fi in-
spectate prin intermediul utilitarului jconsole1 - distribuţia Sun.
Utilitarul jconsole permite apelarea operaţiilor, modificarea atributelor şi sem-
nalează notificările.
1 package b a s i c ;
2 import j a v a . l a n g . management . ∗ ;
3 import j a v a x . management . ∗ ;
5 public c l a s s Main{
6 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
7 S t r i n g domeniu=” ” ;
8 i f ( a r g s . l e n g t h >0) domeniu=a r g s [ 0 ] ;
9 try {
10 // S e r v e r u l p l a t f o r m e i
11 MBeanServer mbs = ManagementFactory . getPlatformMBeanServer ( ) ;
12 // MBeanServer mbs = MBeanServerFactory . createMBeanServer ( ) ;
14 // V a r i a n t a 1
15 // C o n s t r u i r e a ObjectName c o r e s p u n z a t o r MBean−u l u i
16 ObjectName mbeanObjectName =
17 new ObjectName ( domeniu+” : t y p e=I n t r o , i n d e x=1” ) ;
19 // Crearea MBean−u l u i
20 I n t r o mbean = new I n t r o ( ) ;
22 // I n r e g i s t r a r e a MBean−u l u i
23 mbs . r e g i s t e r M B e a n ( mbean , mbeanObjectName ) ;
25 // V a r i a n t a 2
26 mbeanObjectName=new ObjectName ( domeniu+” : t y p e=I n t r o , i n d e x=2” ) ;
27 mbs . createMBean ( ” b a s i c . I n t r o ” , mbeanObjectName ) ;
29 // A s t e p t a r e n e d e f i n i t a
30 System . out . p r i n t l n ( ” Waiting f o r e v e r . . . ” ) ;
31 while ( true ) ;
32 }
33 catch ( E x c e p t i o n e ) {
34 System . e r r . p r i n t l n ( ” E x c e p t i o n : ”+e . g e t M e s s a g e ( ) ) ;
1
În acest caz, este nevoie ca variabilele de tip clasă acoperitoare Double, Long să fie ı̂nlocuite
prin tipuri predefinite.
10.1. STANDARD MBEAN 221
35 }
36 }
37 }
4. În panoul Tree găsim domeniul dat. Prin clic pe domeniu apar MBean-urile
de indice 1 şi 2.
5. Prin clic pe unul din aceste MBean-uri, ı̂n panoul central avem acces la atributele
şi la operaţiile lor.
10.1.3 Notificări
Pentru implementarea reţinerii de către un agent MBean a notificărilor, clasa
ce implementează interfaţa MBean-ului trebuie să extindă clasa Notification-
BroadcasterSupport.
Modificările unui atribut se reţin ı̂ntr-un obiect de tip Notification şi este
transmis prin metoda
sendNotification(Notification notification)
a clasei NotificationBroadcasterSupport.
Suplimentar se defineşte metoda
• o descriere a modificării.
222 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS
• NotificationBroadcasterSupport
Constructori
– NotificationBroadcasterSupport()
Metode
• Notification
Constructori
Metode
Câmpuri
8 // A t r i b u t e
9 private f i n a l S t r i n g l a b e l = ” Fac . Matematica s i I n f o r m a t i c a ” ;
10 private double c u r s E u r o = 3 . 5 0 ;
12 public S t r i n g g e t L a b e l ( ) { . . . }
32 public M B e a n N o t i f i c a t i o n I n f o [ ] g e t N o t i f i c a t i o n I n f o ( ) {
33 S t r i n g [ ] t y p e s = new S t r i n g [ ] {
34 A t t r i b u t e C h a n g e N o t i f i c a t i o n .ATTRIBUTE CHANGE
35 };
36 S t r i n g name = A t t r i b u t e C h a n g e N o t i f i c a t i o n . c l a s s . getName ( ) ;
37 S t r i n g d e s c r i p t i o n = ”An a t t r i b u t e o f t h i s MBean has changed ” ;
38 MBeanNotificationInfo info =
39 new M B e a n N o t i f i c a t i o n I n f o ( t y p e s , name , d e s c r i p t i o n ) ;
40 return new M B e a n N o t i f i c a t i o n I n f o [ ] { i n f o } ;
41 }
43 // O p e r a t i i
44 public S t r i n g s a y H e l l o ( ) { . . . }
Exemplul 10.1.4
1 package a g e n t ;
2 import j a v a . i o . IOException ;
3 import j a v a x . management . ∗ ;
4 import j a v a x . management . remote . ∗ ;
5 import j a v a . u t i l . Sca nne r ;
7 public c l a s s Agent {
8 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
9 try {
10 // Crearea A g e n t u l u i − MBeanServer
11 MBeanServer mbs = MBeanServerFactory . c r e a t e M B e a n S e r v e r ( ) ;
16 S t r i n g sObjectName=domain+” : t y p e=”+className ;
17 ObjectName mbeanObjectName = new ObjectName ( sObjectName ) ;
18 mbs . createMBean ( className , mbeanObjectName ) ;
20 // U t i l i z a r e a MBean−u l u i
21 // A p e l a r e a o p e r a t i i l o r
22 S t r i n g o p e r a t i a=” s a y H e l l o ” ;
23 mbs . i n v o k e ( mbeanObjectName , o p e r a t i a , null , n u l l ) ;
25 o p e r a t i a=”cmmdc” ;
26 System . out . p r i n t l n ( ”Cmmdc a l n u m e r e l o r : ” ) ;
27 Sc anner s c a n n e r=new Sc anne r ( System . i n ) ;
28 System . out . p r i n t l n ( ” Primul numar : ” ) ;
29 long m=s c a n n e r . nextLong ( ) ;
30 System . out . p r i n t l n ( ” Al d o i l e a numar : ” ) ;
31 long n=s c a n n e r . nextLong ( ) ;
32 O b j e c t [ ] param={m, n } ;
33 S t r i n g [ ] s i g n ={” l o n g ” , ” l o n g ” } ;
34 Long r =(Long ) mbs . i n v o k e ( mbeanObjectName , o p e r a t i a , param , s i g n ) ;
35 System . out . p r i n t l n ( ”cmmdc=”+r . t o S t r i n g ( ) ) ;
37 // U t i l i z a r e a A t r i b u t e l o r
38 S t r i n g l a b e l =( S t r i n g ) mbs . g e t A t t r i b u t e ( mbeanObjectName , ” L a b e l ” ) ;
39 System . out . p r i n t l n ( ” V a l o a r e a a t r i b u t u l u i l a b e l : ”+l a b e l ) ;
41 System . out . p r i n t l n ( ” I n t r o d u c e t i c u r s u l e u r o ” ) ;
42 double c u r s E u r o=s c a n n e r . nextDouble ( ) ;
43 A t t r i b u t e c u r s=new A t t r i b u t e ( ” CursEuro ” , c u r s E u r o ) ;
44 mbs . s e t A t t r i b u t e ( mbeanObjectName , c u r s ) ;
45 Double e u r o =(Double ) mbs . g e t A t t r i b u t e ( mbeanObjectName , ” CursEuro ” ) ;
46 System . out . p r i n t l n ( ” V a l o a r e a a t r i b u t u l u i c u r s E u r o : ”+e u r o ) ;
47 }
48 catch ( E x c e p t i o n e ) {
49 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
50 }
51 }
52 }
Exemplul 10.1.5
1 package s e r v e r ;
2 import j a v a . i o . IOException ;
3 import j a v a x . management . ∗ ;
4 import j a v a x . management . remote . ∗ ;
6 public c l a s s MBServer {
7 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
8 S t r i n g h o s t=” l o c a l h o s t ” ;
9 S t r i n g p o r t=” 1099 ” ;
10 i f ( a r g s . l e n g t h ==0){
11 System . out . p r i n t l n ( ”The S e r v i c e name i s r e q u i r e d ” ) ;
12 System . e x i t ( 0 ) ;
13 }
14 i f ( a r g s . l e n g t h >=2)
15 h o s t=a r g s [ 1 ] ;
16 i f ( a r g s . l e n g t h >=3)
17 p o r t=a r g s [ 2 ] ;
18 try {
19 // Crearea MBeanServer
20 MBeanServer mbs = MBeanServerFactory . c r e a t e M B e a n S e r v e r ( ) ;
31 // P o r n i r e a s e r v e r −c o n e c t o r u l u i RMI
32 cs . st art ( ) ;
33 System . out . p r i n t l n ( ” P r e s s Enter t o f i n i s h ! ” ) ;
34 System . i n . r e a d ( ) ;
35 cs . stop ( ) ;
36 }
37 catch ( E x c e p t i o n e ) {
38 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
39 e . printStackTrace ( ) ;
40 }
41 }
42 }
Primul argument care trebuie furnizat programului anterior (args[0] ) este numele
serverului.
Clientul, la rândul lui, este nevoit să creeze un conector RMI către server (agent),
prin intermediul căruia obţine un obiect ce implementează interfaţa MBeanServerConnection.
Prin acest obiect, clientul va putea crea MBean-uri - ı̂n agent - şi le va putea utiliza
resursele.
Şablonul de programare pentru crearea obiectului MBeanServerConnection poate
fi
JMXServiceURL url =
new JMXServiceURL("service:jmx:rmi:///jndi/rmi://host:port/numeServer");
JMXConnector jmxc = JMXConnectorFactory.connect(url,null);
// Obtinerea obiectului de tip MBeanServerConnection
MBeanServerConnection cs = jmxc.getMBeanServerConnection();
mbeanClass proxy =
(mbeanClass)MBeanServerInvocationHandler.newProxyInstance(
mbeanServerConnection,mbeanObjectName,mbeanClass.class,true);
Exemplul 10.1.6 Client ce utilizează un MBean Intro, definit ı̂n Exemplul 10.1.1
1 package c l i e n t ;
2 import j a v a . i o . IOException ;
3 import j a v a . u t i l . ∗ ;
4 import j a v a x . management . ∗ ;
5 import j a v a x . management . remote . ∗ ;
228 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS
7 public c l a s s C l i e n t {
8 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
9 S t r i n g h o s t=” l o c a l h o s t ” ;
10 S t r i n g p o r t=” 1099 ” ;
11 i f ( a r g s . l e n g t h ==0){
12 System . out . p r i n t l n ( ”The S e r v i c e name i s r e q u i r e d ” ) ;
13 System . e x i t ( 0 ) ;
14 }
15 i f ( a r g s . l e n g t h >=2) h o s t=a r g s [ 1 ] ;
16 i f ( a r g s . l e n g t h >=3) p o r t=a r g s [ 2 ] ;
17 Sca nner s c a n n e r=new S c a n n e r ( System . i n ) ;
18 try {
19 // Crearea unui c o n e c t o r RMI s i a o b i e c t u l u i de t i p M B e a n S e r v e r c s e c t i o n
20 S t r i n g s u r l=” s e r v i c e : jmx : rmi : / / / j n d i / rmi : / / ”+
21 h o s t+” : ”+p o r t+” / ”+a r g s [ 0 ] ;
22 // S t r i n g s u r l =” s e r v i c e : jmx : i i o p : / / / j n d i / i i o p ://”+
23 // h o s t +”:”+ p o r t +”/”+ a r g s [ 0 ] ;
24 JMXServiceURL u r l = new JMXServiceURL ( s u r l ) ;
25 JMXConnector jmxc = JMXConnectorFactory . c o n n e c t ( u r l , n u l l ) ;
26 MBeanServerConnection c s = jmxc . getMBeanServerConnection ( ) ;
28 // Domeniile a g e n t u l u i s u n t
29 System . out . p r i n t l n ( ” Domains : ” ) ;
30 S t r i n g domains [ ] = c s . getDomains ( ) ;
31 f o r ( i n t i = 0 ; i < domains . l e n g t h ; i ++) {
32 System . out . p r i n t l n ( ” \ tDomain [ ” + i + ” ] = ” + domains [ i ] ) ;
33 }
35 // i a r domeniul i m p l i c i t
36 S t r i n g domain = c s . g e t D e f a u l t D o m a i n ( ) ;
37 System . out . p r i n t l n ( ” DefaultDomain : ” +domain ) ;
38 // Crearea unui MBean I n t r o
39 S t r i n g className=” b a s i c . I n t r o ” ;
40 S t r i n g sObjectName=domain+” : t y p e=”+className ;
41 ObjectName mbeanObjectName = new ObjectName ( sObjectName ) ;
42 c s . createMBean ( className , mbeanObjectName , null , n u l l ) ;
44 double c u r s E u r o ;
45 long m, n ;
47 // U t i l i z a r e a MBean−u l u i
48 // V a r i a n t a 1 de i n v o c a r e p r i n p r o x y
49 System . out . p r i n t l n ( ” V a r i a n t a de i n v o c a r e p r i n p r o x i ” ) ;
50 IntroMBean proxy=
51 ( IntroMBean ) M B e a n S e r v e r I n v o c a t i o n H a n d l e r . n e w P r o x y I n s t a n c e (
52 cs ,
53 mbeanObjectName ,
54 c l i e n t . IntroMBean . c l a s s ,
55 true ) ;
57 // U t i l i z a r e a o p e r a t i i l o r
58 // o p e r a t i a ” s a y H e l l o ”
59 proxy . s a y H e l l o ( ) ;
61 // o p e r a t i a cmmdc
62 System . out . p r i n t l n ( ”Cmmdc a l n u m e r e l o r : ” ) ;
63 System . out . p r i n t l n ( ” Primul numar : ” ) ;
64 m=s c a n n e r . nextLong ( ) ;
10.1. STANDARD MBEAN 229
69 // U t i l i z a r e a a t r i b u t e l o r
70 System . out . p r i n t l n ( ”Numele : ”+proxy . g e t L a b e l ( ) ) ;
71 System . out . p r i n t l n ( ” I n t r o d u c e t i c u r s u l e u r o ” ) ;
72 c u r s E u r o=s c a n n e r . nextDouble ( ) ;
73 proxy . s e t C u r s E u r o ( c u r s E u r o ) ;
74 System . out . p r i n t l n ( ” Euro : ”+proxy . getCursEuro ( ) ) ;
76 // V a r i a n t a 2 de i n v o c a r e p r i n c o n e x i u n e
77 System . out . p r i n t l n ( ” V a r i a n t a de i n v o c a r e p r i n c o n e x i u n e ” ) ;
78 // A p e l a r e a o p e r a t i i l o r
79 S t r i n g o p e r a t i a=” s a y H e l l o ” ;
80 c s . i n v o k e ( mbeanObjectName , o p e r a t i a , null , n u l l ) ;
81 o p e r a t i a=”cmmdc” ;
82 System . out . p r i n t l n ( ”Cmmdc a l n u m e r e l o r : ” ) ;
83 System . out . p r i n t l n ( ” Primul numar : ” ) ;
84 m=s c a n n e r . nextLong ( ) ;
85 System . out . p r i n t l n ( ” Al d o i l e a numar : ” ) ;
86 n=s c a n n e r . nextLong ( ) ;
87 O b j e c t [ ] param={m, n } ;
88 S t r i n g [ ] s i g n ={” l o n g ” , ” l o n g ” } ;
89 Long r =(Long ) c s . i n v o k e ( mbeanObjectName , o p e r a t i a , param , s i g n ) ;
90 System . out . p r i n t l n ( ”Cmmdc=”+r . t o S t r i n g ( ) ) ;
92 // U t i l i z a r e a A t r i b u t e l o r
93 S t r i n g l a b e l =( S t r i n g ) c s . g e t A t t r i b u t e ( mbeanObjectName , ” L a b e l ” ) ;
94 System . out . p r i n t l n ( ” V a l o a r e a a t r i b u t u l u i l a b e l : ”+l a b e l ) ;
96 System . out . p r i n t l n ( ” I n t r o d u c e t i c u r s u l e u r o ” ) ;
97 c u r s E u r o=s c a n n e r . nextDouble ( ) ;
98 A t t r i b u t e c u r s=new A t t r i b u t e ( ” CursEuro ” , c u r s E u r o ) ;
99 c s . s e t A t t r i b u t e ( mbeanObjectName , c u r s ) ;
100 Double newEuro=(Double ) c s . g e t A t t r i b u t e ( mbeanObjectName , ” CursEuro ” ) ;
101 System . out . p r i n t l n ( ” V a l o a r e a a t r i b u t u l u i e u r o : ”+newEuro ) ;
102 c s . u n r e g i s t e r M B e a n ( mbeanObjectName ) ;
103 }
104 catch ( E x c e p t i o n e ) {
105 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
106 }
107 }
108 }
12 ” WRITE: ”+ a t t r I n f o [ i ] . i s W r i t a b l e ( ) ) ;
13 }
14 }
15 else
16 System . out . p r i n t l n ( ” \ t F a r a a t r i b u t e ! ” ) ;
17 System . out . p r i n t l n ( ”CONSTRUCTORI” ) ;
18 MBeanConstructorInfo [ ] c o n s t r I n f o = i n f o . g e t C o n s t r u c t o r s ( ) ;
19 f o r ( i n t i =0; i <c o n s t r I n f o . l e n g t h ; i ++) {
20 System . out . p r i n t l n ( ” \tNUME: \ t ” + c o n s t r I n f o [ i ] . getName ( ) ) ;
21 System . out . p r i n t l n ( ” \tDESCR : \ t ” + c o n s t r I n f o [ i ] . g e t D e s c r i p t i o n ( ) ) ;
22 System . out . p r i n t l n ( ” \tPARAM: \ t ” +
23 c o n s t r I n f o [ i ] . g e t S i g n a t u r e ( ) . l e n g t h +” p a r a m e t r i ” ) ;
24 }
25 System . out . p r i n t l n ( ”OPERATII” ) ;
26 MBeanOperationInfo [ ] o p I n f o = i n f o . g e t O p e r a t i o n s ( ) ;
27 i f ( opInfo . length > 0) {
28 f o r ( i n t i = 0 ; i < o p I n f o . l e n g t h ; i ++) {
29 System . out . p r i n t l n ( ” \tNUME: \ t ” + o p I n f o [ i ] . getName ( ) ) ;
30 System . out . p r i n t l n ( ” \tDESCR : \ t ” + o p I n f o [ i ] . g e t D e s c r i p t i o n ( ) ) ;
31 System . out . p r i n t l n ( ” \tPARAM: \ t ” +
32 o p I n f o [ i ] . g e t S i g n a t u r e ( ) . l e n g t h +” p a r a m e t r i ” ) ;
33 }
34 }
35 else
36 System . out . p r i n t l n ( ” \ t F a r a o p e r a t i i ” ) ;
37 System . out . p r i n t l n ( ”NOTIFICARI” ) ;
38 MBeanNotificationInfo [ ] n o t i f I n f o = info . g e t N o t i f i c a t i o n s ( ) ;
39 i f ( n o t i f I n f o . length > 0) {
40 f o r ( i n t i = 0 ; i < n o t i f I n f o . l e n g t h ; i ++) {
41 System . out . p r i n t l n ( ” \tNUME: ” + n o t i f I n f o [ i ] . getName ( ) ) ;
42 System . out . p r i n t l n ( ” \tDESCR : ” + n o t i f I n f o [ i ] . g e t D e s c r i p t i o n ( ) ) ;
43 String notifTypes [ ] = n o t i f I n f o [ i ] . getNotifTypes ( ) ;
44 f o r ( i n t j = 0 ; j < n o t i f T y p e s . l e n g t h ; j ++) {
45 System . out . p r i n t l n ( ” \ tTIP : ” + n o t i f T y p e s [ j ] ) ;
46 }
47 }
48 }
49 else
50 System . out . p r i n t l n ( ” \ t F a r a n o t i f i c a r i ” ) ;
51 }
Această metodă poate fi inserată ı̂n oricare din programele agent sau client.
Notificarea la distanţă
Notificarea la distanţă presupune utilizarea unui MBean posedând această fa-
cilitate. Pe partea de client trebuie implementat interfaţa NotificationListener
care declară metoda
Exemplul 10.1.7 Folosind exemplul 10.1.6 - dar cu MBean-ul creat pentru 10.1.3
se crează un client cu notificare, care sesisează modificarea valoarii atributului cursEuro
a MBean-ului IntroN.
6 public c l a s s C l i e n t L i s t e n e r implements N o t i f i c a t i o n L i s t e n e r {
7 public void h a n d l e N o t i f i c a t i o n ( N o t i f i c a t i o n n o t i f i c a t i o n ,
8 O b j e c t handback ) {
9 System . out . p r i n t l n ( ” \ n R e c e i v e d n o t i f i c a t i o n : ” + n o t i f i c a t i o n ) ;
10 A t t r i b u t e C h a n g e N o t i f i c a t i o n myNotif=
11 ( AttributeChangeNotification ) n o t i f i c a t i o n ;
12 System . out . p r i n t l n ( ” Curs i n i t i a l : ” +
13 myNotif . getOldValue ( ) . t o S t r i n g ( ) ) ;
14 System . out . p r i n t l n ( ” Curs c u r e n t : ” +
15 myNotif . getNewValue ( ) . t o S t r i n g ( ) ) ;
16 }
17 }
7 public c l a s s C l i e n t N o t i f {
8 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
9 S t r i n g h o s t=” l o c a l h o s t ” ;
10 S t r i n g p o r t=” 1099 ” ;
11 i f ( a r g s . l e n g t h ==0){
12 System . out . p r i n t l n ( ”The S e r v e r name i s r e q u i r e d ” ) ;
13 System . e x i t ( 0 ) ;
14 }
15 i f ( a r g s . l e n g t h >=2) h o s t=a r g s [ 1 ] ;
16 i f ( a r g s . l e n g t h >=3) p o r t=a r g s [ 2 ] ;
17 Sc anner s c a n n e r=new Sc anner ( System . i n ) ;
18 C l i e n t N o t i f o b j=new C l i e n t N o t i f ( ) ;
19 try {
20 // Crearea unui c o n e c t o r RMI s i a o b i e c t u l u i
21 // de t i p MBeanServerConnection
22 S t r i n g s u r l=” s e r v i c e : jmx : rmi : / / / j n d i / rmi : / / ” +
23 h o s t+” : ”+p o r t+” / ”+a r g s [ 0 ] ;
232 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS
28 S t r i n g domain = c s . g e t D e f a u l t D o m a i n ( ) ;
29 System . out . p r i n t l n ( ” DefaultDomain : ” +domain ) ;
30 // Crearea unui MBean I n t r o
31 S t r i n g className=” b a s i c n . I nt r oN ” ;
32 S t r i n g sObjectName=domain+” : t y p e=”+className ;
33 ObjectName mbeanObjectName = new ObjectName ( sObjectName ) ;
38 // U t i l i z a r e a n o t i f i c a r i i
39 // Crearea unui a s c u l t a t o r
40 C l i e n t L i s t e n e r l i s t e n e r = new C l i e n t L i s t e n e r ( ) ;
41 // A c t i v a r e a n o t i f i c a t o r u l u i
42 c s . a d d N o t i f i c a t i o n L i s t e n e r ( mbeanObjectName , l i s t e n e r , null , o b j ) ;
44 Thread . s l e e p ( 5 0 0 ) ;
45 // D i s p o n i b i l i z a r e a a s c u l t a t o r u l u i de n o t i f i c a r i
46 System . out . p r i n t l n ( ” P r e s s Enter t o f i n i s h ! ” ) ;
47 try {
48 System . i n . r e a d ( ) ;
49 }
50 catch ( j a v a . i o . IOException e ) { }
51 c s . r e m o v e N o t i f i c a t i o n L i s t e n e r ( mbeanObjectName , l i s t e n e r ) ;
52 // D i s p o n i b i l i z a r e a o b i e c t u l u i MBeanObjectName
53 c s . u n r e g i s t e r M B e a n ( mbeanObjectName ) ;
54 }
55 catch ( E x c e p t i o n e ) {
56 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
57 e . printStackTrace ( ) ;
58 }
59 }
63 }
Clasa Client care crează MBean-ul trebuie lansată ı̂naintea clasei ClientNotif. Aceste
două clase pot rula pe calculatoare distincte.
implementat prin
1 import j a v a x . management . ∗ ;
27 public M B e a n N o t i f i c a t i o n I n f o [ ] g e t N o t i f i c a t i o n I n f o ( ) {
28 S t r i n g [ ] t y p e s = new S t r i n g [ ] {
29 A t t r i b u t e C h a n g e N o t i f i c a t i o n .ATTRIBUTE CHANGE
30 };
31 S t r i n g name = A t t r i b u t e C h a n g e N o t i f i c a t i o n . c l a s s . getName ( ) ;
32 S t r i n g d e s c r i p t i o n = ”An a t t r i b u t e o f t h i s MBean has changed ” ;
33 MBeanNotificationInfo info =
34 new M B e a n N o t i f i c a t i o n I n f o ( t y p e s , name , d e s c r i p t i o n ) ;
35 return new M B e a n N o t i f i c a t i o n I n f o [ ] { i n f o } ;
36 }
37 }
7 public c l a s s D e p o z i t S e r v l e t extends H t t p S e r v l e t {
8 MBeanServerConnection c s=n u l l ;
9 ObjectName mbeanObjectName=n u l l ;
10 String host ;
11 S t r i n g p o r t=” 1099 ” ;
12 S t r i n g s e r v e r=” s e r v e r ” ;
14 public void i n i t ( ) {
15 try {
16 super . i n i t ( c o n f i g ) ;
17 h o s t=c o n f i g . g e t I n i t P a r a m e t e r ( ” j m x S e r v e r H o s t ” ) ;
18 S t r i n g s u r l=” s e r v i c e : jmx : rmi : / / / j n d i / rmi : / / ” +
234 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS
78 catch ( E x c e p t i o n e ) {
79 message=”JMX−E r r o r : ”+e . g e t M e s s a g e ( ) ;
80 }
81 }
82 else {
83 message=” C e r e r e a nu p o a t e f i i n d e p l i n i t a ” ;
84 }
85 break ;
86 case 2 :
87 message=”Suma d i n c o n t e s t e ”+v a l u e+” u n i t . ” ;
88 break ;
89 }
90 r e s . setContentType ( ” t e x t / html ” ) ;
91 out . p r i n t l n ( ”<html>” ) ;
92 out . p r i n t l n ( ”<head><t i t l e >Depozit </ t i t l e ></head>” ) ;
93 out . p r i n t l n ( ”<body>” ) ;
94 out . p r i n t l n ( ”<h1>O p e r a t i u n i Cont</h1>” ) ;
95 out . p r i n t l n ( ”<p>” ) ;
96 out . p r i n t l n ( message ) ;
97 out . p r i n t l n ( ”</p>” ) ;
98 out . p r i n t l n ( ”</body></html>” ) ;
99 out . c l o s e ( ) ;
100 }
3 import j a v a x . management . ∗ ;
4 import j a v a x . management . remote . ∗ ;
6 public c l a s s C l i e n t N o t i f {
7 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
8 S t r i n g h o s t=” l o c a l h o s t ” ;
9 S t r i n g p o r t=” 1099 ” ;
10 i f ( a r g s . l e n g t h ==0){
11 System . out . p r i n t l n ( ”The S e r v e r name i s r e q u i r e d ” ) ;
12 System . e x i t ( 0 ) ;
13 }
14 i f ( a r g s . l e n g t h >=2) h o s t=a r g s [ 1 ] ;
15 i f ( a r g s . l e n g t h >=3) p o r t=a r g s [ 2 ] ;
16 Sca nner s c a n n e r=new S c a n n e r ( System . i n ) ;
17 C l i e n t N o t i f o b j=new C l i e n t N o t i f ( ) ;
18 try {
19 // Crearea unui c o n e c t o r RMI s i a o b i e c t u l u i de
20 // t i p MBeanServerConnection
21 S t r i n g s u r l=” s e r v i c e : jmx : rmi : / / / j n d i / rmi : / / ” +
22 h o s t+” : ”+p o r t+” / ”+a r g s [ 0 ] ;
23 JMXServiceURL u r l = new JMXServiceURL ( s u r l ) ;
24 JMXConnector jmxc = JMXConnectorFactory . c o n n e c t ( u r l , n u l l ) ;
25 MBeanServerConnection c s = jmxc . getMBeanServerConnection ( ) ;
27 S t r i n g domain = c s . g e t D e f a u l t D o m a i n ( ) ;
28 System . out . p r i n t l n ( ” DefaultDomain : ” +domain ) ;
29 // Crearea unui MBean I n t r o
30 S t r i n g className=” Cont ” ;
31 S t r i n g sObjectName=domain+” : t y p e=”+className ;
32 ObjectName mbeanObjectName = new ObjectName ( sObjectName ) ;
37 // U t i l i z a r e a n o t i f i c a r i i
38 // Crearea unui a s c u l t a t o r
39 C l i e n t L i s t e n e r l i s t e n e r = new C l i e n t L i s t e n e r ( ) ;
40 // A c t i v a r e a n o t i f i c a t o r u l u i
41 c s . a d d N o t i f i c a t i o n L i s t e n e r ( mbeanObjectName , l i s t e n e r , null , o b j ) ;
43 Thread . s l e e p ( 5 0 0 ) ;
44 // D i s p o n i b i l i z a r e a a s c u l t a t o r u l u i de n o t i f i c a r i
45 System . out . p r i n t l n ( ” P r e s s Enter t o f i n i s h ! ” ) ;
46 try {
47 System . i n . r e a d ( ) ;
48 }
49 catch ( j a v a . i o . IOException e ) { }
50 c s . r e m o v e N o t i f i c a t i o n L i s t e n e r ( mbeanObjectName , l i s t e n e r ) ;
51 // D i s p o n i b i l i z a r e a o b i e c t u l u i MBeanObjectName
52 c s . u n r e g i s t e r M B e a n ( mbeanObjectName ) ;
53 }
54 catch ( E x c e p t i o n e ) {
55 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
56 e . printStackTrace ( ) ;
57 }
58 }
63 c l a s s C l i e n t L i s t e n e r implements N o t i f i c a t i o n L i s t e n e r {
64 public void h a n d l e N o t i f i c a t i o n ( N o t i f i c a t i o n n o t i f i c a t i o n ,
65 O b j e c t handback ) {
66 System . out . p r i n t l n ( ” \ n R e c e i v e d n o t i f i c a t i o n : ” + n o t i f i c a t i o n ) ;
67 A t t r i b u t e C h a n g e N o t i f i c a t i o n myNotif=
68 ( AttributeChangeNotification ) n o t i f i c a t i o n ;
69 System . out . p r i n t l n ( ” S o l d i n i t i a l : ” +
70 myNotif . getOldValue ( ) . t o S t r i n g ( ) ) ;
71 System . out . p r i n t l n ( ” S o l d c u r e n t : ” +
72 myNotif . getNewValue ( ) . t o S t r i n g ( ) ) ;
73 }
74 }
Teme de laborator
tF = 1.8tC + 32o F
package conversie;
public interface Grade extends java.rmi.Remote{
public double celsiusToFahrenheit(double celsius)
// throws java.rmi.RemoteException;
public double fahrenheitToCelsius(double fahrenheit)
// throws java.rmi.RemoteException;
}
2. Să se realizeze conversia a unei sume de bani ı̂ntre USD, EURO şi RON.
Ratele de schimb sunt fixate de un obiect ce implementează interfaţa
239
240 CAPITOLUL 11. TEME DE LABORATOR
package exchange;
public interface IConversie extends java.rmi.Remote{
public double usdToEuro(double usd)
// throws java.rmi.RemoteException;
public double usdToRol(double usd)
// throws java.rmi.RemoteException;
public double euroToUsd(double euro)
// throws java.rmi.RemoteException;
public double euroToRol(double euro)
// throws java.rmi.RemoteException;
public double rolToEuro(double rol)
// throws java.rmi.RemoteException;
public double rolToUsd(double rol)
// throws java.rmi.RemoteException;
}
Rata zilnică de schimb se poate prelua dinamic sub forma unui fişier xml,
apelând http://www.bnr.ro/nbrfxrates.xml.
3. Să se realizeze conversia unui număr natural, cuprins ı̂ntre 1 şi 3999, din cifre
arabe ı̂n cifre romane şi invers.
5. Unui client ı̂i corespunde un număr ı̂ntreg, valoarea iniţială fiind 0. La o apelare
a serverului, clientul transmite un număr care este adunat la numărul care ı̂i
corespunde clientului. Serverul retransmite clientului valoarea actualizată a
numărului. Să se implementeze serviciul descris.
Se defineşte interfaţa
package iprodcons;
public interface IBoundedBuffer extends java.rmi.Remote{
public void put(Object obj) throws java.rmi.RemoteException;
public Object get() throws java.rmi.RemoteException;
}
Se cere:
7. Aplicaţie de e-mail.
Un e-mail este definit printr-un ansamblu de 4 variabile de tip String
package iemail;
import java.io.Serializable;
public Email() {}
package iemail;
import java.rmi.*;
throws RemoteException;
public void writeEmail(String from, String to,
String subject, String body) throws RemoteException,
UnknownUserException;
public void readEmail(String userName,ICallbackEmail ce)
throws RemoteException;
}
package email;
import java.util.*;
import iemail.*;
Pentru a putea folosi serverul de e-mail, un client trebuie ı̂n prealabil să se
ı̂nregistreze (createUser).
Un client ı̂nregistrat se poate conecta la serverul de e-mail (login) după care
poate scrie (trimite) sau citi (recepţiona) mesaje.
Se cere ca la adăgarea unui mesaj (deci ı̂naintea apelării metodei User.addEmail)
să se verifice dacă emitentul este conectat şi dacă destinatarul este ı̂nregistrat.
ı̂n caz contrar se generează excepţia UnknownUserException
package iemail;
public class UnknownUserException extends Exception {
public UnknownUserException() {
super();
}
Citirea mesajelor este lăsată la latitudinea clienţilor ı̂n sensul că clientul im-
plementează metoda printEmail al interfeţei ICallbackEmail.
11.1. PROBLEME PROPUSE 243
package iemail;
import java.rmi.*;
import java.rmi.server.*;
8. Integrare numerică.
Scopul aplicaţiei este calculul unei integrale de un program server cu funcţia
de integrat deţinută de către client. Evaluările funcţiei cerute de formula de
integrare numerică se vor realiza prin apel invers. Integrarea numerică va
fi executat de un server disponibil clienţilor prin mecanismul de fabrică de
obiecte.
Interfaţa fabricii de obiecte este
package integ;
import java.rmi.*;
public interface IFabIntegrator extends Remote{
IIntegrator getIntegrator() throws RemoteException;
}
package integ;
import java.rmi.*;
public interface IIntegrator extends Remote{
double adaptiveSimpson(double leftEnd, double rightEnd,
double epsilon, int initParam) throws RemoteException;
}
declară o metodă ce calculează un şir (Imk )k până ı̂n momentul |Imk −Imk−1 | <
ε.
Propunem utilizarea formulei lui Simpson
b m−1 m−1
b−a
Z X X
f (x)dx ≈ Im = [f (a) + 2 f (a2i ) + 4 f (a2i+1 ) + f (b)]
a 6m i=1 i=0
244 CAPITOLUL 11. TEME DE LABORATOR
unde ai = a + i b−a
2m .
Şirul (mk )k este definit prin mk = 2k m0 .
Semnificaţia parametrilor metodei adaptiveSimpson este
leftEnd a
rightEnd b
epsilon ε
initParam m0
package integ;
import java.rmi.*;
double function(double x)throws RemoteException;
}
9. Agendă telefonică.
Pentru crearea şi ı̂ntreţinerea unei agende telefonice considerăm:
Un ServerCarteTelefon realizează următoarele operaţii:
package itelef;
import java.rmi.*;
public interface ICarteTelefon extends Remote{
void addEntry(Entry e)throws RemoteException;
String lookupNumber(String p)throws RemoteException;
void deleteEntry(Entry e)throws RemoteException;
Entry[] list() throws RemoteException;
void save(String file)throws RemoteException;
void restore(String file)throws RemoteException,ClassNotFoundException;
void modifyEntry(Entry e)throws RemoteException;
}
package itelef;
import java.rmi.*;
public interface IFabCarteTelefon extends Remote{
ICarteTelefon getCarteTelefon() throws RemoteException;
}
package itelef;
import java.rmi.*;
TELEF
ID
NUME
NUMAR
10. Să se realizeze programe client având o interfaţă grafică. Recomandăm uti-
lizarea produsului NetBeans.
R. Exemplu de client pentru problema calculului celui mai mare divizor comun
a două numere cu soclu TCP.
import java.net.*;
import java.io.*;
}
}
12. Să se convertească unităţile de masură pentru masă şi lungime ı̂ntre sistemul
internaţional şi sistemul anglo-saxon.
XML
<marcaj>
corpul elementului
</marcaj>
<marcaj/>
249
250 APPENDIX A. XML
de sfârşit. Caracterele mari şi mici din denumirea unui element sunt distincte (case
sensitive).
Elementele ı̂ncuibărite (nested )- incluse ı̂ntr-un alt element - nu se pot amesteca.
Un comentariu se indică prin
<!--
Text comentariu
-->
Exemplul A.0.1
sau
Dacă un element se declară ca aparţinând unui spaţiu de nume, atunci şi el-
ementele incluse aparţin aceluiaşi spaţiu de nume, exceptând cazurile ı̂n care se
specifică explicit, prin prefix, alt spaţiu de nume.
Exemplul A.0.2
• Verificarea corectitudinii;
Apache-ant
set ANT_HOME=. . .
set JAVA_HOME=. . .
set PATH=%ANT_HOME%\bin;%PATH%
ant.bat %1
numeAtribut = ”valoareAtribut”
<project name="numeProiect"
default="obiectiv"
253
254 APPENDIX B. APACHE-ANT
basedir="catalogDeReferinta">
<target name="numeObiectiv">
sarcini
</target>
. . . . . . .
</project>
Utilizarea lui apache-ant presupune că toate resursele utilizate, cuprinse uzual
ı̂n fişiere cu extensia jar (j ava ar hive) sunt disponibile pe calculatorul local. Dacă
255
. . .
<!-- =================================
target: resolve
================================= -->
<target name="resolve" depends="init"
description="--> retreive dependencies with ivy">
<ivy:retrieve/>
</target>
<!-- =================================
target: report
================================= -->
<target name="report" depends="resolve"
description="--> generates a report of dependencies">
<ivy:report todir="${report.dir}"/>
</target>
. . .
</project>
1
Asemănător cu maven, un alt produs de dezvoltare.
256 APPENDIX B. APACHE-ANT
Appendix C
Scopul acestei anexe este prezentarea bazelor utilizării unui sistem de gestiune a
bazelor de date (SGBD) din Java. Exemplificăm modul de operare şi utilizare pentru
crearea şi exploatarea unei baze de date corespunzătoare unei agende telefonice.
C.1 Derby
Instalarea produsului constă ı̂n dezarhivarea fişierului descărcat ı̂n catalogul
jdk*.*.*\db.
Utilizarea produsului. Va fi utilizată varianta de reţea bazată pe un server al
SGBD care utilizează implicit portul 1527.
Se ı̂ntreprind următoarele operaţii:
1. Lansarea serverului Derby:
set JAVA_HOME=. . .
set DERBY_HOME=. . .
set PATH=%DERBY_HOME%\bin;%PATH%
startNetworkServer.bat
Exemplul C.1.1
257
258 APPENDIX C. UTILIZAREA SGBD ÎN JAVA
cu fişierul ValuesAgendaT.sql
1 i n s e r t into t e l e f values ( ’ aaa ’ , ’ 111111 ’ ) , ( ’ bbb ’ , ’ 222222 ’ ) ,
2 ( ’ c c c ’ , ’ 333333 ’ ) ;
C.2 mysql
Instalarea produsului. Pentru instalare s-a descărcat varianta fără instalare
automată mysql-noinstall-*.*.*-win32.zip. Acest fişier se dezarhivează ı̂ntr-un cata-
log MYSQL HOME.
Implicit, serverul mysql utilizează portul 3306, iar fişierele bazelor de date vor fi
găzduite ı̂n catalogul MYSQL HOME\data.
Pentru utilizarea ı̂n aplicaţii Java trebuie descărcat un conector mysql-connector-
java-*.*.*.tar.gz, conţinând fişierul mysql-connector-java-
*.*.*-bin.jar.
Utilizarea produsului.
Se ı̂ntreprind următoarele operaţii:
set MYSQL_HOME=. . .
set PATH=%MYSQL_HOME%\bin;%PATH%
mysqld
2. Exemplul C.2.1
Crearea bazei de date AgendaTelefonica se va face prin intermediul fişierului
de comenzi
set MYSQL_HOME=d:\mysql-*-win32\bin
set path=%MYSQL_HOME%;%PATH%
mysql -u root < CreateAgendaT.sql
mysql -u root < ValuesAgendaT.sql
1 create d a t a b a s e A g e n d a T e l e f o n i c a ;
2 use AgendaTelefonica ;
4 create table t e l e f (
5 i d i n t primary key a u t o i n c r e m e n t not null ,
6 nume char ( 2 0 ) not null ,
7 numar char ( 1 3 ) not n u l l
8 );
set MYSQL_HOME=d:\mysql-5.0.45-win32
set PATH=%MYSQL_HOME%\bin;%PATH%
mysqladmin -u root shutdown
C.3 PostgrSQL
Instalarea produsului. PostgreSQL este distribuit gratuit. Pentru sistemul de
operare Windows se descarcă o distribuţie cu instalare. Cu drepturi de administrator
al sistemului gazdă, se execută instalarea cu serverul PostgreSQL drept serviciu
Windows. Comunicaţia cu acest server se face prin portul 5432.
Pentru utilizarea ı̂n aplicaţii Java trebuie descărcat un conector postgresql-*.*-
*.jdbc4.jar.
Utilizarea produsului.
Exemplul C.3.1
user este numele unui cont PostgreSQL care se poate crea cu componenta de
administrare pgAdmin III, prin meniul Login Role / New Login Role.
Script-urile sql sunt
createdb.sql
create database "AgendaTelefonica" encoding ’utf8’ owner user;
260 APPENDIX C. UTILIZAREA SGBD ÎN JAVA
createtable.sql
create table telef(id int4 primary key,
nume varchar(20) not null, numar varchar(15) not null);
insertvalues.sql
insert into telef values(1,’aaa’,’111111’);
insert into telef values(2,’bbb’,’222222’);
insert into telef values(3,’ccc’,’333333’);
jdbc:protocol://host:port/numeBazaDate
String jdbcDriver=. . .
String URLBazaDate=. . .
Connection con=null;
try{
//Class.forName(jdbcDriver).newInstance();
con=DriverManager.getConnection(URLBazaDate);
...
}
//catch(ClassNotFoundException e){. . .}
catch(SQLException e){. . .}
Liniile comentate sunt necesare doar ı̂n cazul ı̂n care se lucrează cu o distribuţie
Java mai mică decât 1.6.0.
Odată conexiunea cu baza de date stabilită se generează un obiect de tip Statement
prin intermediul căruia se execută interogarea SQL.
Statement instructiune=con.createStatement();
String sql=. . . //fraza select;
try{
ResultSet rs=instructiune.executeQuery(sql);
while(rs.next()){
prelucrarea rezultatului
}
}
catch(SQLException e){...}
Exemplul C.4.1
6 public c l a s s AgendaT {
7 Statement i n s t r u c t i u n e=n u l l ;
9 public void i n i t ( ) {
10 // SGBD Derby
11 /∗
12 S t r i n g j d b c D r i v e r =”o r g . apache . d e r b y . j d b c . C l i e n t D r i v e r ” ;
13 S t r i n g URLBazaDate=” j d b c : d e r b y : / / 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 ” ;
14 ∗/
15 // SGBD mysql
262 APPENDIX C. UTILIZAREA SGBD ÎN JAVA
16 S t r i n g j d b c D r i v e r=”com . mysql . j d b c . D r i v e r ” ;
17 S t r i n g URLBazaDate=
18 ” j d b c : mysql : / / l o c a l h o s t : 3 3 0 6 / A g e n d a T e l e f o n i c a ? u s e r=r o o t ” ;
20 // PostgreSQL
21 /∗
22 S t r i n g j d b c D r i v e r =”o r g . p o s t g r e s q l . D r i v e r ” ;
23 S t r i n g URLBazaDate=” j d b c : p o s t g r e s q l : / / l o c a l h o s t : 5 4 3 2 / A g e n d a T e l e f o n i c a ” ;
24 S t r i n g username =”. . . ” ;
25 S t r i n g password =”. . . ” ;
26 ∗/
28 C o n n e c t i o n con=n u l l ;
29 try {
30 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 ( ) ;
31 con=DriverManager . g e t C o n n e c t i o n ( URLBazaDate ) ;
32 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 ( ) ;
33 }
34 catch ( ClassNotFoundException e ) {
35 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 ) ;
36 }
37 catch ( SQLException e ) {
38 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 ) ;
39 }
40 catch ( E x c e p t i o n e ) {
41 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 ( ) ) ;
42 }
43 }
75 r s=agenda . 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 ) ;
76 i f ( r s != n u l l ) {
77 System . out . p r i n t l n ( ”S−au g a s i t n u m e r e l e de t e l e f o n : ” ) ;
78 while ( r s . n e x t ( ) ) {
79 System . out . p r i n t l n ( r s . g e t S t r i n g ( ”numar” ) ) ;
80 }
81 }
82 else {
83 System . out . p r i n t l n ( ” Fara t e l e f o n ! ” ) ;
84 }
85 break ;
86 case 2 :
87 System . out . p r i n t l n ( ”Numar” ) ;
88 numar= ’ \ ’ ’+s c a n n e r . n e x t ( ) . t r i m ()+ ’ \ ’ ’ ;
89 s q l=” s e l e c t ∗ from t e l e f where numar=”+numar ;
90 r s=agenda . 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 ) ;
91 i f ( r s != n u l l ) {
92 System . out . p r i n t l n ( ”S−a g a s i t numeley ” +
93 ”y : ” ) ;
94 while ( r s . n e x t ( ) ) {
95 System . out . p r i n t l n ( r s . g e t S t r i n g ( ”nume” ) ) ;
96 }
97 }
98 else {
99 System . out . p r i n t l n ( ”Numar i n e x i s t e n t ! ” ) ;
100 }
101 break ;
102 default : System . out . p r i n t l n ( ”Comanda e r o n a t a ” ) ;
103 }
104 }
105 }
106 }
107 catch ( E x c e p t i o n e ) {
108 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 ( ) ) ;
109 }
110 }
111 }
• Varianta mysql
%MYSQL CONNECTOR JAVA HOME%\mysql-connector-java-*.*.*-bin.jar
C.5.1 apache-openjpa
Aşa cum sugerează numele produsului, openjpa este implementarea oferită de
apache.
C.5. JAVA PERSISTENCE API - JPA 265
6 < !−−
7 We need t o enumerate each p e r s i s t e n t c l a s s f i r s t i n t h e p e r s i s t e n c e . xml
8 S e e : h t t p : // i s s u e s . apache . o r g / j i r a / browse /OPENJPA−78
9 −−>
10 <p e r s i s t e n c e −u n i t name=” none ” t r a n s a c t i o n −t y p e=”RESOURCE LOCAL”>
11 < c l a s s>E n t i t y c l a s s n a m e</ c l a s s>
12 </ p e r s i s t e n c e −u n i t>
14 < !−−
15 A p e r s i s t e n c e u n i t i s a s e t o f l i s t e d p e r s i s t e n t e n t i t i e s as w e l l
16 t h e c o n f i g u r a t i o n o f an E n t i t y M a n a g e r F a c t o r y . We c o n f i g u r e each
17 example i n a s e p a r a t e p e r s i s t e n c e −u n i t .
18 −−>
19 <p e r s i s t e n c e −u n i t name=” P e r s i s t e n c e u n i t n a m e ”
20 t r a n s a c t i o n −t y p e=”RESOURCE LOCAL”>
21 < !−−
22 The default p r o v i d e r can be OpenJPA , or some o t h e r p r o d u c t .
23 This e l e m e n t i s o p t i o n a l i f OpenJPA i s t h e o n l y JPA p r o v i d e r
24 i n t h e c u r r e n t c l a s s l o a d i n g environment , b u t can be s p e c i f i e d
25 i n c a s e s where t h e r e a r e m u l t i p l e JPA i m p l e m e n t a t i o n s a v a i l a b l e .
26 −−>
27 < !−−
28 <p r o v i d e r>
29 o r g . apache . o p e n j p a . p e r s i s t e n c e . P e r s i s t e n c e P r o v i d e r I m p l
30 </ p r o v i d e r>
31 −−>
36 <p r o p e r t i e s>
37 < !−−
38 We can c o n f i g u r e t h e default OpenJPA p r o p e r t i e s h e r e . They
39 happen t o be commented o u t h e r e s i n c e t h e p r o v i d e d e x a m p l e s
40 a l l s p e c i f y t h e v a l u e s v i a System p r o p e r t i e s .
41 −−>
266 APPENDIX C. UTILIZAREA SGBD ÎN JAVA
43 < !−−
44 <p r o p e r t y name=” o p e n j p a . ConnectionURL ”
45 v a l u e=” j d b c : d e r b y : o p e n j p a −d a t a b a s e ; c r e a t e=t r u e ” />
46 <p r o p e r t y name=” o p e n j p a . ConnectionDriverName ”
47 v a l u e=” o r g . apache . derby . j d b c . EmbeddedDriver ” />
48 <p r o p e r t y name=” o p e n j p a . ConnectionUserName ”
49 v a l u e=” u s e r ” />
50 <p r o p e r t y name=” o p e n j p a . ConnectionPassword ”
51 v a l u e=” s e c r e t ” />
52 −−>
53 </ p r o p e r t i e s>
54 </ p e r s i s t e n c e −u n i t>
55 </ p e r s i s t e n c e>
Atributele ce apar ı̂n comentarii, pot fi specificate şi prin proprietăţi System.
Şablonul de prelucrare este
EntityManagerFactory factory=
Persistence.createEntityManagerFactory("nume_unitate_de_persistenta",
System.getProperties());
EntityManager em=factory.createEntityManager();
em.getTransaction().begin();
String sql=fraza SQL sau JPQL
Query query=em.createQuery(sql);
em.getTransaction().commit();
em.close();
factory.close();
Dacă fraza SQL este specifică unui SGBD atunci obiectul de tip Query se instanţiază
prin
Query query=em.createNativeQuery(sql,clasa_Entity_utilizata.class);
Exemplul C.5.1 Aplicaţie pentru ı̂ntreţinerea şi interogarea bazei de date Agen-
daTelefonica.
1 package appagenda ;
2 import j a v a x . p e r s i s t e n c e . ∗ ;
4 @Entity
5 public c l a s s T e l e f implements j a v a . i o . S e r i a l i z a b l e {
6 private i n t i d ;
7 private S t r i n g nume ;
8 private S t r i n g numar ;
10 T e l e f ( ) {}
12 public i n t g e t I d ( ) {
13 return i d ;
14 }
15 public void s e t I d ( i n t i d ) {
16 t h i s . i d=i d ;
17 }
19 public S t r i n g getNume ( ) {
20 return nume ;
21 }
22 public void setNume ( S t r i n g nume ) {
23 t h i s . nume = nume ;
24 }
26 public S t r i n g getNumar ( ) {
27 return numar ;
28 }
29 public void setNumar ( S t r i n g numar ) {
30 t h i s . numar = numar ;
31 }
32 }
5 @SuppressWarnings ( ” unchecked ” )
6 p u b l i c c l a s s AgendaTDAO{
7 Entit yManagerFactory f a c t o r y=n u l l ;
8 EntityManager em ;
10 p u b l i c AgendaTDAO( EntityManage rF a c t or y f a c t o r y ) {
11 t h i s . f a c t o r y=f a c t o r y ;
12 }
14 p u b l i c v o i d addAgendaT ( T e l e f a ) {
15 em=f a c t o r y . c r e a t e E n t i t y M a n a g e r ( ) ;
16 em . g e t T r a n s a c t i o n ( ) . b e g i n ( ) ;
17 //em . p e r s i s t ( a ) ;
18 S t r i n g s q l=” i n s e r t i n t o t e l e f ( nume , numar ) v a l u e s ( \ ’ ” +
19 a . getNume ()+ ” \ ’ , \ ’ ”+a . getNumar ()+ ” \ ’ ) ” ;
20 Query query=em . c r e a t e N a t i v e Q u e r y ( s q l ) ;
21 query . e x e c u t e U p d a t e ( ) ;
22 em . g e t T r a n s a c t i o n ( ) . commit ( ) ;
23 em . c l o s e ( ) ;
24 }
268 APPENDIX C. UTILIZAREA SGBD ÎN JAVA
26 p u b l i c v o i d deleteAgendaT ( S t r i n g nume ) {
27 em=f a c t o r y . c r e a t e E n t i t y M a n a g e r ( ) ;
28 em . g e t T r a n s a c t i o n ( ) . b e g i n ( ) ;
29 S t r i n g s q l=” d e l e t e from T e l e f a where a . nume=\ ’ ”+nume+” \ ’ ” ;
30 Query query=em . c r e a t e Q u e r y ( s q l ) ;
31 query . e x e c u t e U p d a t e ( ) ;
32 em . g e t T r a n s a c t i o n ( ) . commit ( ) ;
33 em . c l o s e ( ) ;
34 }
36 p u b l i c L i s t i n t e r o g a r e A g e n d a T ( S t r i n g nume ) {
37 em=f a c t o r y . c r e a t e E n t i t y M a n a g e r ( ) ;
38 em . g e t T r a n s a c t i o n ( ) . b e g i n ( ) ;
39 S t r i n g s q l=” s e l e c t a from T e l e f a where a . nume=\ ’ ”+nume+” \ ’ ” ;
40 Query query=em . c r e a t e Q u e r y ( s q l ) ;
41 // S t r i n g s q l=” s e l e c t ∗ from t e l e f where nume=\ ’ ”+nume+” \ ’ ” ;
42 // Query query=em . c r e a t e N a t i v e Q u e r y ( s q l , appagenda . T e l e f . c l a s s ) ;
43 L i s t r e s u l t=query . g e t R e s u l t L i s t ( ) ;
44 em . g e t T r a n s a c t i o n ( ) . commit ( ) ;
45 em . c l o s e ( ) ;
46 return r e s u l t ;
47 }
49 p ub l ic L i s t listAgendaT ( ) {
50 em=f a c t o r y . c r e a t e E n t i t y M a n a g e r ( ) ;
51 em . g e t T r a n s a c t i o n ( ) . b e g i n ( ) ;
52 S t r i n g s q l=” s e l e c t a from T e l e f a ” ;
53 Query query=em . c r e a t e Q u e r y ( s q l ) ;
54 // S t r i n g s q l=” s e l e c t ∗ from t e l e f ” ;
55 // Query query=em . c r e a t e N a t i v e Q u e r y ( s q l , appagenda . T e l e f . c l a s s ) ;
56 L i s t r e s u l t=query . g e t R e s u l t L i s t ( ) ;
57 em . g e t T r a n s a c t i o n ( ) . commit ( ) ;
58 em . c l o s e ( ) ;
59 return r e s u l t ;
60 }
61 }
5 public c l a s s AgendaTClient {
6 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
7 EntityManagerFactor y f a c t o r y=
8 P e r s i s t e n c e . c r e a t e E n t i t y M a n a g e r F a c t o r y ( ” appagenda ” ,
9 System . g e t P r o p e r t i e s ( ) ) ;
10 AgendaTDAO dao=new AgendaTDAO( f a c t o r y ) ;
11 S t r i n g ch=”Y” ;
12 int p r e l ;
13 Sca nner s c a n n e r=new S c a n n e r ( System . i n ) ;
14 T e l e f a=n u l l ;
16 while ( ch . s t a r t s W i t h ( ”Y” ) ) {
17 do{
18 System . out . p r i n t l n ( ” Continue ? (Y/N) ” ) ;
19 ch=s c a n n e r . n e x t ( ) . toUpperCase ( ) ;
20 }
C.5. JAVA PERSISTENCE API - JPA 269
8 </ p e r s i s t e n c e −u n i t>
7 <p r o p e r t y name=”db−d r i v e r −l o c a t i o n ”
8 l o c a t i o n=” d : /db−derby −∗−b i n ” />
9 < !−−
10 <p r o p e r t y name=”db−d r i v e r −l o c a t i o n ”
11 l o c a t i o n=” d : / mysql−c o n n e c t o r −j a v a − 5 . 1 . 5 ” />
12 −−>
13 <p r o p e r t y name=” o p e n j p a ” l o c a t i o n=” d : /JavaApp/ apache−openjpa − 1 . 1 . 0 ” />
28 <path i d=” c l a s s p a t h ”
29 d e s c r i p t i o n=”The c l a s s p a t h t o u s e f o r c o m p i l i n g and r u n n i n g ”>
30 <p a t h e l e m e n t path=” ${ b a s e d i r } ” />
31 <p a t h e l e m e n t path=” ${db−d r i v e r −l o c a t i o n }/ l i b / d e r b y c l i e n t . j a r ” />
32 <p a t h e l e m e n t path=” ${db−d r i v e r −l o c a t i o n }/ mysql−c o n n e c t o r −j a v a −5.1.5 − b i n . j a r ” />
33 < f i l e s e t d i r=” ${ o p e n j p a }/ l i b ”>
34 <i n c l u d e name=” ∗ ∗ / ∗ . j a r ” />
35 </ f i l e s e t>
36 </ path>
45 <t a r g e t name=” c o m p i l e ”
46 d e s c r i p t i o n=” Compile t h e package j a v a f i l e s ”>
47 <j a v a c s r c d i r=” ${ package } ” c l a s s p a t h r e f=” c l a s s p a t h ” debug=” y e s ” />
48 </ t a r g e t>
59 < !−−
60 S p e c i f y t h e system p r o p e r t i e s t o u s e when c o n f i g u r i n g
61 OpenJPA . Note t h a t t h e s e w i l l o n l y be used b e c u a s e i n t h e
62 packages , the c a l l to ” P e r s i s t e n c e . createEntityManagerFactory ”
63 i s p a s s e d ” System . g e t P r o p e r t i e s ( ) ” .
64 −−>
72 < !−−
73 T e l l OpenJPA t o a u t o m a t i c a l l y c r e a t e t a b l e s i n t h e d a t a b a s e
74 f o r e n t i t i e s . Note t h a t t h i s s h o u l d be d i s a b l e d when
75 running a g a i n s t a p r o d u c t i o n d a t a b a s e , s i n c e you p r o b a b l y
76 don ’ t want t o be a l t e r i n g t h e schema a t r u n t i m e .
77 −−>
78 <s y s p r o p e r t y key=”o p e n j p a . j d b c . S y n c h r o n i z e M a p p i n g s ”
79 v a l u e=”buildSchema”/>
81 <!−−
82 Output a l l t h e SQL f o r e d u c a t i o n a l p u r p o s e s , but s e t t h e
83 g e n e r a l l o g g i n g l e v e l t o o n l y show w a r n i n g s .
84 −−>
85 <s y s p r o p e r t y key=”o p e n j p a . Log”
86 v a l u e=” D e f a u l t L e v e l=WARN, SQL=TRACE”/>
87 </j av a >
88 </ t a r g e t >
89 </ p r o j e c t >
272 APPENDIX C. UTILIZAREA SGBD ÎN JAVA
Bibliografie
[1] ATHANASIU I., COSTINESCU B., DRĂGOI O.A., POPOVICI F.I., 1998,
Limbajul Java. O perspectivă pragmatică. Ed. Computer Libris Agora, Cluj-
Napoca.
[2] BOIAN F.M., BOIAN R. F., 2004, Tehnologii fundamentale Java pentru
aplicaţii Web. Ed. Albastră, Cluj-Napoca.
[4] BURAGA S. (ed), 2007, Programarea ı̂n Web 2.0., Ed. Polirom, Iaşi.
[5] JURCĂ I., 2000, Programarea reţelelor de calculatoare. Ed. de Vest, Timişoara.
[6] HUNTER J., CRAWFORD W., 1998, Java Servlet Programming. O’Reilly.
[7] ALBOAIE L., BURAGA S., 2006, Servicii Web. Ed. Polirom, Iaşi.
[8] SCHEIBER E., 2007, Programare concurentă şi paralel distribuită ı̂n Java. Ed.
Albastră, Cluj-Napoca.
[9] TANASĂ Ş., OLARU C., 2005, Dezvoltarea aplicaţiilor Web folosind Java. Ed.
Polirom, Bucureşti.
273