Documente Academic
Documente Profesional
Documente Cultură
Facultatea de Matematică–Informatică
Catedra de Informatică
ERNEST SCHEIBER
Braşov
2
Introducere
3
4
• socluri Java;
• mesageria Java;
• servlet;
5
6 CUPRINS
6 Servlet 137
6.1 Marcajul <form> . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
6.2 Server Web - container de servlet . . . . . . . . . . . . . . . . . . . . 139
6.3 Realizarea unui servlet . . . . . . . . . . . . . . . . . . . . . . . . . . 140
6.3.1 Instalarea unui servlet . . . . . . . . . . . . . . . . . . . . . . 140
6.3.2 Compilarea şi apelarea unui servlet . . . . . . . . . . . . . . . 142
6.3.3 Codul unui servlet . . . . . . . . . . . . . . . . . . . . . . . . 143
6.4 Facilităţi de programare cu servlet . . . . . . . . . . . . . . . . . . . 149
6.4.1 Program client al unui servlet . . . . . . . . . . . . . . . . . . 149
6.4.2 Servlete ı̂nlănţuite . . . . . . . . . . . . . . . . . . . . . . . . 152
6.4.3 Sesiune de lucru . . . . . . . . . . . . . . . . . . . . . . . . . 154
6.4.4 Cookie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
6.4.5 Autorizarea accesului prin parola . . . . . . . . . . . . . . . . 157
CUPRINS 7
8 Portlet 205
8.1 Apache-pluto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
8.2 Dezvoltarea unui portlet . . . . . . . . . . . . . . . . . . . . . . . . . 207
8.3 Elemente de programare . . . . . . . . . . . . . . . . . . . . . . . . . 211
8.4 Produse Portal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
8.4.1 uPortal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
8.4.2 Jetspeed-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
Bibliografie 303
Capitolul 1
9
10 CAPITOLUL 1. APPLET - MINIAPLICAŢIE JAVA
import java.applet.*;
import java.awt.*;
Varianta 1
1. Arhivarea fişierelor class ale applet-ului.
1.2. DESFĂŞURAREA UNUI APPLET 11
<BODY>
. . .
<script src="http://java.com/js/deployJava.js"></script>
<script>
var attributes={ code:’numele_clasei_Applet’,
archive:’numele_arhivei_jar’,width:...,height:...};
var parameters={. . .};
var minimumVersion=’1.6’;
deployJava.runApplet(attributes, parameters, minimumVersion);
</script>
. . .
</BODY>
3. Cele două fişiere se depun ı̂ntr-un catalog al unui server Web, asigurând viz-
ibilitatea aplicaţiei ı̂n Internet.
Verificarea aplicaţiei se poate face, dintr-un program navigator, prin simpla
apelare a fişierului html. În acest caz, calculatorul trebuie să fie conectat la
internet.
Dacă dispunem de deployJava.js atunci acest fişier se alătură celorlalte două
resurse, iar atributul src al elementului script va fi src="deployJava.js".
7 public void p a i n t ( G r a p h i c s g ) {
8 S t r i n g name=g e t P a r a m e t e r ( ”nume” ) ;
9 g . d r a w S t r i n g ( ” H e l l o ”+name+” ! ! ” , 5 0 , 60 ) ;
10 }
11 }
10 v a r p a r a m e t e r s={nume : ’ XYZ’ } ;
11 v a r minimumVersion = ’ 1 . 6 . 0 ’ ;
12 d e p l o y J a v a . runApplet ( a t t r i b u t e s , p a r a m e t e r s , minimumVersion ) ;
13 </ s c r i p t>
14 </BODY>
15 </HTML>
Varianta 2
Pe această cale se va edita un fişier de configurare cu extensia jnlp. Realizarea
applet-ului constă din:
<BODY>
. . .
<script src="http://java.com/js/deployJava.js"></script>
1.2. DESFĂŞURAREA UNUI APPLET 13
<script>
var attributes={code:’numele_arhivei_jar’,width:...,height:...};
var parameters={jnlp_href: ’cmmdc.jnlp’};
var minimumVersion=’1.6’;
deployJava.runApplet(attributes, parameters, minimumVersion);
</script>
. . .
</BODY>
Exemplul 1.2.2 Calculul celui mai mare divizor comun a două naturale.
Introducerea datelor exterioare se face prin intermediul unei interfeţe grafice.
Applet-ul extinzând clasa Applet are codul
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 . par se Lo ng ( sm ) ;
31 S t r i n g sn=tn . g e t T e x t ( ) ;
32 long n=Long . pa rs eL ong ( 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 }
8 public void i n i t ( ) {
9 C o n t a i n e r c o n t e n t = getContentPane ( ) ;
10 content . setBackground ( Color . yellow ) ;
11 s e t L a y o u t (new GridLayout ( 3 , 2 , 3 0 , 2 0 ) ) ;
12 J L a b e l lm=new J L a b e l ( ” Primul numar : ” ) ;
13 c o n t e n t . add ( lm ) ;
14 tm=new J T e x t F i e l d ( ” 1 ” , 5 ) ;
15 c o n t e n t . add ( tm ) ;
16 J L a b e l l n=new J L a b e l ( ” Al d o i l e a numar : ” ) ;
17 c o n t e n t . add ( l n ) ;
18 tn=new J T e x t F i e l d ( ” 1 ” , 5 ) ;
19 c o n t e n t . add ( tn ) ;
20 JButton compute=new JButton ( ” 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 c o n t e n t . add ( compute ) ;
23 r e z=new J T e x t F i e l d ( ” 1 ” , 5 ) ;
24 rez . setEditable ( false ) ;
25 c o n t e n t . add ( r e z ) ;
26 s e t V i s i b l e ( true ) ;
27 }
29 public void p a i n t ( G r a p h i c s g ) {
30 S t r i n g sm=tm . g e t T e x t ( ) ;
31 long m=Long . par se Lon g ( sm ) ;
32 S t r i n g sn=tn . g e t T e x t ( ) ;
33 long n=Long . p ars eL ong ( sn ) ;
34 long c=cmmdc(m, n ) ;
35 r e z . s e t T e x t ( (new Long ( c ) ) . t o S t r i n g ( ) ) ;
36 }
• 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.
import netscape.javascript.*;
Pachetul netscape.javascript se află ı̂n distribuţia jdk ı̂n catalogul JAVA HOME\
jre\lib\plugin.jar. Pentru compilare, variabila de sistem classpath trebuie să
conţină această referinţă.
18 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.
19
20 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
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.
2.4. APLICAŢIE CLIENT – SERVER CU SOCLURI 23
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 . S c a n n e r ;
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 }
27 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
28 long m, n , r ;
29 System . out . p r i n t l n ( ”m=” ) ;
30 m=s c a n n e r . nextLong ( ) ;
31 System . out . p r i n t l n ( ”n=” ) ;
32 n=s c a n n e r . nextLong ( ) ;
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 }
24 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA
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:
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 }
2.4. APLICAŢIE CLIENT – SERVER CU SOCLURI 25
Î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 }
26 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA
2.5 Datagrame
Pentru utilizarea datagramelor pachetul java.net pune la dispoziţie clasele
• DatagramSocket
• DatagramPacket
• MulticastSocket
Acest constructor este folosit pentru crearea unui pachet ı̂n vederea expedierii.
Corpul pachetului este conţinut ı̂n tamponul buffer având lung octeţi. Pa-
chetul va fi trimis către adresa şi portul specificat. Trebuie să existe un server
UDP care ascultă la portul specificat pentru trimiterea pachetelor. Un server
UDP poate coexista cu un server TCP care ascultă acelaşi port.
Metode
• InetAddress getAddress()
returnează adresa IP a pachetului.
• 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.
• InetAddress getLocalAddress()
Returnează adresa locală către care este legat acest DatagramSocket;
• int getLocalPort()
Returnează numărul de port unde ascultă DatagramSocket.
• void close()
Închide DatagramSocket.
• byte [ ] getAddress()
Returnează şirul de octeţi corespunzător obiectului InetAddress de referinţă.
• 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 ]+ ” . ” ) ;
2.5. DATAGRAME 31
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 }
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 . S c a n n e 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 ) ;
2.5. DATAGRAME 33
20 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
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 ( ) ) ;
34 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA
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 ) {
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
• MulticastSocket(int port) throws SocketException
Metode
• void joinGroup(InetAddress adresă) throws SocketException
Soclul se ”conectează” la grupul definit de adresa IP (de tip D, adică cuprins
ı̂ntre 224.0.0.0 şi 239.255.255.255).
• void leaveGroup(InetAddress adresă) throws SocketException
Soclul se ”deconectează” la grupul definit de adresa IP.
• void close()
Pregătirea clientului ı̂n vederea recepţionării datagramelor printr-un soclu de tip
MulticastSocket constă din
MulticastSocket socket= new MulticastSocket(port);
InetAddress adresa=InetAddress.getByName("230.0.0.1");
socket.joinGroup(adresa);
În final, clientul se deconectează şi ı̂nchide soclul.
socket.leaveGroup(adresa);
socket.close();
Pachetele trimise de programul server trebuie să se adreseze grupului, identificat
prin adresa IP de tip D.
Astfel prin multicast serverul trimite pachete la o adresă de grup şi la un port
fixat. Pachetele emise de server sunt recepţionate de orice client ce crează un soclu de
tip MulticastSocket pentru portul la care emite serverul şi care se alătură grupului.
Prin broadcast serverul emite datagrame către orice calculator al reţelei locale
la un anumit port. Faptul că emiterea datagramelor este de tip broadcast se indică
prin
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.
36 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA
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.
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();
} }
} }
Introducerea şi extragerea datelor din tampon se poate face ı̂n mod
Metode
Introducerea datelor ı̂n mod relativ:
• ByteBuffer put(byte b)
• ByteBuffer putTip(tip x )
• byte get()
• tip getTip()
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 SocketChannel sc = null ;
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 ( ) ;
42 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 java . u t i l . Scanner ;
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 o c k e t C h a n n e 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 o c k e t C h a n n 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 43
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
44 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 45
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 java . u t i l . Scanner ;
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 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
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 ( ) ;
46 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 // System . s e t P r o p e r t y (” h t t p . p r o x y H o s t ” , ” 1 0 . 3 . 5 . 1 3 3 ” ) ;
9 // System . s e t P r o p e r t y (” h t t p . p r o x y P o r t ” , ” 3 1 2 8 ” ) ;
1
apache-tomcat, apache, Micrsoft IIS (Internet Information Services), etc.
2.7. CONEXIUNI HTTP 47
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.
49
50 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 javax.naming.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
javax.naming.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:
• 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.
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 java . u t i l . Scanner ;
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 }
41 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
42 System . out . p r i n t l n ( ” I n t r o d u c e t i r e f e r i n t a a b s o l u t a a unui c a t a l o g : ” ) ;
43 S t r i n g myName=s c a n n e r . n e x t ( ) ;
44 try {
45 System . out . p r i n t l n ( ” \n c t x . l o o k u p ( ”+myName+” ) p r o d u c e ” ) ;
46 System . out . p r i n t l n ( c t x . l o o k u p (myName ) ) ;
56 NamingEnumeration l s t 1 = c t x . l i s t B i n d i n g s (myName ) ;
57 while ( l s t 1 . hasMore ( ) ) {
58 B i n d i n g bd = ( B i n d i n g ) l s t 1 . n e x t ( ) ;
59 System . out . p r i n t l n ( bd ) ;
60 }
61 ctx . c l o s e ( ) ;
62 }
63 catch ( NamingException e ) {
64 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 ( ) ) ;
65 }
66 }
67 }
sau
java Lookup
caz, ı̂n care, ı̂n catalogul curent se găseşte fişierul jndi.properties cu conţinutul
java.naming.factory.initial=com.sun.jndi.fscontext.RefFSContextFactory
3.1.1 LDAP
LDAP poate fi privit ca un sistem de gestiune a unei baze de date (ne relaţional).
Baza de date este alcătuită din atribute ale căror nume este precizat de protocolul
LDAP.
Punctele de intrare (rădăcinile) sunt date de DN (Distinguished Name). Uzual
DN se defineşte printr-una din variantele
1. o=”organization”,c=”country”
2. o=”organization”
Un utilizator este caracterizat prin atributul cn - common name şi are acces la
LDAP prin precizarea simultană a atributelor DN şi cn.
Vom utiliza produsul OpenDS (Directory Service), ce implementează protocolul
LDAP.
Instalarea constă din:
1. dezarhivarea distribuţiei;
54 CAPITOLUL 3. REGĂSIREA OBIECTELOR PRIN SERVICII DE NUME
Declararea unui utilizator se face prin Manage Entries → Entries → New User,
urmat de completarea datelor cerute.
Schimbarea parolei unui utilizator se face tot din Manage Entries urmat de clic-
dreapta pe DN şi Reset User Password.
Prin această componentă se poate porni şi opri serverul OpenDS, ambele operaţii
putând fi executate şi apelând start-ds, stop-ds din catalogul
OpenDS HOME\bat.
Exemplul 3.1.2 Program pentru ı̂nregistrarea şi ştergerea referinţei unui obiect de
tip Cmmdc.
8 public c l a s s LDAPServerCmmdc {
9 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
10 H a s h t a b l e env = new H a s h t a b l e ( ) ;
11 env . put ( Context . INITIAL CONTEXT FACTORY,
12 ”com . sun . j n d i . l d a p . LdapCtxFactory ” ) ;
13 env . put ( Context . PROVIDER URL,
14 ” l d a p : / / l o c a l h o s t : 3 8 9 / cn=i n f o , dc=example , dc=com” ) ;
15 env . put ( Context . SECURITY PRINCIPAL , ” cn=D i r e c t o r y Manager ” ) ;
16 env . put ( Context . SECURITY CREDENTIALS, ” 1 q2w3e ” ) ; // p a r o l a
17 DirContext ctx = null ;
19 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
3.1. JAVA NAMING AND DIRECTORY INTERFACE 55
27 try {
28 c t x = new I n i t i a l D i r C o n t e x t ( env ) ;
29 c t x . unbind ( ” cn=”+cmmdcObj ) ;
30 i f ( o p e r ==1){
31 Cmmdc o b j=new Cmmdc ( ) ;
32 S t r i n g s t r=” cn=”+cmmdcObj ;
33 c t x . bind ( s t r , o b j ) ;
34 }
35 ctx . c l o s e ( ) ;
36 }
37 catch ( NamingException e ) {
38 System . out . p r i n t l n ( ”LDAPserverCmmdc : ”+e . g e t M e s s a g e ( ) ) ;
39 }
40 }
41 }
Exemplul 3.1.3 Utilizarea unui obiect de tip Cmmdc regăsit pe baza referintei din
serverul LDAP.
8 public c l a s s LDAPClientCmmdc {
9 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
10 H a s h t a b l e env = new H a s h t a b l e ( ) ;
11 env . put ( Context . INITIAL CONTEXT FACTORY,
12 ”com . sun . j n d i . l d a p . LdapCtxFactory ” ) ;
13 env . put ( Context . PROVIDER URL,
14 ” l d a p : / / l o c a l h o s t : 3 8 9 / cn=i n f o , dc=example , dc=com” ) ;
15 env . put ( Context . SECURITY PRINCIPAL , ” cn=D i r e c t o r y Manager ” ) ;
16 env . put ( Context . SECURITY CREDENTIALS, ” 1 q2w3e ” ) ;
17 DirContext ctx = null ;
18 try {
56 CAPITOLUL 3. REGĂSIREA OBIECTELOR PRIN SERVICII DE NUME
19 c t x=new I n i t i a l D i r C o n t e x t ( env ) ;
20 i f ( c t x != n u l l ) {
21 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
22 System . out . p r i n t l n ( ” I n t r o d u c e t i v a l o a r e a a t r i b u t u l u i \” cn \” ” +
23 ” a o b i e c t u l u i Cmmdc” ) ;
24 System . out . p r i n t l n ( ” cn=” ) ;
25 S t r i n g cmmdcObj=s c a n n e r . n e x t ( ) . t r i m ( ) ;
26 O b j e c t o b j e c t = c t x . l o o k u p ( ” cn=”+cmmdcObj ) ;
27 System . out . p r i n t l n ( ” Primul numar” ) ;
28 long a=s c a n n e r . n e x t I n t ( ) ;
29 System . out . p r i n t l n ( ” Al d o i l e a numar” ) ;
30 long b=s c a n n e r . n e x t I n t ( ) ;
31 Cmmdc o b j =(Cmmdc) o b j e c t ;
32 System . out . p r i n t l n ( ” R e z u l t a t u l cmmdc e s t e : ”+o b j . cmmdc( a , b ) ) ;
33 }
34 }
35 catch ( NamingException e ) {
36 System . out . p r i n t l n ( ”LDAPClientCmmdc : ”+e . g e t M e s s a g e ( ) ) ;
37 }
38 }
39 }
Capitolul 4
Invocarea procedurilor la
distanţă
• Invocarea procedurilor la distanţă ı̂n cazul medii neomogene. Soluţia ı̂n acest
caz este dat de Common Object Request Broker 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.
57
58 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 java.rmi.registry.Registry1 .
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 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 // i m p o r t j a v a . rmi . r e g i s t r y . ∗ ;
8 // V a r i a n t a JNDI
9 import j a v a x . naming . ∗ ;
26 // V a r i a n t a d i r e c t a
27 /∗
28 R e g i s t r y r e g i s t r y=L o c a t e R e g i s t r y . g e t R e g i s t r y ( h o s t , p o r t ) ;
29 r e g i s t r y . b i n d (” CmmdcServer ” , s t u b ) ;
30 ∗/
32 // V a r i a n t a JNDI
33 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 ( ) ;
34 System . s e t P r o p e r t y ( Context . INITIAL CONTEXT FACTORY,
35 ”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 ” ) ;
36 System . s e t P r o p e r t y ( Context . PROVIDER URL, ” rmi : / / ”+h o s t+” : ”+s P o r t ) ;
37 Context c t x=new I n i t i a l C o n t e x t ( ) ;
38 c t x . bind ( ”CmmdcServer” , s t u b ) ;
40 <target name=”Rmi”>
41 <exec e x e c u t a b l e=” r m i r e g i s t r y ”>
42 <arg v a l u e=” 1099 ” />
43 </ exec>
44 </ target>
Obiectivele Rmi şi Server se lansează ı̂n ferestre dos distincte care rămân
active pe durata de viaţă a aplicaţiei server.
1 package c l i e n t ;
3 import cmmdc . ∗ ;
4 import j a v a . u t i l . S c a n n e r ;
5 // V a r i a n t a d i r e c t a
6 // i m p o r t j a v a . rmi . r e g i s t r y . ∗ ;
7 // V a r i a n t a JNDI
8 import j a v a x . naming . ∗ ;
10 public c l a s s CmmdcClient {
11 public s t a t i c void main ( S t r i n g a r g s [ ] ) {
12 S t r i n g h o s t=” l o c a l h o s t ” ;
13 i n t p o r t =1099;
14 i f ( a r g s . l e n g t h >0)
15 h o s t=a r g s [ 0 ] ;
16 i f ( a r g s . l e n g t h >1)
17 p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
18 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
19 System . out . p r i n t l n ( ” Primul numar : ” ) ;
20 long m=Long . par se Lon g ( s c a n n e r . n e x t ( ) ) ;
21 System . out . p r i n t l n ( ” Al d o i l e a numar : ” ) ;
22 long n=Long . p ars eL ong ( s c a n n e r . n e x t ( ) ) ;
23 long x =0;
24 try {
25 // V a r i a n t a d i r e c t a
26 /∗
27 R e g i s t r y r e g i s t r y=L o c a t e R e g i s t r y . g e t R e g i s t r y ( h o s t , p o r t ) ;
28 ICmmdc o b j =(ICmmdc) r e g i s t r y . l o o k u p (” CmmdcServer ” ) ;
29 ∗/
30 // V a r i a n t a JNDI
31 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 ( ) ;
32 System . s e t P r o p e r t y ( Context . INITIAL CONTEXT FACTORY,
33 ”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 ” ) ;
34 System . s e t P r o p e r t y ( Context . PROVIDER URL, ” rmi : / / ”+h o s t+” : ”+s P o r t ) ;
35 Context c t x=new I n i t i a l C o n t e x t ( ) ;
36 ICmmdc o b j =(ICmmdc) c t x . l o o k u p ( ”CmmdcServer” ) ;
38 x=o b j . cmmdc(m, n ) ;
39 System . out . p r i n t l n ( ”Cmmdc=”+x ) ;
40 }
41 catch ( E x c e p t i o n e ) {
42 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 ( ) ) ;
43 }
44 }
45 }
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 im po rt 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 }
respectiv
1 package cmmdc0 ;
2 im po rt j a v a . rmi . ∗ ;
3 im po rt j a v a . rmi . s e r v e r . ∗ ;
4 im po rt 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 {
4.1. REMOTE METHOD INVOCATION 67
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 os t , 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
Clientul obţine stub-ul serviciului, prin intermediul căruia apelează metada
getCmmdc() a fabricii de obiecte, obţinând un obiect remote de tip Server-
Cmmdc, ce implementează interfaţa la distanţă ICmmdc0.
1 package cmmdc0 ;
2 im po rt j a v a . rmi . ∗ ;
3 im po rt j a v a . rmi . s e r v e r . ∗ ;
4 im po rt 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 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 im po rt j a v a . u t i l . S c a n n e 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 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
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 ) ;
27 }
28 }
1 package cmmdc0 ;
2 im po rt j a v a . rmi . ∗ ;
4.1. REMOTE METHOD INVOCATION 69
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” ) )
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);
70 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANŢĂ
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 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
15 System . out . p r i n t l n ( ” A l e g e t i v a r i a n t a a l g o r i t m u l u i l u i E u c l i d ” ) ;
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)
21 method=”NERECURSIV” ;
22 else
23 method=”RECURSIV” ;
24 r e t u r n method ;
25 }
şi
1 package cmmdc0 ;
2 im po rt j a v a . u t i l . S c a n n e 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)
4.1. REMOTE METHOD INVOCATION 71
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 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
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 }
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.
72 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANŢĂ
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 }
2. java.class.path=no.classpath
ceea ce previne grupul de activare să ı̂ncarce o clasă din classpath-ul local;
1 package acmmdc ;
3 im po rt j a v a . rmi . ∗ ;
4 im po rt j a v a . rmi . a c t i v a t i o n . ∗ ;
5 im po rt j a v a . rmi . r e g i s t r y . ∗ ;
6 im po rt 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 . out . p r i n t l n ( ” u s a g e : ” ) ;
18 System . out . p r i n t l n ( ” 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 >” ) ;
19 System . e x i t ( 1 ) ;
20 }
21 else {
74 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANŢĂ
22 implClass = args [ 0 ] ;
23 }
25 // 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
26 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 ” ) ;
27 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 ” ) ;
28 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 ” , ” ” ) ;
29 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 ( ) ;
30 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 ) ;
31 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 ” ) ;
32 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 ) ;
33 i f ( filename != n u l l && ! filename . equals ( ” ” ) ) {
34 p r o p s . put ( ” m y a c t i v a t i o n . f i l e ” , filename ) ;
35 }
36 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 ) ;
38 // 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
39 // 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
40 Act ivat ionG roupI D groupID=
41 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 ) ;
42 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 . ” ) ;
44 // 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
45 M a r s h a l l e d O b j e c t data = n u l l ;
46 i f ( filename != n u l l && ! filename . equals ( ” ” ) ) {
47 data = new M a r s h a l l e d O b j e c t ( filename ) ;
48 }
50 A c t i v a t i o n D e s c d e s c=
51 new A c t i v a t i o n D e s c ( groupID , i m p l C l a s s , implCodebase , data ) ;
53 // 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
54 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 ) ;
55 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 . ” ) ;
57 // 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
58 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” ) ;
59 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 ) ;
60 System . e r r . p r i n t l n ( ” Stub bound i n r e g i s t r y . ” ) ;
61 }
62 }
grant {
// allow activation groups to use certain system properties
permission com.sun.rmi.rmid.ExecOptionPermission
4.2. CORBA 75
"-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
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 Broker Arhi-
tecture): 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.
76 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANŢĂ
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
Broker (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 Definition 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.
2. Implementarea interfeţei
1 package cmmdciiop ;
2 im po rt j a v a x . rmi . P o r t a b l e R e m o t e O b j e c t ;
3 im po rt cmmdc . ∗ ;
4 im po rt 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 im po rt j a v a x . naming . I n i t i a l C o n t e x t ;
3 im po rt j a v a x . naming . Context ;
6 p u b l i c c l a s s CmmdcServer {
7 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 ) {
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=” 1050 ” ;
10 i f ( a r g s . l e n g t h >0)
11 h o s t=a r g s [ 0 ] ;
12 i f ( a r g s . l e n g t h >1)
13 p o r t=a r g s [ 1 ] ;
14 try {
15 // 1 : C r e a r e a u n e i i n s t a n t e CmmdcImpl
16 CmmdcImpl cmmdcRef = new CmmdcImpl ( ) ;
18 // 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
19 // u t i l i z a n d JNDI API
20 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 ” ,
21 ”com . sun . j n d i . cosnaming . CNCtxFactory ” ) ;
22 System . s e t P r o p e r t y ( ” j a v a . naming . p r o v i d e r . u r l ” ,
23 ” i i o p : // ”+h o s t+” : ”+p o r t ) ;
24 Context c t x = new I n i t i a l C o n t e x t ( ) ;
25 c t x . r e b i n d ( ” CmmdcService ” , cmmdcRef ) ;
26 System . out . p r i n t l n ( ”Cmmdc S e r v e r : Ready . . . ” ) ;
27 }
28 catch ( Exception e ) {
78 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANŢĂ
32 </ target>
46 <target name=”Orb”>
47 <exec e x e c u t a b l e=” orbd ”>
48 <arg l i n e=”−O R B I n i t i a l P o r t ${ p o r t } −O R B I n i t i a l H o s t ${ h o s t } ” />
49 </ exec>
50 </ target>
1 package cmmdciiop ;
2 import j a v a . rmi . ∗ ;
3 import j a v a x . rmi . ∗ ;
4 import j a v a . n e t . MalformedURLException ;
5 import j a v a x . naming . ∗ ;
6 import j a v a . u t i l . S c a n n e r ;
7 import cmmdc . ∗ ;
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 [ ] ) {
11 S t r i n g h o s t=” l o c a l h o s t ” ;
12 S t r i n g p o r t=” 1050 ” ;
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=a r g s [ 1 ] ;
18 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
19 System . out . p r i n t l n ( ” Primul numar : ” ) ;
20 long m=Long . par se Lon g ( s c a n n e r . n e x t ( ) ) ;
21 System . out . p r i n t l n ( ” Al d o i l e a numar : ” ) ;
22 long n=Long . p ars eL ong ( s c a n n e r . n e x t ( ) ) ;
23 try {
80 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANŢĂ
24 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 ” ,
25 ”com . sun . j n d i . cosnaming . CNCtxFactory ” ) ;
26 System . s e t P r o p e r t y ( ” j a v a . naming . p r o v i d e r . u r l ” ,
27 ” i i o p : / / ”+h o s t+” : ”+p o r t ) ;
28 Context c t x = new I n i t i a l C o n t e x t ( ) ;
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.
Fişierul buildfile pentru executarea clientului:
1 <project name=” C l i e n t ” d e f a u l t=” I n s t a l l ” b a s e d i r=” . ”>
2 <description>C l i e n t a c t i o n s</ description>
3 < !−− s e t g l o b a l p r o p e r t i e s f o r t h i s b u i l d −−>
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;
4.2. CORBA 83
• 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 im po rt CmmdcApp . ∗ ;
2 im po rt o r g . omg . CosNaming . ∗ ;
3 im po rt o r g . omg . CosNaming . NamingContextPackage . ∗ ;
4 im po rt o r g . omg .CORBA. ∗ ;
5 im po rt 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 ) ;
84 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANŢĂ
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
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ă
4.2. CORBA 85
javac CmmdcApp\*.java
1 im po rt java . u t i l . Properties ;
2 im po rt o r g . omg .CORBA. ∗ ;
3 im po rt o r g . omg . CosNaming . ∗ ;
4 im po rt o r g . omg . P o r t a b l e S e r v e r . ∗ ;
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 ) ;
Programul client
1 im po rt java . u t i l . Properties ;
2 im po rt o r g . omg .CORBA. ∗ ;
3 im po rt o r g . omg . CosNaming . ∗ ;
4 im po rt o r g . omg . P o r t a b l e S e r v e r .POA;
6 im po rt CmmdcApp . CmmdcHelper ;
7 im po rt CmmdcApp . Cmmdc ;
8 im po rt j a v a . u t i l . S c a n n e r ;
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 (
4.2. CORBA 87
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 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
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:
2. Activarea serverului:
3. Executarea clientului
java PersistentClient [hostORB [portORB]]
Capitolul 5
89
90 CAPITOLUL 5. MESAJE ÎN JAVA
imqbroker@hostname:7676 ready
serviciul JMS ca serviciu Windows. Dezinstalarea şi instalarea are efect odată cu
repornirea calculatorului.
Compilarea şi executarea unui program necesită completarea variabilei sistem
classpath cu fişierele
• JMS HOME\lib\jms.jar
• JMS HOME\lib\imq.jar
set JAVA_HOME=. . .
set ACTIVEMQ_HOME=. . .
%ACTIVEMQ_HOME%\bin\activemq
Î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.
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{
TopicConnection createTopicConnection() throws JMSException;
TopicConnection createTopicConnection(String userName,
String password) throws JMSException;
}
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
|
|->interface Queue
|
|->interface Topic
Utilizând Oracle-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);
}
96 CAPITOLUL 5. MESAJE ÎN JAVA
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 i m p l e m e n t e a 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 .
28 // ActiveMQConnectionFactory (” t c p : / / l o c a l h o s t : 6 1 6 1 6 ” ) ;
29 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 ( ) ;
30 S e s s i o n s e s s i o n=conn . c r e a t e S e s s i o n ( f a l s e , S e s s i o n .AUTO ACKNOWLEDGE) ;
32 D e s t i n a t i o n q=s e s s i o n . c r e a t e Q u e u e ( queueName ) ;
34 MessageProducer p r o d u c e r=s e s s i o n . c r e a t e P r o d u c e r ( q ) ;
36 TextMessage m=s e s s i o n . c r e a t e T e x t M e s s a g e ( ) ;
37 f o r ( i n t i =0; i <n ; i ++){
38 m. s e t T e x t ( ” H e l l o ”+i ) ;
39 p r o d u c e r . send (m) ;
40 }
41 // 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
5.4. ELEMENTE DE PROGRAMARE - JMS 97
42 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 ( ) ) ;
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 System . out . p r i n t l n ( ” Sen de r f i n i s h e d ” ) ;
50 }
51 }
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()
98 CAPITOLUL 5. MESAJE ÎN JAVA
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 .
24 // ActiveMQConnectionFactory (” t c p : / / l o c a l h o s t : 6 1 6 1 6 ” ) ;
25 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 ( ) ;
26 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) ;
27 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 ) ;
28 MessageConsumer consumer=s e s s i o n . createConsumer ( q ) ;
29 conn . s t a r t ( ) ;
30 Message msg=n u l l ;
31 while ( ( msg=consumer . r e c e i v e ( ) ) ! = n u l l ) {
32 i f ( msg instanceof TextMessage ) {
33 TextMessage m=(TextMessage ) msg ;
34 System . out . p r i n t l n (m. g e t T e x t ( ) ) ;
35 }
36 else
37 break ;
38 }
39 session . close ();
40 conn . c l o s e ( ) ;
41 }
42 catch ( E x c e p t i o n e ) {
43 System . out . p r i n t l n ( ” JMSException : ”+e . g e t M e s s a g e ( ) ) ;
44 }
45 System . out . p r i n t l n ( ” Consumer f i n i s h e d ” ) ;
46 }
47 }
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;
5.4. ELEMENTE DE PROGRAMARE - JMS 99
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 }
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 .
23 // ActiveMQConnectionFactory (” t c p : / / l o c a l h o s t : 6 1 6 1 6 ” ) ;
100 CAPITOLUL 5. MESAJE ÎN JAVA
25 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 ( ) ;
26 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) ;
27 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 ) ;
28 MessageConsumer consumer=s e s s i o n . createConsumer ( q ) ;
29 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 ( ) ;
30 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 ) ;
31 conn . s t a r t ( ) ;
32 t e x t L i s t e n e r . run ( ) ;
33 conn . c l o s e ( ) ;
34 }
35 catch ( E x c e p t i o n e ) {
36 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
37 }
38 System . out . p r i n t l n ( ” Consumer f i n i s h e d ” ) ;
39 }
40 }
ı̂mpreună cu ascultătorul
1 import j a v a x . jms . ∗ ;
2 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 {
3 boolean s f a r s i t =f a l s e ;
4 public void onMessage ( Message message ) {
5 i f ( message instanceof TextMessage ) {
6 TextMessage m=(TextMessage ) message ;
7 try {
8 System . out . p r i n t l n (m. g e t T e x t ( ) ) ;
9 }
10 catch ( JMSException e ) {
11 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
12 }
13 }
14 else
15 s f a r s i t =true ;
16 }
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 .
23 // ActiveMQConnectionFactory (” t c p : / / l o c a l h o s t : 6 1 6 1 6 ” ) ;
25 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 ( ) ;
26 TopicSession session =
27 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) ;
28 Destination t = session . createTopic ( subiect ) ;
29 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 ) ;
34 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 ( ) ;
35 f o r ( i n t i =0; i <n ; i ++){
36 m. s e t T e x t ( ” Despre ”+s u b i e c t+” ”+i ) ;
37 p r o d u c e r . send (m) ;
38 // p u b l i s h e r . p u b l i s h (m) ;
39 }
40 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 ( ) ) ;
41 // 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 ( ) ) ;
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 ( ” P u b l i s h e r f i n i s h e d ” ) ;
49 }
50 }
TopicSubscriber consumer=session.createSubscriber((Topic)t);
102 CAPITOLUL 5. MESAJE ÎN JAVA
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 .
25 // ActiveMQConnectionFactory (” t c p : / / l o c a l h o s t : 6 1 6 1 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 t = session . createTopic ( subiect ) ;
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 , c l i e n t N a m e ) ;
34 conn . s t a r t ( ) ;
35 Message msg=n u l l ;
36 while ( ( msg=consumer . r e c e i v e ( ) ) ! = n u l l ) {
37 i f ( msg instanceof TextMessage ) {
38 TextMessage m=(TextMessage ) msg ;
39 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 ( ) ) ;
40 }
41 else
42 break ;
43 }
44 session . close ();
5.5. MESAJE SOAP PRIN JAVA MESSAGE SERVICE 103
45 conn . c l o s e ( ) ;
46 }
47 catch ( E x c e p t i o n e ) {
48 System . out . p r i n t l n ( ” JMSException : ”+e . g e t M e s s a g e ( ) ) ;
49 }
50 }
51 }
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 ] ;
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).
Execuţia programelor utilizând resurse SOAP necesită declararea ı̂n variabila de
sistem classpath a referinţei către saaj-impl.jar.
• un corp (body);
SOAPPart part=soapMsg.getSOAPPart();
SOAPEnvelope envelope=part.getEnvelope();
SOAPHeader header=envelope.getHeader();
SOAPBody body=envelope.getBody();
În general, un element se include ı̂n elementul părinte, care pote fi chiar şi body, prin
metoda clasei SOAPElement
SOAPElement addChildElement(Name name)
Completăm elementul e1 cu un text: ”primul”, prin
e1.addTextNode("primul");
Exemplul 5.5.1 Mesajul SOAP
1 <SOAP−ENV:Envelope
2 xmlns:SOAP−ENV=” h t t p : // schemas . x m l s o a p . o r g / s o a p / e n v e l o p e / ”>
3 <SOAP−ENV:Header />
4 <SOAP−ENV:Body>
5 <e1>
6 primul
7 <e11>
8 al treilea
9 </ e11>
10 </ e1>
11 <e2>
12 al doilea
13 </ e2>
14 </SOAP−ENV:Body>
15 </SOAP−ENV:Envelope>
se obţine cu programul
1 import j a v a x . xml . soap . ∗ ;
2 import j a v a . i o . ∗ ;
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 Me ss age Fa cto ry mf=Mes sa ge Fac 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 ( ) ;
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 e O u t p u t S t r e a m f=new F i l e O u t p u t S t r e a m ( ”MySOAPMessage . xml” ) ;
23 soapMsg . w r i t e T o ( 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 }
106 CAPITOLUL 5. MESAJE ÎN JAVA
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 {
5.5. MESAJE SOAP PRIN JAVA MESSAGE SERVICE 107
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 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
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 Me ss age Fa ct ory 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 TopicSession session =
40 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) ;
41 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” ) ;
42 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 ) ;
43 mf=Me ss age Fa cto ry . n e w I n s t a n c e ( ) ;
44 soapMsg=mf . c r e a t e M e s s a g e ( ) ;
45 p a r t=soapMsg . getSOAPPart ( ) ;
46 e n v e l o p e=p a r t . g e t E n v e l o p e ( ) ;
47 body=e n v e l o p e . getBody ( ) ;
48 name=e n v e l o p e . createName ( ” n1 ” ) ;
49 elem=body . addChildElement ( name ) ;
50 elem . addTextNode ( (new Long ( a ) ) . t o S t r i n g ( ) ) ;
51 name=e n v e l o p e . createName ( ” n2 ” ) ;
52 elem=body . addChildElement ( name ) ;
53 elem . addTextNode ( (new Long ( b ) ) . t o S t r i n g ( ) ) ;
54 name=e n v e l o p e . createName ( ” t o p i c ” ) ;
55 elem=body . addChildElement ( name ) ;
56 elem . addTextNode ( t o p i c R e s u l t ) ;
57 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 ) ;
58 T o p i c S u b s c r i b e r consumer=
59 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 ) ;
60 Message m=
61 M es s ag e Tr an s fo r me r . SOAPMessageIntoJMSMessage ( soapMsg , s e s s i o n ) ;
62 p r o d u c e r . send (m) ;
63 F i l e O u t p u t S t r e a m f=new F i l e O u t p u t S t r e a m ( ”MySOAPMessage . xml” ) ;
64 soapMsg . w r i t e T o ( f ) ;
65 conn . c l o s e ( ) ;
108 CAPITOLUL 5. MESAJE ÎN JAVA
66 }
67 catch ( E x c e p t i o n e ) {
68 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 ( ) ) ;
69 }
70 System . out . p r i n t l n ( ” Sen de r f i n i s h e d ” ) ;
71 }
• 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 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
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 Me ss age Fa ct ory mf=n u l l ;
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=Me ss age Fa cto ry . n e w I n s t a n c e ( ) ;
5.5. MESAJE SOAP PRIN JAVA MESSAGE SERVICE 109
40 conn . s t a r t ( ) ;
41 Message msg=consumer . r e c e i v e ( ) ;
42 soapMsg=Me s sa ge T ra n sf 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 }
6 public c l a s s MsgSOAPCmmdcServer{
10 public void s e r v i c e ( ) {
11 Mess ag eFa ct ory 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 ” ) ;
110 CAPITOLUL 5. MESAJE ÎN JAVA
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=Me ss age Fa cto ry . 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=Me s sa ge 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 . p ars 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=
63 M es s ag e Tr an s fo r me r . SOAPMessageIntoJMSMessage ( soapMsg , s e s s i o n ) ;
64 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 ) ;
65 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 ) ;
66 p r o d u c e r . send (m) ;
67 }
68 }
69 catch ( E x c e p t i o n e ) {
70 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 ( ) ) ;
71 }
72 System . out . p r i n t l n ( ” S e r v e r f i n i s h e d ” ) ;
73 }
Mesajul SOAP utilizat de client, pentru n1 = 45, n2 = 35 şi topic = nume este
5.5. MESAJE SOAP PRIN JAVA MESSAGE SERVICE 111
<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");
• Ataşament imagine jpeg/png
(a) Crearea unui obiect de tip AttachmentPart cu ı̂ncărcarea imaginii.
URL url=new URL("file://localhost/c:\\. . .\\***.jpg");
DataHandler dataHandler = new DataHandler(url);
AttachmentPart attachment =
soapMsg.createAttachmentPart(dataHandler);
attachment.setContentId("Imagine1");
• Ataşament cu sunet ı̂n format mp3.
(a) Crearea unui obiect de tip AttachmentPart cu ı̂ncărcarea fişierului
mp3.
URL url=new URL("file://localhost/c:\\. . .\\***.mp3");
DataHandler dataHandler=new DataHandler(url);
AttachmentPart attachment =
soapMsg.createAttachmentPart(dataHandler);
attachment.setContentId("attached_mp3");
112 CAPITOLUL 5. MESAJE ÎN JAVA
• Ataşament video.
(a) Fişierele video au de obicei dimensiuni mari. Pentru a putea in-
clude asemenea fişiere trebuie mărită dimensiunea maximă a unui
ataşament prin includerea setării
imq.autocreate.destination.maxBytesPerMsg=35M
ı̂n fişierul mq\lib\props\broker\install.properties.
(b) Crearea unui obiect de tip AttachmentPart cu ı̂ncărcarea fişierului
cu conţinut video.
String video_location="c:\\. . .’’;
URL url=new URL("file://"+video_location);
dataHandler= new DataHandler(url);
AttachmentPart attachment =
soapMsg.createAttachmentPart(dataHandler);
(c) Pentru redarea conţinutului video vom avem nevoie de tipul conţinutului
video, informaţie dată de extensia fişierului video. Aceată dată este
furnizată prin metoda setContentId.
File videoFile = new File(video_location);
String fileName = videoFile.getName();
int index=fileName.lastIndexOf(".");
String ext=fileName.substring(index+1);
attachment.setContentId("attached_video"+ext);
Extragerea ataşamentelor
Tipul unui ataşament se poate deduce din rezultatul metodei getContentId sau
getContentType a clasei AttachmentPart.
Iterator iterator = soapMsg.getAttachments();
while (iterator.hasNext()) {
AttachmentPart attached =
(AttachmentPart)iterator.next();
// Codul de identificare
String id = attached.getContentId();
// Tipul atasamentului
String type = attached.getContentType();
. . .
}
Exemplul 5.5.3 Crearea unui mesaj SOAP cu ataşamente text, imagine, muzică
mp3 şi video. Textul, imaginea, muzica mp3 şi conţinutul video sunt conţinute ı̂n
fişiere. Căile către aceste fişiere se vor da ca proprietăţi.
114 CAPITOLUL 5. MESAJE ÎN JAVA
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 . 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;
42 // Crearea a t a s a m e n t u l u i de t i p t e x t
44 AttachmentPart attachment1=soapMsg . c r e a t e A t t a c h m e n t P a r t ( ) ;
46 F i l e R e a d e r f r = new F i l e R e a d e r (new F i l e ( f i l e l o c a t i o n ) ) ;
47 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 ) ;
49 S t r i n g stringContent = ”” ;
50 S t r i n g l i n e = br . r e a d L i n e ( ) ;
51 while ( l i n e != n u l l ) {
52 stringContent = stringContent . concat ( l i n e ) ;
53 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” ) ;
54 l i n e = br . r e a d L i n e ( ) ;
55 }
57 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 ” ) ;
58 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 ” ) ;
59 soapMsg . addAttachmentPart ( attachment1 ) ;
5.5. MESAJE SOAP PRIN JAVA MESSAGE SERVICE 115
61 // Crearea a t a s a m e n t u l u i de t i p imagine
62 URL u r l = new URL( ” f i l e : / / ”+i m a g e l o c a t i o n ) ;
63 DataHandler d a t a H a n d l e r = new DataHandler ( u r l ) ;
64 AttachmentPart attachment2 =
65 soapMsg . c r e a t e A t t a c h m e n t P a r t ( d a t a H a n d l e r ) ;
67 attachment2 . s e t C o n t e n t I d ( ” a t t a c h e d i m a g e ” ) ;
68 soapMsg . addAttachmentPart ( attachment2 ) ;
91 Message m=
92 M es s ag e Tr an s fo r me r . SOAPMessageIntoJMSMessage ( soapMsg , s e s s i o n ) ;
93 // p u b l i s h e r . p u b l i s h (m) ;
94 p r o d u c e r . send (m) ;
95 F i l e O u t p u t S t r e a m f=new F i l e O u t p u t S t r e a m ( ”MySOAPMessage . xml” ) ;
96 soapMsg . w r i t e T o ( f ) ;
97 conn . c l o s e ( ) ;
98 }
99 catch ( E x c e p t i o n e ) {
100 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 ( ) ) ;
101 }
102 System . out . p r i n t l n ( ” P u b l i s h e r f i n i s e d ” ) ;
103 }
104 }
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 . ∗ ;
7 import n e t . s f . fmj . u t i l i t y . URLUtils ;
8 import n e t . s f . fmj . u i . FmjStudio ;
116 CAPITOLUL 5. MESAJE ÎN JAVA
25 conn . s t a r t ( ) ;
26 Message msg=n u l l ;
27 Me ss age Fa ct ory mf=Me ssa ge Fac to ry . n e w I n s t a n c e ( ) ;
28 while ( ( msg=consumer . r e c e i v e ( ) ) ! = n u l l ) {
29 SOAPMessage soapMsg =
30 M es s ag e Tr an s fo r me r . SOAPMessageFromJMSMessage ( msg , mf ) ;
31 System . out . p r i n t l n ( ” Mesaj SOAP r e c e p t i o n a t ” ) ;
32 // E x t r a g e r e a a t a s a m e n t e l o r
33 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 ( ) ;
34 while ( i t e r a t o r . hasNext ( ) ) {
35 AttachmentPart a t t a c h e d =(AttachmentPart ) i t e r a t o r . n e x t ( ) ;
36 String id = attached . getContentId ( ) ;
37 S t r i n g t y p e = a t t a c h e d . getContentType ( ) ;
38 System . out . p r i n t l n ( ” Attachment ” + i d +
39 ” has c o n t e n t t y p e ” + t y p e ) ;
40 i f ( type . e q u a l s ( ” t e x t / p l a i n ” ) ) {
41 S t r i n g content = ( S t r i n g ) attached . getContent ( ) ;
42 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 ) ;
43 }
44 i f ( t y p e . e q u a l s ( ” image / j p e g ” ) ) {
45 Image image=(Image ) a t t a c h e d . g e t C o n t e n t ( ) ;
46 ShowImage s=new ShowImage ( image ) ;
47 s . show ( ) ;
48 }
49 i f ( t y p e . e q u a l s ( ” a u d i o /x−wav” ) ) {
50 System . out . p r i n t l n ( ” Play MP3” ) ;
51 MP3Player mp3Player=new MP3Player ( a t t a c h e d . getRawContent ( ) ) ;
52 mp3Player . s t a r t ( ) ;
53 }
54 i f ( id . startsWith ( ” attached video ” )){
55 S t r i n g vi d e o F il e N a m e = ” v i d e o F i l e . ”+i d . s u b s t r i n g ( 1 4 ) ;
56 InputStream i n p u t S t r e a m = a t t a c h e d . getRawContent ( ) ;
57 F i l e f=new F i l e ( v i de o F i l eN a m e ) ;
58 OutputStream out=new F i l e O u t p u t S t r e a m ( f ) ;
59 byte b u f [ ] =new byte [ 1 0 2 4 ] ;
60 int l e n ;
61 while ( ( l e n=i n p u t S t r e a m . r e a d ( b u f )) >0) out . w r i t e ( buf , 0 , l e n ) ;
62 out . c l o s e ( ) ;
63 S t r i n g [ ] arguments = new S t r i n g [ 1 ] ;
64 arguments [ 0 ] = URLUtils . c r e a t e U r l S t r ( f ) ;
65 System . out . p r i n t l n ( ” P r e s s Enter t o c o n t i n u e ! ” ) ;
66 System . i n . r e a d ( ) ;
67 System . out . p r i n t l n ( ” Video show ” ) ;
68 FmjStudio . main ( arguments ) ;
5.5. MESAJE SOAP PRIN JAVA MESSAGE SERVICE 117
69 }
70 }
71 }
72 conn . c l o s e ( ) ;
73 }
74 catch ( E x c e p t i o n e ) {
75 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 ( ) ) ;
76 }
77 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 ” ) ;
78 }
79 }
Utilizarea aplicaţiei se face prin ant pe structura iniţială de cataloage şi fişiere
app
|--> resources
| | resursele text, imagine, mp3, video
|--> src
| | MsgAttach.java
| | MsgSOAPPublisher.java
| | MsgSOAPSubscriber.java
| | MP3Player.java
| | ShowImage.java
| logging.properties (din FMJ)
| build.xml
48 </ p r o j e c t>
8 c l a s s MyCanvas e x t e n d s Canvas {
9 Image image=n u l l ;
20 p u b l i c c l a s s ShowImage{
21 MyCanvas mc=n u l l ;
27 p u b l i c v o i d show ( ) {
28 // I n t e r f a t a swing
29 JFrame j f r a m e = new JFrame ( ”The r e c e i v e d image ” ) ;
30 jframe . addNotify ( ) ;
31 j f r a m e . getContentPane ( ) . s e t L a y o u t ( new BorderLayout ( ) ) ;
32 j f r a m e . getContentPane ( ) . add (mc , BorderLayout .CENTER) ;
33 j f r a m e . s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ;
34 jframe . s e t S i z e (200 ,200);
35 jframe . s e t V i s i b l e ( true ) ;
36 }
37 }
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 im po rt j a v a . i o . ∗ ;
2 im po rt javazoom . j l . p l a y e r . P l a y e r ;
4 p u b l i c c l a s s MP3Player e x t e n d s Thread {
5 private Player player ;
7 p u b l i c MP3Player ( InputStream i s ) {
8 try {
9 B u f f e r e d I n p u t S t r e a m b i s=new B u f f e r e d I n p u t S t r e a m ( i s ) ;
10 p l a y e r=new P l a y e r ( b i s ) ;
11 }
12 catch ( Exception e ){
13 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
14 System . e x i t ( 1 ) ;
15 }
16 }
18 p u b l i c v o i d run ( ) {
19 try {
20 player . play ( ) ;
21 }
22 catch ( Exception e ){
23 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
24 }
25 i f ( p l a y e r != n u l l ) p l a y e r . c l o s e ( ) ;
26 }
27 }
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
21 @REM D e l e t e t h e c e r t
22 del qpidBroker . cer
12 MsgSenderT ( S t r i n g queueName , i n t n ) {
13 QUEUE JNDI NAME=queueName ;
14 t h i s . n=n ;
15 }
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 ( ” Sen de r f i n i s h e d ” ) ;
42 }
62 private void c l o s e J N D I ( ) {
63 try {
64 ctx . c l o s e ( ) ;
65 }
66 catch ( NamingException e ) {
67 System . e r r . p r i n t l n ( ” Unable t o c l o s e JNDI Context : ” + e ) ;
68 }
69 }
70 }
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 . ∗ ;
11 SyncMsgReceiverT ( S t r i n g queueName ) {
12 QUEUE JNDI NAME=queueName ;
13 }
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 }
5.6. PROGRAME JMS PRIN APACHE-QPID 123
38 }
39 session . close ();
40 conn . c l o s e ( ) ;
41 }
42 catch ( E x c e p t i o n e ) {
43 System . out . p r i n t l n ( ” JMSException : ”+e . g e t M e s s a g e ( ) ) ;
44 }
45 System . out . p r i n t l n ( ” Consumer f i n i s h e d ” ) ;
46 }
50 private void c l o s e J N D I ( ) { . . . }
52 }
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 TOPIC JNDI NAME=s u b i e c t ;
15 }
29 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 ) ;
30 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 ( ) ;
31 f o r ( i n t i =0; i <n ; i ++){
32 m. s e t T e x t ( ” Despre JMS”+” ”+i ) ;
124 CAPITOLUL 5. MESAJE ÎN JAVA
33 p r o d u c e r . send (m) ;
34 }
35 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 ( ) ) ;
36 session . close ();
37 conn . c l o s e ( ) ;
38 }
39 catch ( E x c e p t i o n e ) {
40 System . out . p r i n t l n ( ” JMSException : ”+e . g e t M e s s a g e ( ) ) ;
41 }
42 System . out . p r i n t l n ( ” P u b l i s h e r f i n i s h e d ” ) ;
43 }
47 private void c l o s e J N D I ( ) { . . . }
49 }
Clasa MsgSubscriberT
1 j a v a x . jms . ∗ ;
2 import j a v a x . naming . ∗ ;
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 TOPIC JNDI NAME=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 ( ) ) ;
5.6. PROGRAME JMS PRIN APACHE-QPID 125
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 }
56 private void c l o s e J N D I ( ) { . . . }
58 }
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 . t o p i c = 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 Oracle-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 rem imqobjmgr add −t t f − l ” C o n n e c t i o n F a c t o r y ”
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 q − l ” queue ”
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
11 rem imqobjmgr add −t t − l ” t o p i c ”
12 −j j a v a . naming . p r o v i d e r . u r l= f i l e : /// c : /Temp
13 −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
• message queue – coadă ı̂n care se păstrează mesaje până ce acestea sunt con-
sumate de o aplicaţie client.
Proprietăţile unei cozi sunt:
– numele, alcătuit din litere, cifre, caracterul de subliniere, cel mult 255 de
caracter.
– persistenţa mesajului ı̂n cazul ı̂ncetării funcţionării serverului (durable
message queue, temporary message queue).
– modul de ştergere a mesajelor după consumarea acestora (auto-delete).
• distribuirea publicare-abonare
• amq.direct
• amq.fanout
• amq.topic
2. Instanţierea sesiunii
3. Declararea cozii
session.sync();
session.close();
con.close();
Exemplul 5.7.1 Crearea unei cozi care să primească mesaje prin distribuire directă
şi fanout.
1 import o r g . apache . q p i d . t r a n s p o r t . ∗ ;
3 public c l a s s DeclareQueue {
4 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
5 i f ( a r g s . l e n g t h <5){
6 System . out . p r i n t l n ( ” Usage j a v a DeclareQueue b r o k e r ” +
7 ” p o r t queueName exchange bindingKey ” ) ;
8 System . e x i t ( 1 ) ;
9 }
10 S t r i n g b r o k e r=a r g s [ 0 ] ;
11 i n t 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 S t r i n g queueName=a r g s [ 2 ] ;
13 S t r i n g exchange=a r g s [ 3 ] ;
14 S t r i n g bindingKey=a r g s [ 4 ] ;
16 // Crearea c o n e x i u n i i
17 C o n n e c t i o n con = new C o n n e c t i o n ( ) ;
18 con . c o n n e c t ( b r o k e r , p o r t , ” t e s t ” , ” g u e s t ” , ” g u e s t ” , f a l s e ) ;
20 // Crearea s e s i u n i i
21 S e s s i o n s e s s i o n = con . c r e a t e S e s s i o n ( 0 ) ;
23 // D e c l a r a r e a c o z i i
24 s e s s i o n . q u e u e D e c l a r e ( queueName , null , n u l l ) ;
25 s e s s i o n . exchangeBind ( queueName , exchange , bindingKey , n u l l ) ;
27 // Confirmarea c r e e r i i c o z i i
28 s e s s i o n . sync ( ) ;
30 // I n c h i d e r e a s e s i u n i i s i a c o n e x i u n i i
31 session . close ();
32 con . c l o s e ( ) ;
33 }
34 }
2. Instanţierea sesiunii
session.messageTransfer(dispecerulDeDirectionare,
MessageAcceptMode.EXPLICIT,
MessageAcquireMode.PRE_ACQUIRED,
new Header(deliveryProps),
mesaj_text);
session.sync();
session.close();
con.close();
1 import o r g . apache . q p i d . t r a n s p o r t . ∗ ;
3 public c l a s s Se nd er {
4 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
5 i f ( a r g s . l e n g t h <5){
6 System . out . p r i n t l n ( ” Usage j a v a S en der b r o k e r p o r t ” +
7 ” exchange r o u t i n g K e y messagesNumber ” ) ;
8 System . e x i t ( 1 ) ;
9 }
10 S t r i n g b r o k e r=a r g s [ 0 ] ;
11 i n t 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 S t r i n g exchange=a r g s [ 2 ] ;
13 S t r i n g r o u t i n g K e y=a r g s [ 3 ] ;
14 i n t n=I n t e g e r . p a r s e I n t ( a r g s [ 4 ] ) ;
16 // Crearea c o n e x i u n i i
17 C o n n e c t i o n con = new C o n n e c t i o n ( ) ;
18 con . c o n n e c t ( b r o k e r , p o r t , ” t e s t ” , ” g u e s t ” , ” g u e s t ” , f a l s e ) ;
5.7. PROTOCOLUL AMQP 131
20 // Crearea s e s i u n i i
21 S e s s i o n s e s s i o n = con . c r e a t e S e s s i o n ( 0 ) ;
23 // P r e c i z a r e a ( daca e s t e n e v o i e ) a c h e i i de r u t a r e
24 D e l i v e r y P r o p e r t i e s d e l i v e r y P r o p s = new D e l i v e r y P r o p e r t i e s ( ) ;
25 d e l i v e r y P r o p s . s etR ou ti ngK ey ( r o u t i n g K e y ) ;
27 // Formarea s i e x p e d i e r e a m e s a j e l o r
28 f o r ( i n t i =0; i <n ; i ++){
29 s e s s i o n . m e s s a g e T r a n s f e r ( exchange ,
30 MessageAcceptMode . EXPLICIT ,
31 MessageAcquireMode . PRE ACQUIRED,
32 new Header ( d e l i v e r y P r o p s ) ,
33 ” Message ” + i ) ;
34 }
35 s e s s i o n . m e s s a g e T r a n s f e r ( exchange ,
36 MessageAcceptMode . EXPLICIT ,
37 MessageAcquireMode . PRE ACQUIRED,
38 new Header ( d e l i v e r y P r o p s ) ,
39 ”” ) ;
41 // Confirmarea r e c e p t i e i m e s a j e l o r
42 s e s s i o n . sync ( ) ;
44 // I n c h i d e r e a s e s i u n i i s i a c o n e x i u n i i
45 session . close ();
46 con . c l o s e ( ) ;
47 }
48 }
2. Instanţierea sesiunii
session.messageSubscribe(numeCoada,
"listener_destination",
MessageAcceptMode.NONE,
MessageAcquireMode.PRE_ACQUIRED,
null, 0, null);
session.messageFlow("listener_destination",
MessageCreditUnit.BYTE, Session.UNLIMITED_CREDIT);
session.messageFlow("listener_destination",
MessageCreditUnit.MESSAGE, 11);
session.sync();
6. Oprirea ascultătorului
session.messageCancel("listener_destination");
session.close();
con.close();
Exemplul 5.7.3 Recepţia mesajelor expediate ı̂n clasa Sender, creata anterior. Pro-
gramul se va termina ı̂n momentul ı̂n care ascultătorul primeşte un mesaj fără
conţinut.
1 import o r g . apache . q p i d . t r a n s p o r t . ∗ ;
3 c l a s s L i s t e n e r implements S e s s i o n L i s t e n e r {
4 boolean s f a r s i t =f a l s e ;
23 public c l a s s R e c e i v e r {
24 public s t a t i c void main ( S t r i n g [ ] a r g s ) throws I n t e r r u p t e d E x c e p t i o n {
25 i f ( a r g s . l e n g t h <3){
26 System . out . p r i n t l n ( ” Usage j a v a S en der b r o k e r p o r t queueName” ) ;
27 System . e x i t ( 1 ) ;
28 }
29 S t r i n g b r o k e r=a r g s [ 0 ] ;
30 i n t p o r t=I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
31 S t r i n g queueName=a r g s [ 2 ] ;
33 // Crearea c o n e x i u n i i
34 C o n n e c t i o n con = new C o n n e c t i o n ( ) ;
35 con . c o n n e c t ( b r o k e r , p o r t , ” t e s t ” , ” g u e s t ” , ” g u e s t ” , f a l s e ) ;
37 // Crearea s e s i u n i i
38 S e s s i o n s e s s i o n = con . c r e a t e S e s s i o n ( 0 ) ;
40 // Generarea u n e i i n s t a n t e a a s c u l t a t o r u l u i
41 L i s t e n e r l i s t e n e r = new L i s t e n e r ( ) ;
42 session . setSessionListener ( listener );
44 // Crearea a b o n a t u l u i c a r e r e c e p t i o n e a z e m e s a j e l e
45 s e s s i o n . m e s s a g e S u b s c r i b e ( queueName ,
46 ”listener destination” ,
47 MessageAcceptMode .NONE,
48 MessageAcquireMode . PRE ACQUIRED,
49 null , 0 , n u l l ) ;
50 s e s s i o n . messageFlow ( ” l i s t e n e r d e s t i n a t i o n ” ,
51 M e s s a g e C r e d i t U n i t .BYTE, S e s s i o n . UNLIMITED CREDIT ) ;
52 s e s s i o n . messageFlow ( ” l i s t e n e r d e s t i n a t i o n ” ,
53 M e s s a g e C r e d i t U n i t .MESSAGE, 1 1 ) ;
55 // Confirmarea t e r m i n a r i i t r a n s m i t e r i i m e s a j e l o r
56 s e s s i o n . sync ( ) ;
58 // A b o n a t u l a s t e a p t a r e c e p t i o n a r e a t u t u r o r m e s a j e l o
59 l i s t e n e r . run ( ) ;
61 // O p r i r e a a s c u l t a t o r u l u i
62 System . out . p r i n t l n ( ” S h u t t i n g down l i s t e n e r f o r l i s t e n e r d e s t i n a t i o n ” ) ;
63 s e s s i o n . messageCancel ( ” l i s t e n e r d e s t i n a t i o n ” ) ;
65 // I n c h i d e r e a s e s i u n i i s i a c o n e x i u n i i
66 session . close ();
134 CAPITOLUL 5. MESAJE ÎN JAVA
67 con . c l o s e ( ) ;
68 }
69 }
Utilizând clasele prezentate mai sus, prin fixarea convenabilă a parametrilor şi
a ordinii de lansare a programelor se poate exemplifica specificul celor trei dispeceri
de direcţionare:
Codurile pentru execuţie prin ant sunt
• Distribuirea directă:
• Distribuirea fanout:
<target name="queue">
<java classname="DeclareQueue" fork="yes" maxmemory="100M">
<classpath refid="qpid.classpath" />
<arg line="localhost 5672 q1 amq.fanout xxx"/>
</java>
<java classname="DeclareQueue" fork="yes" maxmemory="100M">
<classpath refid="qpid.classpath" />
<arg line="localhost 5672 q2 amq.fanout yyy"/>
</java>
</target>
<target name="sender">
<java classname="Sender" fork="yes" maxmemory="100M">
<classpath refid="qpid.classpath" />
<arg line="localhost 5672 amq.fanout zzz 2"/>
</java>
</target>
<target name="receiver">
<sleep seconds="5" />
<parallel>
<java classname="Receiver" fork="yes" maxmemory="100M">
<classpath refid="qpid.classpath" />
<arg line="localhost 5672 q1"/>
</java>
<java classname="Receiver" fork="yes" maxmemory="100M">
5.7. PROTOCOLUL AMQP 135
<target name="queue">
<java classname="DeclareQueue" fork="yes" maxmemory="100M">
<classpath refid="qpid.classpath" />
<arg line="localhost 5672 q1 amq.topic unitbv.#.topic"/>
</java>
<java classname="DeclareQueue" fork="yes" maxmemory="100M">
<classpath refid="qpid.classpath" />
<arg line="localhost 5672 q2 amq.topic unitbv.cs.*"/>
</java>
</target>
<target name="receiver">
<parallel>
<java classname="Receiver" fork="yes" maxmemory="100M">
<classpath refid="qpid.classpath" />
<arg line="localhost 5672 q1"/>
</java>
<java classname="Receiver" fork="yes" maxmemory="100M">
<classpath refid="qpid.classpath" />
<arg line="localhost 5672 q2"/>
</java>
</parallel>
</target>
<target name="sender">
<java classname="Sender" fork="yes" maxmemory="100M">
<classpath refid="qpid.classpath" />
<arg line="localhost 5672 amq.topic unitbv.cs.topic 5"/>
</java>
</target>
În cazul distribuirii fanout şi a celei bazate pe publicare-abonare sunt lansate ı̂n
ordine două cozi cu câte un receptor de mesaje (Receiver ) urmat de producătorul
de mesaje (Sender ).
136 CAPITOLUL 5. MESAJE ÎN JAVA
Capitolul 6
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.
Programarea şi utilizarea unui servlet necesită:
137
138 CAPITOLUL 6. SERVLET
• apache-tomcat
• jetty
• JBoss
• CATALINA HOME= calea la catalogul ı̂n care s-a instalat produsul - TOMCAT HOME;
Pachetul conţine cataloagele1 : bin, common, conf, logs, server, shared, temp,
webapps, work.
Serverul se lansează prin comanda
TOMCAT HOME\bin\startup
TOMCAT HOME\bin\shutdown
1
Numele şi numărul cataloagelor este dependent de distribuţia apache-tomcat.
140 CAPITOLUL 6. SERVLET
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/context/numeApel
6.3. REALIZAREA UNUI SERVLET 143
unde
Contextul este legat de fişierul web.xml şi poate conţine o mulţime de servleţi, fiecare
identificându-se prin numeApel.
Dacă context-ul servletului conţine fişierul index.html atunci aplicaţia se poate
apela prin http:// host:port/context.
Dacă este prezent elementul <welcome-file-list> ı̂n fişierul web.xml atunci
apelarea aplicaţiei poate fi http:// host:port/context/fisier.html—jsp, unde fişier.html
sau jsp este unul din fişierele declarate ı̂ntr-un element <welcome-file> .
<init-param>
<param-name> NumeleParametrului </param-name>
<param-value> Valoare </param-value>
</init-param>
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!.
12 <p>
13 <input type=” submit ”>
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>
6.3. REALIZAREA UNUI SERVLET 147
Compilarea şi arhivarea servlet-ului o vom realiza prin intermediul lui apache-
ant. În acest scop se crează structura:
hello
| |---> src
| | | HelloServlet.java
| |---> lib
| |---> web
| | | web.xml
| |---> web-files
| | | index.html
| build.xml
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 . ∗ ;
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.
• GET
• POST
cu uri=”http://host:port/catalog/numeApel”.
3. Lansarea cererii.
HttpResponse response=httpclient.execute(httpget);
respectiv
HttpResponse response=httpclient.execute(httppost);
4. Preluarea răspunsului.
6.4. FACILITĂŢI DE PROGRAMARE CU SERVLET 151
HttpEntity entity=response.getEntity();
if(entity!=null){
InputStream is=entity.getContent();
int l;
byte[] tmp=new byte[2048];
while((l=is.read(tmp))!=-1){}
. . .
}
1 import j a v a . u t i l . S c a n n e r ;
2 import j a v a . u t i l . L i s t ;
3 import j a v a . u t i l . A r r a y L i s t ;
5 import o r g . apache . h t t p . H t t p E n t i t y ;
6 import o r g . apache . h t t p . HttpResponse ;
7 import o r g . apache . h t t p . c l i e n t . H t t p C l i e n t ;
8 import o r g . apache . h t t p . c l i e n t . methods . HttpPost ;
9 import o r g . apache . h t t p . impl . c l i e n t . D e f a u l t H t t p C l i e n t ;
10 import o r g . apache . h t t p . NameValuePair ;
11 import o r g . apache . h t t p . message . BasicNameValuePair ;
12 import o r g . apache . h t t p . c l i e n t . e n t i t y . UrlEncodedFormEntity ;
14 import j a v a . i o . ∗ ;
16 public c l a s s ClientCmmdcServlet2 {
17 s t a t i c S t r i n g u r i=” h t t p : / / l o c a l h o s t : 8 0 8 0 / m y s e r v l e t /cmmdc” ;
26 // C r e a t e an i n s t a n c e o f H t t p C l i e n t .
27 H t t p C l i e n t h t t p c l i e n t = new D e f a u l t H t t p C l i e n t ( ) ;
29 // C r e a t e a method i n s t a n c e .
30 L i s t <NameValuePair> qparams = new A r r a y L i s t <NameValuePair > ( ) ;
31 qparams . add (new BasicNameValuePair ( ”m” , m) ) ;
32 qparams . add (new BasicNameValuePair ( ”n” , n ) ) ;
33 qparams . add (new BasicNameValuePair ( ” t i p ” , ” t e x t / p l a i n ” ) ) ;
34 try {
35 UrlEncodedFormEntity params=new UrlEncodedFormEntity ( qparams , ”UTF−8” ) ;
36 HttpPost h t t p p o s t=new HttpPost ( u r i ) ;
37 h t t p p o s t . s e t E n t i t y ( params ) ;
38 HttpResponse r e s p o n s e=h t t p c l i e n t . e x e c u t e ( h t t p p o s t ) ;
39 H t t p E n t i t y e n t i t y=r e s p o n s e . g e t E n t i t y ( ) ;
40 i f ( e n t i t y != n u l l ) {
41 InputStream i s=e n t i t y . g e t C o n t e n t ( ) ;
42 int l ;
43 byte [ ] tmp=new byte [ 2 0 4 8 ] ;
44 while ( ( l=i s . r e a d ( tmp))!= −1){}
152 CAPITOLUL 6. SERVLET
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 {
28 }
29 else {
30 try {
31 n=Long . p ars eL ong ( 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 {
22 s e s s i o n . s e t A t t r i b u t e ( ” noAcces ” , c o n t o r ) ;
23 out . p r i n t l n ( ”<html><body>” ) ;
24 out . p r i n t l n ( ”<h1>”+mesaj+”</h1>” ) ;
25 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 ” +
26 contor . intValue ( ) ) ;
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
156 CAPITOLUL 6. SERVLET
Cookie [ ] cookies=request.getCookies();
if(cookies!=null){
for(int i=0;i<cookies.length;i++){
String name=cookies[i].getName();
String valoare=cookies[i].getValue();
. . .
}
Exemplul 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 {
20 c o n t o r ++;
21 mesaj=” Bine a t i r e v e n i t ! ” ;
22 }
23 }
24 }
25 else {
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 {
158 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>
6.4. FACILITĂŢI DE PROGRAMARE CU SERVLET 159
Acest element apare ı̂n corpul elementului <servlet> ataşat servlet-ului. Servletul
se apelează prin http://host:port/context/numeApel.
7 public c l a s s A g e n d a E M a i l S e r v l e t extends H t t p S e r v l e t {
8 Statement i n s t r u c t i u n e=n u l l ;
38 myAtribut=r e q . g e t P a r a m e t e r ( ” c r i t e r i u ” ) ;
39 myVal=r e q . g e t P a r a m e t e r ( ” termen ” ) ;
40 myVal= ’ \ ’ ’+myVal+ ’ \ ’ ’ ;
41 try {
42 S t r i n g s q l=” s e l e c t ∗ from a d r e s e where ”+ myAtribut+” = ”+myVal ;
43 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 ) ;
160 CAPITOLUL 6. SERVLET
44 out . p r i n t l n ( ”<html>” ) ;
45 out . p r i n t l n ( ”<head><t i t l e >AgendaEMail</ t i t l e ></head>” ) ;
46 out . p r i n t l n ( ”<body>” ) ;
47 out . p r i n t l n ( ”<h1>Agenda de Adrese e−m a i l </h1>” ) ;
48 out . p r i n t l n ( ”<p/>” ) ;
49 out . p r i n t l n ( ”<b> Nume <−−> Adresa e−m a i l </b>” ) ;
50 out . p r i n t l n ( ”<br/>” ) ;
51 while ( r s . n e x t ( ) ) {
52 out . p r i n t ( r s . g e t S t r i n g ( ”nume”)+” <−−> ”+r s . g e t S t r i n g ( ” e m a i l ” ) ) ;
53 out . p r i n t l n ( ”<br/>” ) ;
54 }
55 out . p r i n t l n ( ”</body>” ) ;
56 out . p r i n t l n ( ”</html>” ) ;
57 out . c l o s e ( ) ;
58 }
59 catch ( SQLException e ) {
60 System . out . p r i n t l n ( ” SQLException : ”+e . g e t M e s s a g e ( ) ) ;
61 }
62 catch ( E x c e p t i o n e ) {
63 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 ( ) ) ;
64 }
65 }
response.setContentType("image/ext");
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 . ∗ ;
11 // 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
12 String f =
13 ”d : \ \ apache−tomcat − 6 . 0 . 2 0 \ \ webapps \\ m y s e r v l e t \\WEB−INF\\ ”+
14 ” c l a s s e s \\ w a l k i n g s a n t a . g i f ” ;
15 // T r a n f e r a r e a f i s i e r u l u i g r a f i c
16 F i l e I n p u t S t r e a m f i s = new F i l e I n p u t S t r e a m ( f ) ;
17 B u f f e r e d I n p u t S t r e a m b i s = new B u f f e r e d I n p u t S t r e a m ( f i s ) ;
18 byte [ ] b y t e s = new byte [ b i s . a v a i l a b l e ( ) ] ;
19 i n t nread = 0 ;
20 while (−1 != ( nread = b i s . r e a d ( b y t e s ) ) ) {
21 out . w r i t e ( b y t e s , 0 , nread ) ;
22 }
23 }
24 }
1 mport j a v a . i o . ∗ ;
2 import j a v a . awt . ∗ ;
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 . ∗ ;
5 import j a v a x . i m a g e i o . ∗ ;
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 j a v a . u t i l . ∗ ;
36 // Raspunsul c a t r e c l i e n t
37 out . p r i n t l n ( ”<HTML><BODY>” ) ;
38 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>” ) ;
39 out . p r i n t l n ( ”<p><a h r e f =\” h t t p : / / l o c a l h o s t : 8 0 8 0 / m y s e r v l e t / ”+
40 numeFis+” . ”+e x t+”\”>” ) ;
41 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>” ) ;
42 out . p r i n t l n ( ”</BODY></HTML>” ) ;
43 out . c l o s e ( ) ;
44 }
45 finally {
46 // E l i b e r a r e a r e s u r s e l o r
47 i f ( g != n u l l ) g . d i s p o s e ( ) ;
48 i f ( frame != n u l l ) frame . r e m o v e N o t i f y ( ) ;
49 }
50 }
51 }
Clasa GifEncoder care realizează codarea, face parte din pachetul Acme.JPM.Encoders,
disponibil gratuit la adresa web http://www.acme.com.
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 }
164 CAPITOLUL 6. SERVLET
• 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 {
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 Oracle−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 ( ) ;
6.4. FACILITĂŢI DE PROGRAMARE CU SERVLET 165
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 . par se Lon g ( sm ) ;
42 long b=Long . p ars eL ong ( 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 Oracle−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 ” ) ;
166 CAPITOLUL 6. SERVLET
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 }
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 Oracle−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=
6.5. FILEUPLOAD 167
În catalogul lib al servlet-ului trebuie incluse fişierele jar ale serviciului JMS folosit.
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
168 CAPITOLUL 6. SERVLET
• 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
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();
170 CAPITOLUL 6. SERVLET
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 {
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 }
14 </ s c r i p t>
15 </head>
16 <body>
17 <h1> I n c ă r c a r e a unui f i ş i e r </h1>
18 <form
19 action=” h t t p : / / l o c a l h o s t : 8 0 8 0 / u pl oa d / u pl oa d ”
20 e n c t y p e=” m u l t i p a r t / form−data ” method=” p o s t ”
21 name=” l i n e a r ” onSubmit=” r e t u r n c h e c k I t ( ) ”>
22 <p>
23 S e l e c t a ţ i f i ş i e r u l
24 <p>
25 <input type=” f i l e ” name=” m y f i l e ” s i z e =30>
26 <p>
27 <input type=” submit ” value=” Expediaza f i s i e r u l ”>
28 </form>
29 </body>
30 </html>
Exemplul 6.6.1 Fişierul ales de client dintr-o lista disponibilă este descărcat fiind
transmis navigatorului.
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 D o w n l o a d S e r v l e t extends H t t p S e r v l e t {
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 S e r v l e t O u t p u t S t r e a m out=r e s . getOutputStream ( ) ;
9 S t r i n g f i l e =r e q . g e t P a r a m e t e r ( ” f i l e ” ) ;
10 S t r i n g c a l e=” webapps / download / r e s o u r c e s / ” ;
11 try {
12 F i l e I n p u t S t r e a m f i s = new F i l e I n p u t S t r e a m ( c a l e+ f i l e ) ;
13 B u f f e r e d I n p u t S t r e a m b i s = new B u f f e r e d I n p u t S t r e a m ( f i s ) ;
14 byte [ ] b y t e s = new byte [ b i s . a v a i l a b l e ( ) ] ;
15 r e s . setContentType ( ” A p p l i c a t i o n / Octet−stream ” ) ;
16 b i s . read ( bytes ) ;
17 out . w r i t e ( b y t e s ) ;
18 bis . close ( );
19 f i s . close ();
20 out . c l o s e ( ) ;
21 }
22 catch ( E x c e p t i o n e ) {
23 r e s . setContentType ( ” t e x t / p l a i n ” ) ;
24 out . p r i n t l n ( ” C e r e r e a d−v o a s t r a nu p o a t e f i s a t i s f a c u t a ” ) ;
25 }
26 out . c l o s e ( ) ;
27 }
31 doGet ( req , r e s ) ;
32 }
33 }
6.7 Filtru
Un filtru se asemeană unui servlet, dar activitatea ı̂ntreprinsă vizează uzual
contextul, adică ansamblul servleţilor care fac parte din aplicaţia Web.
Un filtru se declară ı̂n fişierul web.xml prin
<web-app>
. . .
<filter>
<filter-name>nume_filtru</filter-name>
<filter-class>clasa_filtrului</filter-class>
</filter>
<filter-mapping>
<filter-name>nume_filtru</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
. . .
</web-app>
Exemplul 6.7.1 Contextul myservlet conţine doi servleţi HelloServlet şi Cmmdc-
Servlet, apelabili respectiv din hello.html, cmmdc.html. Să se programeze un filtru
care
• Dacă se cere ca natura răspunsului să fie “text/xml” atunci invalidează cererea.
1 import j a v a . i o . IOException ;
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 M y F i l t e r D i s p a t c h e r implements F i l t e r {
6 private F i l t e r C o n f i g f i l t e r C o n f i g ;
12 public void d e s t r o y ( ) {
13 this . f i l t e r C o n f i g = null ;
14 }
16 public void d o F i l t e r ( S e r v l e t R e q u e s t r e q u e s t , S e r v l e t R e s p o n s e r e s p o n s e ,
17 F i l t e r C h a i n f i l t e r C h a i n ) throws IOException , S e r v l e t E x c e p t i o n {
18 HttpServletRequest req = ( HttpServletRequest ) request ;
19 HttpServletResponse res = ( HttpServletResponse ) response ;
20 S t r i n g u r i = r e q . getRequestURI ( ) ;
21 i f ( u r i . equals ( ”/ myservlet ” ) | | u r i . equals ( ”/ myservlet /” ) )
22 f i l t e r C h a i n . doFilter ( request , response ) ;
23 else {
24 i f ( u r i . equals ( ”/ myservlet / h e l l o ” )){
25 S t r i n g d i s p a t c h e r U r i=” /cmmdc . html ” ;
26 R e q u e s t D i s p a t c h e r rd=r e q u e s t . g e t R e q u e s t D i s p a t c h e r ( d i s p a t c h e r U r i ) ;
27 rd . f o r w a r d ( r e q u e s t , r e s p o n s e ) ;
28 }
29 else {
30 i n t i n d e x=u r i . l a s t I n d e x O f ( ” . ” ) ;
31 i f ( i n d e x==−1){
32 S t r i n g t i p=r e q . g e t P a r a m e t e r ( ” t i p ” ) ;
33 i f ( t i p . e q u a l s ( ” t e x t /xml” ) ) {
34 r e s . s e n d E r r o r ( H t t p S e r v l e t R e s p o n s e . SC FORBIDDEN ) ;
35 }
36 }
37 f i l t e r C h a i n . doFilter ( request , response ) ;
38 }
39 }
40 }
41 }
6 <web−app>
7 < f i l t e r>
8 < f i l t e r −name> f i l t e r D i s p a t c h e r</ f i l t e r −name>
9 < f i l t e r −c l a s s>M y F i l t e r D i s p a t c h e r</ f i l t e r −c l a s s>
10 </ f i l t e r >
12 < f i l t e r −mapping>
13 < f i l t e r −name> f i l t e r D i s p a t c h e r</ f i l t e r −name>
14 <u r l −p a t t e r n>/∗</ u r l −p a t t e r n>
15 </ f i l t e r −mapping>
6.7. FILTRU 175
17 < s e r v l e t>
18 <s e r v l e t −name>cmmdc</ s e r v l e t −name>
19 <s e r v l e t −c l a s s>CmmdcServlet</ s e r v l e t −c l a s s>
20 </ s e r v l e t>
22 < s e r v l e t>
23 <s e r v l e t −name> h e l l o</ s e r v l e t −name>
24 <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>
25 </ s e r v l e t>
27 <s e r v l e t −mapping>
28 <s e r v l e t −name> h e l l o</ s e r v l e t −name>
29 <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>
30 </ s e r v l e t −mapping>
32 <s e r v l e t −mapping>
33 <s e r v l e t −name>cmmdc</ s e r v l e t −name>
34 <u r l −p a t t e r n>/cmmdc</ u r l −p a t t e r n>
35 </ s e r v l e t −mapping>
37 </web−app>
36 </body>
37 </html>
Capitolul 7
177
178 CAPITOLUL 7. JAVA SERVER PAGE – JSP
1 <html>
2 <body>
3 Hello
4 </body>
5 </html>
ı̂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 :
10 <%= data1 %>
7.1. TEHNOLOGIA JSP 179
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
Variabila Tip/Clasa
out javax.servlet.jsp.JspWriter
request javax.servlet.ServletRequest
response javax.servlet.ServletResponse
session javax.servlet.http.HttpSession
page java.lang.Object, this
pageContext javax.servlet.jsp.PageContext
application javax.servlet.ServletContext
ServletContext.getServletConfig().getContext()
exception java.lang.Throwable
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 :
11 <input type=” t e x t ” name=”name” s i z e =20>
12 <p>
13 <input type=” submit ”>
7.1. TEHNOLOGIA JSP 181
14 </form>
15 </ center>
16 </body>
17 </html>
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>
<%! . . . %>
<jsp:declaration> . . . </jsp:declaration>
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.
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 . pa rse Lo ng ( 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.
• Directiva include permite includerea unor fişiere .html sau .jsp ı̂n document
Exemplul 7.1.4
1 package j s p ;
2 public c l a s s H e l l o B e a n {
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>
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.
13 public S t r i n g getM ( ) {
14 return m;
15 }
16 public S t r i n g getN ( ) {
17 return n ;
18 }
20 public S t r i n g getCmmdc ( ) {
21 long m=Long . par se Lon g ( getM ( ) ) ;
22 long n=Long . p ars eL ong ( getN ( ) ) ;
23 return (new Long (cmmdc(m, n ) ) ) . t o S t r i n g ( ) ;
24 }
28 }
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>
URI Descriere
http://java.sun.com/jsp/jstl/core Biblioteca de bază
http://java.sun.com/jsp/jstl/xml Biblioteca de prelucrare
a documentelor xml
http://java.sun.com/jsp/jstl/fmt Biblioteca de formatare a datelor
http://java.sun.com/jsp/jstl/sql Biblioteca de lucru cu baze de date
http://java.sun.com/jsp/jstl/functions Biblioteca de funcţii ajutătoare
Utilizarea bibliotecilor. În vederea utilizării, cele două fişiere trebuie copiate
ı̂n catalogul lib al aplicaţiei care utilizează bibliotecile.
În pagina / documentul JSP, o bibliotecă utilizată trebuie declarată printr-o
directivă taglib.
${requestScope.numeVariabilă}, ${sessionScope.numeVariabilă},
${applicationScope.numeVariabilă}.
Plasând clauza empty ı̂naintea unei variabile, ${empty numeVariabilă}, se
obţine false sau true după cum variabila are sau nu atribuită o valoare.
Î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 } ” >
23 E−m a i l :<c : out value=” $ {param . e m a i l } ” />
24 </ c : i f>
25 </BODY>
26 </HTML>
• 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>
196 CAPITOLUL 7. JAVA SERVER PAGE – JSP
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>
30 </ tr>
31 </ c : f o r E a c h>
32 </ table>
33 </ c : i f>
34 </BODY>
35 </HTML>
3. Marcajul taglib a fişierului web.xml, care permite serverului Web să găsească
descriptorul bibliotecii de marcaje.
(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://cs.unitbv.ro/mytaglib
</taglib-uri>
<taglib-location>
/WEB-INF/mylibtag.tld
</taglib-location>
</taglib>
7.3. MARCAJE JSP PERSONALE 199
webapps
|--> mytag
| |--> WEB-INF
| | |--> classes
| | | |--> jsp
| | | | |--> DateTag.class
| | | web.xml
| | | 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 : / / c s . u n i t b v . r o / 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>
200 CAPITOLUL 7. JAVA SERVER PAGE – JSP
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=” s i mb 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 : / / c s . u n i t b v . r o / 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>
202 CAPITOLUL 7. JAVA SERVER PAGE – JSP
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 : / / c s . u n i t b v . r o / 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>
204 CAPITOLUL 7. JAVA SERVER PAGE – JSP
Capitolul 8
Portlet
205
206 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 207
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
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 −−>
208 CAPITOLUL 8. PORTLET
25 <t a s k d e f
26 name=” a s s e m b l e ”
27 c l a s s n a m e=” o r g . apache . p l u t o . ant . AssembleTask ”
28 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 ”
29 />
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
210 CAPITOLUL 8. PORTLET
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-1.0.4.jar
| | pluto-ant-tasks-2.0.*.jar
| | pluto-descriptor-api-1.1.6.jar
| | pluto-descriptor-impl-1.1.6.jar
| | pluto-util-2.0.*.jar
| | pluto-container-2.0.0.jar
| | jaxb-api-2.1.jar
| | jaxb-impl-2.1.9.jar
|--> src
| |--> main
| | |--> java
| | | |--> pachetul portletului
| | |--> resource
| | | | NumePortlet.xml
| | |--> webapp
| | | |--> jsp
| | | | | fisierele jsp ale portletului
| | | |--> WEB-INF
| | | | | portlet.xml
| | | | | web.xml
8.3. ELEMENTE DE PROGRAMARE 211
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 ! ” ) ;
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.3. ELEMENTE DE PROGRAMARE 213
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 {
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> .
Exemplul 8.3.4 Cel mai mare divizor comun a două numere naturale ı̂ntr-un port-
let.
Variantă ı̂n care calculul este programat ı̂n portlet.
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 ;
10 throws P o r t l e t E x c e p t i o n , IOException {
11 r e s . setContentType ( ” t e x t / html ” ) ;
12 P o r t l e t R e q u e s t D i s p a t c h e r prd=n u l l ;
13 S t r i n g r e z=r e q . g e t P a r a m e t e r ( ” r e z ” ) ;
14 i f ( r e z==n u l l ) {
15 prd=g e t P o r t l e t C o n t e x t ( ) . g e t R e q u e s t D i s p a t c h e r ( ” / j s p / i n p u t . j s p ” ) ;
16 prd . i n c l u d e ( req , r e s ) ;
17 }
18 else {
19 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 ” ) ;
20 prd . i n c l u d e ( req , r e s ) ;
21 }
22 }
37 }
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 />
8.3. ELEMENTE DE PROGRAMARE 217
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=” ” ;
7 t h i s .m=m;
8 }
9 public void setN ( S t r i n g n ) {
10 t h i s . n=n ;
11 }
12 public S t r i n g getM ( ) {
13 return m;
14 }
15 public S t r i n g getN ( ) {
16 return n ;
17 }
18 public S t r i n g cmmdc ( ) {
19 long m0=Long . pa rs eL ong (m) ;
20 long n0=Long . pa rse Lo ng ( n ) ;
21 long c , r ;
22 do{
23 c=n0 ;
24 r=m0%n0 ;
25 m0=n0 ;
26 n0=r ;
27 }
28 while ( r ! = 0 ) ;
29 return (new Long ( c ) ) . t o S t r i n g ( ) ;
30 }
31 }
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>
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
prd=getPortletContext().getRequestDispatcher("/jsp/outputCmmdc.jsp");
apare
prd=getPortletContext().getRequestDispatcher("/cmmdc");
8.3. ELEMENTE DE PROGRAMARE 219
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>
Metode
• Enumeration<String> getNames()
Suport pentru acces la numele atributelor care au valoare.
• Map<String,String[]> getMap()
Suport pentru acces la atribute.
Exemplul 8.3.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 {
<portlet-preferences>
<preference>
<name>ATTR1</name>
<value>Programare distribuita</value>
<read-only>true</read-only>
</preference>
<preference>
<name>ATTR2</name>
<!--
<value>Analiza numerica</value>
-->
<read-only>true</read-only>
</preference>
</portlet-preferences>
Î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.4.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>
22 <j a v a c c l a s s p a t h r e f=” p r o j e c t . c l a s s p a t h ”
23 d e s t d i r=” ${ package }/${ b u i l d . d i r }/WEB−INF/ c l a s s e s ”
24 s r c d i r=” ${ package }/WEB−INF/ c l a s s e s ” />
25 </ t a r g e t>
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) Pentru fixarea
acestui parametru se va consulta fişierul web.xml.
• Numele portlet-ului aşa cum este definit ı̂n fişierul portlet.xml.
Clic Next.
(d) În meniul Portlet Preferences, clic Next.
224 CAPITOLUL 8. PORTLET
3. Fiecare client care poate utiliza portlet-ul - adică cei din grupul selectat, ı̂l
publică prin componenta Add Content.
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.
Un client elimină un portlet prin clic pe butonul Remove din fereastra portlet-
ului.
Administratorul portalului şterge un portlet prin clic pe butonul de ı̂nchidere
ı̂n lista portlet-elor publicate din AdminTools → Portlet Manager → Modify a
currently published channel.
Asemănător, se pot publica ı̂n uPortal aplicaţii Web. Deosebirea esenţială este
că tipul canalului (Channel Type) este WebProxy sau Inline Frame.
8.4.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-*. Astfel, lansarea se face apelând bin\startup.bat.
Portalul se accesează, dintr-un navigator, prin
8.4. PRODUSE PORTAL 225
http://localhost:8080/jetspeed
Desfăşurarea unui portlet constă ı̂n copierea arhivei war corespunzătoare, re-
alizat ı̂n 8.4.1, ı̂n catalogul
227
228 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. Se arhivează aplicaţia
jar cfv cmmdc.jar *.class
4. Ansamblul
cmmdc
| cmmdc.jar
| cmmdc.html
| launch.jnlp
se copiază ı̂n serverul Web (ı̂n cazul IIS acest loc este catalogul
InetPub\wwwroot).
Dintr-un navigator, apelarea aplicaţiei este http://host/cmmdc/cmmdc.html.
230 CAPITOLUL 9. JAVA WEB START
app
|--- cmmdc.jar
|--- launch.jnlp
WEB-INF
|--- lib
| |--- jnlp-servlet.jar
|--- web.xml
cmmdc.html
6. Utilizând apache-tomcat sau jetty, de exemplu, fişierul war se copiază ı̂n cat-
alogul webapps al serverului web.
Dintr-un navigator, apelarea aplicaţiei se obţine prin
http://host:8080/cmmdc/cmmdc.html.
9.1. JAVA WEB START 231
Dacă aplicaţia Java utilizează imagini grafice acestea trebuie arhivate ı̂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);
Dacă aplicaţia Java utilizează resurse externe date prin fişiere jar atunci:
1. Toate fişierele jar se certifică.
Certificarea resurselor se realizează rulând succesiv
(a) keytool -genkey -keystore myKeystore -alias myself
(b) keytool -selfcert -alias myself -keystore myKeystore
(c) jarsigner -keystore myKeystore resource.jar myself
keytool.exe şi jarsigner.exe se găsesc ı̂n distribuţia jdk.
Primele două acţiuni au ca rezultat obţinerea certificatului myKeystore iar
ultima acţiune reprezintă ı̂nglobarea certificării ı̂n arhiva resource.jar.
Toate fişierele jar trebuie să poarte aceaşi certificare.
2. Fişierele jar certificate se depun ı̂n catalogul app\lib.
3. În fişierul jnlp, ı̂n elementul resources, pentru fiecare fişier jar utilizat se
introduce declaraţia
<jar href=”lib/resource.jar”/>
<security>
<all-permissions />
</security>
Dacă arhiva jar a aplicaţiei Java este executabilă atunci, ı̂n fişierul jnlp, elemen-
tul application-desc poate lipsi.
Într-o arhivă jar executabilă, fişierul MANIFEST.MF indică clasa cu metoda main
şi eventualele resurse externe utilizate (fişiere jar) prin proprietăţile
Main-class: numeClasa
Class-path: lib/resursa1.jar lib/resursa2.jar . . .
Pentru a obţine fişierul MANIFEST.MF cu aceste proprietăţi se editează un fişier text
cu conţinutul de mai sus, denumit de exemplu myManifest.mf, şi se arhivează prin
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:
233
234 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 235
• 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 }
• 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 237
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()
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 ( ) ;
13 // V a r i a n t a 1
14 // 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
15 ObjectName mbeanObjectName =
16 new ObjectName ( domeniu+” : t y p e=I n t r o , i n d e x=1” ) ;
18 // Crearea MBean−u l u i
19 I n t r o mbean = new I n t r o ( ) ;
21 // I n r e g i s t r a r e a MBean−u l u i
22 mbs . r e g i s t e r M B e a n ( mbean , mbeanObjectName ) ;
24 // V a r i a n t a 2
25 mbeanObjectName=new ObjectName ( domeniu+” : t y p e=I n t r o , i n d e x=2” ) ;
26 mbs . createMBean ( ” b a s i c . I n t r o ” , mbeanObjectName ) ;
28 // A s t e p t a r e n e d e f i n i t a
29 System . out . p r i n t l n ( ” Waiting f o r e v e r . . . ” ) ;
30 while ( true ) ;
31 }
32 catch ( E x c e p t i o n e ) {
33 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 ( ) ) ;
34 }
35 }
36 }
1
În acest caz, este nevoie ca variabilele de tip clasă acoperitoare Double, Long să fie ı̂nlocuite
prin tipuri predefinite.
10.1. STANDARD MBEAN 239
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.
• NotificationBroadcasterSupport
Constructori
– NotificationBroadcasterSupport()
Metode
– void sendNotification(Notification notificare)
• Notification
Constructori
– Notification(String type, Object source, long sequenceNumber )
– Notification(String type, Object source, long sequenceNumber , long
timeStamp)
10.1. STANDARD MBEAN 241
Metode
Câmpuri
4 public c l a s s I nt r oN extends N o t i f i c a t i o n B r o a d c a s t e r S u p p o r t
5 implements IntroNMBean {
6 private long sequenceNumber =1;
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 ( ) { . . . }
22 sequenceNumber++,
23 System . c u r r e n t T i m e M i l l i s ( ) ,
24 ” Schimbarea c u r s u l u i Euro ” ,
25 ” cursEuro ” ,
26 ” double ” ,
27 oldCursEuro ,
28 cursEuro ) ;
29 sendNotification (n ) ;
30 }
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 . S c a n n e 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 ( ) ;
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 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
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 name o f t h e s e r v e r 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 . ∗ ;
246 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 <=1){
12 System . out . p r i n t l n ( ”The s e r v e r and domain names a r e r e q u i r e d ” ) ;
13 System . e x i t ( 0 ) ;
14 }
15 S t r i n g serverName=a r g s [ 0 ] ;
16 S t r i n g domain=a r g s [ 1 ] ;
17 i f ( a r g s . l e n g t h >=3) h o s t=a r g s [ 2 ] ;
18 i f ( a r g s . l e n g t h >=4) p o r t=a r g s [ 4 ] ;
19 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
20 try {
21 // 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
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 ] ;
24 // 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 ://”+
25 // h o s t +”:”+ p o r t +”/”+ a r g s [ 0 ] ;
26 JMXServiceURL u r l = new JMXServiceURL ( s u r l ) ;
27 JMXConnector jmxc = JMXConnectorFactory . c o n n e c t ( u r l , n u l l ) ;
28 MBeanServerConnection c s = jmxc . getMBeanServerConnection ( ) ;
30 // Domeniile a g e n t u l u i s u n t
31 System . out . p r i n t l n ( ” Domains : ” ) ;
32 S t r i n g domains [ ] = c s . getDomains ( ) ;
33 f o r ( i n t i = 0 ; i < domains . l e n g t h ; i ++) {
34 System . out . p r i n t l n ( ” \ tDomain [ ” + i + ” ] = ” + domains [ i ] ) ;
35 }
37 // i a r domeniul i m p l i c i t
38 System . out . p r i n t l n ( ” DefaultDomain : ” +c s . g e t D e f a u l t D o m a i n ( ) ) ;
39 System . out . p r i n t l n ( ”Domain : ” +domain ) ;
47 double c u r s E u r o ;
48 long m, n ;
50 // U t i l i z a r e a MBean−u l u i
51 // 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
52 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 ” ) ;
53 IntroMBean proxy=
54 ( 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 (
55 cs ,
56 mbeanObjectName ,
57 c l i e n t . IntroMBean . c l a s s ,
58 true ) ;
60 // U t i l i z a r e a o p e r a t i i l o r
61 // o p e r a t i a ” s a y H e l l o ”
62 proxy . s a y H e l l o ( ) ;
64 // o p e r a t i a cmmdc
65 System . out . p r i n t l n ( ”Cmmdc a l n u m e r e l o r : ” ) ;
10.1. STANDARD MBEAN 247
72 // U t i l i z a r e a a t r i b u t e l o r
73 System . out . p r i n t l n ( ”Numele : ”+proxy . g e t L a b e l ( ) ) ;
74 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 ” ) ;
75 c u r s E u r o=s c a n n e r . nextDouble ( ) ;
76 proxy . s e t C u r s E u r o ( c u r s E u r o ) ;
77 System . out . p r i n t l n ( ” Euro : ”+proxy . getCursEuro ( ) ) ;
79 // 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
80 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 ” ) ;
81 // A p e l a r e a o p e r a t i i l o r
82 S t r i n g o p e r a t i a=” s a y H e l l o ” ;
83 c s . i n v o k e ( mbeanObjectName , o p e r a t i a , null , n u l l ) ;
84 o p e r a t i a=”cmmdc” ;
85 System . out . p r i n t l n ( ”Cmmdc a l n u m e r e l o r : ” ) ;
86 System . out . p r i n t l n ( ” Primul numar : ” ) ;
87 m=s c a n n e r . nextLong ( ) ;
88 System . out . p r i n t l n ( ” Al d o i l e a numar : ” ) ;
89 n=s c a n n e r . nextLong ( ) ;
90 O b j e c t [ ] param={m, n } ;
91 S t r i n g [ ] s i g n ={” l o n g ” , ” l o n g ” } ;
92 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 ) ;
93 System . out . p r i n t l n ( ”Cmmdc=”+r . t o S t r i n g ( ) ) ;
95 // U t i l i z a r e a A t r i b u t e l o r
96 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 ” ) ;
97 System . out . p r i n t l n ( ” V a l o a r e a a t r i b u t u l u i l a b e l : ”+l a b e l ) ;
99 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 ” ) ;
100 c u r s E u r o=s c a n n e r . nextDouble ( ) ;
101 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 ) ;
102 c s . s e t A t t r i b u t e ( mbeanObjectName , c u r s ) ;
103 Double newEuro=(Double ) c s . g e t A t t r i b u t e ( mbeanObjectName , ” CursEuro ” ) ;
104 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 ) ;
105 c s . u n r e g i s t e r M B e a n ( mbeanObjectName ) ;
106 }
107 catch ( E x c e p t i o n e ) {
108 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
109 }
110 }
111 }
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
public void handleNotification(Notification notification, Object
handback )
Ataşarea şi disponibilizarea clasei ce implementează interfaţa Notification
Listener se obţin prin metodele interfeţei MBeanServerConnection:
10.1. STANDARD MBEAN 249
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 . g e tO l d V a l u e ( ) . 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 }
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 <=1){
11 System . out . p r i n t l n ( ”The s e r v e r and domain names a r e r e q u i r e d ” ) ;
12 System . e x i t ( 0 ) ;
13 }
14 S t r i n g serverName=a r g s [ 0 ] ;
15 S t r i n g domain=a r g s [ 1 ] ;
16 i f ( a r g s . l e n g t h >=3) h o s t=a r g s [ 2 ] ;
17 i f ( a r g s . l e n g t h >=4) p o r t=a r g s [ 3 ] ;
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 ] ;
250 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS
36 // U t i l i z a r e a n o t i f i c a r i i
37 // Crearea unui a s c u l t a t o r
38 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 ( ) ;
39 // A c t i v a r e a n o t i f i c a t o r u l u i
40 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 ) ;
42 Thread . s l e e p ( 5 0 0 ) ;
43 // 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
44 System . out . p r i n t l n ( ” P r e s s Enter t o f i n i s h ! ” ) ;
45 try {
46 System . i n . r e a d ( ) ;
47 }
48 catch ( j a v a . i o . IOException e ) { }
49 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 ) ;
50 // 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
51 c s . u n r e g i s t e r M B e a n ( mbeanObjectName ) ;
52 }
53 catch ( E x c e p t i o n e ) {
54 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
55 e . printStackTrace ( ) ;
56 }
57 }
61 }
Clasa Client care crează MBean-ul trebuie lansată ı̂naintea clasei ClientNotif. Aceste
două clase pot rula pe calculatoare distincte.
implementat prin
10.1. STANDARD MBEAN 251
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 ( S e r v l e t C o n f i g c o n f i g ) {
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 : / / ”+h o s t+” : ”+p o r t+” / ”+s e r v e r ;
19 // S t r i n g s u r l =” s e r v i c e : jmx : i i o p : / / / j n d i / i i o p ://”+ h o s t +”:”+ p o r t +”/”+ s e r v e r ;
252 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS
79 catch ( E x c e p t i o n e ) {
80 message=”JMX−E r r o r : ”+e . g e t M e s s a g e ( ) ;
81 }
82 }
83 else {
84 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 ” ;
85 }
86 break ;
87 case 2 :
88 message=”Suma d i n c o n t e s t e ”+v a l u e+” u n i t . ” ;
89 break ;
90 }
91 r e s . setContentType ( ” t e x t / html ” ) ;
92 out . p r i n t l n ( ”<html>” ) ;
93 out . p r i n t l n ( ”<head><t i t l e >Depozit </ t i t l e ></head>” ) ;
94 out . p r i n t l n ( ”<body>” ) ;
95 out . p r i n t l n ( ”<h1>O p e r a t i u n i Cont</h1>” ) ;
96 out . p r i n t l n ( ”<p>” ) ;
97 out . p r i n t l n ( message ) ;
98 out . p r i n t l n ( ”</p>” ) ;
99 out . p r i n t l n ( ”</body></html>” ) ;
100 out . c l o s e ( ) ;
101 }
Serverul MBean este cel prezentat ı̂n Exemplul 10.1.5. Clientlul care urmăreşte de
la distanţa contul are codul
254 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS
1 import j a v a . i o . IOException ;
2 import j a v a x . management . ∗ ;
3 import j a v a x . management . remote . ∗ ;
5 public c l a s s C l i e n t N o t i f {
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 h o s t=” l o c a l h o s t ” ;
8 S t r i n g p o r t=” 1099 ” ;
9 i f ( a r g s . l e n g t h ==0){
10 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 ” ) ;
11 System . e x i t ( 0 ) ;
12 }
13 i f ( a r g s . l e n g t h >=2) h o s t=a r g s [ 1 ] ;
14 i f ( a r g s . l e n g t h >=3) p o r t=a r g s [ 2 ] ;
15 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 ( ) ;
16 try {
17 // 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
18 // t i p MBeanServerConnection
19 S t r i n g s u r l=” s e r v i c e : jmx : rmi : / / / j n d i / rmi : / / ” +
20 h o s t+” : ”+p o r t+” / ”+a r g s [ 0 ] ;
21 JMXServiceURL u r l = new JMXServiceURL ( s u r l ) ;
22 JMXConnector jmxc = JMXConnectorFactory . c o n n e c t ( u r l , n u l l ) ;
23 MBeanServerConnection c s = jmxc . getMBeanServerConnection ( ) ;
25 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 ( ) ;
26 System . out . p r i n t l n ( ” DefaultDomain : ” +domain ) ;
27 // Crearea unui MBean I n t r o
28 S t r i n g className=” Cont ” ;
29 S t r i n g sObjectName=domain+” : t y p e=”+className ;
30 ObjectName mbeanObjectName = new ObjectName ( sObjectName ) ;
35 // U t i l i z a r e a n o t i f i c a r i i
36 // Crearea unui a s c u l t a t o r
37 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 ( ) ;
38 // A c t i v a r e a n o t i f i c a t o r u l u i
39 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 ) ;
41 Thread . s l e e p ( 5 0 0 ) ;
42 // 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
43 System . out . p r i n t l n ( ” P r e s s Enter t o f i n i s h ! ” ) ;
44 try {
45 System . i n . r e a d ( ) ;
46 }
47 catch ( j a v a . i o . IOException e ) { }
48 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 ) ;
49 // 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
50 c s . u n r e g i s t e r M B e a n ( mbeanObjectName ) ;
51 }
52 catch ( E x c e p t i o n e ) {
53 System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
54 e . printStackTrace ( ) ;
55 }
56 }
61 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 {
62 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 ,
63 O b j e c t handback ) {
64 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 ) ;
65 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=
66 ( AttributeChangeNotification ) n o t i f i c a t i o n ;
67 System . out . p r i n t l n ( ” S o l d i n i t i a l : ” +
68 myNotif . g e tO l d V a l u e ( ) . t o S t r i n g ( ) ) ;
69 System . out . p r i n t l n ( ” S o l d c u r e n t : ” +
70 myNotif . getNewValue ( ) . t o S t r i n g ( ) ) ;
71 }
72 }
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.
Programul server (RMI) implementează interfaţa
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;
}
257
258 CAPITOLUL 11. TEME DE LABORATOR
Rata zilnică de schimb preia dinamic sub forma unui fişier xml, apelând
http://www.bnr.ro/nbrfxrates.xml.
3. Să se realizeze conversia unui număr natural, din cifre arabe ı̂n cifre romane
şi invers.
Pentru numere x ∈ (3999, 3999999], x = a ∗ 1000 + b se va folosi scrierea sub
forma (A)B, unde A, B reprezintă conversiile lui a, respectiv b.
Exemplu: Conversia numărului 2289463 este (MMCCLXXXIX)CDLXIII.
Pentru numere x ∈ (4000000, 3999999999], x = a ∗ 1000000 + b ∗ 1000 + c se
va folosi scrierea sub forma [A](B)C, unde A, B, C reprezintă conversiile lui
a, b, c.
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.*;
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.
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. În cazul aplicaţiei RMI, evaluările funcţiei
cerute de formula de integrare numerică se vor realiza prin apel invers. Inte-
grarea numerică va fi executat de un server disponibil clienţilor prin mecanis-
mul 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
Z b m−1 m−1
b−a X X
f (x)dx ≈ Im = [f (a) + 2 f (a2i ) + 4 f (a2i+1 ) + f (b)]
a 6m i=1 i=0
unde ai = a + i b−a
2m .
Şirul (mk )k este definit prin mk = 2k m0 .
Semnificaţia parametrilor metodei adaptiveSimpson este
262 CAPITOLUL 11. TEME DE LABORATOR
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 utilizând RMI 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;
11.1. PROBLEME PROPUSE 263
package itelef;
import java.rmi.*;
public interface IFabCarteTelefon extends Remote{
ICarteTelefon getCarteTelefon() throws RemoteException;
}
package itelef;
import java.rmi.*;
TELEF
ID
NUME
NUMAR
264 CAPITOLUL 11. TEME DE LABORATOR
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.*;
new VisualCmmdcClient().setVisible(true);
}
S AA LL ZZ JJ ZZZ C
| | | | | | |-> cifra de control
| | | | | |-> numar de ordine atribuit persoanei
| | | | |-> codul judetului
| | | |-> ziua nasterii
| | |-> Luna nasterii
| |-> Anul nasterii
|-> Cifra sexului (M/F)
1/2 nascuti intre 1 ian 1900 si 31 dec 1999
3/4 nascuti intre 1 ian 1800 si 31 dec 1899
5/6 nascuti intre 1 ian 2000 si 31 dec 2099
7/8 rezidenti
11.1. PROBLEME PROPUSE 267
Unealta de dezvoltare
apache-ant
Începem această secţiune prin a introduce câteva elemente privind sintaxa ı̂ntr-
un document xml pentru că apache-ant va face apel la un fişier xml.
XML
EXtensible Markup Language (XML) reprezintă un limbaj pentru definirea mar-
cajelor de semantică, care ı̂mpart un document ı̂n părţi identificabile ı̂n document.
Din 1998, XML este un standard World Wide Web Consortium (W3C).
Totodată XML este un meta-limbaj pentru definirea sintaxei de utilizat ı̂n alte
domenii.
XML descrie structura şi semantica şi nu formatarea.
Structura unui document XML este
<marcaj>
corpul elementului
</marcaj>
269
270 APPENDIX A. UNEALTA DE DEZVOLTARE APACHE-ANT
<marcaj/>
Un marcaj poate avea atribute date prin sintaxa
numeAtribut="valoareAtribut"
Valoarea unui atribut este cuprinsă ı̂ntre ghilimele (””).
<marcaj numeAtribut="valoareAtribut" . . .>
corpul elementului
</marcaj>
Există un singur element rădăcină. Elementele unui document XML formează
un arbore. Fiecărui marcaj de ı̂nceput al unui element trebuie să-i corespundă un
marcaj 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,
adică un marcaj de sfârşit corespunde ultimului marcaj de ı̂nceput.
Un comentariu se indică prin
<!--
Text comentariu
-->
Exemplul A.0.1 Fişier XML - denumirile elementelor şi conţinutul lor permit ı̂nţelegerea
simplă a semanticii introduse ı̂n document.
• există preambul;
• ı̂n cazul că există o referinţă către XML Schema atunci documentul XML este
conform schemei.
Prelucrarea unui document XML ı̂n Java se poate face pe baza interfeţelor de
programare:
apache-ant
Utilitarul apache-ant asigură executarea unui şir de comenzi de operare. Aceste
comenzi se ı̂nregistrează ı̂ntr-un fişier de tip xml, cu denumirea build.xml. Astfel,
apache-ant se substituie unui fişier de comenzi bat ı̂n Windows sau unui script shell
din Linux/Unix. Avantajul obţinut constă ı̂n independenţa faţă de platforma de
calcul (Windows, Linux).
set JAVA_HOME=. . .
set ANT_HOME=. . .
%ANT_HOME%\bin\ant.bat %1
Parametrul %1 acestui fişier de comenzi reprezintă obiectivul care se doreşte a
fi atins. Dacă se modifică denumirea sau locaţia fişierului build.xml atunci fişierul
de comenzi se invocă cu opţiunea -buildfile.
Un fişier build.xml corespunde unui proiect (project), alcătuit din unul sau mai
multe obiective (target). Atingerea fiecarărui obiectiv constă din ı̂ndeplinirea uneia
sau mai multor sarcini (task). Apache-ant conţine o familie predefinită de sarcini.
Programatorul are datoria fixării atributelor sarcinilor. Manualul din documentaţia
produsului conţine descrierea atributelor cât şi exemple. În general, o sarcină
reprezintă o operaţie executată uzual ı̂n linia de comandă.
Atributele se dau, respectând sintaxa XML
numeAtribut = ”valoareAtribut”
Astfel, un proiect apare sub forma
<project name="numeProiect"
default="obiectiv"
basedir="catalogDeReferinta">
<target name="numeObiectiv">
sarcini
</target>
. . . . . . .
</project>
Dacă la apelarea lui Apache-ant lipseşte parametrul opţional atunci se va executa
obiectivul default.
Într-un proiect se pot defini variabile prin marcajul
<property name=”numeVariabila” value=”valoareVariabila” />
O variabilă definită se va utiliza cu sintaxa ${numeVariabila}.
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ă
calculatorul este conectat la Internet, atunci resursele publice pot fi descărcate
ı̂mpreună cu toate dependinţele şi utilizate prin apache-ant, folosind suplimentar
apache-ivy 1 .
In vederea utilizării lui apache-ivy se copiază fişierul ivy-*.jar din distribuţia
apache-ivy ı̂n ANT HOME\lib.
Fişierul build.xml conţine ı̂n plus
. . .
<!-- =================================
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">
1
Asemănător cu maven, un alt produs de dezvoltare.
274 APPENDIX A. UNEALTA DE DEZVOLTARE APACHE-ANT
<ivy:report todir="${report.dir}"/>
</target>
. . .
</project>
Scopul acestei anexe este prezentarea bazelor utilizării unui Sistem de Gestiune
a Bazelor de Date (SGBD - Data Bases Management System - DBMS) din Java.
Exemplificăm modul de operare şi utilizare pentru crearea şi exploatarea unei baze
de date corespunzătoare unei agende telefonice.
Exemplul B.1.1
275
276 APPENDIX B. UTILIZAREA SGBD ÎN JAVA
cu fişierul ValuesAgendaE.sql
1 i n s e r t into a d r e s e ( nume , e m a i l ) values ( ’ aaa ’ , ’ aaa@yahoo . com ’ ) ,
2 ( ’ bbb ’ , ’ bbb@gmail . com ’ ) , ( ’ c c c ’ , ’ cc c@un itb v . r o ’ ) ,
3 ( ’ aaa ’ , ’ xyz@unitbv . r o ’ ) ;
Putem crea tabele şi le ı̂ncărca cu valori prin ant. În acest caz, ı̂n prealabil
trebuie creată baza de date prin intermediul utilitarului ij:
connect ’jdbc:derby:AgendaEMail;create=true’;
<?xml version="1.0"?>
<project name="db" basedir="." default="usage">
<property file="build.properties"/>
<path id="master-classpath">
<pathelement path="${db}"/>
</path>
<target name="createTables">
<echo message="CREATE TABLES USING: ${db.driver} ${db.url}"/>
<sql driver="${db.driver}"
url="${db.url}"
userid="${db.user}"
password="${db.pw}"
onerror="continue"
src="${createTable}">
<classpath refid="master-classpath"/>
</sql>
</target>
<target name="dropTables">
<echo message="DROP TABLES USING: ${db.driver} ${db.url}"/>
<sql driver="${db.driver}"
url="${db.url}"
userid="${db.user}"
password="${db.pw}"
onerror="continue">
<classpath refid="master-classpath"/>
B.2. MYSQL 277
</sql>
</target>
<target name="loadData">
<echo message="LOAD DATA USING: ${db.driver} ${db.url}"/>
<sql driver="${db.driver}"
url="${db.url}"
userid="${db.user}"
password="${db.pw}"
onerror="continue"
src="${valuesTable}">
<classpath refid="master-classpath"/>
</sql>
</target>
<target name="printData">
<echo message="PRINT DATA USING: ${db.driver} ${db.url}"/>
<sql driver="${db.driver}"
url="${db.url}"
userid="${db.user}"
password="${db.pw}"
onerror="continue"
print="true">
<classpath refid="master-classpath"/>
</sql>
</target>
</project>
createTable=AntCreateAdrese.sql
valuesTable=ValuesAgendaE.sql
db=. . ./db-derby-10.5.3.0-bin/lib/derbyclient.jar
B.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.
278 APPENDIX B. UTILIZAREA SGBD ÎN JAVA
Utilizarea produsului.
Se ı̂ntreprind următoarele operaţii:
1. Lansarea serverului mysql :
set MYSQL_HOME=. . .
set PATH=%MYSQL_HOME%\bin;%PATH%
mysqld
2. Unui utilizator i se poate atasa o parolă, executând ı̂ntr-o sesiune mysql comen-
zile
set password for ’root’@’localhost’=password(’parola’);
set password for ’root’@’127.0.01’=password(’parola’);
4 create table a d r e s e (
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 e m a i l char ( 3 0 ) not n u l l
8 );
B.3 PostgreSQL
Instalarea produsului. PostgreSQL este distribuit gratuit. Vom folosi o ver-
siune fără instalare automată, care se dezarhivează ı̂n catalogul ...\pgsql.
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.
set PG_HOME=d:\pgsql
%PG_HOME%\bin\createuser
În cele ce urmează vom presupune că utilizatorul are numele postgres. Nu-
mele utilizatorul postgres este predefinit. Dacă se alege alt nume atunci se va
executa suplimentar
%PG_HOME%\bin\createdb nume_utilizator
• Exemplul B.3.1
Crearea aceleiaşi baze de date AgendaTelefonică se face cu fişierul de comenzi
(agendat.bat)
set PG_HOME=d:\pgsql
%PG_HOME%\bin\psql -U postgres -f createdb.sql
%PG_HOME%\bin\psql -U postgres -d AgendaEMail -f createtable.sql
%PG_HOME%\bin\psql -U postgres -d AgendaEMail -f insertvalues.sql
createdb.sql
createtable.sql
280 APPENDIX B. UTILIZAREA SGBD ÎN JAVA
insertvalues.sql
B.4 HyperSQL
Instalarea produsului. Instalarea constă din dezarhivarea fişierului descărcat
ı̂ntr-un catalog pe care-l notăm HSQL HOME. HypereSQL se distribuie gratuit.
Comunicaţia cu acest serverul se face prin portul 9001.
Conectorul Java este conţinut ı̂n distribuţia produsului şi este fişierul hsqldb.jar.
Utilizarea produsului.
CreateTable.sql
\c true
DROP TABLE adrese;
\c false
InsertValues.sql
• Start → Programs → Oracle Database 10g Express Edition → Run SQL Com-
mand Line. În fereastra DOS se lansează connect.
Ca user : system putem schimba portul HTTP din 8080 ı̂n 9090(de exemplu),
prin
exec dbms_xdb.sethttpport(9090)
Exemplul B.5.1
1. @CreateAgendaE.sql
2. @ValuesAgendaE.sql
cu fişierul ValuesAgendaE.sql
1 insert into adrese values (1 , ’ aaa ’ , ’ aaa@unitbv . r o ’ );
2 insert into adrese values (2 , ’ bbb ’ , ’ bbb@yahoo . com ’ );
3 insert into adrese values (3 , ’ ccc ’ , ’ ccc@gmail . com ’ );
4 insert into adrese values (4 , ’ aaa ’ , ’ xyz@yahoo . com ’ );
282 APPENDIX B. UTILIZAREA SGBD ÎN JAVA
Pentru a avea acces la o bază de date trebuie stabilită o conexiune la acea bază
de date. În acest sens este necesar cunoaşterea:
• driver-ului de acces la sistemul de gestiune a bazei de date (SGBD) (String
jdbcDriver )
Tip SGBD Driver Fişierul
driver-ului
access sun.jdbc.odbc.JdbcOdbcDriver
mysql com.mysql.jdbc.Driver mysql-connector-java-*.*.*-bin.jar
(www.mysql.com)
derby org.apache.derby.jdbc.ClientDriver derbyclient.jar
javadb
(distribuţia derby)
postgresql org.postgresql.Driver postgresql-*.*-*.jdbc4.jar
hypeqsql org.hsqldb.jdbcDriver hsqldb.jar
oraclexe oracle.jdbc.driver.OracleDriver ojdbc14.jar
String jdbcDriver=. . .
String URLBazaDate=. . .
Connection con=null;
try{
Class.forName(jdbcDriver).newInstance();
con=DriverManager.getConnection(URLBazaDate);
...
}
catch(ClassNotFoundException e){. . .}
catch(SQLException e){. . .}
Statement instructiune=con.createStatement();
String sql=. . . //fraza select;
try{
ResultSet rs=instructiune.executeQuery(sql);
while(rs.next()){
prelucrarea rezultatului
}
}
catch(SQLException e){...}
Exemplul B.6.1
4 import j a v a . u t i l . ∗ ;
6 public c l a s s AgendaE {
7 Statement i n s t r u c t i u n e=n u l l ;
14 // SGBD mysql
15 /∗
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=” j d b c : mysql : / / l o c a l h o s t : 3 3 0 6 / AgendaEMail ? u s e r=r o o t ” ;
18 ∗/
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 / AgendaEMail ” ;
24 // S t r i n g username=p o s t g r e s ” ;
25 // S t r i n g password =”;
26 ∗/
28 // HyperSQL
29 /∗
30 S t r i n g j d b c D r i v e r =”o r g . h s q l d b . j d b c D r i v e r ” ;
31 S t r i n g URLBazaDate=” j d b c : h s q l d b : h s q l : / / l o c a l h o s t / AgendaEMail ” ;
32 // S t r i n g username=”SA” ;
33 // S t r i n g password =””;
34 ∗/
36 // O r a c l e 10 g E x p r e s s E d i t i o n
37 /∗
38 S t r i n g j d b c D r i v e r =” o r a c l e . j d b c . d r i v e r . O r a c l e D r i v e r ” ;
39 S t r i n g URLBazaDate=” j d b c : o r a c l e : t h i n : @ l o c a l h o s t : 1 5 2 1 :XE” ;
40 ∗/
42 C o n n e c t i o n con=n u l l ;
43 try {
44 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 ( ) ;
45 i f ( username != n u l l )
46 con = DriverManager . g e t C o n n e c t i o n ( URLBazaDate , username , password ) ;
47 else
48 con = DriverManager . g e t C o n n e c t i o n ( URLBazaDate ) ;
49 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 ( ) ;
50 }
51 catch ( ClassNotFoundException e ) {
52 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 ) ;
53 }
54 catch ( SQLException e ) {
55 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 ) ;
56 }
57 catch ( E x c e p t i o n e ) {
58 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 ( ) ) ;
59 }
60 }
• Varianta Derby
derby.jar, derbytools.jar, derbyclient.jar, derbynet.jar din cata-
logul %DERBY INSTALL%\lib.
• Varianta mysql
%MYSQL CONNECTOR JAVA HOME%\mysql-connector-java-*.*.*-bin.jar
9 public Adrese ( ) { }
4 public i n t e r f a c e AdreseDAO {
5 public void c r e a t e A d r e s e ( Adrese i n r e g ) throws E x c e p t i o n ;
6 public void u p d a t eA d r e s e ( Adrese i n r e g ) throws E x c e p t i o n ;
7 public Adrese r e a d A d r e s e ( i n t i n r e g I d ) throws E x c e p t i o n ;
8 public void d e l e t e A d r e s e ( i n t i n r e g I d ) throws E x c e p t i o n ;
9 public L i s t <Adrese> s e a r c h A d r e s e ( S e a r c h C r i t e r i a s e a r c h C r i t e r i a )
10 throws E x c e p t i o n ;
11 }
Căutarea unei ı̂nregistrări se poate face după nume sau după adresa de email.
Unui nume ı̂i pot corespunde mai multe adrese de email, iar dintr-o adresă nu
putem şti cui ı̂i aparţine. Clasa SearchCriteria este o componentă prin care se
fixează criteriul de cătare.
1 package agendae . dao ;
2 import j a v a . i o . S e r i a l i z a b l e ;
4 public c l a s s S e a r c h C r i t e r i a implements S e r i a l i z a b l e {
5 private S t r i n g nume=n u l l ;
6 private S t r i n g e m a i l=n u l l ;
8 public S t r i n g getNume ( ) {
9 return nume ;
10 }
11 public void setNume ( S t r i n g nume ) {
12 t h i s . nume = nume ;
13 }
14 public S t r i n g g e t E m a i l ( ) {
15 return e m a i l ;
16 }
17 public void s e t E m a i l ( S t r i n g e m a i l ) {
18 this . email = email ;
19 }
20 }
Dacă nume=null atunci se cere lista numelor care corespund la o adresă email,
iar dacă email=null atunci se cere lista adreselor de email corespunzătoare
unui nume.
Deoarece fiecare SGBD are propriul dialect SQL clasa ce implementează interfaţa
DAO este specifică SGBD-ului. Utilizând Derby / JavaDB codul implementării
AdreseDAODerbyImpl este
1 package agendae . dao ;
2 import j a v a . s q l . SQLException ;
3 import j a v a . s q l . C o n n e c t i o n ;
4 import j a v a . s q l . P r e p a r e d S t a t e m e n t ;
5 import j a v a . s q l . R e s u l t S e t ;
6 import j a v a . s q l . Statement ;
B.7. MODELUL DAO 289
7 import j a v a . u t i l . A r r a y L i s t ;
8 import j a v a . u t i l . L i s t ;
3 public c l a s s DAOFactory {
4 private s t a t i c DAOFactory i n s t a n c e ;
5 private s t a t i c AdreseDAODerbyImpl adreseDAODerbyImpl=n u l l ;
6 static {
7 i n s t a n c e = new DAOFactory ( ) ;
8 }
9 private DAOFactory ( ) {
10 adreseDAODerbyImpl=new AdreseDAODerbyImpl ( ) ;
11 }
12 public s t a t i c DAOFactory g e t I n s t a n c e ( ) {
13 return i n s t a n c e ;
14 }
1 package agendae ;
2 import j a v a . u t i l . ∗ ;
3 import agendae . dao . ∗ ;
5 public c l a s s AgendaEClient {
6 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
7 AdreseDAO dao=DAOFactory . g e t I n s t a n c e ( ) . getAdreseDAO ( ) ;
8 Adrese e n t i t y=n u l l ;
9 L i s t <Adrese> l i s t =n u l l ;
10 I t e r a t o r <Adrese> i t e r a t o r=n u l l ;
11 S e a r c h C r i t e r i a s c=n u l l ;
12 S t r i n g ch=”Y” ;
13 int p r e l ;
14 S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
15 while ( ch . s t a r t s W i t h ( ”Y” ) ) {
16 do{
17 System . out . p r i n t l n ( ” Continue ? (Y/N) ” ) ;
18 ch=s c a n n e r . n e x t ( ) . toUpperCase ( ) ;
19 }
20 while ( ( ! ch . s t a r t s W i t h ( ”Y” ))&&(! ch . s t a r t s W i t h ( ”N” ) ) ) ;
21 i f ( ch . s t a r t s W i t h ( ”Y” ) ) {
22 System . out . p r i n t l n ( ” Natura p r e l u c r a r i i ? ” ) ;
23 System . out . p r i n t l n ( ” Adaugare ( C r e a t e ) : 1 ”);
24 System . out . p r i n t l n ( ” S t e r g e r e ( D e l e t e ) : 2 ”);
25 System . out . p r i n t l n ( ” A c t u a l i z a r e ( Update ) : 3 ”);
26 System . out . p r i n t l n ( ” Cautare dupa c h e i e ( Read ) : 4 ” ) ;
27 System . out . p r i n t l n ( ” Cautare ( Read ) : 5 ”);
28 p r e l=s c a n n e r . n e x t I n t ( ) ;
29 S t r i n g nume , e m a i l ;
30 int id ;
31 switch ( p r e l ) {
32 case 1 :
33 System . out . p r i n t l n ( ”ADAUGARE” ) ;
34 System . out . p r i n t l n ( ”Numele : ” ) ;
35 nume=s c a n n e r . n e x t ( ) . t r i m ( ) ;
36 System . out . p r i n t l n ( ” Adresa e−m a i l : ” ) ;
37 e m a i l=s c a n n e r . n e x t ( ) . t r i m ( ) ;
38 e n t i t y=new Adrese ( ) ;
39 e n t i t y . setNume ( nume ) ;
40 e n t i t y . setEmail ( email ) ;
41 try {
42 dao . c r e a t e A d r e s e ( e n t i t y ) ;
43 System . out . p r i n t l n ( ” O p e r a t i a a f o s t e x e c u t a t a cu s u c c e s ! ” ) ;
44 }
45 catch ( E x c e p t i o n e ) {
46 System . out . p r i n t l n ( ” E x c e p t i e : ”+e . g e t M e s s a g e ( ) ) ;
47 }
48 break ;
49 case 2 :
50 System . out . p r i n t l n ( ”STERGERE” ) ;
51 System . out . p r i n t l n ( ” I d : ” ) ;
52 i d=s c a n n e r . n e x t I n t ( ) ;
53 try {
54 dao . d e l e t e A d r e s e ( i d ) ;
55 System . out . p r i n t l n ( ” O p e r a t i a a f o s t e x e c u t a t a cu s u c c e s ! ” ) ;
56 }
57 catch ( E x c e p t i o n e ) {
58 System . out . p r i n t l n ( ” E x c e p t i e : ”+e . g e t M e s s a g e ( ) ) ;
59 }
B.7. MODELUL DAO 293
60 break ;
61 case 3 :
62 System . out . p r i n t l n ( ”ACTUALIZARE” ) ;
63 System . out . p r i n t l n ( ”Numele : ” ) ;
64 nume=s c a n n e r . n e x t ( ) . t r i m ( ) ;
65 System . out . p r i n t l n ( ” Adresa e−m a i l : ” ) ;
66 e m a i l=s c a n n e r . n e x t ( ) . t r i m ( ) ;
67 System . out . p r i n t l n ( ” Cheia i n r e g i s t r a r i i ( I d ) : ” ) ;
68 i d=s c a n n e r . n e x t I n t ( ) ;
69 e n t i t y=new Adrese ( ) ;
70 e n t i t y . setNume ( nume ) ;
71 e n t i t y . setEmail ( email ) ;
72 entity . setId ( id ) ;
73 try {
74 dao . u p d a t eA d r e s e ( e n t i t y ) ;
75 System . out . p r i n t l n ( ” O p e r a t i a a f o s t e x e c u t a t a cu s u c c e s ! ” ) ;
76 }
77 catch ( E x c e p t i o n e ) {
78 System . out . p r i n t l n ( ” E x c e p t i e : ”+e . g e t M e s s a g e ( ) ) ;
79 }
80 break ;
81 case 4 :
82 System . out . p r i n t l n ( ”CAUTARE DUPA CHEIE” ) ;
83 System . out . p r i n t l n ( ” I d : ” ) ;
84 i d=s c a n n e r . n e x t I n t ( ) ;
85 try {
86 e n t i t y=dao . r e a d A d r e s e ( i d ) ;
87 System . out . p r i n t l n ( ”Nume : ”+e n t i t y . getNume ( ) ) ;
88 System . out . p r i n t l n ( ” Email : ”+e n t i t y . g e t E m a i l ( ) ) ;
89 }
90 catch ( E x c e p t i o n e ) {
91 System . out . p r i n t l n ( ” E x c e p t i e : ”+e . g e t M e s s a g e ( ) ) ;
92 }
93 break ;
94 case 5 :
95 System . out . p r i n t l n ( ” C r i t e r i u l de c a u t a r e : ” ) ;
96 System . out . p r i n t l n ( ”Dupa nume : 1 ” ) ;
97 System . out . p r i n t l n ( ”Dupa e m a i l : 2 ” ) ;
98 i n t c r i t e r i u=s c a n n e r . n e x t I n t ( ) ;
99 switch ( c r i t e r i u ) {
100 case 1 :
101 System . out . p r i n t l n ( ”Numele : ” ) ;
102 nume=s c a n n e r . n e x t ( ) . t r i m ( ) ;
103 s c=new S e a r c h C r i t e r i a ( ) ;
104 s c . setNume ( nume ) ;
105 try {
106 l i s t =dao . s e a r c h A d r e s e ( s c ) ;
107 i t e r a t o r= l i s t . i t e r a t o r ( ) ;
108 while ( i t e r a t o r . hasNext ( ) ) {
109 Adrese i n r e g =( Adrese ) i t e r a t o r . n e x t ( ) ;
110 System . out . p r i n t l n ( i n r e g . g e t I d ()+ ” : ”+
111 i n r e g . getNume ()+ ” : ”+i n r e g . g e t E m a i l ( ) ) ;
112 }
113 }
114 catch ( E x c e p t i o n e ) {
115 System . out . p r i n t l n ( ” E x c e p t i e : ”+e . g e t M e s s a g e ( ) ) ;
116 }
117 break ;
118 case 2 :
294 APPENDIX B. UTILIZAREA SGBD ÎN JAVA
B.8.1 apache-openjpa
Aşa cum sugerează numele produsului, openjpa este implementarea oferită de
apache.
Instalarea revine la dezarhivarea fişierului descărcat.
Utilizarea. Compilarea şi execuţia unei aplicaţii o vom face prin intermediul
lui apache-ant. Construim structura de cataloage şi fişiere:
|--> catalogul_aplicatiei
|--> META-INF
| | persistence.xml
| build.xml
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 ”
296 APPENDIX B. UTILIZAREA SGBD ÎN JAVA
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 −−>
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 B.8.1 Aplicaţie pentru ı̂ntreţinerea şi interogarea bazei de date Agen-
daEMail.
Tabelei adrese a bazei de date ı̂i corespunde clasa Adrese
1 package agendae . dao ;
2 import j a v a . i o . S e r i a l i z a b l e ;
3 import j a v a x . p e r s i s t e n c e . ∗ ;
5 @Entity
6 public c l a s s Adrese implements S e r i a l i z a b l e {
7 private i n t i d ;
8 private S t r i n g nume ;
9 private S t r i n g e m a i l ;
11 public Adrese ( ) { }
19 public i n t g e t I d ( ) {
20 return i d ;
21 }
22 public void s e t I d ( i n t i d ) {
23 this . id = id ;
24 }
26 public S t r i n g getNume ( ) {
27 return nume ;
28 }
29 public void setNume ( S t r i n g nume ) {
30 t h i s . nume = nume ;
31 }
33 public S t r i n g g e t E m a i l ( ) {
34 return e m a i l ;
35 }
36 public void s e t E m a i l ( S t r i n g e m a i l ) {
37 this . email = email ;
298 APPENDIX B. UTILIZAREA SGBD ÎN JAVA
38 }
39 }
Accessarea bazei de date se face prin clasa AdreseDAOImpl. Această clasă im-
plementează interfaţa AdreseDAO, dată ı̂n secţiunea anterioară.
1 package agendae . dao ;
2 im po rt j a v a . u t i l . L i s t ;
3 im po rt j a v a x . p e r s i s t e n c e . ∗ ;
5 @SuppressWarnings ( ” unchecked ” )
6 p u b l i c c l a s s AdreseDAOImpl implements AdreseDAO{
7 E n ti t y M an a g e rF a c t or y f a c t o r y=n u l l ;
8 EntityManager em ;
10 p u b l i c AdreseDAOImpl ( E n ti t y M an a g e 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 c r e a t e A d r e s e ( Adrese i n r e g ) {
15 S t r i n g name=i n r e g . getNume ( ) ;
16 S t r i n g e m a i l=i n r e g . g e t E m a i l ( ) ;
17 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 ( ) ;
18 em . g e t T r a n s a c t i o n ( ) . b e g i n ( ) ;
19 S t r i n g s q l=”INSERT INTO a d r e s e ( nume , e m a i l ) VALUES( \ ’ ”+name+” \ ’ , \ ’ ”+e m a i l+” \ ’ ) ” ;
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 }
26 p u b l i c v o i d up d a t e A d r e s e ( Adrese i n r e g ) {
27 S t r i n g nume=” \ ’ ”+i n r e g . getNume ()+ ” \ ’ ” ;
28 S t r i n g e m a i l=” \ ’ ”+i n r e g . g e t E m a i l ()+ ” \ ’ ” ;
29 i n t i n r e g I d=i n r e g . g e t I d ( ) ;
30 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 ( ) ;
31 em . g e t T r a n s a c t i o n ( ) . b e g i n ( ) ;
32 S t r i n g s q l=”UPDATE Adrese e n t i t y SET e n t i t y . nume=”+nume+
33 ” , e n t i t y . e m a i l=”+e m a i l+” WHERE e n t i t y . i d=”+i n r e g I d ;
34 Query query=em . c r e a t e Q u e r y ( s q l ) ;
35 query . e x e c u t e U p d a t e ( ) ;
36 em . g e t T r a n s a c t i o n ( ) . commit ( ) ;
37 em . c l o s e ( ) ;
38 }
40 p u b l i c Adrese r e a d A d r e s e ( i n t i n r e g I d ) {
41 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 ( ) ;
42 em . g e t T r a n s a c t i o n ( ) . b e g i n ( ) ;
43 S t r i n g s q l=”SELECT e n t i t y FROM Adrese e n t i t y WHERE e n t i t y . i d=”+i n r e g I d ;
44 Query query=em . c r e a t e Q u e r y ( s q l ) ;
45 Adrese i n r e g =( Adrese ) query . g e t S i n g l e R e s u l t ( ) ;
46 em . g e t T r a n s a c t i o n ( ) . commit ( ) ;
47 em . c l o s e ( ) ;
48 return inreg ;
49 }
55 Query query=em . c r e a t e Q u e r y ( s q l ) ;
56 query . e x e c u t e U p d a t e ( ) ;
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 }
61 p u b l i c L i s t<Adrese> s e a r c h A d r e s e ( S e a r c h C r i t e r i a s e a r c h C r i t e r i a ) {
62 S t r i n g nume=s e a r c h C r i t e r i a . getNume ( ) ;
63 S t r i n g e m a i l=s e a r c h C r i t e r i a . g e t E m a i l ( ) ;
64 S t r i n g searchSQL ;
65 i f ( nume==n u l l ) {
66 searchSQL=” e n t i t y . e m a i l =\ ’ ”+e m a i l+” \ ’ ” ;
67 }
68 else{
69 searchSQL=” e n t i t y . nume=\ ’ ”+nume+” \ ’ ” ;
70 }
71 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 ( ) ;
72 em . g e t T r a n s a c t i o n ( ) . b e g i n ( ) ;
73 S t r i n g s q l=”SELECT e n t i t y FROM Adrese e n t i t y WHERE ”+searchSQL ;
74 System . out . p r i n t l n ( s q l ) ;
75 Query query=em . c r e a t e Q u e r y ( s q l ) ;
76 L i s t<Adrese> l i s t =( L i s t<Adrese>) query . g e t R e s u l t L i s t ( ) ;
77 em . g e t T r a n s a c t i o n ( ) . commit ( ) ;
78 em . c l o s e ( ) ;
79 return l i s t ;
80 }
81 }
Programul client este acelaşi cu cel utilizat anterior (AgendaEClient). iar clientul
este AgendaTClient
Fişierul persistence.xml pentru exemplul de mai sus este
1 <?xml version=” 1 . 0 ” e n c o d i n g=”UTF−8” ?>
2 < p e r s i s t e n c e xmlns=” h t t p : // j a v a . sun . com/xml/ ns / p e r s i s t e n c e ”
3 x m l n s : x s i=” h t t p : //www. w3 . o r g /2001/XMLSchema−i n s t a n c e ”
4 version=” 1 . 0 ”>
10 <p r o p e r t y name=” d b d r i v e r ”
11 v a l u e=” o r g . apache . derby . j d b c . C l i e n t D r i v e r ” />
12 <p r o p e r t y name=” d b u r l ”
13 v a l u e=” j d b c : d e r b y : // l o c a l h o s t : 1 5 2 7 /${ dbname} ” />
15 < !−−
16 <p r o p e r t y name=” d b d r i v e r ”
17 v a l u e=”com . mysql . j d b c . D r i v e r ” />
18 <p r o p e r t y name=” d b u r l ”
19 v a l u e=” j d b c : m y s q l : // l o c a l h o s t : 3 3 0 6 / AgendaEMail ? u s e r=r o o t ” />
20 −−>
64 < !−−
65 S p e c i f y t h e sy s te m 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
66 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
67 packages , the c a l l to ” P e r s i s t e n c e . createEntityManagerFactory ”
68 i s p a s s e d ” System . g e t P r o p e r t i e s ( ) ” .
69 −−>
71 < !−−
72 By default , u s e t h e stand −a l o n e Derby d a t a b a s e ( p r o v i d e d ) .
73 This can e a s i l y be c h a n g e s t o u s e your own d a t a b a s e ’ s d r i v e r ,
74 p r o v i d e d you e n s u r e i t i s a c c e s s i b l e i n t h e c l a s s p a t h .
75 −−>
76 <s y s p r o p e r t y key=”o p e n j p a . ConnectionDriverName ”
77 v a l u e =”${ d b d r i v e r }”/>
78 <s y s p r o p e r t y key=”o p e n j p a . ConnectionURL ” v a l u e =”${ d b u r l }”/>
79 <!−−
80 <s y s p r o p e r t y key=”o p e n j p a . ConnectionUserName ” v a l u e =”${ d b u s e r }”/>
81 <s y s p r o p e r t y key=”o p e n j p a . ConnectionPassword ” v a l u e =”${ dbpass }”/>
82 −−>
83 <!−−
84 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
85 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
86 r u n n i n g 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
87 don ’ t want t o be a l t e r i n g t h e schema a t runtime .
88 −−>
89 <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 ”
90 v a l u e=” buildSchema ” />
92 < !−−
93 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 , b u t s e t t h e
94 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 .
95 −−>
96 <s y s p r o p e r t y key=” o p e n j p a . Log”
97 v a l u e=” D e f a u l t L e v e l=WARN, SQL=TRACE” />
98 </ j a v a>
99 </ t a r g e t>
100 </ p r o j e c t>
302 APPENDIX B. 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.
303