distr1

303
Universitatea Transilvania din Bra¸ sov Facultatea de Matematic˘ a–Informatic˘ a Catedra de Informatic˘ a ERNEST SCHEIBER PROGRAMARE DISTRIBUIT ˘ A ˆ IN JAVA Bra¸ sov

Upload: serbu-florin-adrian

Post on 25-Jun-2015

255 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: DISTR1

Universitatea Transilvania din BrasovFacultatea de Matematica–Informatica

Catedra de Informatica

ERNEST SCHEIBER

PROGRAMARE DISTRIBUITA INJAVA

Brasov

Page 2: DISTR1

2

Page 3: DISTR1

Introducere

Retelele locale, internetul, raspandirea pe o arie geografica a resurselor si alocatiilor ın care se petrec actiuni ce tin de o activitate bine definita sau sunturmarite, gestionate din alte locuri au drept consecinta existenta aplicatiilor dis-tribuite. Termenul distribuit se refera tocmai la faptul ca componente ale aplicatieise afla pe calculatoare diferite dar ıntre care au loc schimburi de date. Dacapartile unei aplicatii sau resursele utilizate se gasesc pe calculatoare distincte atunciaplicatia se numeste distribuita.

Intre partile sau resursele unei aplicatii distribuite au loc schimburi de date,ceea ce se face utilizand diferite mecanisme la realizarea carora concura sistemul decalcul, sistemul de operare si limbajul de programare.

Astfel se vorbeste de programare distribuita ca mijloc de realizare a aplicatiilordistribuite. Pe langa algoritm, structuri de date, limbaj de programare, la realizareaunei aplicatii distribuite intervin comunicatiile: schimbul de date dintre doua com-ponente aflate pe calculatoare diferite.

Punem ın evidenta doua modele de aplicatii distribuite:

• client-server: Programul server executa cererile clientilor. Amintim urmatoareletehnologii Java pentru realizarea aplicatiilor client-server:

– RMI (Remote Method Invocation)

– CORBA (Common Object Request Brocker Arhitecture)

– JMS (Java Message Service)

– Servlet si JSP (Java Server Pages)

– Portlet

– Java Web Start

– Java Management Extentions (JMX)

• dispecer-lucrator: Programul dispecer distribuie sarcinile de executat lucratorilorsi le coordoneaza activitatea. Exista multe abordari de programere a aplicatiilordispecer-lucrator.

Scopul acestui curs este prezentarea tehnologiilor de programare Java care permitprogramarea aplicatiilor client - server:

3

Page 4: DISTR1

4

• socluri Java;

• apelarea metodelor de la distanta (Remote Method Invocation - RMI );

• CORBA - Common Object Request Brocker Arhitecture;

• mesageria Java;

• servlet;

• Java Server Pages - JSP;

• Portlet si Portal;

• Java Management Extentions - JMX.

Metodele si instrumentele de programare vor fi exemplificate pe problema foartesimpla de calcul a celui mai mare divizor comun a doua numere naturale. Codulmetodei de calcul este

1 public long cmmdc( long m, long n){2 long r , c ;3 do{4 c=n ;5 r=m%n ;6 m=n ;7 n=r ;8 }9 while ( r !=0) ;

10 return c ;11 }

Pentru aplicatiile care utilizeaza o baza de date, sistemul de gestiune a bazei dedate (SGBD) va fi una dintre sistemele Derby/Javadb sau mysql.

Page 5: DISTR1

Cuprins

1 Applet - Miniaplicatie Java 9

1.1 Clasa Applet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

1.2 Desfasurarea unui applet . . . . . . . . . . . . . . . . . . . . . . . . . 10

1.3 Comunicare Java - JavaScript ıntr-un applet . . . . . . . . . . . . . . 17

2 Programare cu socluri Java 19

2.1 Aplicatii client – server . . . . . . . . . . . . . . . . . . . . . . . . . . 19

2.2 Notiuni despre retele . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.3 Soclu TCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.3.1 Clasa java.net.Socket . . . . . . . . . . . . . . . . . . . . . 21

2.3.2 Clasa java.net.ServerSocket . . . . . . . . . . . . . . . . . 21

2.4 Aplicatie client – server cu socluri . . . . . . . . . . . . . . . . . . . 22

2.5 Datagrame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

2.5.1 Clasa java.net.DatagramPacket. . . . . . . . . . . . . . . . 26

2.5.2 Clasa java.net.DatagramSocket . . . . . . . . . . . . . . . 27

2.5.3 Clasa java.net.InetAddress . . . . . . . . . . . . . . . . . 29

2.5.4 Aplicatii client – server cu datagrame. . . . . . . . . . . . . . 31

2.5.5 Multicast vs. Broadcast . . . . . . . . . . . . . . . . . . . . . 35

2.6 Canale de comunicatie . . . . . . . . . . . . . . . . . . . . . . . . . . 36

2.6.1 Clasa java.nio.Buffer . . . . . . . . . . . . . . . . . . . . . 36

2.6.2 Clasa java.nio.ByteBuffer . . . . . . . . . . . . . . . . . . 39

2.6.3 Clasa java.net.InetSocketAddress . . . . . . . . . . . . . 40

2.6.4 Clasa java.nio.channels.ServerSocketChannel . . . . . . 40

2.6.5 Clasa java.nio.channels.SocketChannel . . . . . . . . . . 41

2.6.6 Clasa java.nio.channels.DatagramChannel . . . . . . . . . 43

2.7 Conexiuni HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

3 Regasirea obiectelor prin servicii de nume 49

3.1 Java Naming and Directory Interface . . . . . . . . . . . . . . . . . . 49

3.1.1 LDAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

5

Page 6: DISTR1

6 CUPRINS

4 Invocarea procedurilor la distanta 57

4.1 Remote Method Invocation . . . . . . . . . . . . . . . . . . . . . . . 57

4.1.1 Crearea unei aplicatii RMI . . . . . . . . . . . . . . . . . . . 60

4.1.2 Tipare de programare . . . . . . . . . . . . . . . . . . . . . . 65

4.1.3 Obiect activabil la distanta . . . . . . . . . . . . . . . . . . . 71

4.2 CORBA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

4.2.1 Conexiunea RMI - CORBA . . . . . . . . . . . . . . . . . . . 76

4.2.2 Aplicatie Java prin CORBA . . . . . . . . . . . . . . . . . . . 81

5 Mesaje ın Java 89

5.1 Java Message Service (JMS) . . . . . . . . . . . . . . . . . . . . . . . 89

5.2 Open Message Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

5.3 Apache ActiveMQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

5.4 Elemente de programare - JMS . . . . . . . . . . . . . . . . . . . . . 92

5.4.1 Trimiterea unui mesaj . . . . . . . . . . . . . . . . . . . . . . 92

5.4.2 Receptia sincrona a unui mesaj . . . . . . . . . . . . . . . . . 97

5.4.3 Receptia asincrona a unui mesaj . . . . . . . . . . . . . . . . 99

5.4.4 Publicarea mesajelor . . . . . . . . . . . . . . . . . . . . . . . 100

5.4.5 Subscrierea si receptia mesajelor . . . . . . . . . . . . . . . . 101

5.5 Mesaje SOAP prin Java Message Service . . . . . . . . . . . . . . . . 103

5.5.1 SOAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

5.5.2 Mesaje SOAP . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

5.5.3 Atasamente SOAP . . . . . . . . . . . . . . . . . . . . . . . . 111

5.6 Programe JMS prin apache-qpid . . . . . . . . . . . . . . . . . . . . 119

5.7 Protocolul AMQP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

5.7.1 Crearea unei cozi . . . . . . . . . . . . . . . . . . . . . . . . . 128

5.7.2 Expedierea / publicarea unui mesaj . . . . . . . . . . . . . . 129

5.7.3 Receptionarea mesajelor . . . . . . . . . . . . . . . . . . . . . 131

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 si apelarea unui servlet . . . . . . . . . . . . . . . 142

6.3.3 Codul unui servlet . . . . . . . . . . . . . . . . . . . . . . . . 143

6.4 Facilitati de programare cu servlet . . . . . . . . . . . . . . . . . . . 149

6.4.1 Program client al unui servlet . . . . . . . . . . . . . . . . . . 149

6.4.2 Servlete ınlantuite . . . . . . . . . . . . . . . . . . . . . . . . 152

6.4.3 Sesiune de lucru . . . . . . . . . . . . . . . . . . . . . . . . . 154

6.4.4 Cookie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155

6.4.5 Autorizarea accesului prin parola . . . . . . . . . . . . . . . . 157

Page 7: DISTR1

CUPRINS 7

6.4.6 Servlet cu conexiune la o baza de date . . . . . . . . . . . . . 159

6.4.7 Imagini furnizate de servlet . . . . . . . . . . . . . . . . . . . 161

6.4.8 Servlet cu RMI . . . . . . . . . . . . . . . . . . . . . . . . . . 163

6.4.9 Servlet cu JMS . . . . . . . . . . . . . . . . . . . . . . . . . . 164

6.5 FileUpload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167

6.6 Descarcarea unui fisier . . . . . . . . . . . . . . . . . . . . . . . . . . 172

6.7 Filtru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173

7 Java Server Page – JSP 177

7.1 Tehnologia JSP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177

7.1.1 Declaratii JSP . . . . . . . . . . . . . . . . . . . . . . . . . . 182

7.1.2 Directive JSP . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

7.1.3 Marcaje JSP predefinite . . . . . . . . . . . . . . . . . . . . . 184

7.1.4 Componenta Java (Java Bean) . . . . . . . . . . . . . . . . . 185

7.1.5 Pagini JSP cu componente Java . . . . . . . . . . . . . . . . 186

7.2 JSP Standard Tag Library JSTL . . . . . . . . . . . . . . . . . . . . 189

7.2.1 Biblioteca de baza . . . . . . . . . . . . . . . . . . . . . . . . 190

7.2.2 Biblioteca de lucru cu baze de date . . . . . . . . . . . . . . . 195

7.3 Marcaje JSP personale . . . . . . . . . . . . . . . . . . . . . . . . . . 196

7.3.1 Marcaje fara atribute si fara corp. . . . . . . . . . . . . . . . 196

7.3.2 Marcaje cu atribute si fara corp. . . . . . . . . . . . . . . . . 200

7.3.3 Marcaje cu corp. . . . . . . . . . . . . . . . . . . . . . . . . . 202

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

9 Java Web Start 227

9.1 Java Web Start . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227

10 Java Management Extensions 233

10.1 Standard MBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234

10.1.1 Crearea unui Standard MBean . . . . . . . . . . . . . . . . . 234

10.1.2 Crearea unui MBeanServer . . . . . . . . . . . . . . . . . . . 236

10.1.3 Notificari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239

10.1.4 Agent MBean . . . . . . . . . . . . . . . . . . . . . . . . . . . 242

10.1.5 Invocarea la distanta . . . . . . . . . . . . . . . . . . . . . . . 243

Page 8: DISTR1

8 CUPRINS

11 Teme de laborator 25711.1 Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257

A Unealta de dezvoltare apache-ant 269

B Utilizarea SGBD ın Java 275B.1 Derby / Javadb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275B.2 mysql . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277B.3 PostgreSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279B.4 HyperSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280B.5 Oracle XE 10g . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281B.6 Sablonul de utilizare a unei baze de date . . . . . . . . . . . . . . . . 282B.7 Modelul DAO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286B.8 Java Persistence API - JPA . . . . . . . . . . . . . . . . . . . . . . . 294

B.8.1 apache-openjpa . . . . . . . . . . . . . . . . . . . . . . . . . . 295

Bibliografie 303

Page 9: DISTR1

Capitolul 1

Applet - Miniaplicatie Java

O categorie deosebita de programe Java ıl reprezinta miniaplicatiile (applet-uri), care se executa prin intermediul unui program de navigare ın WWW (WorldWide Web) – browser (Mozilla Firefox, Google Chrome, Microsoft InternetExplorer,Opera, Apple Safari. La aparitia limbajului de programare Java, acest tip deaplicatie a reprezentat unul din factorii de impact prin noutatea si simplitateasolutiei oferite.

Applet-ul este o resursa program, depusa ıntr-o zona publica, accesibila prinInternet (server Web.) Un program de navigare preia codul applet-ului si ıl executa.Apelarea unui applet se face dintr-un fisier html.

Datorita acestui mod de folosire, applet-urile au o structura speciala si suntsupuse la reguli stricte de securitate, printre care acela de a nu putea scrie informatiipe calculatorul pe care se executa - calculatorul clientului.

Metoda actuala de apelare a unui applet se face prin intermediul unei resurseDeployment Toolkit(DT) - o biblioteca de functii javascript. Resursa DT este apela-bila la adresa http://java.com/js/deployJava.js iar codul se poate consulta lawww.java.com/js/deployJava.js.

DT utilizeaza protocolul Java Network Launching Protocol (jnlp) si evita prob-lemele de compatibilitate cu programul navigator. Aceasta resursa realizeaza descarcareaapplet-ului cat si lansarea ın executie. Pe calculatorul client, adica pe care ruleazaapplet-ul, trebuie sa fie instalat jre - Java Runtime Environment - versiunea pe 32biti.

Programarea unui applet se face prin extinderea clasei java.applet.Applet

sau javax.swing.JApplet. Clasa Applet extinde clasa java.awt.Panel iar clasaJApplet extinde clasa Applet.

Interfata grafica, ın cazul extinderii clasei Applet, va utiliza controlurile apartinandinterfetei de programare AWT (Abstract Window Toolkit), iar ın cazul extinderii cla-sei JApplet se vor utiliza controluri Swing.

9

Page 10: DISTR1

10 CAPITOLUL 1. APPLET - MINIAPLICATIE JAVA

1.1 Clasa Applet

Structura unui applet este

import java.applet.*;

import java.awt.*;

public classNumeClasa extends Applet{public void init(){

Actiuni efectuate la instantierea clasei applet-ului.}public void start(){

Actiuni efectuate la lansarea applet-ului ın executie sau lareıntoarcerea ın pagina applet-ului.

}public void paint(Graphics g){

Actiuni efectuate ori de cate ori este necesara redesenareaferestrei applet-ului.

}public void stop(){

Actiuni efectuate la oprirea applet-ului, ca urmare aınchiderii ferestrei corespunzatoare applet-ului.

}public void destroy(){

Actiuni efectuate la distrugerea applet-ului, ce au loc candnavigatorul paraseste documentul html din care s-a apelatapplet-ul.

}}

Executarea applet-ului este controlat de programul navigator si revine la apelareametodelor init, start, stop. Acest fenomen se numeste inversarea controlului.

1.2 Desfasurarea unui applet

Prin desfasurarea (deployment) unei aplicatii se ıntelege realizarea structurilor decataloage si fisiere dar si a operatiilor care trebuie ıntreprinse ın vederea functionariiunei aplicatii distribuite.

Desfasurarea unui applet se poate face ın mai multe feluri:

Varianta 1

1. Arhivarea fisierelor class ale applet-ului.

Page 11: DISTR1

1.2. DESFASURAREA UNUI APPLET 11

2. Editarea fisierului html de apelare a applet-ului. Sablonul specific apelariiapplet-ului este

<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 doua fisiere se depun ıntr-un catalog al unui server Web, asigurand viz-ibilitatea aplicatiei ın Internet.

Verificarea aplicatiei se poate face, dintr-un program navigator, prin simplaapelare a fisierului html. In acest caz, calculatorul trebuie sa fie conectat lainternet.

Daca dispunem de deployJava.js atunci acest fisier se alatura celorlalte douaresurse, iar atributul src al elementului script va fi src="deployJava.js".

Exemplul 1.2.1 ”Hello ”+nume. Numele se transmite miniaplicatiei ca parametru.

Codul applet-ului este:

1 import java . awt . ∗ ;2 import java . app le t . ∗ ;

4 public class Inceput extends Applet{5 public void i n i t ( ){}

7 public void paint ( Graphics g ){8 St r ing name=getParameter ( ”nume” ) ;9 g . drawString ( ” He l lo ”+name+” ! ! ” , 50 , 60 ) ;

10 }11 }

Fisierul html de apelare (inceput.html)

1 <HTML>2 <HEAD>3 <TITLE> Hel lo </TITLE>4 </HEAD>5 <BODY>6 <script src=” http :// java . com/ j s / deployJava . j s ”></ script>7 <script>8 var a t t r i b u t e s = { code : ’ Inceput . c l a s s ’ , a r ch ive : ’ inceput . ja r ’ ,9 width : 300 , he ight : 3 0 0} ;

Page 12: DISTR1

12 CAPITOLUL 1. APPLET - MINIAPLICATIE JAVA

10 var parameters={nume : ’XYZ’} ;11 var minimumVersion = ’ 1 . 6 . 0 ’ ;12 deployJava . runApplet ( a t t r i b u t e s , parameters , minimumVersion ) ;13 </ script>14 </BODY>15 </HTML>

Varianta 2

Pe aceasta cale se va edita un fisier de configurare cu extensia jnlp. Realizareaapplet-ului consta din:

1. Arhivarea fisierelor class ale applet-ului.

2. Editarea unui fisier de configurare jnlp. Structura acestui fisier este

<?xml version="1.0" encoding="UTF-8"?>

<jnlp spec="1.0+" codebase="http://host:port/cale_applet" href="">

<information>

<title>. . .</title>

<vendor>. . .</vendor>

</information>

<resources>

<!-- Application Resources -->

<j2se version="1.6+"

href="http://java.sun.com/products/autodl/j2se"

max-heap-size="128m" />

<jar href="numele_arhivei_jar" main="true" />

</resources>

<applet-desc

name="numele_simbolic_al_applet-ului"

main-class="clasa_principala_a_applet-ului"

width="latimea_ferestrei_applet-ului"

height="inaltimea_ferestrei_applet-ului">

</applet-desc>

</jnlp>

3. Editarea fisierului html de apelare a applet-ului. Sablonul specific apelariiapplet-ului este

<BODY>

. . .

<script src="http://java.com/js/deployJava.js"></script>

Page 13: DISTR1

1.2. DESFASURAREA 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>

4. Cele trei fisiere (eventual patru cu deployJava.js) se depun ıntr-un catalog alunui server Web, asigurand vizibilitatea aplicatiei ın Internet.

Exemplul 1.2.2 Calculul celui mai mare divizor comun a doua naturale.

Introducerea datelor exterioare se face prin intermediul unei interfete grafice.Applet-ul extinzand clasa Applet are codul

1 import java . awt . ∗ ;2 import java . app le t . ∗ ;3 import java . awt . event . ∗ ;

5 public class VisualCmmdc extends Applet implements Act ionL i s t ene r {6 TextFie ld tm , tn , r e z ;

8 public void i n i t ( ){9 setBackground ( Color . ye l low ) ;

10 GridLayout g l=new GridLayout ( 3 , 2 , 3 0 , 2 0 ) ;11 setLayout ( g l ) ;12 Label lm=new Label ( ”Primul numar : ” ) ;13 add ( lm ) ;14 tm=new TextFie ld ( ”1” , 5 ) ;15 add (tm ) ;16 Label ln=new Label ( ”Al d o i l e a numar : ” ) ;17 add ( ln ) ;18 tn=new TextFie ld ( ”1” , 5 ) ;19 add ( tn ) ;20 Button compute=new Button ( ” Calcu leaza ” ) ;21 compute . addAct ionLis tener ( this ) ;22 add ( compute ) ;23 r e z=new TextFie ld ( ”1” , 5 ) ;24 r e z . s e t E d i t a b l e ( fa l se ) ;25 add ( r ez ) ;26 }

28 public void paint ( Graphics g ){29 St r ing sm=tm . getText ( ) ;30 long m=Long . parseLong (sm ) ;31 St r ing sn=tn . getText ( ) ;32 long n=Long . parseLong ( sn ) ;33 long c=cmmdc(m, n ) ;34 r e z . setText ( (new Long ( c ) ) . t oS t r i ng ( ) ) ;35 }

37 public void act ionPerformed ( ActionEvent ae ){38 r epa in t ( ) ;39 }

Page 14: DISTR1

14 CAPITOLUL 1. APPLET - MINIAPLICATIE JAVA

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

iar ın cazul extinderii clasei JApplet

1 import java . awt . ∗ ;2 import javax . swing . ∗ ;3 import java . awt . event . ∗ ;

5 public class VisualCmmdc extends JApplet implements Act ionL i s t ene r {6 JTextFie ld tm , tn , r e z ;

8 public void i n i t ( ){9 Container content = getContentPane ( ) ;

10 content . setBackground ( Color . ye l low ) ;11 setLayout (new GridLayout ( 3 , 2 , 3 0 , 2 0 ) ) ;12 JLabel lm=new JLabel ( ”Primul numar : ” ) ;13 content . add ( lm ) ;14 tm=new JTextFie ld ( ”1” , 5 ) ;15 content . add (tm ) ;16 JLabel ln=new JLabel ( ”Al d o i l e a numar : ” ) ;17 content . add ( ln ) ;18 tn=new JTextFie ld ( ”1” , 5 ) ;19 content . add ( tn ) ;20 JButton compute=new JButton ( ” Calcu leaza ” ) ;21 compute . addAct ionLis tener ( this ) ;22 content . add ( compute ) ;23 r e z=new JTextFie ld ( ”1” , 5 ) ;24 r e z . s e t E d i t a b l e ( fa l se ) ;25 content . add ( r ez ) ;26 s e t V i s i b l e ( true ) ;27 }

29 public void paint ( Graphics g ){30 St r ing sm=tm . getText ( ) ;31 long m=Long . parseLong (sm ) ;32 St r ing sn=tn . getText ( ) ;33 long n=Long . parseLong ( sn ) ;34 long c=cmmdc(m, n ) ;35 r e z . setText ( (new Long ( c ) ) . t oS t r i ng ( ) ) ;36 }

38 public void act ionPerformed ( ActionEvent ae ){39 r epa in t ( ) ;40 }

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

Fisierul de configurare jnlp (cmmdc.jnlp) este

1 <?xml version=” 1 .0 ” encoding=”UTF−8”?>2 <j n l p spec=”1.0+” codebase=” ht tp : // l o c a l h o s t : 8 0 8 0 /cmmdc” h r e f=””>3 <i n fo rmat ion>4 < t i t l e>Visua l Cmmdc</ t i t l e>5 <vendor>Trans i l van ia Un ive r s i ty o f Brasov</ vendor>6 </ in fo rmat ion>7 <r e s o u r c e s>8 < !−− App l i ca t ion Resources −−>

Page 15: DISTR1

1.2. DESFASURAREA UNUI APPLET 15

9 < j 2 s e version=”1.6+”10 h r e f=” ht t p : // java . sun . com/ products / autodl / j 2 s e ”11 max−heap−s i z e=”128m” />

13 < j a r h r e f=”cmmdc . j a r ” main=” true ” />14 </ r e s o u r c e s>15 <applet−desc16 name=”VisualCmmdc Applet ”17 main−c l a s s=”VisualCmmdc”18 width=”300”19 he ight=”300”>20 </ applet−desc>21 </ j n l p>

iar apelarea se face din (VisualCmmdc.html)

1 <html>2 <body bgco lo r=”#AAEEAA”>3 <c en te r>4 <h1> Cel mai mare d i v i z o r comun </h1>5 <s c r i p t s r c=” deployJava . j s ”></ s c r i p t>6 <s c r i p t>7 var a t t r i b u t e s = { code : ’cmmdc ’ , width:300 , he i gh t : 300 } ;8 var parameters = { j n l p h r e f : ’cmmdc . j n l p ’ } ;9 var minimumVersion = ’ 1 .6 ’ ;

10 deployJava . runApplet ( a t t r i b u t e s , parameters , minimumVersion ) ;11 </ s c r i p t>12 </ cente r>13 </body>14 </html>

sau cu descarcarea fisierului jnlp1

1 <HTML>2 <BODY BGCOLOR=”#AAEEAA”>3 <CENTER>4 <h1> Cel mai mare d i v i z o r comun </h1>5 <s c r i p t s r c=” h t t p : // java . com/ j s / deployJava . j s ”></ s c r i p t>6 <s c r i p t>7 deployJava . launch ( ’cmmdc . j n l p ’ ) ;8 </ s c r i p t>9 </CENTER>

10 </BODY>11 </HTML>

O alternativa (depasita) la modurile de apelare al applet-ului descrise anterioreste prin utilizarea elementului html <applet>.

Atributele obligatorii ale unui element applet sunt

• code

Valoarea atributului este numele clasei applet-ului.

• width

Valoarea atributului este latimea ferestrei atribuita de navigator applet-ului laafisarea documentului html.

1Functioneaza ın navigatoarele Mozilla Firefox, Microsoft Internet Explorer.

Page 16: DISTR1

16 CAPITOLUL 1. APPLET - MINIAPLICATIE JAVA

• height

Valoarea atributului este ınaltimea ferestrei atribuita de navigator applet-uluila afisarea documentului html.

Atribute optionale sunt

• codebase

Valoarea atributului este adresa URL ( Universal Resource Locator) sau caleala fisierul cu clasa applet-ului. In lipsa acestui parametru, cautarea clasei areloc ın catalogul din care a fost ıncarcata sursa html.

• vspace

Valoarea atributului este lungimea, exprimata ın pixeli, care se lasa liberadeasupra si dedesuptul ferestrei miniaplicatiei.

• hspace

Valoarea parametrului este lungimea, exprimata ın pixeli, care se lasa liberala stanga si la dreapta ferestrei applet-ului.

In marcajul <applet> prin intermediul elementului <param> pot fi inclusi parametrice pot fi preluati de applet. Un parametru se defineste prin atributele:

• name

Valoarea atributului este numele variabilei recunoscuta ın applet.

• value

Valoarea atributului este valoarea receptionata de applet si este de tip String.Preluarea se realizeaza cu metoda

public String getParameter(String name)

Documentul html de apelare al applet-ului Inceput este:

1 <HTML>2 <HEAD>3 <TITLE> Hel lo </TITLE>4 </HEAD>5 <BODY>6 <CENTER>7 <APPLET8 code = ” Inceput . c l a s s ”9 width = ”500”

10 height = ”300” >11 </APPLET>12 </CENTER>13 </BODY>14 </HTML>

Page 17: DISTR1

1.3. COMUNICARE JAVA - JAVASCRIPT INTR-UN APPLET 17

Daca fisierul class al applet-ului nu se afla ın acelasi catalog cu documentul htmlatunci localizarea clasei se face cu valoarea atributului codebase =

"file://host/calea catre catalogul clasei applet-ului"

Pentru testare, ın locul navigatorului se poate folosi programul appletviewer.exedin distributia jdk.

1.3 Comunicare Java - JavaScript ıntr-un applet

Dintr-un applet set apela functii JavaScript definite ın documentul html din carese apeleaza applet-ul.

Prin intermnediul unui obiect de tip netscape.javascript.JSObject, creatprinstatic JSObject getWindow(java.applet.Applet applet)se apeleaza metodacall(String numeFunctieJavaScript, java.lang.Object[] args).

Sablonul de utilizare este

import netscape.javascript.*;

public void init(){

. . .

JSObject window=JSObject.getWindow(null);

window.call("numeFunctieJavaScript",args);

. . .

}

Pachetul netscape.javascript se afla ın distributia jdk ın catalogul JAVA HOME\jre\lib\plugin.jar. Pentru compilare, variabila de sistem classpath trebuie sacontina aceasta referinta.

Page 18: DISTR1

18 CAPITOLUL 1. APPLET - MINIAPLICATIE JAVA

Page 19: DISTR1

Capitolul 2

Programare cu socluri Java

Limbajul de programare Java ofera facilitati de elaborare ale unor programe careutilizeaza si interactioneaza cu resurse din Internet si din World Wide Web.

In plus limbajul Java permite utilizarea URL-ului (Universal Resource Locator– adresa resurselor ın Internet), a soclurilor (socket) si a datagramelor.

2.1 Aplicatii client – server

O aplicatie client – server se compune din:

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

• componenta client - alcatuita din programe / clase care permit accesul la serversi apelarea serviciilor acestuia.

Serverul si clientul (clientii) ruleaza, de obicei, pe calculatoare distincte. Unserver trebuie sa satisfaca cererile mai multor clienti.

Durata de viata a unei aplicatii client – server este data de durata functionariiserverului. Aceasta durata poate fi alcatuita din intervale disjuncte de timp, ıntreacele intervale, din diverse motive, serverul este inactiv.

Intervalul de timp determinat de conectarea unui client la server si pana ladeconectare poarta numele de sesiune. In aceasta perioada, clientul poate invocamai multe servicii ale serverului. Un client poate initia mai multe sesiuni.

Un client trebuie sa-si regaseasca datele ın cadrul unei sesiuni, ıntre sesiuni, petoata durata de viata a aplicatiei. Astfel se pune problema retinerii / persistenteidatelor pentru fiecare client ın parte.

19

Page 20: DISTR1

20 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA

Autentificare si autorizare

Uzual, pentru a folosi serviciul unui server, un client trebuie sa se ınregistreze,moment ın care i se stabilesc drepturile de care dispune la utilizarea serviciilor oferitede server.

La apelarea serverului, clientul este autentificat - adica i se recunoaste identitatea- si apoi i se asigura accesul la servicii ın limita drepturilor pe care le are.

2.2 Notiuni despre retele

Calculatoarele ce ruleaza ın Internet comunica ıntre ele folosind protocolul TCP(Transport Control Protocol) sau UDP (User Datagram Protocol).

Intr-un program Java se utilizeaza clasele pachetului java.net prin intermediulcarora se acceseaza nivelele deservite de protocoalele TCP sau UDP. In felul acestase pot realiza comunicatii independente de platforma de calcul. Pentru a alege careclasa Java sa fie utilizata trebuie cunoscuta diferenta dintre TCP si UDP.

TCP Cand doua aplicatii comunica ıntre ele se stabileste o conexiune prin in-termediul careia se schimba date. Folosind protocolul TCP, comunicatia garanteazaca datele trimise dintr-un capat ajung ın celalalt capat cu pastrarea ordinii ın careau fost trimise. Acest tip de comunicatie seamana cu o convorbire telefonica. TCPfurnizeaza un canal sigur de comunicatie ıntre aplicatii.

UDP Utilizarea protocolului UDP presupune trimiterea unor pachete de date –numite datagrame – de la o aplicatie la alta fara sa se asigure faptul ca datagrameleajung la destinatie si nici ordinea lor de sosire. Acest tip de comunicatie seamanacu trimiterea scrisorilor prin posta.

2.3 Soclu TCP

Conexiunile bazate pe protocolul HTTP (Hyper Text Transfer Protocol) reprezintaun mecanism de nivel ınalt pentru accesarea resurselor din Internet.

Aplicatii de tip client – server se pot realiza utilizand comunicatii de nivel scazut.Pentru a comunica utilizand TCP programul client si programul server stabilesc oconexiune sigura. Fiecare program se leaga la conexiune printr-un soclu (socket).Un soclu este capatul unei cai de comunicatie bidirectional ıntre doua programece ruleaza ın retea. Un soclu este legat de un port – prin care nivelul TCP poateidentifica aplicatia careia ıi sunt transmise datele. Din punct de vedere fizic, un porteste o adresa de memorie cuprinsa ıntre 0 si 65535.

Pentru a comunica atat clientul cat si serverul citesc date de la si scriu date lasoclul legat la conexiunea dintre ele.

Page 21: DISTR1

2.3. SOCLU TCP 21

In pachetul java.net clasele Socket si ServerSocket implementeaza un socludin partea clientului si respectiv din partea serverului.

Clientul cunoaste numele calculatorului pe care ruleaza serverul cat si portul lacare acesta este conectat. Pentru stabilirea conexiunii, clientul ıncearca un rendez-vous cu serverul de pe masina serverului si la portul serverului. Daca totul de-curge bine, serverul accepta conexiunea. Dupa acceptare, serverul creaza pentruclient un nou soclu legat la un alt port ın asa fel ıncat ascultarea cererilor la soclulinitial sa poata continua ın timp ce sunt satisfacute cererile clientului conectat. Dinpartea clientului, dupa acceptarea conexiunii soclul este creat si este utilizat pentrucomunicatia cu serverul.

2.3.1 Clasa java.net.Socket

Resursele clasei Socket sunt destinate clientului.

Constructori

• public Socket(String host, int port) throws UnknownHostException,

IOException

Creaza un soclu conectat la calculatorul cu portul specificat.

• public Socket(InetAddress host, int port) throws IOException

Creaza un soclu conectat la calculatorul cu portul specificat.

Metode

• public InputStream getInputStream() throws IOException

Returneaza un flux de intrare atasat soclului, pentru citirea (preluarea) informatiilorde la soclu.

• public OutputStream getOutputStream() throws IOException

Returneaza un flux de iesire atasat soclului, pentru scrierea (transmiterea)informatiilor la soclu.

• public synchronized void close() throws IOException

ınchide soclul de referinta.

2.3.2 Clasa java.net.ServerSocket

Resursele clasei ServerSocket sunt destinate serverului.

Constructori

Page 22: DISTR1

22 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA

• public ServerSocket(int port) throws IOException

Creaza un soclu la portul specificat. Daca port=0, atunci va fi utilizat oriceport disponibil. Capacitatea sirului (tamponului) de asteptare pentru cererilede conectare se fizeaza la valoarea implicita 50. Cererile ın exces vor fi refuzate.

• public ServerSocket(int port, int lung) throws IOException

In plus fixeaza lungimea sirului (tamponului) de asteptare.

• public ServerSocket(int port, int lung, InetAddress adr)throws IOException

Se specifica ın plus calculatorul de la care se asteapta cereri. Daca adr=null,

atunci se accepta cereri de la orice calculator.

Metode

• public Socket accept() throws IOException

Metoda blocheaza procesul (firul de executie) apelant pana la sosirea uneicereri de conectare si creaza un soclu client prin care se va desfasura comuni-carea cu solicitantul acceptat.

• public synchronized void close() throws IOException

ınchide soclul de referinta.

2.4 Aplicatie client – server cu socluri

Serverul trebuie sa satisfaca simultan solicitarile mai multor clienti. Fiecareclient apeleaza programul server la acelasi port si ın consecinta cererile de conectaresunt receptionate de acelasi ServerSocket. Serverul receptioneaza apelurile secvential.La un apel, se creaza de partea severului un soclu prin care se va face schimbul dedate cu clientul. Cererile clientilor pot fi satisface concurent/paralel, utilizand firede executie ce implementeaza serviciul oferit sau secvential - ın cazul unor serviciide durata scurta.

Exemplul 2.4.1 Sistem client - server pentru calculul celui mai mare divizor comuna doua numere naturale. Portul obiectului de tip ServerSocket este 7999.

Programul client CmmdcClient se conecteaza la server, transmite serveruluicele doua numere naturale si receptioneaza rezultatul pe care apoi ıl afiseaza.

In esenta orice program client trebuie sa execute:

1. Deschide/creaza un soclu.

Page 23: DISTR1

2.4. APLICATIE CLIENT – SERVER CU SOCLURI 23

2. Deschide/creaza fluxuri de date pentru comunicatia cu serverul.

3. Transmite si receptioneaza date potrivit specificului aplicatiei (protocoluluiserverului). Acest pas variaza de la un program client la altul.

4. Inchiderea fluxurilor de date.

5. Inchiderea soclului.

1 import java . i o . ∗ ;2 import java . net . ∗ ;3 import java . u t i l . Scanner ;

5 public class CmmdcClient {6 public stat ic void main ( St r ing [ ] a rgs ) throws IOException {7 St r ing host=” l o c a l h o s t ” ;8 int port =7999;9 i f ( args . length >0)

10 host=args [ 0 ] ;11 i f ( args . length >1)12 port=I n t e g e r . pa r s e In t ( args [ 1 ] ) ;13 Socket cmmdcSocket = null ;14 DataInputStream in=null ;15 DataOutputStream out=null ;

17 try {18 cmmdcSocket = new Socket ( host , port ) ;19 out=new DataOutputStream ( cmmdcSocket . getOutputStream ( ) ) ;20 in=new DataInputStream ( cmmdcSocket . getInputStream ( ) ) ;21 }22 catch ( Exception e ) {23 System . e r r . p r i n t l n ( ” Connection Error : ”+e . getMessage ( ) ) ;24 System . e x i t ( 1 ) ;25 }

27 Scanner scanner=new Scanner ( System . in ) ;28 long m, n , r ;29 System . out . p r i n t l n ( ”m=” ) ;30 m=scanner . nextLong ( ) ;31 System . out . p r i n t l n ( ”n=” ) ;32 n=scanner . nextLong ( ) ;

34 try{35 out . writeLong (m) ;36 out . writeLong (n ) ;37 r=in . 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 . getMessage ( ) ) ;42 }

44 out . c l o s e ( ) ;45 in . c l o s e ( ) ;46 cmmdcSocket . c l o s e ( ) ;47 }48 }

Page 24: DISTR1

24 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA

Se presupune ca programul server ruleaza pe calculatorul local si utilizeaza portul7999. Daca acesti parametri se modifica - de exemplu serverul ruleaza ın retea pecalculatorul atlantis la portul 8200 - atunci la apelare transmitem acesti parametriprin java CmmdcClient atlantis 8200

Partea server este alcatuita din mai multe clase:

• Clasa MyMServer, independenta de un serviciu anume, preia apelurile clientilorsi lanseaza satisfacerea cererii.

1 import java . net . ∗ ;2 import java . i o . ∗ ;

4 public class MyMServer {5 public stat ic void main ( St r ing [ ] a rgs ) throws IOException {6 int port =7999;7 boolean l i s t e n i n g=true ;8 ServerSocket s e rve rSocke t = null ;9 try {

10 s e rve rSocke t = new ServerSocket ( port ) ;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 port : ”+port ) ;14 System . out . p r i n t l n ( e . getMessage ( ) ) ;15 System . e x i t ( 1 ) ;16 }

18 while ( l i s t e n i n g )19 // var ian ta 120 new AppThread ( s e rve rSocke t . accept ( ) ) . s t a r t ( ) ;21 // var ian ta 222 /∗23 {24 Socket socke t=serverSocke t . accept ( ) ;25 t r y {26 DataOutputStream out=27 new DataOutputStream ( socke t . getOutputStream ( ) ) ;28 DataInputStream in=29 new DataInputStream ( socke t . getInputStream ( ) ) ;30 l ong m=0,n=0,r ;31 App app=new App ( ) ;32 m=in . readLong ( ) ;33 n=in . 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 socke t . c l o s e ( ) ;39 }40 catch ( IOException e ){41 System . err . p r i n t l n (” Server comunication error : ”+42 e . getMessage ( ) ) ;43 }44 }45 ∗/46 s e rve rSocke t . c l o s e ( ) ;47 }48 }

Page 25: DISTR1

2.4. APLICATIE CLIENT – SERVER CU SOCLURI 25

In ciclul while, la receptia unei solicitari de conexiune se creaza si se lanseazaun fir de executie a carei metoda run contine actiunile ce raspund solicitarii.

O solutie mai eficienta este utilizarea unui bazin de fire de executie:

static final int NTHREADS=100;

static ExecutorService exec=Executors.newFixedThreadPool(NTHREADS);

. . .

while(listening){

AppThread obj=new AppThread(serverSocket.accept());

exec.execute(obj);

}

. . .

• Clasa AppTread - fir de executie responsabil de preluarea datelor si de trans-mitere a rezultatului.

1 import java . net . ∗ ;2 import java . i o . ∗ ;

4 public class AppThread extends Thread{5 Socket socke t=null ;

7 public AppThread ( Socket socke t ){8 this . s ocke t=socket ;9 }

11 public void run ( ){12 try{13 DataOutputStream out=new DataOutputStream ( socke t . getOutputStream ( ) ) ;14 DataInputStream in=new DataInputStream ( socke t . getInputStream ( ) ) ;15 long m=0,n=0, r ;16 App app=new App ( ) ;17 m=in . readLong ( ) ;18 n=in . readLong ( ) ;19 r=app . cmmdc(m, n ) ;20 out . writeLong ( r ) ;21 out . c l o s e ( ) ;22 in . c l o s e ( ) ;23 socke t . c l o s e ( ) ;24 }25 catch ( IOException e ){26 System . e r r . p r i n t l n ( ” Server comunication e r r o r : ”+e . getMessage ( ) ) ;27 }28 }29 }

• Clasa App corespunzatoare calcului celui mai mare divizor comul a doua nu-mere naturale.

1 public class App{2 public long cmmdc( long m, long n ) { . . .}3 }

Page 26: DISTR1

26 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA

Rularea programelor. Se porneste la ınceput programul server MyMServer

iar apoi clientul CmmdcClient. Clientul se poate rula de pe orice calculator alretelei. Daca programul client se executa pe alt calculator decat cel pe care ruleazaprogramul server, atunci la apelarea clientului trebuie precizat numele calculatoruluiserver si eventual portul utilizat.

2.5 Datagrame

Pentru utilizarea datagramelor pachetul java.net pune la dispozitie clasele

• DatagramSocket

• DatagramPacket

• MulticastSocket

O aplicatie trimite si receptioneaza pachete DatagramPacket prin intermediulunui DatagramSocket. Un pachet DatagramPacket poate fi trimis la mai multidestinatari prin intermediul unui MulticastSocket.

Reamintim ca o datagrama este un mesaj trimis prin retea a carei sosire nu estegarantata iar momentul de sosire este neprecizat.

2.5.1 Clasa java.net.DatagramPacket.

Trimiterea unui pachet UDP necesita crearea unui obiectDatagramPachet care contine corpul mesajului si adresa destinatiei. Apoi acestobiect DatagramPacket poate fi pus ın retea ın vederea trimiterii sale. Primirea unuipachet UDP necesita crearea unui obiect DatagramPacket si apoi acceptarea unuipachet UDP din retea. Dupa primire, se poate extrage din obiectul DatagramPacketadresa sursa si continutul mesajului.

Constructori

Exista doi constructori pentru datagrame UDP. Primul constructor este folositpentru primirea de pachete si necesita doar furnizarea unei memorii tampon, iarcelalalt este folosit pentru trimiterea de pachete si necesita specificarea adresei des-tinatarului.

• DatagramPacket(byte[ ] buffer,int lung)

Acest contructor este folosit pentru primirea pachetelor. Un pachet se memo-reaza ın tamponul buffer avand lung octeti. Daca lungimea pachetului depasesteaceasta lungime, atunci pachetul este trunchiat iar octetii ın plus se pierd.

• DatagramPacket(byte[ ] buffer,int lung ,InetAddress adresa ,int port)

Page 27: DISTR1

2.5. DATAGRAME 27

Acest constructor este folosit pentru crearea unui pachet ın vederea expedierii.Corpul pachetului este continut ın tamponul buffer avand lung octeti. Pa-chetul va fi trimis catre adresa si portul specificat. Trebuie sa existe un serverUDP care asculta la portul specificat pentru trimiterea pachetelor. Un serverUDP poate coexista cu un server TCP care asculta acelasi port.

Metode

• InetAddress getAddress()

returneaza adresa IP a pachetului.

• int getPort()

returneaza portul.

• byte[] getData()

returneaza continutul pachetului.

• int getLength()

returneaza lungimea pachetului.

• void setAddress(InetAddress adresa)

fixeaza adresa IP a pachetului.

• void setPort(int port)

fixeaza portul.

• void setData(byte[] buffer)

fixeaza continutul pachetului.

• void setLength(int lung)

fixeaza lungimea pachetului.

2.5.2 Clasa java.net.DatagramSocket

Aceasta clasa se foloseste atat pentru trimiterea, cat si pentru primirea obiectelorDatagramPacket. Un obiect DatagramSocket asculta la un port cuprins ıntre 1si 65535 (porturile cuprinse ıntre 1 si 1023 sunt rezervate pentru aplicatiile sis-tem). Deoarece UDP nu este orientat pe conexiune, se va crea un singur obiectDatagramSocket pentru trimiterea pachetelor catre diferite destinatii si primireapachetelor de la diferite surse.

Constructori

Page 28: DISTR1

28 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA

• DatagramSocket() throws SocketException

Creaza un obiect DatagramSocket cu un numar de port aleator;

• DatagramSocket(int port) throws SocketException

Creaza un obiect DatagramSocket cu numarul de port specificat;

• DatagramSocket(int port, InetAddress adresa) throws SocketException

Creaza un obiect DatagramSocket cu numarul de port specificat la adresaspecificata;

MetodeClasa DatagramSocket contine metode pentru trimiterea si primirea de obiecte

DatagramPacket, ınchiderea soclului, determinarea informatiilor adresei locale sisetarea timpului de primire.

• void send(DatagramPacket pachet) throws IOException

Trimite pachetul prin retea. Daca se trimit pachete la o destinatie necunoscutasau care nu asculta, ın cele din urma se genereaza o exceptie IOException.

• void receive(DatagramPacket pachet) throws IOException

Metoda primeste un singur pachet UDP ın obiectul pachet specificat. Apoi,pachetul poate fi inspectat pentru determinarea adresei IP sursa, portul sursasi lungimea mesajului. Executia metodei este blocata pana cand se primestecu succes un pachet sau se scurge timpul de asteptare.

• InetAddress getLocalAddress()

Returneaza adresa locala catre care este legat acest DatagramSocket;

• int getLocalPort()

Returneaza numarul de port unde asculta DatagramSocket.

• void close()

Inchide DatagramSocket.

• void setSoTimeout(int timpDeAsteptere) throws SocketException

Metoda fixeaza timpul de asteptare (ın milisecunde) a soclului. Metoda receive()se va bloca pentru timpul de asteptare specificat pentru primirea unui pachetUDP, dupa care va arunca o exceptie Interrupted Exception. Daca valoareaparametrului este 0, atunci soclul este blocat.

• int getSoTimeout() throws SocketException

Returneaza timpul de asteptare.

Page 29: DISTR1

2.5. DATAGRAME 29

• void setSendBufferSize(int lungime) throws SocketException

Fixeaza lungimea tamponului de trimitere a soclului la valoarea specificata.Nu poate fi trimis mesaj UDP de lungime mai mare de aceasta valoare.

• int getSendBufferSize() throws SocketException

Returneaza lungimea tamponului de trimitere a soclului.

• void setReceiveBufferSize(int lungime) throws SocketException

Fixeaza lungimea tamponului de primire a soclului la valoarea specificata. Nupoate fi primit un mesaj UDP de lungime mai mare de aceasta valoare.

• int getReceiveBufferSize() throws SocketException

Returneaza lungimea tamponului de primire a soclului.

• void connect(InetAddress adresa, int port) throws SocketException

Conecteaza soclul la adresa si portul specificat. Aceasta metoda nu este cerutapentru operatiile uzuale UDP.

• void disconnect()

Deconecteaza soclul conectat.

• InetAddress getInetAddress()

Returneaza obiectul InetAddress catre care este conectat soclul sau null dacaacesta nu este conectat.

• int getPort()

Returneaza portul la care este conectat soclul sau -1 daca acesta nu este conec-tat.

2.5.3 Clasa java.net.InetAddress

Datele pot fi trimise prin retea indicand adresa IP corespunzatoare masiniidestinatie. Clasa InetAddress furnizeaza acces la adresele IP.

Nu exista constructori pentru aceasta clasa. Instantele trebuie create folosindmetodele statice:

• InetAddress getLocalHost() throws UnknownHostException

Returneaza un obiect InetAddress corespunzator masinii locale.

• InetAddress getByName(String host) throws UnknownHostException

Returneaza un obiect InetAddress corespunzator masinii host, parametrucare poate fi specificat prin nume (de exemplu ”atlantis”) sau prin adresaIP (”168.192.0.1”).

Page 30: DISTR1

30 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA

• InetAddress [ ]getAllByName(String host)throws UnknownHostException

Returneaza un sir de obiecte InetAddress corespunzator fiecarei adrese IP amasinii host.

Metodele clasei InetAddress

• byte [ ] getAddress()

Returneaza sirul de octeti corespunzator obiectului InetAddress de referinta.

• String getHostName()

Returneaza numele masinii gazda.

• String getHostAddress()

Returneaza adresa IP a masinii gazda.

• boolean isMulticastAddress()

Returneaza true daca obiectul InetAddress reprezinta o adresa IP multicast(primul octet cuprins ıntre 224 si 239).

Exemplul urmator afiseaza numele si adresa calculatorului gazda cat si acela alcalculatoarelor ale caror nume este transmis programului ca parametru.

Exemplul 2.5.1

1 import java . net . ∗ ;

3 public class AdreseIP{4 public stat ic void main ( St r ing arg [ ] ) {5 InetAddress adresa=null ;6 try{7 adresa=InetAddress . getLocalHost ( ) ;8 System . out . p r i n t l n ( ” C a l c u l a t o r u l gazda are : ” ) ;9 System . out . p r i n t l n ( ”numele : ”+adresa . getHostName ( ) ) ;

10 System . out . p r i n t l n ( ” adresa IP : ”+adresa . getHostAddress ( ) ) ;11 }12 catch ( UnknownHostException e ){13 System . out . p r i n t l n ( ”UnknownHostException : ”+e . getMessage ( ) ) ;14 }15 i f ( arg . length >0){16 for ( int i =0; i<arg . l ength ; i ++){17 try{18 adresa=InetAddress . getByName( arg [ i ] ) ;19 System . out . p r i n t l n ( ” C a l c u l a t o r u l ”+arg [ i ]+” are : ” ) ;20 System . out . p r i n t l n ( ” adresa IP \”getByName\” : ”+adresa ) ;21 byte [ ] b=adresa . getAddress ( ) ;22 for ( int j =0; j<b . l ength ; j++)23 i f (b [ j ]<0)24 System . out . p r i n t (256+b [ j ]+” . ” ) ;

Page 31: DISTR1

2.5. DATAGRAME 31

25 else26 System . out . p r i n t (b [ j ]+” . ” ) ;27 System . out . p r i n t l n ( ) ;28 }29 catch ( UnknownHostException e ){30 System . out . p r i n t l n ( ”UnknownHostException : ”+31 e . getMessage ( ) ) ;32 }33 }34 }35 }36 }

2.5.4 Aplicatii client – server cu datagrame.

Un pachet de tip DatagramPacket este alcatuit dintr-un sir de octeti. Este da-toria programatorului sa transforme datele (mesajul) ın siruri de octeti la expedieresi la receptie.

Transformarea unui obiect serializabil ıntr-un sir de octeti si invers se poaterealiza cu schema

Object Object

ObjectOutputStream ObjectInputStream

ByteArrayOutputStream ByteArrayInputStream

output - DatagramPacket input - DatagramPacket

? 6

? 6

? 6

? 6

Fie socket un obiect de tip DatagramSocket prin intermediul caruia se executaexpedierea / receptionarea pachetelor de tip DatagramPacket.

In principiu expedierea si transformarea obiectului obj ıntr-un sir de octeti sepoate realiza cu secventa de cod

ByteArrayOutputStream baos=new ByteArrayOutputStream(256);

ObjectOutputStream out=new ObjectOutputStream(baos);

out.writeObject(obj);

byte[] bout=baos.toByteArray();

DatagramPacket packet=new DatagramPacket(bout,bout.length,

address,port);

socket.send(packet);

unde address si port sunt adresa si portul utilizat de expeditorul mesajului. Dacapacket este un obiect DatagramPacket receptionat atunci metodele getAddress()

si getPort() furnizeaza adresa si portul expeditoruluiReceptionarea si transformarea inversa este

Page 32: DISTR1

32 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA

byte[] bin=new byte[256];

packet=new DatagramPacket(bin,bin.length);

socket.receive(packet);

ByteArrayInputStream bais=new ByteArrayInputStream(bin);

ObjectInputStream in=new ObjectInputStream(bais);

obj=in.readObject();

Daca mesajul este un obiect String atunci el se transforma ıntr-un sir de octeticu metoda byte[] String.getByte() si invers, el se obtine prin new String(bin)

sau new String(packet.getData()).

Exemplul 2.5.2 Programam serviciul calculului celui mai mare divizor comun adoua numere.

In vederea transportului definim clasa

1 import java . i o . ∗ ;

3 public class Protoco l implements S e r i a l i z a b l e {4 long x , y ;5 Protoco l ( long x , long y ){6 this . x=x ;7 this . y=y ;8 }9 }

Clientul va trimite un obiect Protocol, care va contine datele problemei si vareceptiona un obiect de acelasi tip cu rezultatul (cel mai mare divizor comun) ınprimul camp al obiectului.

Programul client este

1 import java . net . ∗ ;2 import java . i o . ∗ ;3 import java . u t i l . Scanner ;

5 public class ClientCmmdc{6 public stat ic void main ( St r ing [ ] a rgs ){

8 St r ing hos tServe r=” l o c a l h o s t ” ;9 int por tSe rve r =7999;

10 i f ( args . length >0)11 hos tServe r=args [ 0 ] ;12 i f ( args . length >1)13 por tSe rve r=I n t e g e r . pa r s e In t ( args [ 1 ] ) ;14 try{15 // Crearea unui soc lu Datagramsocket16 DatagramSocket socke t=new DatagramSocket ( ) ;

18 // Formarea mesaju lu i19 Protoco l p=new Protoco l ( 0 , 0 ) ;

Page 33: DISTR1

2.5. DATAGRAME 33

20 Scanner scanner=new Scanner ( System . in ) ;21 System . out . p r i n t l n ( ” I n t r o d u c e t i primul numar : ” ) ;22 p . x=scanner . 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=scanner . nextLong ( ) ;

26 // Transformarea mesa ju lu i in t r−un s i r de o c t e t i

28 ByteArrayOutputStream baos=new ByteArrayOutputStream ( 2 5 6 ) ;29 ObjectOutputStream out=new ObjectOutputStream ( baos ) ;30 out . wr i teObject (p ) ;31 byte [ ] bout=baos . toByteArray ( ) ;

33 // Expedierea mesaju lu i

35 InetAddress address=InetAddress . getByName( hos tServe r ) ;36 DatagramPacket packet=new37 DatagramPacket ( bout , bout . length , address , por tServe r ) ;38 socke t . send ( packet ) ;

40 // Asteptarea raspunsu lu i

42 byte [ ] bin=new byte [ 2 5 6 ] ;43 packet=new DatagramPacket ( bin , bin . l ength ) ;44 socke t . r e c e i v e ( packet ) ;

46 // Pre lucrarea raspunsu lu i

48 ByteArrayInputStream ba i s=new ByteArrayInputStream ( bin ) ;49 ObjectInputStream in=new ObjectInputStream ( ba i s ) ;50 p=(Protoco l ) in . readObject ( ) ;51 System . out . p r i n t l n ( ”Cmmdc = ”+p . x ) ;

53 socke t . c l o s e ( ) ;54 }55 catch ( Exception e ){56 System . out . p r i n t l n ( e . getMessage ( ) ) ;57 }58 }59 }

Programul server este

1 import java . net . ∗ ;2 import java . i o . ∗ ;

4 public class ServerCmmdc{5 public stat ic void main ( St r ing [ ] a rgs ){

7 DatagramSocket socke t=null ;8 int s e rve rPor t =7999;9 try{

10 // Crearea unui soc lu DatagramSocket

12 socke t=new DatagramSocket ( s e rve rPor t ) ;

14 }15 catch ( Exception e ){16 System . out . p r i n t l n ( ”DatagramSocket−e r ror−”+e . getMessage ( ) ) ;

Page 34: DISTR1

34 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA

17 System . e x i t ( 0 ) ;18 }

20 // Ac 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 packet=null ;24 App app=new App ( ) ;25 Protoco l p=null ;

27 while ( l i s t e n i n g ){28 try{

30 // Receptionarea unui mesaj

32 byte [ ] bin=new byte [ 2 5 6 ] ;33 packet=new DatagramPacket ( bin , bin . l ength ) ;34 socke t . r e c e i v e ( packet ) ;

36 // Pre lucrarea da t e l o r

38 ByteArrayInputStream ba i s=new ByteArrayInputStream ( bin ) ;39 ObjectInputStream in=new ObjectInputStream ( ba i s ) ;40 p=(Protoco l ) in . readObject ( ) ;

42 // Rezolvarea c e r e r i i c l i e n t u l u i

44 p . x=app . cmmdc(p . x , p . y ) ;45 p . y=0;

47 // Transformarea mesa ju lu i de raspuns in t r−un s i r de o c t e t i

49 ByteArrayOutputStream baos=new ByteArrayOutputStream ( 2 5 6 ) ;50 ObjectOutputStream out=new ObjectOutputStream ( baos ) ;51 out . wr i teObject (p ) ;52 byte [ ] bout=baos . toByteArray ( ) ;

54 // Expedierea mesaju lu i ne c e s i t a cunoasterea e x p e d i t o r u l u i

56 InetAddress address=packet . getAddress ( ) ;57 int port=packet . getPort ( ) ;58 packet=new DatagramPacket ( bout , bout . length , address , port ) ;59 socke t . send ( packet ) ;60 }61 catch ( Exception e ){62 System . out . p r i n t l n ( e . getMessage ( ) ) ;63 }64 }65 socke t . c l o s e ( ) ;66 }67 }

Clasa App este cea utilizata la exemplul cu socluri TCP.

Page 35: DISTR1

2.5. DATAGRAME 35

2.5.5 Clasa java.net.MulticastSocket

Multicast vs. Broadcast

Prin intermediul unui soclu de tip MulticastSocket se pot receptiona datagrameexpediate de un server catre toti clientii cu un asemenea soclu.

Constructori

• MulticastSocket(int port) throws SocketException

Metode

• void joinGroup(InetAddress adresa) throws SocketException

Soclul se ”conecteaza” la grupul definit de adresa IP (de tip D, adica cuprinsıntre 224.0.0.0 si 239.255.255.255).

• void leaveGroup(InetAddress adresa) throws SocketException

Soclul se ”deconecteaza” la grupul definit de adresa IP.

• void close()

Pregatirea clientului ın vederea receptionarii datagramelor printr-un soclu de tipMulticastSocket consta din

MulticastSocket socket= new MulticastSocket(port);

InetAddress adresa=InetAddress.getByName("230.0.0.1");

socket.joinGroup(adresa);

In final, clientul se deconecteaza si ınchide soclul.

socket.leaveGroup(adresa);

socket.close();

Pachetele trimise de programul server trebuie sa se adreseze grupului, identificatprin adresa IP de tip D.

Astfel prin multicast serverul trimite pachete la o adresa de grup si la un portfixat. Pachetele emise de server sunt receptionate de orice client ce creaza un soclu detip MulticastSocket pentru portul la care emite serverul si care se alatura grupului.

Prin broadcast serverul emite datagrame catre orice calculator al retelei localela un anumit port. Faptul ca emiterea datagramelor este de tip broadcast se indicaprin

DatagramSocket.setBroadcast(true)

Orice client care ısi creaza un soclu la portul la care emite serverul receptioneazadatagramele trimise de server. Adresa utilizata de server la crearea datagramelortrebuie sa identifice reteaua.

Observatie. In cazul unui calculator ”izolat” este nevoie de instalarea driveruluiMicrosoft Loopback Adapter, care simuleaza existenta unei placi de retea active.

Page 36: DISTR1

36 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA

Exemplul 2.5.3 Multicast si Broadcast: programele server emit din cinci ıncinci secunde ora exacta. Un client va receptiona cate cinci datagrame.

Codurile sunt date ın Fig. 2.1 si Fig. 2.2, respectiv pentru partea de server sicea de client.

2.6 Canale de comunicatie

Odata cu versiunea j2sdk1.4 apar clase noi pentru operatii de intrare - iesire ınpachetele java.nio si java.nio.channels. Pachetul java.nio.channels contineclase pentru comunicatia ın retea, si anume canalele de comunicatie.

Informatia transportata printr-un canal de comunicatie trebuie ınglobata ınobiecte container de tip Buffer.

2.6.1 Clasa java.nio.Buffer

Ierarhia claselor Buffer

abstract Buffer

ByteBuffer

ShortBuffer

IntBuffer

LongBuffer

FloatBuffer

DoubleBuffer

CharBuffer

Un obiect de tip typeBuffer este un tampon (container) care contine date detipul specificat de denumirea clasei.

Un obiect de tip Buffer este caracterizat de

• capacitate (capacity) numarul elementelor care pot fi ınmagazitate ın tampon;

• limita (limit) marginea superiora a indicelui;

• indice (position) valoarea curenta a indicelui, ce corespunde unui cursor ceindica ınceputul zonei unde se introduc sau de unde se extrag date din tampon.

Metode generale

• clear() permite unui obiect de tip Buffer sa fie reıncarcat. Fixeaza limita =capacitate si indice = 0.

• flip() pregateste obiectul de tip Buffer pentru consultare (citire). Fixeazalimita =numarul elementelor din tampon si indice = 0.

• rewind() pregateste obiectul de tip Buffer pentru re-citire.

Page 37: DISTR1

2.6. CANALE DE COMUNICATIE 37

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;

public class MulticastServer{ public class BroadcastServer{

public static void main(String[] args){ public static void main(String[] args){

long FIVE_SECONDS = 5000; long FIVE_SECONDS = 5000;

boolean sfarsit=false; boolean sfarsit=false;

DatagramSocket socket = null; DatagramSocket socket = null;

int serverPort=7000; int serverPort=7000;

int clientPort=7001; int clientPort=7001;

byte[] buf = new byte[256]; byte[] buf = new byte[256];

Date data=null; Date data = null;

DatagramPacket packet = null; DatagramPacket packet = null;

try{ try{

socket=new DatagramSocket(serverPort); socket=new DatagramSocket(serverPort);

} }

catch(SocketException e){ catch(SocketException e){

System.out.println(e.getMessage()); System.out.println(e.getMessage());

} }

while (! sfarsit){ while (! sfarsit) {

try{ try{

data=new Date(); data=new Date();

String df=DateFormat. String df=DateFormat.

getTimeInstance().format(data); getTimeInstance().format(data);

buf = df.getBytes(); buf = df.getBytes();

// send it

InetAddress group = InetAddress group =

InetAddress.getByName("230.0.0.1"); InetAddress.getByName("192.168.0.255");

packet=new DatagramPacket(buf, packet=new DatagramPacket(buf,

buf.length,group,clientPort); buf.length,group,clientPort);

socket.setBroadcast(true);

socket.send(packet); socket.send(packet);

// sleep for a while

Thread.sleep(FIVE_SECONDS); Thread.sleep(FIVE_SECONDS);

} }

catch (Exception e) { catch (Exception e) {

System.out.println(e.getMessage()); System.out.println(e.getMessage());

} }

} }

socket.close(); socket.close();

} }

} }

Table 2.1: Clasele server.

Page 38: DISTR1

38 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA

MulticastClient BroadcastClient

import java.io.*; import java.io.*;

import java.net.*; import java.net.*;

public class MulticastClient { public class BroadcastClient {

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

} }

} }

Table 2.2: Clasele client.

Page 39: DISTR1

2.6. CANALE DE COMUNICATIE 39

2.6.2 Clasa java.nio.ByteBuffer

Instantierea unui obiect se obtine prin metoda statica

static ByteBuffer allocate(capacitate)

Introducerea si extragerea datelor din tampon se poate face ın mod

• relativ - implica modificarea indicelui tamponului;

• absolut - fara modificarea indicelui.

MetodeIntroducerea datelor ın mod relativ:

• ByteBuffer put(byte b)

• ByteBuffer putTip(tip x)

Extragerea datelor ın mod relativ:

• byte get()

• tip getTip()

Introducerea datelor ın mod absolut:

• ByteBuffer put(int index,byte b)

• ByteBuffer putTip(int index,tip x)

Extragerea datelor ın mod absolut:

• byte get(int index)

• tip getTip(int index)

unde tip poate fi char, short, int, long, float, double.

Alte metode

• public final boolean hasRemaining()

Daca indicele nu este egal cu limita atunci returneaza true, semnaland existentaın tampon a unor octeti.

• static ByteBuffer wrap(byte[] array)

• public static ByteBuffer wrap(byte[] array,int offset,int length)

Converteste sirul de octeti ıntr-un obiect Bytebuffer.

Page 40: DISTR1

40 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA

• public final byte[] array()

Transformarea inversa, obiectul ByteBuffer este convertit ıntr-un sir de octeti.

Un obiect de tip ByteBuffer se poate percepe ca un obiect de tip LongBuffer,

DoubleBuffer, etc prin

ByteBuffer bb=ByteBuffer.allocate(10);

LongBuffer lb=bb.asLongBuffer();

DoubleBuffer db=bb.asDoubleBuffer();

2.6.3 Clasa java.net.InetSocketAddress

Clasa InetSocketAddress extinde clasa SocketAddress si ıncapsuleaza adresaunui calculator din Internet ımpreuna cu un port ın vederea legarii la un ServerSocket.

Constructori:

• InetSocketAddress(InetAddress addr,int port)

• InetSocketAddress(String numeCalculator,int port)

• InetSocketAddress(int port)

2.6.4 Clasa java.nio.channels.ServerSocketChannel

Crearea unui obiect de tip ServerSocketChannel se realizeaza prin

static ServerSocketChannel open() throws IOException

Unui asemenea obiect i se asociaza un ServerSocket prin metoda

ServerSocket socket() throws IOException.

Obiectul de tip ServerSocket trebuie leagat la un port de comunicatie prin metoda

void bind(InetSocketAddress endpoint) throws IOException.

Sablonul de utilizare este

try{

ServerSocketChannel ssc=ServerSocketChannel.open();

ServerSocket ss=ssc.socket();

InetSocketAddress isa=new InetSocketAddress(addr,port);

ss.bind(isa);

}

catch(Exception e){. . .}

La apelul unui client, serverul trebuie sa genereze un obiect de tip Socket

Channel prin care se vor derula comunicatiile cu clientul. Acest canal de comunicatiese obtine cu metoda accept().

Page 41: DISTR1

2.6. CANALE DE COMUNICATIE 41

2.6.5 Clasa java.nio.channels.SocketChannel

Crearea unui obiect de tip SocketChannel se realizeaza prin

static SocketChannel open() throws IOException

Acest obiect trebuie conectat la obiectul ServerSocketChannel al serverului cumetoda connect(InetSocketAddress addr).

Datele vehiculate printr-un SocketChannel sunt de tip ByteBuffer. Datele setransmit prin metoda

int write(ByteBuffer sursa)

si se receptioneaza prin metoda

int read(ByteBuffer destinatie)

Valoarea returnata de cele doua metode reprezinta numarul octetilor trimisi /receptionati.

Doar octetii unui obiect de tip ByteBuffer cuprinsi ıntre indice si limita sunttransmisi prin canal. Astfel, dupa ıncarcarea unui obiectului ByteBuffer cu metoderelative trebuie apelata metoda flip().

Canalul se ınchide cu metoda close().

Exemplul 2.6.1 Calculul celui mai mare divizor comun a doua numere naturale.

Aplicatie client-server bazat pe canale de comunicatie prin socluri are programulserver

1 import java . i o . ∗ ;2 import java . net . ∗ ;3 import java . n io . ∗ ;4 import java . n io . channe l s . ∗ ;5 import java . u t i l . ∗ ;

7 public class SocketChannelCmmdcServer {

9 private stat ic void s e r v i c i u ( ServerSocketChannel s s c ){10 SocketChannel sc = null ;11 try {12 sc=s s c . accept ( ) ;13 ByteBuf fer bb = ByteBuffer . a l l o c a t e ( 1 6 ) ;14 // LongBuffer l b = bb . asLongBuffer ( ) ;15 sc . read (bb ) ;16 // Varianta 117 long m=bb . getLong ( 0 ) ;18 long n=bb . getLong ( 8 ) ;19 // Varianta 220 // long m=l b . ge t ( 0 ) ;21 // long 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 ( ) ;

Page 42: DISTR1

42 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA

25 // Varianta 126 bb . putLong (0 , r ) ;27 // Varianta 228 // l b . put ( r ) ;29 sc . wr i t e (bb ) ;30 sc . c l o s e ( ) ;31 }32 catch ( Exception e ){33 System . out . p r i n t l n ( ” Server e r r o r : ”+e . getMessage ( ) ) ;34 }35 }

37 public stat ic void main ( St r ing [ ] a rgs ){38 int port =7999;39 ServerSocketChannel s s c=null ;40 try{41 s s c = ServerSocketChannel . open ( ) ;42 InetSocketAddress i s a=new InetSocketAddress ( port ) ;43 ServerSocket s s=s s c . socket ( ) ;44 s s . bind ( i s a ) ;45 }46 catch ( IOException e ){47 System . out . p r i n t l n ( ” ServerSocketChannelError : ”+e . getMessage ( ) ) ;48 System . e x i t ( 0 ) ;49 }50 System . out . p r i n t l n ( ” Server ready . . . ” ) ;51 while ( true ){52 s e r v i c i u ( s s c ) ;53 }54 }55 }

si clientul

1 import java . i o . ∗ ;2 import java . net . ∗ ;3 import java . n io . ∗ ;4 import java . n io . channe l s . ∗ ;5 import java . u t i l . Scanner ;

7 public class SocketChannelCmmdcClient {8 public stat ic void main ( St r ing [ ] a rgs ) {9 St r ing host=” l o c a l h o s t ” ;

10 int port =7999;11 i f ( args . length >0)12 host=args [ 0 ] ;13 i f ( args . length >1)14 port=I n t e g e r . pa r s e In t ( args [ 1 ] ) ;15 SocketChannel sc=null ;16 try{17 InetSocketAddress i s a=new InetSocketAddress ( host , port ) ;18 sc=SocketChannel . open ( ) ;19 sc . connect ( i s a ) ;20 }21 catch ( UnknownHostException e ) {22 System . e r r . p r i n t l n ( ” Server necunoscut : ”+host+” ”+e . getMessage ( ) ) ;23 System . e x i t ( 1 ) ;24 }25 catch ( IOException e ) {26 System . e r r . p r i n t l n ( ” Conectare i m p o s i b i l a l a : ”+

Page 43: DISTR1

2.6. CANALE DE COMUNICATIE 43

27 host+” pe por tu l ”+port+” ”+e . getMessage ( ) ) ;28 System . e x i t ( 1 ) ;29 }30 Scanner scanner=new Scanner ( System . in ) ;31 long m, n , r ;32 System . out . p r i n t l n ( ”m=” ) ;33 m=scanner . nextLong ( ) ;34 System . out . p r i n t l n ( ”n=” ) ;35 n=scanner . nextLong ( ) ;

37 ByteBuffer bb=ByteBuffer . a l l o c a t e ( 1 6 ) ;38 // Varianta 139 bb . putLong (0 ,m) . putLong (8 , n ) ;40 // Varianta 241 // LongBuffer l b=bb . asLongBuffer ( ) ;42 // l b . put (0 ,m) . put (1 ,n ) ;43 try{44 sc . wr i t e (bb ) ;45 bb . c l e a r ( ) ;46 sc . read (bb ) ;47 // Varianta 148 r=bb . getLong ( 0 ) ;49 // Varianta 250 // r=l b . g e t ( 0 ) ;51 System . out . p r i n t l n ( ”Cmmdc : ”+r ) ;52 sc . c l o s e ( ) ;53 }54 catch ( Exception e ){55 System . e r r . p r i n t l n ( ” Eroare de comunicat ie ”+e . getMessage ( ) ) ;56 }57 }58 }

Varianta comentata corespunde cazului ın care se utilizeara clasa acoperitoare LongBuffer.

2.6.6 Clasa java.nio.channels.DatagramChannel

Sablonul de programare pentru instantierea unui obiect de tip DatagramChannel

este

DatagramChannel dc=null;

InetSocketAddress isa=new InetSocketAddress(port);

try{

dc=DatagramChannel.open();

DatagramSocket datagramSocket=dc.socket();

datagramSocket.bind(isa);

}

catch(Exception e){. . .}

unde port este portul folosit de DatagramChannel. Daca port=0 atunci se alegealeator un port disponibil.

Transmiterea unui obiect ByteBuffer se face cu metoda

Page 44: DISTR1

44 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA

public int send(ByteBuffer src, SocketAddress target) throws

IOException

Metoda returneaza numarul de octeti expediati. Receptia unui ByteBuffer se obtinecu metoda

public SocketAddress receive(ByteBuffer dst) throws IOException

Obiectul returnat reprezinta adresa expeditorului.

Exemplul 2.6.2 Calculul celui mai mare divizor comun a doua numere naturale.

1 import java . i o . ∗ ;2 import java . net . ∗ ;3 import java . n io . ∗ ;4 import java . n io . channe l s . ∗ ;5 import java . u t i l . ∗ ;

7 public class DatagramChannelCmmdcServer {8 public stat ic void main ( St r ing [ ] a rgs ){9 int port =7999;

10 DatagramChannel dc=null ;11 InetSocketAddress i s a=new InetSocketAddress ( port ) ;12 try{13 dc=DatagramChannel . open ( ) ;14 }15 catch ( IOException e ){16 System . out . p r i n t l n ( e . getMessage ( ) ) ;17 }18 DatagramSocket datagramSocket=dc . socke t ( ) ;19 try{20 datagramSocket . bind ( i s a ) ;21 }22 catch ( SocketExcept ion e ){23 System . out . p r i n t l n ( e . getMessage ( ) ) ;24 }25 System . out . p r i n t l n ( ” Server ready . . . ” ) ;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 ByteBuffer bb=ByteBuffer . a l l o c a t e ( 1 6 ) ;31 // LongBuffer l b=bb . asLongBuffer ( ) ;32 SocketAddress c l i e n t=dc . r e c e i v e (bb ) ;33 // Varianta 134 long m=bb . getLong ( 0 ) ;35 long n=bb . getLong ( 8 ) ;36 // Varianta 237 // long m=l b . ge t ( 0 ) ;38 // long 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 // Varianta 143 bb . putLong (0 , r ) ;44 // Varianta 2

Page 45: DISTR1

2.6. CANALE DE COMUNICATIE 45

45 // l b . put (0 , r ) ;46 dc . send (bb , c l i e n t ) ;47 }48 catch ( Exception e ){49 System . out . p r i n t l n ( ” Eroare s e r v e r : ”+e . getMessage ( ) ) ;50 System . e x i t ( 1 ) ;51 }52 }53 }54 }

1 import java . i o . ∗ ;2 import java . net . ∗ ;3 import java . n io . ∗ ;4 import java . n io . channe l s . ∗ ;5 import java . u t i l . Scanner ;

7 public class DatagramChannelCmmdcClient {8 public stat ic void main ( St r ing [ ] a rgs ) throws IOException {9 St r ing se rverHost=” l o c a l h o s t ” ;

10 int port =7999;11 i f ( args . length >0)12 se rverHost=args [ 0 ] ;13 i f ( args . length >1)14 port=I n t e g e r . pa r s e In t ( args [ 1 ] ) ;15 InetSocketAddress s e r v e r=null , i s a=null ;16 try{17 s e r v e r=new InetSocketAddress ( InetAddress . getByName( se rverHost ) , port ) ;18 }19 catch ( UnknownHostException e ){20 System . out . p r i n t l n ( ”Unknown host : ”+e . getMessage ( ) ) ;21 System . e x i t ( 1 ) ;22 }23 i s a=new InetSocketAddress ( 0 ) ;24 DatagramChannel dc=null ;25 try {26 dc=DatagramChannel . open ( ) ;27 DatagramSocket socke t = dc . socket ( ) ;28 socke 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 the DatagramChannel ”+ e . getMessage ( ) ) ;32 System . e x i t ( 1 ) ;33 }34 long m, n , r ;35 Scanner scanner=new Scanner ( System . in ) ;36 System . out . p r i n t l n ( ”m=” ) ;37 m=scanner . nextLong ( ) ;38 System . out . p r i n t l n ( ”n=” ) ;39 n=scanner . nextLong ( ) ;40 ByteBuffer bb=ByteBuffer . a l l o c a t e ( 1 6 ) ;41 // Varianta 142 bb . putLong (0 ,m) . putLong (8 , n ) ;43 // Varianta 244 // LongBuffer l b=bb . asLongBuffer ( ) ;45 // l b . put (0 ,m) . put (1 ,n ) ;46 try{47 dc . send (bb , s e r v e r ) ;48 bb . c l e a r ( ) ;

Page 46: DISTR1

46 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA

49 dc . r e c e i v e (bb ) ;50 // Varianta 151 r=bb . getLong ( 0 ) ;52 // Varianta 253 // r=l b . g e t ( 0 ) ;54 System . out . p r i n t l n ( ”Cmmdc = ”+r ) ;55 }56 catch ( Exception e ){57 System . e r r . p r i n t l n ( ” C l i en t e r r o r : ”+e . getMessage ( ) ) ;58 }59 f ina l ly {60 i f ( dc !=null ) dc . d i s connec t ( ) ;61 }62 }63 }

2.7 Conexiuni HTTP

Clasa java.net.URL permite realizarea unei conexiuni cu un server Web1 potrivitprotocolului HTTP (Hyper Text Transport Protocol) si accesarea fisierelor - uzualhtml - din zona publica.

Constructori

• URL(String spec) throws MalformedURLException

Creaza un obiect URL legat de resursa specificata de spec, care trebuie sa fie oreferinta URL valida.

Metode

• InputStream openStream() throws IOException

Returneaza fluxul de intrare pentru citirea resursei.

Exemplul 2.7.1 Pe baza referintei catre un fisier html dintr-un catalog vizibil alunui server Web, sa se afiseze continutul fisierului.

In codul reprodus mai jos, fisierul Hello.html se afla pe un server apache-tomcat,ın catalogul webapps\myservlet.

1 import java . net . ∗ ;2 import java . i o . ∗ ;

4 public class ReadHTTP{5 public stat ic void main ( St r ing [ ] a rgs ){6 try{7 St r ing adr=” http :// l o c a l h o s t :8080/ myserv let / He l lo . html” ;8 //System . se tProper ty (” h t t p . proxyHost ” , ”10 .3 . 5 . 133”) ;9 //System . se tProper ty (” h t t p . proxyPort ” ,”3128”);

1apache-tomcat, apache, Micrsoft IIS (Internet Information Services), etc.

Page 47: DISTR1

2.7. CONEXIUNI HTTP 47

10 URL u r l=new URL( adr ) ;11 InputStream in=u r l . openStream ( ) ;12 InputStreamReader i s r=new InputStreamReader ( in ) ;13 BufferedReader br=new BufferedReader ( i s r ) ;14 St r ing s ;15 do{16 s=br . readLine ( ) ;17 i f ( s !=null )18 System . out . p r i n t l n ( s ) ;19 }20 while ( s !=null ) ;21 br . c l o s e ( ) ;22 i s r . c l o s e ( ) ;23 in . c l o s e ( ) ;24 }25 catch ( Exception e ){26 System . out . p r i n t l n ( e . getMessage ( ) ) ;27 }28 }29 }

Page 48: DISTR1

48 CAPITOLUL 2. PROGRAMARE CU SOCLURI JAVA

Page 49: DISTR1

Capitolul 3

Regasirea obiectelor prinservicii de nume

Oricarui obiect ıi sunt asociate un nume si o referinta. Regasirea / cautareaobiectului se face pornind de la numele obiectului, prin referinta se ajunge la obiect.

Exemple date prin sablonul (Nume ⇒ Referinta ⇒ Obiect)

1. Accesul la o carte ıntr-o biblioteca:

Titlul cartii ⇒ Referinta cartii din biblioteca ⇒ Carte

2. Contactul telefonic cu o persoana:

Nume persoana ⇒ Numar telefon ⇒ Persoana

Un serviciu de nume contine asocieri dintre nume de obiecte si obiecte si poateoferi facilitati de regasire a obiectelor.

3.1 Java Naming and Directory Interface

Java Naming and Directory Interface - JNDI este o interfata de programare (Ap-plication Programming Interface - API ) care descrie functionalitatea unui serviciude nume.

Cuvantul servici este utilizat ın sens comun, entitate care pune la dispozitiefacilitati de folosire.

Alaturi de interfata JNDI, arhitectura JNDI mai contine interfata Service ProviderInterface - SPI. Implementarea interfetei SPI de un furnizor de servicii JNDI are caefect independenta programului Java de furnizorul de servicii JNDI.

JNDI este implementat de serviciile de nume:

• Filesystem are ca obiect asocierea dintre numele de fisier sau catalog cu obiec-tul corespunzator.

49

Page 50: DISTR1

50 CAPITOLUL 3. REGASIREA OBIECTELOR PRIN SERVICII DE NUME

• DNS - Domain Name System are ca obiect asocierea dintre adresa Internet cuadresa IP.

• RMI registry utilizat ın aplicatii RMI, din Java. Are ca obiect asocierea ıntreun nume de serviciu de invocare ale obiectelor la distanta cu un delegat alserviciului (stub).

• COS - Common Object Service Naming utilizat ın aplicatii CORBA. Are caobiect asocierea ıntre numele unui serviciu de invocare ale obiectelor la distantacu referinta la serviciu.

• LDAP - Lightweight Directory Access Protocol defineste un protocol pentruaccesarea datelor retinute ıntr-un catalog LDAP (LDAP directory, informa-tion directory). Un catalog LDAP permite retinerea si regasirea referintelorobiectelor definite pe un calculator.

Interfata javax.naming.Context

Printr-un context se va ıntelege o multime de asocieri nume - obiect. Core-spunzator unui context, JNDI defineste interfata Context, cu metodele

• void bind(String nume,Object object)

• void rebind(String nume,Object object)

• void unbind(String nume)

• Object lookup(String nume)

• NamingEnumeration list(String nume)

Returneaza lista cu nume obiectelor ımpreuna cu tipul lor.

• NamingEnumeration listBindings(String nume)

Returneaza lista cu nume obiectelor ımpreuna cu tipul si locatia acestora.

Specificatiile JNDI prevad definirea unui context initial, implementat prin clasajavax.naming.InitialContext, clasa ce implementeaza interfata Context.

Constructori.

• public InitialContext() throws NamingException

• public void InitialContext(Hashtable<?,?> environment)throwsNamingException

Page 51: DISTR1

3.1. JAVA NAMING AND DIRECTORY INTERFACE 51

Pentru crearea contextului initial trebuie specificata clasa care creaza contextulinitial prin parametrul java.naming.factory.initial sau constantaContect.INITIAL CONTEXT FACTORY.

Acest parametru se poate da ın mai multe moduri:

• Includerea ın obiectul Hashtable care apare ın constructorul clasei InitalContext.

Hashtable env=new Hashtable()

env.put("java.naming.factory.initial",...);

Context ctx=InitialContext(env);

sau

Hashtable env=new Hashtable()

env.put(Context.INITIAL_CONTEXT_FACTORY,...);

Context ctx=new InitialContext(env);

• Ca parametru de sistem furnizat la lansarea programului Java, prin

java -Djava.naming.factory.initial=... ClasaJava

Parametrul se poate da ın interiorul programului prin

System.setProperty("java.naming.factory.initial",...);

sau

System.setProperty(Context.INITIAL_CONTEXT_FACTORY,...);

• Atribut ın fisierul de proprietati jndi.properties.

In aceste ultime doua cazuri, contextul initial se creaza prin

Context ctx=new InitialContext();

Functie de serviciul de nume, clasa care creaza contextul initial este dat ın tabelul

Serviciul de nume Clasa

Filesystem com.sun.jndi.fscontect.RefFSContextFactory

COS com.sun.jndi.cosnaming.CNCtxFactory

RMI com.sun.jndi.rmi.registry.RegistryContextFactory

DNS com.sun.jndi.dns.DnsContextFactory

LDAP com.sun.jndi.ldap.LdapCtxFactory

Page 52: DISTR1

52 CAPITOLUL 3. REGASIREA OBIECTELOR PRIN SERVICII DE NUME

Exemplul 3.1.1 Utilizand serviciul JNDI Filesystem se creaza un context prin in-termediul careia se afiseaza continutul unui catalog indicat de client.

1 import javax . naming . ∗ ;2 import java . i o . F i l e ;3 import java . u t i l . Hashtable ;4 import java . u t i l . Scanner ;

6 class Lookup{7 public stat ic void main ( St r ing [ ] a rgs ) {8 Context ctx=null ;9 /∗

10 // Varianta 111 Hashtab le env = new Hashtab le (11 ) ;12 env . put ( Context .INITIAL CONTEXT FACTORY,13 ”com. sun . jnd i . f s c on t e x t . RefFSContextFactory ” ) ;14 t r y {15 c t x = new In i t i a lCon t e x t ( env ) ;16 }17 catch (NamingException e ) {18 System . out . p r i n t l n (” In i t i a lCon t e x tEr ro r : ”+e . getMessage ( ) ) ;19 }20 ∗/21 /∗22 // Varianta 223 System . se tProper ty (” java . naming . f a c t o r y . i n i t i a l ” ,24 ”com. sun . jnd i . f s c on t e x t . RefFSContextFactory ” ) ;25 t r y {26 c t x = new In i t i a lCon t e x t ( ) ;27 }28 catch (NamingException e ) {29 System . out . p r i n t l n (” In i t i a lCon t e x tEr ro r : ”+e . getMessage ( ) ) ;30 }31 ∗/

33 // Varianta 334 try{35 ctx = 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 . getMessage ( ) ) ;39 }

41 Scanner scanner=new Scanner ( System . in ) ;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 abso luta a unui ca ta l og : ” ) ;43 St r ing myName=scanner . next ( ) ;44 try{45 System . out . p r i n t l n ( ”\n ctx . lookup ( ”+myName+” ) produce ” ) ;46 System . out . p r i n t l n ( ctx . lookup (myName ) ) ;

48 System . out . p r i n t l n ( ”\nContinutul c a t a l o g u l u i ”+myName+” e s t e :\n” ) ;49 NamingEnumeration l s t=ctx . l i s t (myName) ;50 while ( l s t . hasMore ( ) ){51 NameClassPair nc = ( NameClassPair ) l s t . next ( ) ;52 System . out . p r i n t l n ( nc ) ;53 }

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

Page 53: DISTR1

3.1. JAVA NAMING AND DIRECTORY INTERFACE 53

56 NamingEnumeration l s t 1 = ctx . l i s t B i n d i n g s (myName) ;57 while ( l s t 1 . hasMore ( ) ) {58 Binding bd = ( Binding ) l s t 1 . next ( ) ;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 . getMessage ( ) ) ;65 }66 }67 }

Apelarea clasei, ın varianta data, consta din

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

sau

java Lookup

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

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

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

3.1.1 LDAP

LDAP poate fi privit ca un sistem de gestiune a unei baze de date (ne relational).Baza de date este alcatuita din atribute ale caror nume este precizat de protocolulLDAP.

Punctele de intrare (radacinile) sunt date de DN (Distinguished Name). UzualDN se defineste printr-una din variantele

1. o=”organization”,c=”country”

2. o=”organization”

3. dc=”domain content 1”,c=”domain content 2”

De exemplu, dc=”example”,dc=”com”

Un utilizator este caracterizat prin atributul cn - common name si are acces laLDAP prin precizarea simultana a atributelor DN si cn.

Vom utiliza produsul OpenDS (Directory Service), ce implementeaza protocolulLDAP.

Instalarea consta din:

1. dezarhivarea distributiei;

Page 54: DISTR1

54 CAPITOLUL 3. REGASIREA OBIECTELOR PRIN SERVICII DE NUME

2. se completeaza sursa fisierului OpenDS-*\setup.bat cuset OPENDS JAVA HOME=... ca prima linie;

3. se executa OpenDS-*\setup.bat. Prin intermediul unei interfete grafice sefixeaza

• o parola pentru cn=Directory Manager. Fie 1q2w3e aceasta parola.

• un punct de intrare, fie acesta DN: dc=example,dc=com.

Implicit, serverul OpenDS utilizeaza portul 389.Operatiile de configurare se fac utilizand interfata grafica a componentei OpenDS

Directory Server Control Panel, lansat prin

set OPENDS_JAVA_HOME=. . .

set OpenDS_HOME=. . .\OpenDS-*

%OpenDS_HOME%\bat\control-panel.bat

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 si Reset User Password.

Prin aceasta componenta se poate porni si opri serverul OpenDS, ambele operatiiputand fi executate si apeland start-ds, stop-ds din catalogulOpenDS HOME\bat.

Exemplul 3.1.2 Program pentru ınregistrarea si stergerea referintei unui obiect detip Cmmdc.

Prin intermediul OpenDS Directory Server Control Panel se creaza se creazao intrare/utilizator care va fi legat de un obiect Cmmdc. Presupunem ca aceastaintrare este cn=info.

1 import java . u t i l . Hashtable ;2 import java . u t i l . Scanner ;3 import javax . naming . Context ;4 import javax . naming . NamingException ;5 import javax . naming . d i r e c t o r y . DirContext ;6 import javax . naming . d i r e c t o r y . I n i t i a l D i r C o n t e x t ;

8 public class LDAPServerCmmdc {9 public stat ic void main ( St r ing [ ] a rgs ) {

10 Hashtable env = new Hashtable ( ) ;11 env . put ( Context . INITIAL CONTEXT FACTORY,12 ”com . sun . j n d i . ldap . LdapCtxFactory” ) ;13 env . put ( Context .PROVIDER URL,14 ” ldap :// l o c a l h o s t :389/ cn=in fo , dc=example , dc=com” ) ;15 env . put ( Context .SECURITY PRINCIPAL, ”cn=Direc tory Manager” ) ;16 env . put ( Context .SECURITY CREDENTIALS, ”1q2w3e” ) ; // paro la17 DirContext ctx = null ;

19 Scanner scanner=new Scanner ( System . in ) ;

Page 55: DISTR1

3.1. JAVA NAMING AND DIRECTORY INTERFACE 55

20 System . out . p r i n t l n ( ” A l e g e t i ope ra t i a : 1− bind ; 2− unbind” ) ;21 int oper=scanner . next Int ( ) ;22 System . out . p r i n t l n ( ” I n t r o d u c e t i va loa rea 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 St r ing cmmdcObj=scanner . next ( ) . tr im ( ) ;

27 try {28 ctx = new I n i t i a l D i r C o n t e x t ( env ) ;29 ctx . unbind ( ”cn=”+cmmdcObj ) ;30 i f ( oper==1){31 Cmmdc obj=new Cmmdc( ) ;32 St r ing s t r=”cn=”+cmmdcObj ;33 ctx . bind ( s t r , obj ) ;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 . getMessage ( ) ) ;39 }40 }41 }

Codul clasei Cmmdc este

1 public class Cmmdc implements java . i o . S e r i a l i z a b l e {2 public long cmmdc( long a , long b) {3 while (b != 0) {4 long r = a % b ;5 a = b ;6 b = r ;7 }8 return a ;9 }

10 }

Exemplul 3.1.3 Utilizarea unui obiect de tip Cmmdc regasit pe baza referintei dinserverul LDAP.

1 import java . u t i l . Hashtable ;2 import javax . naming . Context ;3 import javax . naming . NamingException ;4 import javax . naming . d i r e c t o r y . DirContext ;5 import javax . naming . d i r e c t o r y . I n i t i a l D i r C o n t e x t ;6 import java . u t i l . Scanner ;

8 public class LDAPClientCmmdc {9 public stat ic void main ( St r ing [ ] a rgs ) {

10 Hashtable env = new Hashtable ( ) ;11 env . put ( Context . INITIAL CONTEXT FACTORY,12 ”com . sun . j n d i . ldap . LdapCtxFactory” ) ;13 env . put ( Context .PROVIDER URL,14 ” ldap :// l o c a l h o s t :389/ cn=in fo , dc=example , dc=com” ) ;15 env . put ( Context .SECURITY PRINCIPAL, ”cn=Direc tory Manager” ) ;16 env . put ( Context .SECURITY CREDENTIALS, ”1q2w3e” ) ;17 DirContext ctx = null ;18 try {

Page 56: DISTR1

56 CAPITOLUL 3. REGASIREA OBIECTELOR PRIN SERVICII DE NUME

19 ctx=new I n i t i a l D i r C o n t e x t ( env ) ;20 i f ( ctx != null ) {21 Scanner scanner=new Scanner ( System . in ) ;22 System . out . p r i n t l n ( ” I n t r o d u c e t i va loa rea 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 St r ing cmmdcObj=scanner . next ( ) . tr im ( ) ;26 Object ob j e c t = ctx . lookup ( ”cn=”+cmmdcObj ) ;27 System . out . p r i n t l n ( ”Primul numar” ) ;28 long a=scanner . next Int ( ) ;29 System . out . p r i n t l n ( ”Al d o i l e a numar” ) ;30 long b=scanner . next Int ( ) ;31 Cmmdc obj=(Cmmdc) ob j e c t ;32 System . out . p r i n t l n ( ” Rezu l ta tu l cmmdc e s t e : ”+obj . cmmdc( a , b ) ) ;33 }34 }35 catch ( NamingException e ) {36 System . out . p r i n t l n ( ”LDAPClientCmmdc : ”+e . getMessage ( ) ) ;37 }38 }39 }

Page 57: DISTR1

Capitolul 4

Invocarea procedurilor ladistanta

Invocarea procedurilor la distanta (Remote Procedure Call – RPC ) ınseamnaapelarea unei metode a unui obiect aflat pe un alt calculator ca si cum acesta s-arafla pe calculatorul local.

Se vor prezenta doua cazuri:

• Invocarea procedurilor la distanta ın cazul mediului omogen Java. Denumireatehnologiei ın acest caz este Invocarea metodelor la distanta – Remote MethodInvocation (RMI). Prin mediu omogen se ıntelege faptul ca atat compontentaserver cat si componenta client sunt programate ın acelasi limbaj de progra-mare, Java ın cazul de fata.

• Invocarea procedurilor la distanta ın cazul medii neomogene. Solutia ın acestcaz este dat de Common Object Request Broker Arhitecture (CORBA).

4.1 Remote Method Invocation

Regasirea obiectelor la distanta. Ideea gasirii unui obiect la distanta este caserverul ınscrie un reprezentant al sau – numit stub (ciot) – ıntr-un obiect registry -registru. Acest obiect se creaza cu programul rmiregistry.exe din distributia javasi se lanseaza ın executie prin

start rmiregistry [port ]

unde valoarea implicita a portului este 1099. Comanda start apartine sistemuluide operare. rmiregistry este un serviciu de nume JNDI.

Un client obtine din registry stub-ul serverului, prin intermediul caruia realizeazacomunicatia cu programul server.

57

Page 58: DISTR1

58 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANTA

Cand un obiect al clientului apeleaza o metoda a unui obiect aflat la distanta,se va face, de fapt, un apel de metoda a unui obiect care reprezinta serverul. Acestaeste stub-ul, aflat pe aceasi masina cu clientul.

Rolul acestui obiect este sa ımpacheteze (marshalling) parametrii de apel aimetodei ıntr-un mesaj ce va fi transferat prin retea. Impachetarea se face ıntr-omaniera independenta de calculator, mai precis sirurile de caractere si obiecte sunttransmise ıntr-un format care nu se bazeaza pe referinte. Pentru obiecte se utilizeazaserializarea obiectelor Java.

Serializarea datelor reprezinta transformarea acestora din tipuri de date diferiteıntr-un sir de octeti care va fi transportat prin retea fara interpretare, dar carepastreaza informatiile despre structura initiala a datelor.

Deserializarea este procesul invers de refacere a structurilor trimise prin retea.

Mesajul asamblat este transmis catre server, care stie sa desfaca mesajul receptionatinvocand ın mod corespunzator metoda referita de client.

Atunci cand clientul face apel la o metoda aflata pe o alta masina, este invo-cat stub-ul client, care ıncepe conversatia cu serverul. Acest lucru este complettransparent utilizatorului, care are impresia ca invoca o metoda locala.

Metodele apelate la distanta trebuie declarate ca apartinand unei interfete ceextinde interfata java.rmi.Remote. Fiecare asemenea metoda trebuie sa arunce oexceptie java.rmi.RemoteException. Obiectele care circula prin retea trebuie saimplementeze interfata java.io.Serializable.

Structura unei aplicatii RMI. O aplicatie RMI este alcatuita din trei com-ponente:

1. O interfata la distanta (remote) ın care se declara serviciile puse la dispozitiede server;

2. Aplicatia server care poate implementa serviciile interfetei la distanta si ınscrieın registry stub-ul corespunzator;

3. Aplicatia client ce apeleaza unul sau mai multe servicii ale serverului.

Nici o clipa nu trebuie scapat din vedere faptul ca cele trei componente evolueazape calculatoare diferite.

Registrul rmiregistry implementeaza interfata java.rmi.registry.Registry1.Metodele oferite sunt:

• void bind(String numeServiciu, Remote obj)throwsRemoteException, AlreadyBoundException, AccessException

Inregistreaza ın registry obiectul obj ce implementeaza interfata Remote subnumele numeServiciu.

1Varianta directa, fara a folosi facilitatile JNDI pentru rmiregistry.

Page 59: DISTR1

4.1. REMOTE METHOD INVOCATION 59

• void rebind(String numeServiciu, Remote obj)throwsRemoteException, AccessException

Reınregistreaza ın registry obiectul obj ce implementeaza interfata Remote subnumele numeServiciu.

Aceasta metoda poate fi apelata doar daca programul care face ınregistrarease afla pe aceasi masina ca registrul registry.

• String[] list()throws RemoteException, AccessException

Returneaza o lista a tuturor serviciilor ınregistrate ın registry.

• Remote lookup(String numeServiciu)throwsRemoteException, NotBoundException, AccessException

Returneaza stub-ul serviciului ınregistrat sub numele numeServiciu.

• void unbind(String numeServiciu)throwsRemoteException, NotBoundException, AccessException

Sterge din registru serviciul.

Localizarea registrului se obtine utilizand metoda statica getRegistry a claseijava.rmi.registry.LocateRegistry.

• public static Registry getRegistry() throws RemoteException

• public static Registry getRegistry(String host)throws RemoteException

• public static Registry getRegistry(int port)throws RemoteException

• public static Registry getRegistry(String host,int port)throws RemoteException

Metoda public static Registry createRegistry(int port)throws RemoteException creaza un registru la portul specificat pe calculatorullocal.

Ansamblul (host,port) determina ın mod univoc o aplicatie / serviciu.

Interfata Remote serveste la marcarea interfetelor ale caror metode urmeaza a fiapelate de pe alta masina virtuala Java.

Un obiect de tip java.rmi.server.UnicastRemoteObject mijloceste transmitereaobiectelor si serveste la generarea unui stub unui serviciu. Generarea stub-ului unuiserviciu se obtine prin intermediul metodei statice

static Remote UnicastRemoteObject.exportObject(Remote obj,int port)

Page 60: DISTR1

60 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANTA

Inregistrarea stub-ului unui serviciu descris de interfata IService si imple-mentat de clasa ServiceImpl ın registry se face prin

ServiceImpl obj=new ServiceImpl();

IService stub=(IService)UnicastRemoteObject.exportObject(obj,0);

// Varianta cu apel rmiregistry direct

/*

Registry registry=LocateRegistry.getRegistry(host,port);

registry.bind("MyServiceName",stub);

*/

// Varianta JNDI

String sPort=(new Integer(port)).toString();

System.setProperty(Context.INITIAL_CONTEXT_FACTORY,

"com.sun.jndi.rmi.registry.RegistryContextFactory");

System.setProperty(Context.PROVIDER_URL,"rmi://"+host+":"+sPort);

Context ctx=new InitialContext();

ctx.bind("MyServiceName",stub);

Un client care doreste sa foloseasca trebuie sa cunoasca :

• calculatorul pe care se gaseste obiectul registry si portul la care asculta servi-ciul;

• numele sub care serviciul s-a ınregistrat ın registry;

• metodele puse la dispozitie de serviciu.

4.1.1 Crearea unei aplicatii RMI

Exemplificam construirea unei aplicatii RMI ın care serviciul asigurat de servereste calculul celui mai mare divizor comun a doua numere naturale.

Pentru exemplele2 care urmeaza, presupunem ca textele sursa se retin ın subcat-aloage ale unui catalog src, la care are acces doar programatorul, iar clasele obtinuteprin compilare se depun ın subcataloagele unui catalog public\classes, accesibilprin retea.

Dezvoltarea unei aplicatii se va face pe un calculator. In acest sens, celor 3componente li se asociaza cataloagele \i - pentru interfata la distanta, \s - pentrucomponenta server si \c - pentru componenta client. Pasi necesari compilarii sidesfasurarii componentelor aplicatiei se vor realiza prin intermediul lui ant.

Pentru fiecare componenta se vor executa succesiv obiectivele:

1. Install - creaza o structura de cataloage src si public\classes.2Sistemul de operare utilizat este Windows

Page 61: DISTR1

4.1. REMOTE METHOD INVOCATION 61

2. Init - creaza structura de cataloage specifica aplicatiei.

3. Compile - compileaza programele sursa.

Dezvoltarea unei aplicatii RMI consta din parcurgerea urmatorilor pasi:

1. Definitea interfetei la distanta.

1 package cmmdc ;2 public interface ICmmdc extends java . rmi . Remote{3 long cmmdc( long a , long b) throws java . rmi . RemoteException ;4 }

Presupunem ca programatorul interfetei retine textul sursaICmmdc.java ın catalogul \i\src\cmmdc.

2. Compilarea si arhivarea interfetei se poate realiza fisierul ant-build

1 <project name=” I n t e r f a c e ” d e f a u l t=” I n s t a l l ” ba s ed i r=” . ”>2 <description> I n t e r f a c e a c t i o n s </description>3 < !−− s e t g l o b a l p r op e r t i e s f o r t h i s b u i l d −−>

5 <property name=” package ” value=”cmmdc”/>

7 <target name=” I n s t a l l ”>8 < !−− Create the b u i l d d i r e c t o r y s t r u c t u r e used by compile −−>9 <delete d i r=” s r c ”/>

10 <mkdir d i r=” s r c ”/>11 <delete d i r=” pub l i c ”/>12 <mkdir d i r=” pub l i c ”/>13 <delete d i r=” pub l i c / c l a s s e s ”/>14 <mkdir d i r=” pub l i c / c l a s s e s ”/>15 </target>

17 <target name=” I n i t ”>18 < !−− Create the time stamp −−>19 <tstamp/>20 <mkdir d i r=” s r c /${package}”/>21 <mkdir d i r=” pub l i c / c l a s s e s /${package}”/>22 </target>

24 <target name=”Compile” depends=” I n i t ”25 description=” compile the source ” >26 <javac s r c d i r=” s r c ” i n c l u d e s=”${package }/∗∗”27 d e s t d i r=” pub l i c / c l a s s e s ”/>28 <jar based i r=” pub l i c / c l a s s e s ”29 d e s t f i l e=” pub l i c / c l a s s e s /${package }/${ package } . j a r ”30 i n c l u d e s=”${package }/∗ . c l a s s ” />31 </target>32 </project>

3. Implementarea interfetei remote prin construirea aplicatiei server.

Page 62: DISTR1

62 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANTA

1 package s e r v e r ;

3 import cmmdc . ∗ ;4 import java . rmi . ∗ ;5 import java . rmi . s e r v e r . ∗ ;6 // Varianta d i r e c t a7 // import java . rmi . r e g i s t r y . ∗ ;8 // Varianta JNDI9 import javax . naming . ∗ ;

11 public class CmmdcImpl implements ICmmdc{

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

15 public stat ic void main ( St r ing args [ ] ) {16 St r ing host=” l o c a l h o s t ” ;17 int port =1099;18 i f ( args . length >0)19 host=args [ 0 ] ;20 i f ( args . length >1)21 port=I n t e g e r . pa r s e In t ( args [ 1 ] ) ;22 try {23 CmmdcImpl obj=new CmmdcImpl ( ) ;24 ICmmdc stub=(ICmmdc) UnicastRemoteObject . exportObject ( obj , 0 ) ;

26 // Varianta d i r e c t a27 /∗28 Reg i s t ry r e g i s t r y=LocateReg is t ry . g e tReg i s t r y ( host , por t ) ;29 r e g i s t r y . bind (”CmmdcServer” , s tub ) ;30 ∗/

32 // Varianta JNDI33 St r ing sPort=(new I n t e g e r ( port ) ) . t oS t r i ng ( ) ;34 System . se tProper ty ( Context . INITIAL CONTEXT FACTORY,35 ”com . sun . j n d i . rmi . r e g i s t r y . RegistryContextFactory ” ) ;36 System . se tProper ty ( Context .PROVIDER URL, ”rmi : // ”+host+” : ”+sPort ) ;37 Context ctx=new I n i t i a l C o n t e x t ( ) ;38 ctx . bind ( ”CmmdcServer” , stub ) ;

40 System . out . p r i n t l n ( ”CmmdcServer ready ” ) ;41 }42 catch ( Exception e ) {43 System . out . p r i n t l n ( ”CmmdcImpl e r r : ” + e . getMessage ( ) ) ;44 }45 }46 }

Textul sursa al programului server CmmdcImpl.java se retine ın catalogul\s\src\server

4. (a) Compilarea programului server;

(b) Crearea obiectului registry ;

(c) Lansarea serverului ın lucru

se obtin cu ant cu

Page 63: DISTR1

4.1. REMOTE METHOD INVOCATION 63

1 <project name=” Server ” d e f a u l t=” I n s t a l l ” ba s ed i r=” . ”>2 <description>3 Server a c t i o n s4 </description>5 < !−− s e t g l o b a l p r op e r t i e s f o r t h i s b u i l d −−>

7 <property name=” package ” value=” s e r v e r ”/>8 <property name=” i n t e r f a c e−j a r ” location=”/ i / pub l i c / c l a s s e s /cmmdc” />9 <property name=” jar− f i l e ” va lue=”cmmdc . j a r ” />

10 <property name=” s e r v i c e−c l a s s ” value=”CmmdcImpl” />11 <property name=” host ” value=” l o c a l h o s t ” />12 <property name=” port ” value=”1099” />

14 <target name=” I n s t a l l ”>15 < !−− Create the time stamp −−>16 <tstamp/>17 < !−− Create the b u i l d d i r e c t o r y s t r u c t u r e used by compile −−>18 <delete d i r=” s r c ”/>19 <mkdir d i r=” s r c ”/>20 <delete d i r=” pub l i c ”/>21 <mkdir d i r=” pub l i c ”/>22 <delete d i r=” pub l i c / c l a s s e s ”/>23 <mkdir d i r=” pub l i c / c l a s s e s ”/>24 </target>

26 <target name=” I n i t ”>27 <mkdir d i r=” s r c /${package}”/>28 <mkdir d i r=” pub l i c / c l a s s e s /${package}”/>29 <copy f i l e=”${ i n t e r f a c e−j a r }/${ ja r− f i l e }” t o d i r=” pub l i c / c l a s s e s ” />30 </target>

32 <target name=”Compile” depends=” I n i t ”33 description=” compile the source ” >34 <javac s r c d i r=” s r c ”35 i n c l u d e s=”${package }/∗∗” d e s t d i r=” pub l i c / c l a s s e s ”36 classpath=” pub l i c / c l a s s e s /${ ja r− f i l e }” />37 <unjar src=” pub l i c / c l a s s e s /${ ja r− f i l e }” dest=” pub l i c / c l a s s e s ” />38 </target>

40 <target name=”Rmi”>41 <exec executab l e=” r m i r e g i s t r y ”>42 <arg value=”1099” />43 </exec>44 </target>

46 <target name=” Server ”>47 <java classname=”${package } . ${ s e r v i c e−c l a s s }”48 classpath=”/ s / pub l i c / c l a s s e s ” f o rk=” true ”>49 <jvmarg50 value=”−Djava . rmi . s e r v e r . codebase= f i l e : / s / pub l i c / c l a s s e s /” />51 <arg l i n e=”${ host } ${ port }” />52 </ java>53 </target>54 </project>

Parametrul -Djava.rmi.server.codebase fixeaza locatia interfetei la distantade pe calculatorul server.

Page 64: DISTR1

64 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANTA

Obiectivele Rmi si Server se lanseaza ın ferestre dos distincte care ramanactive pe durata de viata a aplicatiei server.

5. Realizarea programului client

1 package c l i e n t ;

3 import cmmdc . ∗ ;4 import java . u t i l . Scanner ;5 // Varianta d i r e c t a6 // import java . rmi . r e g i s t r y . ∗ ;7 // Varianta JNDI8 import javax . naming . ∗ ;

10 public class CmmdcClient {11 public stat ic void main ( St r ing args [ ] ) {12 St r ing host=” l o c a l h o s t ” ;13 int port =1099;14 i f ( args . length >0)15 host=args [ 0 ] ;16 i f ( args . length >1)17 port=I n t e g e r . pa r s e In t ( args [ 1 ] ) ;18 Scanner scanner=new Scanner ( System . in ) ;19 System . out . p r i n t l n ( ”Primul numar : ” ) ;20 long m=Long . parseLong ( scanner . next ( ) ) ;21 System . out . p r i n t l n ( ”Al d o i l e a numar : ” ) ;22 long n=Long . parseLong ( scanner . next ( ) ) ;23 long x=0;24 try {25 // Varianta d i r e c t a26 /∗27 Reg i s t ry r e g i s t r y=LocateReg is t ry . g e tReg i s t r y ( host , por t ) ;28 ICmmdc ob j=(ICmmdc) r e g i s t r y . lookup (”CmmdcServer ” ) ;29 ∗/30 // Varianta JNDI31 St r ing sPort=(new I n t e g e r ( port ) ) . t oS t r i ng ( ) ;32 System . se tProper ty ( Context . INITIAL CONTEXT FACTORY,33 ”com . sun . j n d i . rmi . r e g i s t r y . RegistryContextFactory ” ) ;34 System . se tProper ty ( Context .PROVIDER URL, ”rmi : // ”+host+” : ”+sPort ) ;35 Context ctx=new I n i t i a l C o n t e x t ( ) ;36 ICmmdc obj=(ICmmdc) ctx . lookup ( ”CmmdcServer” ) ;

38 x=obj . cmmdc(m, n ) ;39 System . out . p r i n t l n ( ”Cmmdc=”+x ) ;40 }41 catch ( Exception e ) {42 System . out . p r i n t l n ( ”CmmdcClient except ion : ”+e . getMessage ( ) ) ;43 }44 }45 }

Sursa programului client CmmdcClient.java apartine catalogului\c\src\client

6. Compilarea programului client si lansarea acestuia ın executie.

Page 65: DISTR1

4.1. REMOTE METHOD INVOCATION 65

1 <project name=” Cl i en t ” d e f a u l t=” I n s t a l l ” ba s ed i r=” . ”>2 <description> Cl i en t a c t i o n s </description>3 < !−− s e t g l o b a l p r op e r t i e s f o r t h i s b u i l d −−>

5 <property name=” package ” value=” c l i e n t ”/>6 <property name=” i n t e r f a c e−j a r ” location=”/ i / pub l i c / c l a s s e s /cmmdc”/>7 <property name=” jar− f i l e ” va lue=”cmmdc . j a r ” />8 <property name=” host ” value=” l o c a l h o s t ” />9 <property name=” port ” value=”1099” />

10 <property name=” c l i e n t−c l a s s ” value=”CmmdcClient” />

12 <target name=” I n s t a l l ”>13 < !−− Create the b u i l d d i r e c t o r y s t r u c t u r e used by compile −−>14 <delete d i r=” s r c ”/>15 <mkdir d i r=” s r c ”/>16 <delete d i r=” c l a s s e s ”/>17 <mkdir d i r=” c l a s s e s ”/>18 </target>

20 <target name=” I n i t ”>21 < !−− Create the time stamp −−>22 <tstamp/>23 <mkdir d i r=” s r c /${package}”/>24 <mkdir d i r=” c l a s s e s /${package}”/>25 <copy f i l e=”${ i n t e r f a c e−j a r }\${ ja r− f i l e }” t o d i r=” c l a s s e s ” />26 </target>

28 <target name=”Compile” depends=” I n i t ”29 description=” compile the source ”>30 <javac s r c d i r=” s r c ”31 i n c l u d e s=”${package }/∗ . java ” d e s t d i r=” c l a s s e s ”32 classpath=” c l a s s e s \${ j a r− f i l e }” />33 </target>

35 <target name=”Run” depends=”Compile”36 description=” Star t thr c l i e n t ”>37 <java classname=”${package } . ${ c l i e n t−c l a s s }” f o rk=” true ”>38 <classpath>39 <pathelement location=” c l a s s e s /${ j a r− f i l e }” />40 <pathelement path=” c l a s s e s ” />41 </classpath>42 <arg l i n e=”${ host } ${ port }” />43 </ java>44 </target>45 </project>

4.1.2 Tipare de programare

Fabrica de obiecte

Tiparul fabrica de obiecte va permite crearea dinamica a unui server, fapt carenu este posibil pe schema prezentata ın paragraful precedent. Prin aceea schema,se va crea o clasa - fabrica de obiecte - care implementeaza cate o metoda get, cereturneaza o instanta de server. Aceste metode sunt declarate ıntr-o interfata la

Page 66: DISTR1

66 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANTA

distanta. Un client, apeland o asemenea metoda, va instantia serverul dorit si vaobtine stub-ul corespunzator.

Programarea unui server care poate fi lansat dinamic trebuie sa satisfaca restrictiile:

• Clasa serverului extinde clasa UnicastRemoteObject.

• Exista un constructor fara argumente ce arunca exceptia java.rmi.Remote

Exception.

Pentru exemplificarea tehnicii de lucru reluam aplicatia pentru calculul celui maimare divizor comun a doua numere naturale, considerand interfata

1 package cmmdc0 ;2 import java . rmi . ∗ ;3 pub l i c i n t e r f a c e ICmmdc0 extends Remote{4 pub l i c long compute ( long m, long n) throws RemoteException ;5 }

Aceasa interfata va fi implementata de clasa ServerCmmdc. Metoda computeeste o metoda de calcul a celui mai mare divizor comun a doua numere.

Obiecte de tip ServerCmmdc se creaza, de la distanta prin fabrica de obiecteFabObiecte, o clasa ce implementeaza interfata

1 package cmmdc0 ;2 import java . rmi . ∗ ;3 pub l i c i n t e r f a c e IFabObiecte extends Remote{4 pub l i c ICmmdc0 getCmmdc ( ) throws RemoteException ;5 }

Codurile claselor ServerCmmdc si FabObiecte sunt

1 package cmmdc0 ;2 import java . rmi . ∗ ;3 import java . rmi . s e r v e r . ∗ ;4 import java . i o . ∗ ;5 import java . u t i l . ∗ ;

7 pub l i c c l a s s ServerCmmdc extends UnicastRemoteObject implements ICmmdc0{

9 pub l i c ServerCmmdc ( ) throws RemoteException{}

11 pub l i c long compute ( long m, long n) throws RemoteException{12 . . .13 }14 }

respectiv

1 package cmmdc0 ;2 import java . rmi . ∗ ;3 import java . rmi . s e r v e r . ∗ ;4 import java . rmi . r e g i s t r y . ∗ ;

6 pub l i c c l a s s FabObiecte implements IFabObiecte {

Page 67: DISTR1

4.1. REMOTE METHOD INVOCATION 67

8 pub l i c ICmmdc0 getCmmdc ( ) throws RemoteException{9 ServerCmmdc cmmdc=new ServerCmmdc ( ) ;

10 r e turn cmmdc ;11 }

13 pub l i c s t a t i c void main ( S t r ing args [ ] ) {14 St r ing host=” l o c a l h o s t ” ;15 i n t port =1099;16 i f ( a rgs . length >0)17 host=args [ 0 ] ;18 i f ( a rgs . length >1)19 port=I n t e g e r . pa r s e In t ( args [ 1 ] ) ;20 t ry {21 FabObiecte obj=new FabObiecte ( ) ;22 IFabObiecte stub=(IFabObiecte ) UnicastRemoteObject . exportObject ( obj , 0 ) ;23 Reg i s t ry r e g i s t r y=LocateReg i s t ry . g e tReg i s t ry ( host , port ) ;24 r e g i s t r y . bind ( ” ObjectFactory ” , stub ) ;25 System . out . p r i n t l n ( ” ObjectFactory ready ” ) ;26 }27 catch ( Exception e ){28 System . out . p r i n t l n ( ” Factory e r r ”+e . getMessage ( ) ) ;29 }30 }31 }

Aplicatia client se compune din doua clase

1. RemoteClient

Clientul obtine stub-ul serviciului, prin intermediul caruia apeleaza metadagetCmmdc() a fabricii de obiecte, obtinand un obiect remote de tip Server-Cmmdc, ce implementeaza interfata la distanta ICmmdc0.

1 package cmmdc0 ;2 import java . rmi . ∗ ;3 import java . rmi . s e r v e r . ∗ ;4 import java . rmi . r e g i s t r y . ∗ ;

6 pub l i c c l a s s RemoteClient extends UnicastRemoteObject{

8 ICmmdc0 remote=n u l l ;

10 pub l i c RemoteClient ( ) throws RemoteException{}

12 pub l i c RemoteClient ( S t r ing host , i n t port ) throws RemoteException{13 IFabObiecte f a b r i c a=n u l l ;14 t ry {15 Reg i s t ry r e g i s t r y=LocateReg i s t ry . g e tReg i s t ry ( host , port ) ;16 IFabObiecte obj=(IFabObiecte ) r e g i s t r y . lookup ( ” ObjectFactory ” ) ;17 remote=obj . getCmmdc ( ) ;18 }19 catch ( Exception e ){20 System . out . p r i n t l n ( ” C l i en tExcept i on : ”+e . getMessage ( ) ) ;21 }22 }23 }

Page 68: DISTR1

68 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANTA

2. ClientCmmdc0

Apeleaza metoda compute a obiectului remote.

1 package cmmdc0 ;2 import java . u t i l . Scanner ;

4 pub l i c c l a s s ClientCmmdc0{

6 pub l i c s t a t i c void main ( St r ing args [ ] ) {7 St r ing host=” l o c a l h o s t ” ;8 i n t port =1099;9 i f ( a rgs . length >0)

10 host=args [ 0 ] ;11 i f ( a rgs . length >1)12 port=I n t e g e r . pa r s e In t ( args [ 1 ] ) ;13 Scanner scanner=new Scanner ( System . in ) ;14 t ry {15 RemoteClient ct=new RemoteClient ( host , port ) ;16 System . out . p r i n t l n ( ”m=” ) ;17 long m=scanner . nextLong ( ) ;18 System . out . p r i n t l n ( ”n=” ) ;19 long n=scanner . nextLong ( ) ;20 long x=ct . 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 en tExcept i on : ”+e . getMessage ( ) ) ;25 }26 System . e x i t ( 0 ) ;27 }28 }

Apelul invers – Callback

Se numeste apel invers apelarea de catre programul server a unei metode a clien-tului.

In RMI realizarea unui apel invers presupune:

1. definirea unei interfete la distanta ce va fi implementat de programul client;

2. programul client ce implementeaza interfata extinde clasa UnicastRemote Object

si are un constructor ce arunca o exceptie java.rmi.RemoteException.

Extindem aplicatia anterioara cu posibilitatea suplimentara a serverului (Server-Cmmdc) de a alege metoda de calcul a celui mai mare divizor comun dintre variantanerecursiva si cea recursiva a algorimului lui Euclid.

Extindem interfata ICmmdc0 cu metoda

public void setMethod(ICallbackCmmdc obj)throws RemoteException;

1 package cmmdc0 ;2 import java . rmi . ∗ ;

Page 69: DISTR1

4.1. REMOTE METHOD INVOCATION 69

3 pub l i c i n t e r f a c e ICmmdc0 extends Remote{4 pub l i c long compute ( long m, long n) throws RemoteException ;5 pub l i c void setMethod ( ICallbackCmmdc obj ) throws RemoteException ;6 }

unde ICallbackCmmdc este interfata

1 package cmmdc0 ;2 import java . rmi . ∗ ;3 pub l i c i n t e r f a c e ICallbackCmmdc extends Remote{4 pub l i c S t r ing getMethod ( ) throws RemoteException ;5 }

ce va fi implementata ın clasa RemoteClient.Programul ServerCmmdc devine

1 package cmmdc0 ;2 import java . rmi . ∗ ;3 import java . rmi . s e r v e r . ∗ ;4 import java . i o . ∗ ;

6 pub l i c c l a s s ServerCmmdc extends UnicastRemoteObject7 implements ICmmdc0{8 p r i v a t e S t r ing method=n u l l ;

10 pub l i c ServerCmmdc ( ) throws RemoteException{}

12 pub l i c long compute ( long m, long n){13 long x=0;14 i f ( method . equa l s ( ”NERECURSIV” ) )15 x=n e r e c u r s i v (m, n ) ;16 i f ( method . equa l s ( ”RECURSIV” ) )17 x=r e c u r s i v (m, n ) ;18 r e turn x ;19 }

21 pub l i c void setMethod ( ICallbackCmmdc obj ) throws RemoteException{22 method=obj . getMethod ( ) ;23 }

25 p r i v a t e long r e c u r s i v ( long a , long b){26 i f ( a==b)27 r e turn a ;28 e l s e29 i f ( a<b)30 r e turn r e c u r s i v ( a , b−a ) ;31 e l s e32 r e turn r e c u r s i v ( a−b , b ) ;33 }

35 p r i v a t e long n e r e c u r s i v ( long m, long n){36 long r , c ;37 do{38 c=n ;39 r=m%n ;40 m=n ;41 n=r ;42 }43 whi le ( r !=0) ;

Page 70: DISTR1

70 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANTA

44 r e turn c ;45 }46 }

Dupa obtinerea stub-ului, clientul apeleaza metoda setMethod a serverului re-mote, care, prin apel invers, apeleaza metoda getMethod din RemoteClient. Clientulstabileste metoda de calcul si apeleaza metoda compute a lui remote.

Programele client devin

1 package cmmdc0 ;2 import java . rmi . ∗ ;3 import java . rmi . s e r v e r . ∗ ;4 import java . rmi . r e g i s t r y . ∗ ;5 import java . u t i l . Scanner ;

7 pub l i c c l a s s RemoteClient extends UnicastRemoteObject8 implements ICallbackCmmdc{9 ICmmdc0 remote=n u l l ;

11 pub l i c RemoteClient ( ) throws RemoteException{}

13 pub l i c S t r ing getMethod ( ){14 Scanner scanner=new Scanner ( System . in ) ;15 System . out . p r i n t l n ( ” A l e g e t i va r i anta a l g o r i t m u l u i l u i Eucl id ” ) ;16 System . out . p r i n t l n ( ”1 − a l go r i tmu l ne−r e c u r s i v ” ) ;17 System . out . p r i n t l n ( ”2 − a l go r i tmu l r e c u r s i v ” ) ;18 i n t x=scanner . next Int ( ) ;19 St r ing method=n u l l ;20 i f ( x==1)21 method=”NERECURSIV” ;22 e l s e23 method=”RECURSIV” ;24 r e turn method ;25 }

27 pub l i c RemoteClient ( S t r ing host , i n t port ) throws RemoteException{28 IFabObiecte f a b r i c a=n u l l ;29 t ry {30 Reg i s t ry r e g i s t r y=LocateReg i s t ry . g e tReg i s t ry ( host , port ) ;31 IFabObiecte obj=(IFabObiecte ) r e g i s t r y . lookup ( ” ObjectFactory ” ) ;32 remote=obj . getCmmdc ( ) ;33 }34 catch ( Exception e ){35 System . out . p r i n t l n ( ” C l i en tExcept i on : ”+e . getMessage ( ) ) ;36 }37 }38 }

si

1 package cmmdc0 ;2 import java . u t i l . Scanner ;

4 pub l i c c l a s s ClientCmmdc0{5 pub l i c s t a t i c void main ( S t r ing args [ ] ) {6 St r ing host=” l o c a l h o s t ” ;7 i n t port =1099;8 i f ( a rgs . length >0)

Page 71: DISTR1

4.1. REMOTE METHOD INVOCATION 71

9 host=args [ 0 ] ;10 i f ( a rgs . length >1)11 port=I n t e g e r . pa r s e In t ( args [ 1 ] ) ;12 Scanner scanner=new Scanner ( System . in ) ;13 t ry {14 RemoteClient ct=new RemoteClient ( host , port ) ;15 ct . remote . setMethod ( ct ) ;16 System . out . p r i n t l n ( ”m=” ) ;17 long m=scanner . nextLong ( ) ;18 System . out . p r i n t l n ( ”n=” ) ;19 long n=scanner . nextLong ( ) ;20 long x=ct . 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 en tExcept i on : ”+e . getMessage ( ) ) ;25 }26 System . e x i t ( 0 ) ;27 }28 }

4.1.3 Obiect activabil la distanta

O instanta a clasei UnicastRemoteObject reprezinta un obiect la distanta careruleaza ın permanenta, folosind resursele masinii server.

Incepand cu versiunea JDK 1.2, prin ıntroducerea clasei java.rmi.activa-tion.Activatable si a programului rmid (...\jdk...\bin\rmid.exe) se pot crea pro-grame care ınregistreaza informatii despre obiecte la distanta ce vor fi create siexecutate la cerere.

Invocarea de la distanta a unei metode apartinand unui asemenea obiect are caefect activarea obiectului.

Pe fiecare masina virtuala Java exista un grup de activare (activation group),care realizeaza activarea. Activarea este facuta de un activator. Un activator contineo tabela care face legatura dintre clasa obiectului cu URL-ul acestuia si eventual, cudate necesare initializarii obiectului. Atunci cand activatorul constata ca nu existaun obiect referit, face apel la grupul de activare care va produce activarea obiectului.

Din punctul de vedere al clientului utilizarea mecanismului de activare la distantanu implica modificari. Modificarile intervin numai din punctul de vedere al serveruluisi al ınregistrarii sale.

Reluam aplicatia dezvoltata la ınceputul capitolului, privind calculul celui maimare divizor comun a doua numere naturale.

Aplicatia server este compusa din doua clase

1. o clasa ce implementeaza interfata ICmmdc : CmmdcActivabil;

2. clasa Setup, cu metoda main, care face posibila mecanismul de activare siınscrie serviciul ın registry. Aceasta clasa este preluata din tutorialul dedicatactivarii a documentatiei ce ınsoteste distributia Java.

Page 72: DISTR1

72 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANTA

Clasa ce implementeaza interfata la distanta trebuie

1. sa extinda clasa Activatable;

2. sa aiba un constructor ce are doi parametrii

(a) un identificator al grupului de activare, de tip ActivationID, utilizat dedemonul de activare rmid;

(b) un obiect de tip MarshalledObject cu date de initializare a obiectuluiactivabil. In cazul nostru, acest parametru nu va fi folosit.

Codul sursa al clasei CmmdcActivabil este

1 package acmmdc ;2 import java . rmi . ∗ ;3 import java . rmi . a c t i v a t i o n . ∗ ;4 import cmmdc . ∗ ;

6 pub l i c c l a s s CmmdcActivabil extends Act ivatab l e7 implements ICmmdc{

9 pub l i c CmmdcActivabil ( Act ivat ionID id , Marshal ledObject data )10 throws RemoteException{11 super ( id , 0 ) ;12 }

14 pub l i c long cmmdc( long m, long n ) { . . .}15 }

Clasa Setup necesita o serie de date furnizare ca proprietati:

1. drepturile de securitate ale grupului de activare

myactivation.policy=group.policy;

cu continutul

grant codeBase "${myactivation.impl.codebase}" {

// permission to read and write object’s file

permission java.io.FilePermission "${myactivation.file}","read,write";

// permission to listen on an anonymous port

permission java.net.SocketPermission "*:1024-","accept";

};

2. java.class.path=no.classpath

ceea ce previne grupul de activare sa ıncarce o clasa din classpath-ul local;

3. localizarea (URL) clasei ce implementeaza interfata

myactivation.impl.codebase;

Page 73: DISTR1

4.1. REMOTE METHOD INVOCATION 73

4. localizarea unui fisier cu date de initializare a obiectului activabil

myactivation.file;

5. numele sub care ınregistreaza serviciul ın registry

myactivation.name.

Programul Setup realizeaza:

1. Construirea unui descriptor al grupului de activare. Grupul de activare esteun container ce gestioneaza obiectele activabile continute.

2. Inregistrarea descriptorului grupului de activare si obtinerea unui identificatoral grupului de activare.

3. Construirea descriptorului de activare. Trebuie cunoscute

• idendificatorul grupului de activare;

• numele clasei ce implementeaza interfata la distanta;

• localizarea (URL) clasei ce implementeaza interfata la distanta;

• obiectul de tip MarshalledObject, cu datele de initializare a obiectuluiactivabil.

4. Inregistrarea descriptorului de activare, ın urma careia se obtine stub-ul obiec-tului activabil.

5. Inregistrarea stub-ului ımpreuna cu numele serviciului ın registry.

Codul clasei setup este

1 package acmmdc ;

3 import java . rmi . ∗ ;4 import java . rmi . a c t i v a t i o n . ∗ ;5 import java . rmi . r e g i s t r y . ∗ ;6 import java . u t i l . P r o p e r t i e s ;

8 pub l i c c l a s s Setup{

10 p r i v a t e Setup ( ) {}

12 pub l i c s t a t i c void main ( S t r ing [ ] a rgs ) throws Exception {

14 // Argumentul l i n i e i de comanda15 St r ing implClass = ”” ;16 i f ( a rgs . l ength < 1) {17 System . out . p r i n t l n ( ” usage : ” ) ;18 System . out . p r i n t l n ( ” java [ opt ions ] examples . a c t i v a t i o n . Setup <implClass>” ) ;19 System . e x i t ( 1 ) ;20 }21 e l s e {

Page 74: DISTR1

74 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANTA

22 implClass = args [ 0 ] ;23 }

25 // Const ru i rea d e s c r i p t o r u l u i g rupu lu i de a c t i v a r e26 St r ing p o l i c y=System . getProperty ( ” myact ivat ion . p o l i c y ” , ”group . p o l i c y ” ) ;27 St r ing implCodbase=System . getProperty ( ” myact ivat ion . impl . codebase ” ) ;28 St r ing filename=System . getProperty ( ” myact ivat ion . f i l e ” , ”” ) ;29 P r o p e r t i e s props = new P r o p e r t i e s ( ) ;30 props . put ( ” java . s e c u r i t y . p o l i c y ” , p o l i c y ) ;31 props . put ( ” java . c l a s s . path” , ” no c l a s spa th ” ) ;32 props . put ( ” myact ivat ion . impl . codebase ” , implCodebase ) ;33 i f ( filename != n u l l && ! filename . equals ( ”” ) ) {34 props . put ( ” myact ivat ion . f i l e ” , filename ) ;35 }36 ActivationGroupDesc groupDesc = new ActivationGroupDesc ( props , n u l l ) ;

38 // I n r e g i s t r a r e a grupu lu i de a c t i v a r e pentr ob t ine r ea39 // 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 e40 ActivationGroupID groupID=41 ActivationGroup . getSystem ( ) . r eg i s t e rGroup ( groupDesc ) ;42 System . e r r . p r i n t l n ( ” Act ivat ion group d e s c r i p t o r r e g i s t e r e d . ” ) ;

44 // Const ru i rea d e s c r i p t o r u l u i de a c t i v a r e45 Marshal ledObject data = n u l l ;46 i f ( filename != n u l l && ! filename . equals ( ”” ) ) {47 data = new Marshal ledObject ( filename ) ;48 }

50 Act ivat ionDesc desc=51 new Act ivat ionDesc ( groupID , implClass , 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 e54 Remote stub = Act ivatab l e . r e g i s t e r ( desc ) ;55 System . e r r . p r i n t l n ( ” Act ivat ion 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 in r e g i s t r y58 St r ing name = System . getProperty ( ” myact ivat ion . name” ) ;59 LocateReg i s t ry . g e tReg i s t ry ( ) . reb ind (name , stub ) ;60 System . e r r . p r i n t l n ( ”Stub bound in r e g i s t r y . ” ) ;61 }62 }

Sursele celor doua programe CmmdcActivabil.java si respectiv Setup.java suntın catalogul \c\src\acmmdc.

Lansarea serverului ın executie consta din

1. Pornirea demon-ului rmid

start rmid -J-Djava.security.policy=rmid.policy

-J-Dmyactivation.policy=group.policy

unde rmid.policy este

grant {

// allow activation groups to use certain system properties

permission com.sun.rmi.rmid.ExecOptionPermission

Page 75: DISTR1

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=*";};

iar group.policy are codul

grant codeBase "${myactivation.impl.codebase}" {

// permission to read and write object’s file

permission java.io.FilePermission "${myactivation.file}","read,write";

// permission to listen on an anonymous port

permission java.net.SocketPermission "*:1024-","accept";

};

2. Pornirea registry-ului

start rmiregistry

3. Lansarea programului Setup

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

Localizarea (URL) interfetei la distanta se precizeaza prinjava.rmi.server.codebase;

Drept client se utilizeaza programul realizat ın sectiunea 4.1.

4.2 CORBA

Retelele de calculatoare sunt eterogene ın timp ce majoritatea interfetelor deprogramare a aplicatiilor sunt orientate spre platforme omogene.

Pentru a facilita integrarea unor sisteme dezvoltate separat, ıntr-un singur mediudistribuit eterogen, OMG (Object Management Group – consortiu cuprinzand peste800 de firme) a elaborat standardul CORBA (Common Object Request Broker Arhi-tecture): un cadru de dezvoltare a aplicatiilor distribuite ın medii eterogene.

La CORBA au aderat toate marile firme de software - cu exceptia Microsoft,firma care a dezvoltat propriul sau model DCOM (Distributed Component ObjectModel), incompatibil CORBA.

Page 76: DISTR1

76 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANTA

CORBA contine programe client care utilizeaza diferite obiecte distribuite ınsistem. Deoarece ın multe sisteme de operare prelucrarile trebuie sa evolueze ıntr-un proces, orice obiect trebuie sa evolueze ıntr-un proces. In alte cazuri, obiectelepot evolua ın fire de executie sau ın biblioteci dll. CORBA omogenizeaza acesteposibilitati prin precizarea ca obiectele exista ın servere. Fiecare obiect este asociatcu un singur server.

Interconectarea obiectelor. Implementarea si localizarea unui obiect sunt as-cunse clientului. Comunicarea ıntre client si obiect este facilitata de Object Request

Broker (ORB) – care permite obiectelor sa se regaseaca unele pe altele ın retea. Elajuta obiectele sa faca cereri si sa primeasca raspunsuri de la alte obiecte aflateın retea. Acestea se desfasoara transparent pentru client – care nu stie unde estelocalizat obiectul, care este mecanismul utilizat pentru a comunica cu el, cum esteactivat sau memorat acesta.

ORB este un pachet de servicii, independent de aplicatii, dar care permit aplicatiilorsa interactioneze prin retea. ORB face parte din middleware – un intermediar ıntresoftul de retea si cel de aplicatie.

Un ORB se poate executa local pe un singur calculator sau poate fi conectatcu oricare alt ORB din Internet, folosind protocolul IIOP -- Internet Inter ORB

Protocol, definit de CORBA 2.CORBA face o separare ıntre interfata unui obiect si implementarea sa si foloseste

un limbaj neutru pentru definirea interfetelor: IDL -- Interface Definition Language.

IDL permite realizarea descrierii de interfete independent de limbajul de pro-gramare si de sistemul de operare folosit. O interfata IDL defineste legatura dintreclient si server.

4.2.1 Conexiunea RMI - CORBA

Firma Oracle - Sun Microsystems a dezvoltat o solutie prin care programele RMIpot fi adaptate pentru a putea accesa obiecte CORBA. Aceasta este cunoscuta subnumele de solutia RMI-IIOP, concretizata printr-o serie de pachete din distributiajdk. In acest fel nu mai este necesar utilizarea limbajului IDL pentru descriereainterfetelor la distanta.

Instrumente necesare utilizarii solutiei RMI-IIOP:

• compilatorul rmic

Optiunea -iiop genereaza stub-ul si legatura (tie) din partea serverului.

Cu optiunea -d se specifica catalogul ın care aceste fisiere sunt scrise.

• serviciul ORB care asigura regasirea resurselor CORBA. Acest server se lanseazaın executie prin

start orbd -ORBInitialPort [port ]

Programele orbd, rmic sunt ın distributia jdk.

Page 77: DISTR1

4.2. CORBA 77

Transformarea unui program RMI ıntr-un program RMI-IIOP

Exemplificam prin aplicatia care implementeaza un serviciu de calcul a celui maimare divizor comun a doua numere naturale. Etapele realizarii aplicatiei sunt:

1. Elaborarea interfetei este identica cu cea a aplicatiei RMI.

2. Implementarea interfetei

1 package cmmdciiop ;2 import javax . rmi . PortableRemoteObject ;3 import cmmdc . ∗ ;4 import java . rmi . ∗ ;

6 // Se ext inde c l a s a PortableRemoteObject7 // s i nu UnicastRemoteObject

9 pub l i c c l a s s CmmdcImpl extends PortableRemoteObject implements ICmmdc{10 // Const ructoru l c l a s e i11 pub l i c CmmdcImpl ( ) throws RemoteException {}

13 pub l i c long cmmdc( long a , long b ) { . . .}14 }

3. Realizarea programului server.

1 package cmmdciiop ;2 import javax . naming . I n i t i a l C o n t e x t ;3 import javax . naming . Context ;

6 pub l i c c l a s s CmmdcServer {7 pub l i c s t a t i c void main ( S t r ing [ ] a rgs ) {8 St r ing host=” l o c a l h o s t ” ;9 St r ing port=”1050” ;

10 i f ( a rgs . length >0)11 host=args [ 0 ] ;12 i f ( a rgs . length >1)13 port=args [ 1 ] ;14 t ry {15 // 1 : Crearea unei i n s t a n t e CmmdcImpl16 CmmdcImpl cmmdcRef = new CmmdcImpl ( ) ;

18 // 2 : I n r e g i s t r a r e a unei r e f e r i n t e a s e r v i c i u l u i19 // u t i l i z a n d JNDI API20 System . se tProper ty ( ” java . 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 . se tProper ty ( ” java . naming . prov ide r . u r l ” ,23 ” i i o p : //”+host+” : ”+port ) ;24 Context ctx = new I n i t i a l C o n t e x t ( ) ;25 ctx . reb ind ( ”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 ) {

Page 78: DISTR1

78 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANTA

29 System . out . p r i n t l n ( ”CmmdcServer: ” + e . getMessage ( ) ) ;30 }31 }32 }

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

5. Generarea stub-ului cmmdc. ICmmdc Stub.class corespunzator interfetei ICm-mdc si a fisierului Tie cmmdciiop. CmmdcImpl Tie.class corespunzator claseiCmmdcImpl. Acestea se obtin ruland utilitarul rmic - din distrubutia Java –cu optiunea -iiop

rmic -iiop cmmdciiop.CmmdcImpl

6. Pornirea serverului CORBA de regasire a serviciilor

start orbd -ORBInitialPort 1050

7. Lansarea serverului ın executie.

Activitatile legate de server se obtin prin ant cu fisierul build

1 <project name=” Server ” d e f a u l t=” I n s t a l l ” ba s ed i r=” . ”>2 <description>Server a c t i o n s</description>3 < !−− s e t g l o b a l p r op e r t i e s f o r t h i s b u i l d −−>

5 <property name=” package ” value=”cmmdciiop”/>6 <property name=” i n t e r f a c e−package ” value=”cmmdc” />7 <property name=” i n t e r f a c e−j a r ” location=”/ i / pub l i c / c l a s s e s /cmmdc” />8 <property name=” jar− f i l e ” va lue=”cmmdc . j a r ” />9 <property name=” s e r v i c e−c l a s s ” value=”CmmdcServer” />

10 <property name=” implementation−c l a s s ” value=”CmmdcImpl” />11 <property name=” host ” value=” l o c a l h o s t ” />12 <property name=” port ” value=”1050” />

14 <target name=” I n s t a l l ”>15 < !−− Create the time stamp −−>16 <tstamp/>17 < !−− Create the b u i l d d i r e c t o r y s t r u c t u r e used by compile −−>18 <delete d i r=” s r c ”/>19 <mkdir d i r=” s r c ”/>20 <delete d i r=” pub l i c ”/>21 <mkdir d i r=” pub l i c ”/>22 <delete d i r=” pub l i c / c l a s s e s ”/>23 <mkdir d i r=” pub l i c / c l a s s e s ”/>24 </target>

26 <target name=” I n i t ”>27 <mkdir d i r=” s r c /${package}”/>28 <mkdir d i r=” pub l i c / c l a s s e s /${package}”/>29 <copy f i l e=”${ i n t e r f a c e−j a r }/${ ja r− f i l e }” t o d i r=” pub l i c / c l a s s e s ” />30 <unjar src=” pub l i c / c l a s s e s /${ ja r− f i l e }” dest=” pub l i c / c l a s s e s ” />31 <delete d i r=” pub l i c / c l a s s e s /META−INF” />

Page 79: DISTR1

4.2. CORBA 79

32 </target>

34 <target name=”Compile” depends=” I n i t ”35 description=” compile the source ” >36 <javac s r c d i r=” s r c ” d e s t d i r=” pub l i c / c l a s s e s ”37 i n c l u d e s=”${package }\∗∗”38 classpath=” pub l i c \ c l a s s e s \${ ja r− f i l e }” />39 <rmic classname=”${package }\${ implementation−c l a s s }”40 sourcebase=” s r c ”41 i i o p=” yes ”42 base=” pub l i c / c l a s s e s ”43 classpath=” pub l i c / c l a s s e s ” />44 </target>

46 <target name=”Orb”>47 <exec executab l e=”orbd”>48 <arg l i n e=”−ORBInit ia lPort ${ port } −ORBInitialHost ${ host }” />49 </exec>50 </target>

52 <target name=” Server ” description=” Star t thr s e r v e r ” >53 <java classname=”${package } . ${ s e r v i c e−c l a s s }” f o rk=” true ”>54 <classpath>55 <pathelement location=” pub l i c / c l a s s e s /${ ja r− f i l e }” />56 <pathelement path=” pub l i c / c l a s s e s ” />57 </classpath>58 <arg l i n e=”${ host } ${ port }” />59 </ java>60 </target>61 </project>

8. Editarea programului client.

1 package cmmdciiop ;2 import java . rmi . ∗ ;3 import javax . rmi . ∗ ;4 import java . net . MalformedURLException ;5 import javax . naming . ∗ ;6 import java . u t i l . Scanner ;7 import cmmdc . ∗ ;

9 public class CmmdcClient {10 public stat ic void main ( St r ing args [ ] ) {11 St r ing host=” l o c a l h o s t ” ;12 St r ing port=”1050” ;13 i f ( args . length >0)14 host=args [ 0 ] ;15 i f ( args . length >1)16 port=args [ 1 ] ;

18 Scanner scanner=new Scanner ( System . in ) ;19 System . out . p r i n t l n ( ”Primul numar : ” ) ;20 long m=Long . parseLong ( scanner . next ( ) ) ;21 System . out . p r i n t l n ( ”Al d o i l e a numar : ” ) ;22 long n=Long . parseLong ( scanner . next ( ) ) ;23 try {

Page 80: DISTR1

80 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANTA

24 System . se tProper ty ( ” java . 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 . se tProper ty ( ” java . naming . prov ide r . u r l ” ,27 ” i i o p :// ”+host+” : ”+port ) ;28 Context ctx = new I n i t i a l C o n t e x t ( ) ;

30 // STEP 1: Get the Object r e f e r ence from the Name Servc txe31 // using JNDI c a l l .32 Object o b j r e f = ctx . lookup ( ”CmmdcService” ) ;33 System . out . p r i n t l n ( ” C l i en t : Obtained a r e f . to Cmmdc s e r v e r . ” ) ;

35 // STEP 2: Narrow the o b j e c t r e f e r ence to the concre te type and36 // invoke the method .37 ICmmdc obj = (ICmmdc) PortableRemoteObject . narrow ( ob j r e f , ICmmdc . class ) ;38 long x=obj . cmmdc(m, n ) ;39 System . out . p r i n t l n ( ”Cmmdc=”+x ) ;40 }41 catch ( Exception e ) {42 System . out . p r i n t l n ( ” Exception ” + e . getMessage ( ) ) ;43 }44 }45 }

9. Compilarea si lansarea clientului ın executie. Clientul trebuie sa dispuna defisierul stub (cmmdc. ICmmdc Stub.class) si bineınteles de interfata ICmmdc.jar.

Fisierul buildfile pentru executarea clientului:

1 <project name=” Cl i en t ” d e f a u l t=” I n s t a l l ” ba s ed i r=” . ”>2 <description>Cl i en t a c t i o n s</description>3 < !−− s e t g l o b a l p r op e r t i e s f o r t h i s b u i l d −−>

5 <property name=” package ” value=”cmmdciiop”/>6 <property name=” i n t e r f a c e−j a r ” location=”/ i / pub l i c / c l a s s e s /cmmdc” />7 <property name=” jar− f i l e ” va lue=”cmmdc . j a r ” />8 <property name=” server−package ” value=”cmmdciiop” />9 <property name=” i n t e r f a c e−package ” value=”cmmdc” />

10 <property name=” i n t e r f a c e−stub−l o c a t i o n ”11 location=”/ s / pub l i c / c l a s s e s /${ i n t e r f a c e−package}” />12 <property name=”stub−c l a s s ” value=”∗ Stub . c l a s s ” />13 <property name=” host ” value=” l o c a l h o s t ” />14 <property name=” port ” value=”1050” />15 <property name=” c l i e n t−c l a s s ” value=”CmmdcClient” />

17 <target name=” I n s t a l l ”>18 < !−− Create the b u i l d d i r e c t o r y s t r u c t u r e used by compile −−>19 <delete d i r=” s r c ”/>20 <mkdir d i r=” s r c ”/>21 <delete d i r=” c l a s s e s ”/>22 <mkdir d i r=” c l a s s e s ”/>23 </target>

25 <target name=” I n i t ”>26 < !−− Create the time stamp −−>27 <tstamp/>28 <mkdir d i r=” s r c /${package}”/>29 <mkdir d i r=” c l a s s e s /${package}”/>30 <delete d i r=” c l a s s e s /${ s e rver−package}” />

Page 81: DISTR1

4.2. CORBA 81

31 <mkdir d i r=” c l a s s e s /${ s e rver−package}”/>32 <delete d i r=” c l a s s e s /${ i n t e r f a c e−package}” />33 <mkdir d i r=” c l a s s e s /${ i n t e r f a c e−package} ”/>34 <copy f i l e=”${ i n t e r f a c e−j a r }\${ ja r− f i l e }” t o d i r=” c l a s s e s ” />35 <copy t o d i r=” c l a s s e s /${ i n t e r f a c e−package}” >36 <f i l e s e t d i r=”${ i n t e r f a c e−stub−l o c a t i o n }”37 i n c l u d e s=”${ stub−c l a s s }” />38 </copy>39 <unjar src=” c l a s s e s /${ j a r− f i l e }” dest=” c l a s s e s ” />40 <delete d i r=” c l a s s e s /META−INF” />41 </target>

43 <target name=”Compile” depends=” I n i t ”44 description=” compile the source ” >45 <javac s r c d i r=” s r c ” d e s t d i r=” c l a s s e s ”46 i n c l u d e s=”${package }\∗ . java ” classpath=” c l a s s e s ” />47 </target>

49 <target name=”Run” depends=”Compile” description=”Run the c l i e n t ” >50 <java classname=”${package } . ${ c l i e n t−c l a s s }” f o rk=” true ”>51 <classpath>52 <pathelement location=” c l a s s e s /${ ja r− f i l e }” />53 <pathelement path=” c l a s s e s ” />54 </classpath>55 <arg l i n e=”${ host } ${ port }”/>56 </ java>57 </target>58 </project>

4.2.2 Aplicatie Java prin CORBA

Scopul acestei sectiuni este prezentarea dezvoltarii unei aplicatii pe baza uneiinterfete bazat pe IDL.

Pentru dezvoltarea aplicatiilor ın limbajul de programare Java, translatareainterfetei IDL ın Java se realizeaza cu utilitarul idlj din distributia jdk.

Corespondenta ıntre entitatile IDL si Java este data ın Tabelul 4.1

Legarea cererii unui client de codul serviciului care satisface cererea utilizeazacomponenta CORBA Portable Object Adapter (POA).

Model cu server temporal

Exemplificam dezvoltarea unei aplicatii distribuite CORBA ın cazul ın care ser-viciul pus la dispozitie de server este calculul celui mai mare divizor comun a douanumere naturale.

Dezvoltarea unei aplicatii distribuite CORBA cu mediul nativ Java presupuneparcurgerea urmatoarelor pasi:

1. Realizarea interfetei IDL care ınseamna

(a) Editarea programului de interfata:

Page 82: DISTR1

82 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANTA

Tip IDL Tip Java

module packageboolean booleanchar, wchar charoctet bytestring, wstring java.lang.Stringshort, unsigned short shortlong, unsigned long intlong long, unsigned long long longfloat floatdouble doublefixed java.math.BigDecimalenum, struct, union classsequence, array arrayinterface (non-abstract) signature interface,

operations interface,helper class, holder class

Any org.omg.CORBA.Any

Table 4.1: Entitati IDL si Java

1 module CmmdcApp{2 interface Cmmdc{3 long long cmmdc( in long long a , in long long b ) ;4 } ;5 } ;

Salvam acest text ıntr-un fisier denumit Cmmdc.idl.

Cmmdc va fi numele serviciului cautat de un client si implementat deserver. Serviciul contine o singura metoda cmmdc.

(b) Translatarea ın Java

idlj -fall Cmmdc.idl

Programul idlj creaza un subcatalog CmmdcApp cu un pachet Java CmmdcApp

continand fisierele:

• Cmmdc.java

• CmmdcPOA.java ;

• CmmdcOperations.java;

Page 83: DISTR1

4.2. CORBA 83

• CmmdcStub.java;

• CmmdcHelper.java;

• CmmdcHolder.java.

2. Realizarea programelor server. Punem ın evidenta programul servant Cmmd-cImpl.java ce implementeaza interfata Cmmdc.

1 import CmmdcApp . ∗ ;2 import org . omg .CORBA. ∗ ;

4 pub l i c c l a s s CmmdcImpl extends CmmdcPOA {5 p r i v a t e ORB orb ;

7 pub l i c CmmdcImpl(ORB orb ){8 t h i s . orb = orb ;9 }

11 pub l i c long cmmdc( long a , long b ) { . . .}12 }

si programul CmmdcServer.java, care ınscrie ın registrul ORB referintele ser-vantului. Activitatile ce trebuie ıntreprinse sunt declarate prin comentarii ıntextul sursa al programului

1 import CmmdcApp . ∗ ;2 import org . omg . CosNaming . ∗ ;3 import org . omg . CosNaming . NamingContextPackage . ∗ ;4 import org . omg .CORBA. ∗ ;5 import org . omg . Por tab l eServer . ∗ ;

7 pub l i c c l a s s CmmdcServer {8 pub l i c s t a t i c void main ( S t r ing args [ ] ) {9 t ry {

10 // c r ea r ea s i i n i t i a l i z a r e a ORB11 ORB orb = ORB. i n i t ( args , n u l l ) ;

13 // obt ine r ea unei r e f e r i n t e rootpoa s i a c t i v a r e a managerului POAManager14 POA rootpoa = POAHelper . narrow ( orb . r e s o l v e i n i t i a l r e f e r e n c e s ( ”RootPOA” ) ) ;15 rootpoa . the POAManager ( ) . a c t i v a t e ( ) ;

17 // c r ea r ea unui se rvant18 CmmdcImpl cmmdcImpl = new CmmdcImpl( orb ) ;

20 // obt ine r ea unei r e f e r i n t e a s e r v a n t u l u i21 org . omg .CORBA. Object r e f = rootpoa . 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 // Obtinerea s e r v i c i u l u i NameService25 org . omg .CORBA. Object objRef =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 ( objRef ) ;

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 in s e r v i c i u l NameService30 St r ing name = ”CmmdcService” ;31 NameComponent path [ ] = ncRef . to name ( name ) ;32 ncRef . reb ind ( path , h r e f ) ;

Page 84: DISTR1

84 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANTA

34 System . out . p r i n t l n ( ”CmmdcServer ready and wai t ing . . . ” ) ;

36 // in a s t ep ta r ea c l i e n t i l o r37 orb . run ( ) ;38 }39 catch ( Exception e ) {40 System . e r r . p r i n t l n ( ”ERROR: ” + e ) ;41 e . pr intStackTrace ( System . out ) ;42 }43 System . out . p r i n t l n ( ”CmmdcServer Ex i t ing . . . ” ) ;44 }45 }

3. Realizarea programului client CmmdcClient.java:

1 import CmmdcApp . ∗ ;2 import org . omg . CosNaming . ∗ ;3 import org . omg . CosNaming . NamingContextPackage . ∗ ;4 import org . omg .CORBA. ∗ ;5 import java . u t i l . Scanner ;

7 pub l i c c l a s s CmmdcClient{8 s t a t i c Cmmdc cmmdcImpl ;

10 pub l i c s t a t i c void main ( St r ing args [ ] ) {11 t ry {12 // c r ea r ea s i i n i t i a l i z a r e a unui r eprezentant ORB13 ORB orb = ORB. i n i t ( args , n u l l ) ;

15 // obt ine r ea unei r e f e r i n t e pentru s e r v i c i u l denumir i l o r16 // s e r v i c i i l o r i n r e g i s t r a t e17 org . omg .CORBA. Object objRef =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 ( objRef ) ;

21 // obt ine r ea unei r e f e r i n t e l a s e r v i c i u l d o r i t22 St r ing name = ”CmmdcService” ;23 cmmdcImpl = CmmdcHelper . narrow ( ncRef . r e s o l v e s t r (name ) ) ;

25 System . out . p r i n t l n ( ”Obtained a handle on s e r v e r o b j e c t : ” + cmmdcImpl ) ;26 Scanner scanner=new Scanner ( System . in ) ;27 long m, n ;28 System . out . p r i n t l n ( ”m=” ) ;29 m=scanner . nextLong ( ) ;30 System . out . p r i n t l n ( ”n=” ) ;31 n=scanner . nextLong ( ) ;32 System . out . p r i n t l n ( ”Cmmdc=”+cmmdcImpl . cmmdc(m, n ) ) ;33 }34 catch ( Exception e ) {35 System . out . p r i n t l n ( ”ERROR : ” + e ) ;36 e . pr intStackTrace ( System . out ) ;37 }38 }39 }

Programele se compileaza

Page 85: DISTR1

4.2. CORBA 85

javac CmmdcApp\*.java

4. Pornirea serviciului de intregistrare a numelor cu programul orbd.exe dindistributia jdk.

start orbd -ORBInitialHost localhost -ORBInitialPort 1050

5. Pornirea programului server prin

start java CmmdcServer -ORBInitialHost localhost -ORBInitialPort 1050

6. Lansarea programului client prin

java CmmdcClient -ORBInitialHost localhost -ORBInitialPort 1050

Model cu server persistent

Se considera aceasi interfata Cmmdc.idl.Partea de server este alcatuita din clasa servant CmmdcImpl.java care imple-

menteaza interfata Cmmdc -prezentat ın sectiunea anterioara si clasa PersistentServercare asigura

• legatura cu serviciile ORB;

• accesul la clasa servantului.

1 import java . u t i l . P r o p e r t i e s ;2 import org . omg .CORBA. ∗ ;3 import org . omg . CosNaming . ∗ ;4 import org . omg . Por tab l eServer . ∗ ;

6 pub l i c c l a s s P e r s i s t e n t S e r v e r {7 pub l i c s t a t i c void main ( St r ing args [ ] ) {8 P r o p e r t i e s p r o p e r t i e s = System . g e t P r o p e r t i e s ( ) ;9 p r o p e r t i e s . put ( ” org . omg .CORBA. ORBInitialHost ” , ” l o c a l h o s t ” ) ;

10 p r o p e r t i e s . put ( ” org . omg .CORBA. ORBInit ia lPort ” , ”1050” ) ;11 t ry {12 // Pas 1 : I n s t a n t i e r e ORB13 ORB orb = ORB. i n i t ( args , p r o p e r t i e s ) ;

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 i16 CmmdcImpl se rvant = new CmmdcImpl( orb ) ;

18 // Pas3 3 : Crearea unui o b i e c t POA cu s e c u r i t a t e a P e r s i s t e n t Po l i cy19 // ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗20 // Pas 3−1 : Obtinerea r a d a c i n i i rootPOA

Page 86: DISTR1

86 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANTA

21 POA rootPOA = POAHelper . narrow ( orb . r e s o l v e i n i t i a l r e f e r e n c e s ( ”RootPOA” ) ) ;22 // Pas 3−2 : Create s e c u r i t a t i i P e r s i s t e n t Po l i cy23 Pol i cy [ ] p e r s i s t e n t P o l i c y = new Po l i cy [ 1 ] ;24 p e r s i s t e n t P o l i c y [ 0 ] = rootPOA . c r e a t e l i f e s p a n p o l i c y (25 Li f e spanPo l i cyVa lue .PERSISTENT) ;26 // Pas 3−3 : Crearea o b i e c t u l u i POA cu s e c u r i t a t e a the P e r s i s t e n t Po l i cy27 POA persistentPOA = rootPOA . create POA ( ”childPOA” , nu l l , p e r s i s t e n t P o l i c y ) ;28 // Pas 3−4 : Act ivarea managerului PersistentPOA POAManager ,29 persistentPOA . the POAManager ( ) . a c t i v a t e ( ) ;30 // ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗

32 // Pas 4 : Asoc i e rea s e r v a n t u l u i cu PersistentPOA33 persistentPOA . a c t i v a t e o b j e c t ( se rvant ) ;

35 // Pas 5 : Fixarea c o n t e x t u l u i RootNaming s i l e g a r e a de numele s e r v a n t u l u i36 // Numele s e r v i c i u l u i ORBD : ’ NameService ’37 // Numele s e r v a n t u l u i ’ PersistentCmmdcServer ’

39 org . omg .CORBA. Object obj = 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” ) ;40 NamingContextExt rootContext = NamingContextExtHelper . narrow ( obj ) ;41 NameComponent [ ] nc = rootContext . to name ( ” PersistentCmmdcServer ” ) ;42 rootContext . reb ind ( nc , persistentPOA . s e r v a n t t o r e f e r e n c e ( se rvant ) ) ;

44 // Pas 6 : Gata pentru r e c e p t i a c e r e r i l o r c l i e n t i l o r45 orb . run ( ) ;46 }47 catch ( Exception e ) {48 System . e r r . p r i n t l n ( ” Exception in P e r s i s t e n t Server Startup ” + e ) ;49 }50 }51 }

Programul client

1 import java . u t i l . P r o p e r t i e s ;2 import org . omg .CORBA. ∗ ;3 import org . omg . CosNaming . ∗ ;4 import org . omg . Por tab l eServer .POA;

6 import CmmdcApp. CmmdcHelper ;7 import CmmdcApp.Cmmdc;8 import java . u t i l . Scanner ;

10 pub l i c c l a s s P e r s i s t e n t C l i e n t {11 pub l i c s t a t i c void main ( S t r ing args [ ] ) {12 St r ing host=” l o c a l h o s t ” ;13 St r ing port=”1050” ;14 i f ( a rgs . length >0)15 host=args [ 0 ] ;16 i f ( a rgs . length >1)17 port=args [ 1 ] ;18 t ry {19 // Pas 1 : I n i t i a l i z a r e ORB20 ORB orb = ORB. i n i t ( args , n u l l ) ;

22 // Pas 2 : Rezolvarea p e r s i s t e n t e i23 // S e r v i c i u l NameService ru l ea za pe host cu por tu l port24 // Numele s e r v i c i u l u i c e rut l u i NameService e s t e25 // ” PersistentCmmdcServer ”26 org . omg .CORBA. Object obj = orb . s t r i n g t o o b j e c t (

Page 87: DISTR1

4.2. CORBA 87

27 ” corbaname: : ”+host+” : ”+port+”#PersistentCmmdcServer ” ) ;28 Cmmdc cmmdc=CmmdcHelper . narrow ( obj ) ;

30 // Pas 3 : U t i l i z a r e a s e r v i c i u l u i31 Scanner scanner=new Scanner ( System . in ) ;32 System . out . p r i n t l n ( ” Ca l l i ng P e r s i s t e n t Server . . ” ) ;33 i n t m, n , r ;34 System . out . p r i n t l n ( ”m=” ) ;35 m=scanner . next Int ( ) ;36 System . out . p r i n t l n ( ”n=” ) ;37 n=scanner . next Int ( ) ;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 ( ” Exception in P e r s i s t e n t C l i e n t . java . . . ” + e ) ;42 e . pr intStackTrace ( ) ;43 }44 }45 }

Serverul trebuie sa fie pe acelasi calculator pe care ruleaza orbd. Executareaaplicatiei presupune:

1. Pornirea serviciului de intregistrare a numelor cu programul orbd.exe dindistributia jdk.

start orbd -ORBInitialPort 1050 -serverPollingTime 200

2. Activarea serverului:

(a) Se lanseaza utilitarul servertoolservertool -ORBInitialPort 1050

(b) Se ınregistreaza serverul ımpreuna cu numele serviciului pe care ıl ındeplineste:

servertool > register -server PersistentServer

-applicationName PersistentCmmdcServer

-classpath cale_catre_fisierele_server\

Indeplinirea actiunii de ınregistrare a serverului este indicat printr-un mesajde forma server registered (serverid=257).

Serviciul se sterge prin comandaservertool > unregister -serverid 257

Programul de ınregistrare servertool se ınchide prinservertool > quit

Page 88: DISTR1

88 CAPITOLUL 4. INVOCAREA PROCEDURILOR LA DISTANTA

3. Executarea clientului

java PersistentClient [hostORB [portORB]]

Page 89: DISTR1

Capitolul 5

Mesaje ın Java

Comunicatia prin apelul la distanta - inclusiv RMI - este sincron: programulapelant se blocheaza si asteapta ca metoda apelata sa se termine si sa furnizezerezultatul cerut. Cu alte cuvinte apelul de procedura la distanta cere atat clientuluicat si serverului sa fie simultan disponibile.

Comunicatiile asincrone ıntre programe permit realizarea unor sisteme de pro-grame cu un grad mult mai scazut de cuplare. Asemenea aplicatii se pot realizaprin comunicatii de mesaje, mesaje care sunt retinute de un intermediar (serviciude mesagerie, server, broker, messaging middleware).

In prezent protocolul pentru realizarea aplicatiilor bazate pe comunicatii demesaje este Advanced Message Queue Protocol - AMQP. AMQP este un proto-col dezvoltat de mai multe firme bazat pe standardele World Wide Web Consortium(W3C) si Internet Engineering Task Force (IETF) pentru comunicare cu mesaje prinintermediul unui serviciu de mesagerie si care se doreste independent de limbajul deprogramare.

Modelul AMQP ınglobeaza standardul Java Message Servuce - JMS, dezvoltatde Oracle - Sun Microsystems.

Comunicatia se realizeaza prin socluri TCP.

5.1 Java Message Service (JMS)

JMS defineste un cadru de programare Java (API) pentru realizarea aplicatiilorbazate pe comunicatii asincrone. Exista mai multe implementari JMS, dintre caresemnalam:

• Open Message Queue a firmei Oracle. Numele anterior al produsului a fostSun Java System Message Queue

• ActiveMQ realizata de fundatia apache.

• qpid realizata de fundatia apache.

89

Page 90: DISTR1

90 CAPITOLUL 5. MESAJE IN JAVA

O aplicatie JMS este alcatuita din

• un furnizor JMS (provider JMS) : un sistem de mesagerie ce implementeazaspecificatiile JMS;

• client JMS : aplicatie Java care trimite si receptioneaza mesaje;

• mesaje : obiecte utilizate ın schimbul de informatii de clienti JMS;

• obiecte administrator : obiecte (resurse) create de administrator pentru a fiutilizate de clientii JMS, precum fabrica de conexiuni, obiectele destinatieımpreuna cu resursele lor.

Modele de comunicatie:

• Comunicatii punctuale : Un mesaj este generat de un producator (expeditor)si la care va avea acces un singur consumator (destinatar). Mesajul este depusıntr-o coada, de unde este preluat de catre consumatorul care s-a legat decoada. Daca de coada nu se leaga nici un consumator, atunci mesajul estepastrat ın coada.

• Comunicatii axate pe subiect (topic) : Mesajele sunt depuse (publicate) ındestinatii specifice subiectului. Consumatorii ce au subscris la acel subiectau acces la mesajele respective. Mai multi producatori pot genera mesajespecifice unui subiect, mesaje care pot fi accesate de consumatorii care ausubscris subiectului.

Structura unui mesaj Un mesaj este alcatuit din

• Antet (header) : contine informatii pentru identificarea destinatiei cat si pentruidentificarea mesajului.

• Proprietati : au caracter optional si sunt sub forma (nume, valoare). Pro-prietatile ajuta consumatorii sa selecteze mesajele.

• Corpul mesajului : optional. Potrivit specificatiilor JMS exista 6 tipuri demesaje.

– Message : mesaj fara corp;

– StreamMessage : corpul mesajului contine un flux Java de date de tippredefinit;

– ByteMessage :

– MapMessage : corpul mesajului contine o familie de perechi (nume, val-oare);

– TextMessage : corpul mesajului contine un string;

– ObjectMessage : corpul mesajului contine un obiect serializat.

Page 91: DISTR1

5.2. OPEN MESSAGE QUEUE 91

5.2 Open Message Queue

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

• Se dezarhiveaza fisierul openmq* *-installer-WINNT.zip si se lanseaza ın executieprogramul de instalare.

• Se dezarhiveaza fisierul openmq* *-binary-WINNT.zip si se fixeaza atributelefisierului mq\etc\imqenv.conf.

Lansarea serviciului JMS. Orice aplicatie JMS necesita functionarea servici-ului JMS. Serviciul JMS se instaleaza prin

imqbrokerd -tty

Optiunea -tty are ca efect afisarea mesajelor pe ecran. Functionarea corecta esteindicata prin mesajul

imqbroker@hostname:7676 ready

Daca se doreste schimbarea portului atunci se foloseste optiunea -port port.

Pe un calculator pot coexista mai multe servicii JMS doar daca folosesc porturidistincte si au nume diferite. In acest caz, lansarea unui nou serviciu se face prin

imqbrokerd -tty -port port -name name

Cu utilitarul imqsvcadmin putem

• dezinstala : imqsvcadmin remove

• verifica : imqsvcadmin query

• instala : imqsvcadmin install

serviciul JMS ca serviciu Windows. Dezinstalarea si instalarea are efect odata curepornirea calculatorului.

Compilarea si executarea unui program necesita completarea variabilei sistemclasspath cu fisierele

• JMS HOME\lib\jms.jar

• JMS HOME\lib\imq.jar

5.3 Apache ActiveMQ

Instalarea se face dezarhivand fisierul descarcat ıntr-un catalog ACTIVEMQ HOME.

Acest fisier este specific sistemului de operare utilizat, Windows sau Linux.

Lansarea serverului JMS se obtine prin

Page 92: DISTR1

92 CAPITOLUL 5. MESAJE IN JAVA

set JAVA_HOME=. . .

set ACTIVEMQ_HOME=. . .

%ACTIVEMQ_HOME%\bin\activemq

In cazul unui calculator izolat este nevoie de instalarea driver-ului Microsoft loopbackAdaptor care sinuleaza existenta functonarii unei placi de retea active.

Distributia apache-activemq-5.*.* contine, ca exemplu, clasa EmbeddedBroker.javacare lanseaza serverul JMS ın lucru.

Compilarea unui program necesita prezenta ın variabila de sistem classpath areferintei catre fisierul ACTIVEMQ HOME\activemq-all-*.*.*.jar. Pentru executie,variabila de sistem classpath nevoie sa contina referintele catre fisierele jar dincatalogul ACTIVEMQ HOME\lib.

5.4 Elemente de programare - JMS

5.4.1 Trimiterea unui mesaj

Trimiterea unui mesaj necesita:

1. Generarea unei fabrici de conexiuni. Fabrica de conexiuni este un obiect ad-ministrator. Aceasta operatie este specifica distributiei JMS.

• In cazul de fata folosim obiectele create prin MessageQueue.

Se poate obtine prin

ConnectionFactory cf=

new com.sun.messaging.ConnectionFactory();

Clasa com.sun.messaging.ConnectionFactory contine metodasetProperty( String name, String value) prin intermediul careia seprecizeaza calculatorul si portul furnizorului de servicii JMS, fixand atributele"imqBrokerHostName" si respectiv "imqBrokerHostPort".

• Utilizand apache-activemq, fabrica de conexiuni se obtine prin

org.apache.activemq.ActiveMQConnectionFactory cf=

new org.apache.activemq.ActiveMQConnectionFactory

("tcp://host:61616");

2. Generarea conexiunii.

Se realizeaza prin

Connection conn=cf.createConnection();

Pentru realizarea acestui obiectiv se utilizeaza metoda createConnection,

dupa caz, dintr-una din clasele

Page 93: DISTR1

5.4. ELEMENTE DE PROGRAMARE - JMS 93

class ConnectionFactory{

Connection createConnection() throws JMSException;

Connection createConnection(String userName,String password)

throws JMSException;

}

class QueueConnectionFactory{

QueueConnection createQueueConnection() throws JMSException;

QueueConnection createQueueConnection(String userName,

String password) throws JMSException;

}

class TopicConnectionFactory{

TopicConnection createTopicConnection() throws JMSException;

TopicConnection createTopicConnection(String userName,

String password) throws JMSException;

}

unde Connection, QueueConnection, TopicConnection sunt interfete dinjavax.jms.

Amintim urmatoarele metode ale unei interfete Connection

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;

}

Un obiect ce implementeaza interfata Connection asigura legatura clientuluicu furnizorul JMS. Acest obiect este creat de fabrica de conexiuni.

Page 94: DISTR1

94 CAPITOLUL 5. MESAJE IN JAVA

Un client JMS trebuie sa ınchida conexiunile create.

Metoda start() asigura pornirea sau repornirea conexiunii ın vederea receptionariimesajelor sosite.

3. Crearea unei sesiuni de lucru se face cu o metoda createSession().

Session session=conn.createSession(false,

Session.AUTO_ACKNOWLEDGE);

Primul argument asigura (true) sau nu (false) caracterul indivizibil al unitatiide lucru, adica al unei sesiuni.

Al doilea argument indica modul de confirmare al receptarii mesajului.

Un obiect de tip Session defineste un context format dintr-un singur fir deexecutie ın care are loc producerea si consumul de mesaje.

Sunt definite

interface Session{

| MessageProducer createProducer(Destination destination);

| MessageConsumer createConsumer(Destination destination);

| Message createMessage();

| TextMessage createTextMessage();

| TextMessage createTextMessage(String s);

| StreamMessage createStreamMessage();

| MapMessage createMapMessage();

| ObjectMessage createObjectMessage();

| ObjectMessage createObjectMessage(Serializable object);

| BytesMessage createBytesMessage();

| }

|->interface QueueSession{

| QueueSender createQueueSender(Queue queue);

| QueueReceiver createQueueReceiver(Queue queue);

| }

|->interface TopicSession{

TopicPublisher createPublisher(Topic topic);

TopicSubscriber createSubscriber(Topic topic);

TopicSubscriber createDurableSubscriber(Topic topic,

String name);

}

4. Generarea obiectului destinatie.

In cazul comunicatiilor punctuale obiectul destinatie este de tip Queue, iarcrearea se face prin

Page 95: DISTR1

5.4. ELEMENTE DE PROGRAMARE - JMS 95

Destination numeDestinatie=sesssion.createQueue(String numeCoada)

iar pentru comunicatii axate pe subiect obiectul destinatie, de tip Topic seinstantiaza prin

Destination numeDestinatie=sesssion.createTopic(String numeSubiect)

Sunt definite arborescentele:

interface Destination

|

|->interface Queue

|

|->interface Topic

class Destination implements Destination

|

|->class Queue implements Destination, Queue, Serializable

|

|->class Topic implements Destination, Topic, Serializable

Utilizand Oracle-Sun Java System Message Queue obiecte de tip Queue sauTopic se pot crea si prin

Queue q=new com.sun.messaging.Queue(String numeCoada);

Topic t=new com.sun.messaging.Topic(String numeSubiect);

5. Generarea producatorului de mesaje. Se realizeaza prin

MessageProducer producer=session.createProducer(obiectDestinatie);

Sunt definite interfetele

interface MessageProducer{

void send(Message mesaj);

}

interface QueueSender{

void send(Message mesaj);

}

interface TopicPublisher{

void publish(Message mesaj);

}

Page 96: DISTR1

96 CAPITOLUL 5. MESAJE IN JAVA

6. Generarea mesajelor. Un mesaj de tip TextMessage se poate crea prin

TextMessage m=session.createTextMessage();

m.setText(string);

7. Expedierea mesajelor se face cu metoda send(...) a producatorului demesaje.

Exemplul 5.4.1 Clasa urmatoare genereaza ıntr-un fir de executie, un numar demesaje de tip TextMessage ıntr-o comunicatie punctuala. Sfarsitul expedierii mesajelorse indica prin generarea unui mesaj de tip Message. Numarul mesajelor este indicatde un parametru al constructorului.

1 import javax . jms . ∗ ;

3 public class MsgSenderT extends Thread{4 int n ;5 St r ing queueName ;

7 MsgSenderT ( St r ing queueName , int n){8 this . queueName=queueName ;9 this . n=n ;

10 }

12 public void run ( ){13 try{14 // Varianta Oracle−Sun Message Queue15 com . sun . messaging . QueueConnectionFactory c f=16 new com . sun . messaging . QueueConnectionFactory ( ) ;

18 // se tProper ty e s t e metoda a c l a s e i19 // com. sun . messaging . QueueConnnectionFactory20 // ce implementeaza i n t e r f a t a QueueConnectionFactory21 // dar nu a i n t e r f e t e i QueueConnectionFactory .22 // c f . se tProper ty (” imqBrokerHostName” ,” hos t ” ) ;23 // c f . se tProper ty (” imqBrokerHostPort ” ,”7676”);

25 // Varianta Apache−MessageQueue26 // org . apache . act ivemq . ActiveMQConnectionFactory c f=27 //new org . apache . act ivemq .28 // ActiveMQConnectionFactory (” tcp :// l o c a l h o s t :61616”) ;29 Connection conn=c f . c reateConnect ion ( ) ;30 Se s s i on s e s s i o n=conn . c r e a t e S e s s i o n ( false , S e s s i on .AUTOACKNOWLEDGE) ;

32 Dest inat i on q=s e s s i o n . createQueue ( queueName ) ;

34 MessageProducer producer=s e s s i o n . c reateProducer ( q ) ;

36 TextMessage m=s e s s i o n . createTextMessage ( ) ;37 for ( int i =0; i<n ; i ++){38 m. setText ( ” He l lo ”+i ) ;39 producer . send (m) ;40 }41 // indicam s f a r s i t u l t r i m i t e r i i mesa je lor

Page 97: DISTR1

5.4. ELEMENTE DE PROGRAMARE - JMS 97

42 producer . send ( s e s s i o n . createMessage ( ) ) ;43 s e s s i o n . c l o s e ( ) ;44 conn . c l o s e ( ) ;45 }46 catch ( Exception e ){47 System . out . p r i n t l n ( ”JMSException : ”+e . getMessage ( ) ) ;48 }49 System . out . p r i n t l n ( ” Sender f i n i s h e d ” ) ;50 }51 }

5.4.2 Receptia sincrona a unui mesaj

Primele patru actiuni sunt identice cu cele de la trimiterea unui mesaj, adica

1. Generarea unei fabrici de conexiuni.

2. Generarea conexiunii.

3. Crearea unei sesiuni de lucru.

4. Generarea obiectului destinatie.

5. Generarea consumatorului de mesaje. Se realizeaza prin

MessageConsumer consumer=session.createConsumer(q);

q desemnand obiectul destinatie.

Sunt definite interfetele

interface MessageConsumer{

| Message receive();

| Message receive(long timeout);

| Message receiveNoWait();

| }

|-> interface QueueReceiver

|

|-> interface TopicSubscriber

6. Receptia mesajelor se face cu una din metodele consumatorului de mesaje:

• Message receive()

• Message receive(long timeout)

• Message receiveNoWait()

Page 98: DISTR1

98 CAPITOLUL 5. MESAJE IN JAVA

Exemplul 5.4.2 Receptia de tip sincron a mesajelor ıntr-un fir de executie esteefectuat de clasa urmatoare:

1 import javax . jms . ∗ ;

3 public class SyncMsgReceiverT extends Thread{4 St r ing queueName ;

6 SyncMsgReceiverT ( St r ing queueName){7 this . queueName=queueName ;8 }

10 public void run ( ){11 try{12 // Varianta Oracle−Sun Message Queue13 com . sun . messaging . QueueConnectionFactory c f=14 new com . sun . messaging . QueueConnectionFactory ( ) ;15 // se tProper ty e s t e metoda a c l a s e i QueueConnnectionFactory16 // ce implementeaza i n t e r f a t a QueueConnectionFactory17 // dar nu e s t e a i n t e r f e t e i .18 // c f . se tProper ty (” imqBrokerHostName” ,” hos t ” ) ;19 // c f . se tProper ty (” imqBrokerHostPort ” ,”7676”);

21 // Varianta Apache−MessageQueue22 //org . apache . act ivemq . ActiveMQConnectionFactory c f=23 //new org . apache . act ivemq .24 // ActiveMQConnectionFactory (” tcp :// l o c a l h o s t :61616”) ;25 Connection conn=c f . c reateConnect ion ( ) ;26 Se s s i on s e s s i o n=conn . c r e a t e S e s s i o n ( false , S e s s i on .AUTOACKNOWLEDGE) ;27 Dest inat i on q=s e s s i o n . createQueue ( queueName ) ;28 MessageConsumer consumer=s e s s i o n . createConsumer ( q ) ;29 conn . s t a r t ( ) ;30 Message msg=null ;31 while ( ( msg=consumer . r e c e i v e ( ) ) != null ){32 i f (msg instanceof TextMessage ){33 TextMessage m=(TextMessage )msg ;34 System . out . p r i n t l n (m. getText ( ) ) ;35 }36 else37 break ;38 }39 s e s s i o n . c l o s e ( ) ;40 conn . c l o s e ( ) ;41 }42 catch ( Exception e ){43 System . out . p r i n t l n ( ”JMSException : ”+e . getMessage ( ) ) ;44 }45 System . out . p r i n t l n ( ”Consumer f i n i s h e d ” ) ;46 }47 }

Exemplul 5.4.3 Trimiterea si receptia mesajelor se face prin aplicatia

1 class MsgHelloT{2 public stat ic void main ( St r ing [ ] a rgs ){3 int n=3;

Page 99: DISTR1

5.4. ELEMENTE DE PROGRAMARE - JMS 99

4 St r ing queueName=”MyQueue” ;5 i f ( args . length >0)6 queueName=args [ 0 ] ;7 i f ( args . length >1)8 n=I n t e g e r . pa r s e In t ( args [ 1 ] ) ;9 MsgSenderT sender=new MsgSenderT (queueName , n ) ;

10 SyncMsgReceiverT r e c e i v e r =new SyncMsgReceiverT ( queueName ) ;11 r e c e i v e r . s t a r t ( ) ;12 sender . s t a r t ( ) ;13 }14 }

5.4.3 Receptia asincrona a unui mesaj

Receptia asincrona a mesajelor presupune implementarea interfeteiMessageListener ce contine o singura metoda

public void onMessage(Message mesaj);

care fixeaza prelucrarea mesajului.Metoda MessageConsumer.setMessageListener(MessageListener obj) fixeaza

obiectul ce implementeaza interfata Messagelistener.

Astfel, caracterul asincron consta din faptul ca mesajele sunt preluate de as-cultator - adica obiectul ce implementeaza interfata MessageListener si nu declientul JMS.

Exemplul 5.4.4 In ideea exemplelor anterioare, un consumator de tip asincron almesajelor este dat ın clasa urmatoare:

1 import javax . jms . ∗ ;2 public class AsyncMsgReceiverT extends Thread{3 St r ing queueName ;

5 AsyncMsgReceiverT ( St r ing queueName){6 this . queueName=queueName ;7 }

9 public void run ( ){10 try{11 // Varianta Oracle−Sun Message Queue12 com . sun . messaging . QueueConnectionFactory c f=13 new com . sun . messaging . QueueConnectionFactory ( ) ;14 // se tProper ty e s t e metoda a c l a s e i QueueConnnectionFactory15 // ce implementeaza i n t e r f a t a QueueConnectionFactory16 // dar nu e s t e a i n t e r f e t e i .17 // c f . se tProper ty (” imqBrokerHostName” ,” hos t ” ) ;18 // c f . se tProper ty (” imqBrokerHostPort ” ,”7676”);

20 // Varianta Apache−MessageQueue21 //org . apache . act ivemq . ActiveMQConnectionFactory c f=22 //new org . apache . activemq .23 // ActiveMQConnectionFactory (” tcp :// l o c a l h o s t :61616”) ;

Page 100: DISTR1

100 CAPITOLUL 5. MESAJE IN JAVA

25 Connection conn=c f . c reateConnect ion ( ) ;26 Se s s i on s e s s i o n=conn . c r e a t e S e s s i o n ( false , S e s s i on .AUTOACKNOWLEDGE) ;27 Dest inat i on q==s e s s i o n . createQueue ( queueName ) ;28 MessageConsumer consumer=s e s s i o n . createConsumer ( q ) ;29 TextLi s tener t e x t L i s t e n e r=new TextLi s tener ( ) ;30 consumer . s e tMessageL i s t ene 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 ( Exception e ){36 System . out . p r i n t l n ( e . getMessage ( ) ) ;37 }38 System . out . p r i n t l n ( ”Consumer f i n i s h e d ” ) ;39 }40 }

ımpreuna cu ascultatorul

1 import javax . jms . ∗ ;2 public class TextLi s tener implements MessageListener {3 boolean s f a r s i t=fa l se ;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. getText ( ) ) ;9 }

10 catch ( JMSException e ){11 System . out . p r i n t l n ( e . getMessage ( ) ) ;12 }13 }14 else15 s f a r s i t=true ;16 }

18 public void run ( ){19 while ( ! s f a r s i t ) ;20 }21 }

5.4.4 Publicarea mesajelor

Publicarea mesajelor corespunzatoare unui subiect se face asemanator cu trans-miterea mesajelor ın comunicatia punctuala, dar folosind instante ale claselor dedi-cate acestui tip de comunicatie.

Exemplul 5.4.5

1 import javax . jms . ∗ ;

3 public class MsgPublisherT extends Thread{4 int n ;5 St r ing s u b i e c t ;

Page 101: DISTR1

5.4. ELEMENTE DE PROGRAMARE - JMS 101

7 MsgPublisherT ( St r ing sub iec t , int n){8 this . n=n ;9 this . s u b i e c t=s u b i e c t ;

10 }

12 public void run ( ){13 try{14 // Varianta Oracle−Sun Message Queue15 com . sun . messaging . TopicConnectionFactory c f=16 new com . sun . messaging . TopicConnectionFactory ( ) ;17 // c f . se tProper ty (” imqBrokerHostName” ,” hos t ” ) ;18 // c f . se tProper ty (” imqBrokerHostPort ” ,”7676”);

20 // Varianta Apache−MessageQueue21 // org . apache . activemq . ActiveMQConnectionFactory c f=22 // new org . apache . act ivemq .23 // ActiveMQConnectionFactory (” tcp :// l o c a l h o s t :61616”) ;

25 TopicConnection conn=c f . createTopicConnect ion ( ) ;26 TopicSess ion s e s s i o n =27 conn . c r ea t eTop i cSe s s i on ( false , S e s s i on .AUTOACKNOWLEDGE) ;28 Dest inat i on t = s e s s i o n . c reateTopic ( s u b i e c t ) ;29 MessageProducer producer = s e s s i o n . c reateProducer ( t ) ;

31 //Topic t=new com. sun . messaging . Topic ( s u b i e c t ) ;32 //TopicPub l i sher pu b l i s h e r=se s s i on . c r ea t ePub l i s h e r ( t ) ;

34 TextMessage m=s e s s i o n . createTextMessage ( ) ;35 for ( int i =0; i<n ; i ++){36 m. setText ( ”Despre ”+s u b i e c t+” ”+i ) ;37 producer . send (m) ;38 // pub l i s h e r . pu b l i s h (m) ;39 }40 producer . send ( s e s s i o n . createMessage ( ) ) ;41 // pub l i s h e r . pu b l i s h ( s e s s i on . createMessage ( ) ) ;42 s e s s i o n . c l o s e ( ) ;43 conn . c l o s e ( ) ;44 }45 catch ( Exception e ){46 System . out . p r i n t l n ( ”JMSException : ”+e . getMessage ( ) ) ;47 }48 System . out . p r i n t l n ( ” Pub l i she r f i n i s h e d ” ) ;49 }50 }

Varianta comentata este o solutie specifica implementarii Oracle-Sun Java Sys-tem Message Queue.

5.4.5 Subscrierea si receptia mesajelor

Daca t este obiectul de tip Destination, clientii se aboneaza - subscriu - unuisubiect prin

TopicSubscriber consumer=session.createSubscriber((Topic)t);

Page 102: DISTR1

102 CAPITOLUL 5. MESAJE IN JAVA

Subscrierea este este valabila atata timp cat clientul este activ. Pentru a primi toatemesajele specifice subiectului, chiar si cand clientul este inactiv, acesta trebuie sa fiedurabil, adica crearea consumatorului sa se faca prin

conn.setClientID("myID");

TopicSubscriber consumer=

session.createDurableSubscriber((Topic)t,"nameClient");

In ambele cazuri, clientul primeste doar mesajele publicate din momentul subscrierii.

Exemplul 5.4.6

1 import javax . jms . ∗ ;

3 public class MsgSubscriberT extends Thread{4 St r ing s u b i e c t ;5 St r ing c l i e n t I D ;6 St r ing cl ientName ;

8 MsgSubscriberT ( St r ing sub iec t , S t r ing c l i en t ID , S t r ing cl ientName ){9 this . s u b i e c t=s u b i e c t ;

10 this . c l i e n t I D=c l i e n t I D ;11 this . c l ientName=clientName ;12 }

14 public void run ( ){15 try{16 // Varianta Oracle−Sun Message Queue17 com . sun . messaging . TopicConnectionFactory c f=18 new com . sun . messaging . TopicConnectionFactory ( ) ;19 // c f . se tProper ty (” imqBrokerHostName” ,” hos t ” ) ;20 // c f . se tProper ty (” imqBrokerHostPort ” ,”7676”);

22 // Varianta Apache−MessageQueue23 //org . apache . act ivemq . ActiveMQConnectionFactory c f=24 //new org . apache . act ivemq .25 // ActiveMQConnectionFactory (” tcp :// l o c a l h o s t :61616”) ;

27 TopicConnection conn=c f . createTopicConnect ion ( ) ;28 conn . s e tC l i en t ID ( c l i e n t I D ) ;29 TopicSess ion s e s s i o n=30 conn . c r ea t eTop i cSe s s i on ( false , S e s s i on .AUTOACKNOWLEDGE) ;31 Dest inat i on t = s e s s i o n . c reateTop ic ( s u b i e c t ) ;32 TopicSubscr iber consumer=33 s e s s i o n . c r ea t eDurab l eSubsc r ibe r ( ( Topic ) t , cl ientName ) ;34 conn . s t a r t ( ) ;35 Message msg=null ;36 while ( ( msg=consumer . r e c e i v e ( ) ) != null ){37 i f (msg instanceof TextMessage ){38 TextMessage m=(TextMessage )msg ;39 System . out . p r i n t l n ( cl ientName+” r e c e i v e d : ”+m. getText ( ) ) ;40 }41 else42 break ;43 }44 s e s s i o n . c l o s e ( ) ;

Page 103: DISTR1

5.5. MESAJE SOAP PRIN JAVA MESSAGE SERVICE 103

45 conn . c l o s e ( ) ;46 }47 catch ( Exception e ){48 System . out . p r i n t l n ( ”JMSException : ”+e . getMessage ( ) ) ;49 }50 }51 }

Apelarea celor doua activitati se face prin

Exemplul 5.4.7

1 class MsgPS{2 public stat ic void main ( St r ing [ ] a rgs ){3 St r ing s u b i e c t=”JMS” ;4 int n=3,noAbonati =3;5 i f ( args . length >0)6 s u b i e c t=args [ 0 ] ;7 i f ( args . length >1)8 n=I n t e g e r . pa r s e In t ( args [ 1 ] ) ;9 MsgPublisherT p u b l i s h e r=new MsgPublisherT ( sub iec t , n ) ;

10 MsgSubscriberT [ ] abonat=new MsgSubscriberT [ noAbonati ] ;11 p u b l i s h e r . s t a r t ( ) ;12 for ( int i =0; i<noAbonati ; i ++){13 abonat [ i ]=new MsgSubscriberT ( sub i ec t , ”ID”+i , ” id ”+i ) ;14 abonat [ i ] . s t a r t ( ) ;15 }16 }17 }

5.5 Mesaje SOAP prin Java Message Service

Rezultatele acestei sectiuni sunt valabile doar ın cazul pachetului Oracle-SunJava System Message Queue.

5.5.1 SOAP

SOAP - Simple Object Access Protocol - este un protocol de comunicatii ıntreaplicatii. In prezent SOAP este protocolul standard pentru servicii Web prin Inter-net. SOAP este independent de platforma de calcul si de limbajul de programare.

SOAP se bazeaza pe XML (eXtended Markup Language) si este un standardW3C (World Wide Web Consortium).

Executia programelor utilizand resurse SOAP necesita declararea ın variabila desistem classpath a referintei catre saaj-impl.jar.

5.5.2 Mesaje SOAP

Un mesaj SOAP este un document XML constand din

• o ınvelitoare (envelope) care poate contine

Page 104: DISTR1

104 CAPITOLUL 5. MESAJE IN JAVA

• un numar arbitrar de antete (header);

• un corp (body);

• un numar variabil de obiecte atasate (attachments) MIME (Multipurpose In-ternet Mail Exchange).

Astfel un mesaj SOAP apare sub forma documentului XML

<?xml version="1.0" encoding="UTF-8"?>

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">

<Header/>

<Body>

<Fault/>

</Body>

</Envelope>

Facilitatile Java de manipulare a mesajelor SOAP sunt continute ın pachetuljavax.xml.soap, din distributia jdk.

In acesta sectiune vom crea mesaje SOAP, le transformam ın mesaje JMS pecare le trimitem furnizorului JMS, de unde un client le receptioneaza, dupa caretransforma mesajul JMS ın mesaj SOAP si regaseste datele expediate. Solutia estespecifica implementarii Oracle-Sun Java System Message Queue.

Crearea unui mesaj SOAP

MessageFactory mf=MessageFactory.newInstance();

SOAPMessage soapMsg=mf.createMessage();

Mesajul creat are definita structura de baza a mesajului SOAP: invelitoarea, unantetul si corpul. Aceste elemente pot fi accesate prin

SOAPPart part=soapMsg.getSOAPPart();

SOAPEnvelope envelope=part.getEnvelope();

SOAPHeader header=envelope.getHeader();

SOAPBody body=envelope.getBody();

Completarea corpului unui mesaj SOAP

Generam numele elementului, ”e1” ın cazul exemplului,

Name n1=envelope.createName("e1");

In body un element se poate include, pe baza numelui creat prin

SOAPElement e1=body.addBodyElement(n1);

Page 105: DISTR1

5.5. MESAJE SOAP PRIN JAVA MESSAGE SERVICE 105

In general, un element se include ın elementul parinte, care pote fi chiar si body, prinmetoda clasei SOAPElement

SOAPElement addChildElement(Name name)

Completam elementul e1 cu un text: ”primul”, prin

e1.addTextNode("primul");

Exemplul 5.5.1 Mesajul SOAP

1 <SOAP−ENV:Envelope2 xmlns:SOAP−ENV=” h t t p : // schemas . xmlsoap . org / soap / enve l ope /”>3 <SOAP−ENV:Header/>4 <SOAP−ENV:Body>5 <e1>6 pr imul7 <e11>8 a l t r e i l e a9 </e11>

10 </e1>11 <e2>12 a l d o i l e a13 </e2>14 </SOAP−ENV:Body>15 </SOAP−ENV:Envelope>

se obtine cu programul

1 import javax . xml . soap . ∗ ;2 import java . i o . ∗ ;

4 public class MsgSOAP{5 public stat ic void main ( St r ing [ ] a rgs ){6 Name name=null ;7 try{8 MessageFactory mf=MessageFactory . newInstance ( ) ;9 SOAPMessage soapMsg=mf . createMessage ( ) ;

10 SOAPPart part=soapMsg . getSOAPPart ( ) ;11 SOAPEnvelope enve lope=part . getEnvelope ( ) ;12 SOAPBody body=enve lope . getBody ( ) ;13 Name n1=enve lope . createName ( ”e1” ) ;14 SOAPElement e1=body . addBodyElement ( n1 ) ;15 e1 . addTextNode ( ” primul ” ) ;16 Name n2=enve lope . createName ( ”e2” ) ;17 SOAPElement e2=body . addBodyElement ( n2 ) ;18 e2 . addTextNode ( ” a l d o i l e a ” ) ;19 Name n11 =enve lope . createName ( ”e11 ” ) ;20 SOAPElement e11=e1 . addChildElement ( n11 ) ;21 e11 . addTextNode ( ” a l t r e i l e a ” ) ;22 FileOutputStream f=new FileOutputStream ( ”MySOAPMessage . xml” ) ;23 soapMsg . writeTo ( f ) ;24 }25 catch ( Exception e ){26 System . out . p r i n t l n ( ” Exception : ”+e . getMessage ( ) ) ;27 }28 }29 }

Page 106: DISTR1

106 CAPITOLUL 5. MESAJE IN JAVA

Un mesaj SOAP se poate salva ıntr-un fisier text cu

FileOutputStream f=new FileOutputStream(. . .);

soapMsg.writeTo(f);

Transformarea unui mesaj SOAP ın mesaj JMS

SOAPMessage soapMsg=. . .

Message msg=

MessageTransformer.SOAPMessageIntoJMSMessage(soapMsg,session);

Transformarea unui mesaj JMS ın mesaj SOAP

MessageFactory mf=. . .

Message msg=. . .

SOAPMessage soapMsg =

MessageTransformer.SOAPMessageFromJMSMessage(msg,mf);

Preluarea elementelor din corpul unui mesaj SOAP

SOAPBody body=. . .

SOAPBodyElement element=null;

Iterator iterator=body.getChildElements();

while(iterator.hasNext()){

element=(SOAPBodyElement)iterator.next();

String name=element.getElementName();

if(name.getLocalName().equals("numeCamp")){

String s=element.getValue();

. . .

}

}

Exemplul 5.5.2 Un client introduce ıntr-un mesaj SOAP doua numere ıntregi,transmite mesajul altui program care calculeaza cel mai mare divizor comun al celordoua numere si transmite clientului rezultatul tot sub forma unui mesaj SOAP.

Activitatea clientului este se compune din

• Transmiterea catre server a cererii. Mesajul este alcatuit din cele doua numeresi un topic, indicativ dupa care se va gasi raspunsul.

1 import javax . jms . ∗ ;2 import javax . xml . soap . ∗ ;3 import com . sun . messaging . xml . MessageTransformer ;4 import java . u t i l . ∗ ;

6 public class MsgSOAPClientSender{

Page 107: DISTR1

5.5. MESAJE SOAP PRIN JAVA MESSAGE SERVICE 107

8 long a , b ;9 St r ing top i cRe su l t ;

10 St r ing c l i en t ID , cl ientName ;

12 MsgSOAPClientSender ( S t r ing c l i en t ID , S t r ing cl ientName ){13 this . c l i e n t I D=c l i e n t I D ;14 this . c l ientName=clientName ;15 Scanner scanner=new Scanner ( System . in ) ;16 System . out . p r i n t l n ( ” I n t r o d u c e t i m : ” ) ;17 a=scanner . 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=scanner . nextLong ( ) ;20 System . out . p r i n t l n ( ” I n t r o d u c e t i ’ Topic ’−ul ra spunsu lu i ” ) ;21 t op i cRe su l t=scanner . next ( ) ;22 }

24 public void s e r v i c e ( ){25 MessageFactory mf=null ;26 SOAPMessage soapMsg=null ;27 SOAPPart part=null ;28 SOAPEnvelope enve lope=null ;29 SOAPBody body=null ;30 SOAPElement elem=null ;31 Name name=null ;32 try{33 com . sun . messaging . TopicConnectionFactory c f=34 new com . sun . messaging . TopicConnectionFactory ( ) ;35 // c f . se tProper ty (” imqBrokerHostName” ,” a t l a n t i s ” ) ;36 // c f . se tProper ty (” imqBrokerHostPort ” ,”7676”);37 TopicConnection conn=c f . createTopicConnect ion ( ) ;38 conn . s e tC l i en t ID ( c l i e n t I D ) ;39 TopicSess ion s e s s i o n =40 conn . c r ea t eTop i cSe s s i on ( false , S e s s i on .AUTOACKNOWLEDGE) ;41 Dest inat i on tDate=s e s s i o n . c reateTopic ( ”Cmmdc” ) ;42 MessageProducer producer=s e s s i o n . c reateProducer ( tDate ) ;43 mf=MessageFactory . newInstance ( ) ;44 soapMsg=mf . createMessage ( ) ;45 part=soapMsg . getSOAPPart ( ) ;46 enve lope=part . getEnvelope ( ) ;47 body=enve lope . getBody ( ) ;48 name=enve lope . createName ( ”n1” ) ;49 elem=body . addChildElement (name ) ;50 elem . addTextNode ( (new Long ( a ) ) . t oS t r i ng ( ) ) ;51 name=enve lope . createName ( ”n2” ) ;52 elem=body . addChildElement (name ) ;53 elem . addTextNode ( (new Long (b ) ) . t oS t r i ng ( ) ) ;54 name=enve lope . createName ( ” t op i c ” ) ;55 elem=body . addChildElement (name ) ;56 elem . addTextNode ( top i cRe su l t ) ;57 Dest inat i on tResu l t=s e s s i o n . c reateTop ic ( t op i cRe su l t ) ;58 TopicSubscr iber consumer=59 s e s s i o n . c r ea t eDurab l eSubsc r ibe r ( ( Topic ) tResult , cl ientName ) ;60 Message m=61 MessageTransformer . SOAPMessageIntoJMSMessage ( soapMsg , s e s s i o n ) ;62 producer . send (m) ;63 FileOutputStream f=new FileOutputStream ( ”MySOAPMessage . xml” ) ;64 soapMsg . writeTo ( f ) ;65 conn . c l o s e ( ) ;

Page 108: DISTR1

108 CAPITOLUL 5. MESAJE IN JAVA

66 }67 catch ( Exception e ){68 System . out . p r i n t l n ( ” Exception : ”+e . getMessage ( ) ) ;69 }70 System . out . p r i n t l n ( ” Sender f i n i s h e d ” ) ;71 }

73 public stat ic void main ( St r ing [ ] a rgs ){74 i f ( args . length <2){75 System . out . p r i n t l n ( ”Usage : ” ) ;76 System . out . p r i n t l n ( ” java MsgSOAPClientSender c l i e n t I D clientName ” ) ;77 System . e x i t ( 0 ) ;78 }79 MsgSOAPClientSender c l i e n t=new MsgSOAPClientSender ( args [ 0 ] , a rgs [ 1 ] ) ;80 c l i e n t . s e r v i c e ( ) ;81 }82 }

• Receptionarea raspunsului.

1 import javax . jms . ∗ ;2 import javax . xml . soap . ∗ ;3 import com . sun . messaging . xml . MessageTransformer ;4 import java . u t i l . ∗ ;

6 public class MsgSOAPClientReceiver{

8 St r ing top i cRe su l t ;9 St r ing c l i en t ID , cl ientName ;

11 MsgSOAPClientReceiver ( S t r ing c l i en t ID , S t r ing cl ientName ){12 this . c l i e n t I D=c l i e n t I D ;13 this . c l ientName=clientName ;14 Scanner scanner=new Scanner ( System . in ) ;15 System . out . p r i n t l n ( ” I n t r o d u c e t i ’ Topic ’−ul ra spunsu lu i ” ) ;16 t op i cRe su l t=scanner . next ( ) ;17 }

19 public void s e r v i c e ( ){20 MessageFactory mf=null ;21 SOAPMessage soapMsg=null ;22 SOAPPart part=null ;23 SOAPEnvelope enve lope=null ;24 SOAPBody body=null ;25 SOAPBodyElement element=null ;26 Name name=null ;27 try{28 com . sun . messaging . TopicConnectionFactory c f=29 new com . sun . messaging . TopicConnectionFactory ( ) ;30 // c f . se tProper ty (” imqBrokerHostName” ,” a t l a n t i s ” ) ;31 // c f . se tProper ty (” imqBrokerHostPort ” ,”7676”);32 TopicConnection conn=c f . createTopicConnect ion ( ) ;33 conn . s e tC l i en t ID ( c l i e n t I D ) ;34 TopicSess ion s e s s i o n=conn . c r ea t eTop i cSe s s i on ( false ,35 Se s s i on .AUTOACKNOWLEDGE) ;36 Dest inat i on tResu l t=s e s s i o n . c reateTop ic ( t op i cRe su l t ) ;37 TopicSubscr iber consumer=38 s e s s i o n . c r ea t eDurab l eSubsc r ibe r ( ( Topic ) tResult , cl ientName ) ;39 mf=MessageFactory . newInstance ( ) ;

Page 109: DISTR1

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=MessageTransformer . SOAPMessageFromJMSMessage (msg , mf ) ;43 System . out . p r i n t l n ( ” C l i en t Mesaj SOAP r e c e p t i o n a t ” ) ;44 part=soapMsg . getSOAPPart ( ) ;45 enve lope=part . getEnvelope ( ) ;46 body=enve lope . getBody ( ) ;47 I t e r a t o r i t e r a t o r=body . getChi ldElements ( ) ;48 St r ing s=”” ;49 while ( i t e r a t o r . hasNext ( ) ){50 element=(SOAPBodyElement) i t e r a t o r . next ( ) ;51 name=element . getElementName ( ) ;52 i f (name . getLocalName ( ) . equa l s ( ”cmmdc” ) )53 s=element . getValue ( ) ;54 }55 System . out . p r i n t l n ( ”Cmmdc: ”+s ) ;56 conn . c l o s e ( ) ;57 }58 catch ( Exception e ){59 System . out . p r i n t l n ( ” Exception : ”+e . getMessage ( ) ) ;60 }61 System . out . p r i n t l n ( ” Rece iver f i n i s h e d ” ) ;62 }

64 public stat ic void main ( St r ing [ ] a rgs ){65 i f ( args . length <2){66 System . out . p r i n t l n ( ”Usage : ” ) ;67 System . out . p r i n t l n ( ” java MsgSOAPClientReceiver c l i e n t I D clientName ” ) ;68 System . e x i t ( 0 ) ;69 }70 MsgSOAPClientReceiver c l i e n t=new MsgSOAPClientReceiver ( args [ 0 ] , a rgs [ 1 ] ) ;71 c l i e n t . s e r v i c e ( ) ;72 }73 }

Programul server este

1 import javax . jms . ∗ ;2 import javax . xml . soap . ∗ ;3 import com . sun . messaging . xml . MessageTransformer ;4 import java . u t i l . I t e r a t o r ;

6 public class MsgSOAPCmmdcServer{

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

10 public void s e r v i c e ( ){11 MessageFactory mf=null ;12 SOAPMessage soapMsg=null ;13 SOAPPart part=null ;14 SOAPEnvelope enve lope=null ;15 SOAPBody body=null ;16 SOAPBodyElement element=null ;17 SOAPElement elem=null ;18 Name name=null ;19 try{20 com . sun . messaging . TopicConnectionFactory21 c f=new com . sun . messaging . TopicConnectionFactory ( ) ;22 // c f . se tProper ty (” imqBrokerHostName” ,” a t l a n t i s ” ) ;

Page 110: DISTR1

110 CAPITOLUL 5. MESAJE IN JAVA

23 // c f . se tProper ty (” imqBrokerHostPort ” ,”7676”);24 TopicConnection conn=c f . createTopicConnect ion ( ) ;25 TopicSess ion s e s s i o n=conn . c r ea t eTop i cSe s s i on ( false ,26 Se s s i on .AUTOACKNOWLEDGE) ;27 Dest inat i on tDate=s e s s i o n . c reateTopic ( ”Cmmdc” ) ;28 TopicSubscr iber 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=null ;31 mf=MessageFactory . newInstance ( ) ;32 while ( true ){33 msg=consumer . r e c e i v e ( ) ;34 soapMsg=MessageTransformer . SOAPMessageFromJMSMessage (msg , mf ) ;35 System . out . p r i n t l n ( ” Server Mesaj SOAP r e c e p t i o n a t ” ) ;36 part=soapMsg . getSOAPPart ( ) ;37 enve lope=part . getEnvelope ( ) ;38 body=enve lope . getBody ( ) ;39 I t e r a t o r i t e r a t o r=body . getChi ldElements ( ) ;40 St r ing sn1=”” , sn2=”” , t op i cRe su l t=”” ;41 while ( i t e r a t o r . hasNext ( ) ){42 element=(SOAPBodyElement) i t e r a t o r . next ( ) ;43 name=element . getElementName ( ) ;44 i f (name . getLocalName ( ) . equa l s ( ”n1” ) )45 sn1=element . getValue ( ) ;46 i f (name . getLocalName ( ) . equa l s ( ”n2” ) )47 sn2=element . getValue ( ) ;48 i f (name . getLocalName ( ) . equa l s ( ” t op i c ” ) )49 t op i cResu l t=element . getValue ( ) ;50 }51 System . out . p r i n t l n ( sn1+” : ”+sn2+” : ”+top i cRe su l t ) ;52 long a=Long . parseLong ( sn1 ) ;53 long b=Long . parseLong ( sn2 ) ;54 long c=cmmdc( a , b ) ;55 soapMsg=mf . createMessage ( ) ;56 part=soapMsg . getSOAPPart ( ) ;57 enve lope=part . getEnvelope ( ) ;58 body=enve lope . getBody ( ) ;59 name=enve lope . createName ( ”cmmdc” ) ;60 elem=body . addChildElement (name ) ;61 elem . addTextNode ( (new Long ( c ) ) . t oS t r i ng ( ) ) ;62 Message m=63 MessageTransformer . SOAPMessageIntoJMSMessage ( soapMsg , s e s s i o n ) ;64 Dest inat i on tResu l t=s e s s i o n . c reateTop ic ( t op i cRe su l t ) ;65 MessageProducer producer=s e s s i o n . c reateProducer ( tResu l t ) ;66 producer . send (m) ;67 }68 }69 catch ( Exception e ){70 System . out . p r i n t l n ( ” Exception : ”+e . getMessage ( ) ) ;71 }72 System . out . p r i n t l n ( ” Server f i n i s h e d ” ) ;73 }

75 public stat ic void main ( St r ing [ ] a rgs ){76 MsgSOAPCmmdcServer s e r v e r=new MsgSOAPCmmdcServer ( ) ;77 s e r v e r . s e r v i c e ( ) ;78 }79 }

Mesajul SOAP utilizat de client, pentru n1 = 45, n2 = 35 si topic = nume este

Page 111: DISTR1

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>

5.5.3 Atasamente SOAP

Crearea atasamentelor

1. Crearea mesajului SOAP

MessageFactory mf=MessageFactory.newInstance();

SOAPMessage soapMsg=mf.createMessage();

2. • Atasament text

(a) Crearea unui obiect de tip AttachmentPart

AttachmentPart attachment=soapMsg.createAttachmentPart();

(b) Completarea continutuluiString stringContent=. . .

attachment.setContent(stringContent, "text/plain");

Continutului i se poate atasa un cod de identificareattachment.setContentId("Text1");

• Atasament imagine jpeg/png

(a) Crearea unui obiect de tip AttachmentPart cu ıncarcarea imaginii.

URL url=new URL("file://localhost/c:\\. . .\\***.jpg");

DataHandler dataHandler = new DataHandler(url);

AttachmentPart attachment =

soapMsg.createAttachmentPart(dataHandler);

attachment.setContentId("Imagine1");

• Atasament cu sunet ın format mp3.

(a) Crearea unui obiect de tip AttachmentPart cu ıncarcarea fisieruluimp3.

URL url=new URL("file://localhost/c:\\. . .\\***.mp3");

DataHandler dataHandler=new DataHandler(url);

AttachmentPart attachment =

soapMsg.createAttachmentPart(dataHandler);

attachment.setContentId("attached_mp3");

Page 112: DISTR1

112 CAPITOLUL 5. MESAJE IN JAVA

• Atasament video.

(a) Fisierele video au de obicei dimensiuni mari. Pentru a putea in-clude asemenea fisiere trebuie marita dimensiunea maxima a unuiatasament prin includerea setariiimq.autocreate.destination.maxBytesPerMsg=35M

ın fisierul mq\lib\props\broker\install.properties.

(b) Crearea unui obiect de tip AttachmentPart cu ıncarcarea fisieruluicu continut video.

String video_location="c:\\. . .’’;

URL url=new URL("file://"+video_location);

dataHandler= new DataHandler(url);

AttachmentPart attachment =

soapMsg.createAttachmentPart(dataHandler);

(c) Pentru redarea continutului video vom avem nevoie de tipul continutuluivideo, informatie data de extensia fisierului video. Aceata data estefurnizata 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);

3. Includerea atasamentului ın mesajul SOAP

soapMsg.addAttachmentPart(attachment);

Extragerea atasamentelor

Tipul unui atasament se poate deduce din rezultatul metodei getContentId saugetContentType 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();

// Preluarea unui string

if (type.equals("text/plain")) {

Object content = attached.getContent();

Page 113: DISTR1

5.5. MESAJE SOAP PRIN JAVA MESSAGE SERVICE 113

. . .

}

// Preluarea unei imagini

if (type.equals("image/jpeg")){

Image image=(Image)attached.getContent();

. . .

}

// Preluarea unei inregistrari mp3

if(type.equals("audio/x-wav")){

System.out.println("Play MP3");

MP3Player mp3Player=new MP3Player(attached.getRawContent());

mp3Player.play();

}

// Preluarea continutului video

if(id.startsWith("attached_video")){

String videoFileName = "videoFile."+id.substring(14);

// Salvarea continutului video intr-un fisier local

InputStream inputStream = attached.getRawContent();

File f=new File(videoFileName);

OutputStream out=new FileOutputStream(f);

byte buf[]=new byte[1024];

int len;

while((len=inputStream.read(buf))>0) out.write(buf,0,len);

out.close();

// Redarea continutului video utilizand FMJ

String[]arguments = new String[1];

arguments[0]=URLUtils.createUrlStr(f);

System.out.println("Video show");

FmjStudio.main(arguments);

}

Valoarea rezultata din metoda getContentType ın cazul unui atasament video diferade tipul acesteia. Astfel pentru tipul avi valoarea retunata este application/x-troff-msvideo,iar pentru wmv se obtine content/unknown. Redarea continutului video se face uti-lizand produsul Free Media for Java - FMJ.

Exemplul 5.5.3 Crearea unui mesaj SOAP cu atasamente text, imagine, muzicamp3 si video. Textul, imaginea, muzica mp3 si continutul video sunt continute ınfisiere. Caile catre aceste fisiere se vor da ca proprietati.

Page 114: DISTR1

114 CAPITOLUL 5. MESAJE IN JAVA

1 import javax . jms . ∗ ;2 import javax . xml . soap . ∗ ;3 import com . sun . messaging . xml . MessageTransformer ;4 import java . i o . ∗ ;5 import javax . a c t i v a t i o n . DataHandler ;6 import java . net .URL;

8 public class MsgSOAPPublisher extends Thread{

10 St r ing f i l e l o c a t i o n , image locat ion , mp3 locat ion , v i d e o l o c a t i o n ;11 MsgSOAPPublisher ( S t r ing f i l e l o c a t i o n , S t r ing image locat ion ,12 St r ing mp3 locat ion , S t r ing v i d e o l o c a t i o n ){13 this . f i l e l o c a t i o n=f i l e l o c a t i o n ;14 this . image l o ca t i on=image l o ca t i on ;15 this . mp3 locat ion=mp3 locat ion ;16 this . v i d e o l o c a t i o n=v i d e o l o c a t i o n ;17 }

19 public void run ( ){20 try{21 com . sun . messaging . TopicConnectionFactory c f=22 new com . sun . messaging . TopicConnectionFactory ( ) ;23 // c f . se tProper ty (” imqBrokerHostName” ,” jonathan ”) ;24 // c f . se tProper ty (” imqBrokerHostPort ” ,”7676”);25 TopicConnection conn=c f . createTopicConnect ion ( ) ;26 TopicSess ion s e s s i o n=27 conn . c r ea t eTop i cSe s s i on ( false , S e s s i on .AUTOACKNOWLEDGE) ;28 //Topic t=new com. sun . messaging . Topic (”Date ” ) ;29 //TopicPub l i sher pu b l i s h e r=se s s i on . c r ea t ePub l i s h e r ( t ) ;30 Dest inat i on t=s e s s i o n . c reateTop ic ( ”Date” ) ;31 MessageProducer producer=s e s s i o n . c reateProducer ( t ) ;

33 MessageFactory mf=MessageFactory . newInstance ( ) ;34 SOAPMessage soapMsg=mf . createMessage ( ) ;35 SOAPPart part=soapMsg . getSOAPPart ( ) ;36 SOAPEnvelope enve lope=part . getEnvelope ( ) ;37 SOAPBody body=enve lope . getBody ( ) ;38 Name bodyName=enve lope . createName ( ” v e r i f ” ) ;39 SOAPElement element=body . addBodyElement (bodyName ) ;40 element . addTextNode ( ”MyAttachment” ) ;

42 // Crearea atasamentu lu i de t i p t e x t

44 AttachmentPart attachment1=soapMsg . createAttachmentPart ( ) ;

46 Fi leReader f r = new Fi leReader (new F i l e ( f i l e l o c a t i o n ) ) ;47 BufferedReader br = new BufferedReader ( f r ) ;

49 St r ing s t r ingContent = ”” ;50 St r ing l i n e = br . readLine ( ) ;51 while ( l i n e != null ) {52 s t r ingContent = str ingContent . concat ( l i n e ) ;53 s t r ingContent = str ingContent . concat ( ”\n” ) ;54 l i n e = br . readLine ( ) ;55 }

57 attachment1 . setContent ( str ingContent , ” t ext / p l a i n ” ) ;58 attachment1 . setContentId ( ” a t ta ched t ex t ” ) ;59 soapMsg . addAttachmentPart ( attachment1 ) ;

Page 115: DISTR1

5.5. MESAJE SOAP PRIN JAVA MESSAGE SERVICE 115

61 // Crearea atasamentu lu i de t i p imagine62 URL u r l = new URL( ” f i l e : // ”+image l o ca t i on ) ;63 DataHandler dataHandler = new DataHandler ( u r l ) ;64 AttachmentPart attachment2 =65 soapMsg . createAttachmentPart ( dataHandler ) ;

67 attachment2 . setContentId ( ” attached image ” ) ;68 soapMsg . addAttachmentPart ( attachment2 ) ;

70 // Crearea unui atasament de t i p mp371 u r l=new URL( ” f i l e : // ”+mp3 locat ion ) ;72 dataHandler= new DataHandler ( u r l ) ;73 AttachmentPart attachment3 =74 soapMsg . createAttachmentPart ( dataHandler ) ;

76 attachment3 . setContentId ( ” attached mp3 ” ) ;77 soapMsg . addAttachmentPart ( attachment3 ) ;

79 // Crearea unui atasament v ideo80 u r l=new URL( ” f i l e : // ”+v i d e o l o c a t i o n ) ;81 dataHandler= new DataHandler ( u r l ) ;82 AttachmentPart attachment4 =83 soapMsg . createAttachmentPart ( dataHandler ) ;84 F i l e v i d e o F i l e = new F i l e ( v i d e o l o c a t i o n ) ;85 St r ing f i leName = v i d e o F i l e . getName ( ) ;86 int index=fi leName . la s t IndexOf ( ” . ” ) ;87 St r ing ext=fi leName . s ub s t r i ng ( index +1);88 attachment4 . setContentId ( ” at tached v ideo ”+ext ) ;89 soapMsg . addAttachmentPart ( attachment4 ) ;

91 Message m=92 MessageTransformer . SOAPMessageIntoJMSMessage ( soapMsg , s e s s i o n ) ;93 // pub l i s h e r . pu b l i s h (m) ;94 producer . send (m) ;95 FileOutputStream f=new FileOutputStream ( ”MySOAPMessage . xml” ) ;96 soapMsg . writeTo ( f ) ;97 conn . c l o s e ( ) ;98 }99 catch ( Exception e ){

100 System . out . p r i n t l n ( ” Exception : ”+e . getMessage ( ) ) ;101 }102 System . out . p r i n t l n ( ” Pub l i she r f i n i s e d ” ) ;103 }104 }

Exemplul 5.5.4 Consumarea unui mesaj SOAP cu atasamente

1 import javax . jms . ∗ ;2 import javax . xml . soap . ∗ ;3 import com . sun . messaging . xml . MessageTransformer ;4 import java . u t i l . I t e r a t o r ;5 import java . i o . ∗ ;6 import java . awt . ∗ ;7 import net . s f . fmj . u t i l i t y . URLUtils ;8 import net . s f . fmj . u i . FmjStudio ;

Page 116: DISTR1

116 CAPITOLUL 5. MESAJE IN JAVA

10 public class MsgSOAPSubscriber extends Thread{

12 public void run ( ){13 try{14 com . sun . messaging . TopicConnectionFactory c f=15 new com . sun . messaging . TopicConnectionFactory ( ) ;16 // c f . se tProper ty (” imqBrokerHostName” ,” jonathan ”) ;17 // c f . se tProper ty (” imqBrokerHostPort ” ,”7676”);18 TopicConnection conn=c f . createTopicConnect ion ( ) ;19 TopicSess ion s e s s i o n=20 conn . c r ea t eTop i cSe s s i on ( false , S e s s i on .AUTOACKNOWLEDGE) ;21 //Topic t=new com. sun . messaging . Topic (”Date ” ) ;22 Dest inat i on t=s e s s i o n . c reateTop ic ( ”Date” ) ;23 TopicSubscr iber consumer=s e s s i o n . c r e a t e S u b s c r i b e r ( ( Topic ) t ) ;

25 conn . s t a r t ( ) ;26 Message msg=null ;27 MessageFactory mf=MessageFactory . newInstance ( ) ;28 while ( ( msg=consumer . r e c e i v e ( ) ) != null ){29 SOAPMessage soapMsg =30 MessageTransformer . 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 // Extragerea atasamente lor33 I t e r a t o r i t e r a t o r = soapMsg . getAttachments ( ) ;34 while ( i t e r a t o r . hasNext ( ) ) {35 AttachmentPart attached=(AttachmentPart ) i t e r a t o r . next ( ) ;36 St r ing id = attached . getContentId ( ) ;37 St r ing type = attached . getContentType ( ) ;38 System . out . p r i n t l n ( ”Attachment ” + id +39 ” has content type ” + type ) ;40 i f ( type . equa l s ( ” t ext / p l a i n ” ) ) {41 St r ing content = ( St r ing ) attached . getContent ( ) ;42 System . out . p r i n t l n ( ”Attachment conta in s :\n” + content ) ;43 }44 i f ( type . equa l s ( ” image/ jpeg ” ) ){45 Image image=(Image ) attached . getContent ( ) ;46 ShowImage s=new ShowImage ( image ) ;47 s . show ( ) ;48 }49 i f ( type . equa l s ( ” audio /x−wav” ) ){50 System . out . p r i n t l n ( ”Play MP3” ) ;51 MP3Player mp3Player=new MP3Player ( attached . getRawContent ( ) ) ;52 mp3Player . s t a r t ( ) ;53 }54 i f ( id . s tartsWith ( ” at tached v ideo ” ) ){55 St r ing videoFileName = ” v i d e o F i l e . ”+id . su b s t r i n g ( 1 4 ) ;56 InputStream inputStream = attached . getRawContent ( ) ;57 F i l e f=new F i l e ( videoFileName ) ;58 OutputStream out=new FileOutputStream ( f ) ;59 byte buf [ ]=new byte [ 1 0 2 4 ] ;60 int l en ;61 while ( ( l en=inputStream . read ( buf ))>0) out . wr i t e ( buf , 0 , l en ) ;62 out . c l o s e ( ) ;63 St r ing [ ] arguments = new St r ing [ 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 ( ” Press Enter to cont inue ! ” ) ;66 System . in . read ( ) ;67 System . out . p r i n t l n ( ”Video show” ) ;68 FmjStudio . main ( arguments ) ;

Page 117: DISTR1

5.5. MESAJE SOAP PRIN JAVA MESSAGE SERVICE 117

69 }70 }71 }72 conn . c l o s e ( ) ;73 }74 catch ( Exception e ){75 System . out . p r i n t l n ( ” Exception : ”+e . getMessage ( ) ) ;76 }77 System . out . p r i n t l n ( ” Subsc r ibe r f i n i s h e d ” ) ;78 }79 }

Apelarea celor doua fire de executie se face prin

1 class MsgAttach{2 public stat ic void main ( St r ing [ ] a rgs ){3 St r ing f i l e l o c a t i o n=System . getProperty ( ” f i l e l o c a t i o n ” ) ;4 St r ing image l o ca t i on=System . getProperty ( ” image l o ca t i on ” ) ;5 St r ing mp3 locat ion=System . getProperty ( ” mp3 locat ion ” ) ;6 MsgSOAPPublisher p u b l i s h e r=7 new MsgSOAPPublisher ( f i l e l o c a t i o n , image locat ion , mp3 locat ion ) ;8 MsgSOAPSubscriber s u b s c r i b e r=new MsgSOAPSubscriber ( ) ;9 p u b l i s h e r . s t a r t ( ) ;

10 s u b s c r i b e r . s t a r t ( ) ;11 }12 }

Utilizarea aplicatiei se face prin ant pe structura initiala de cataloage si fisiere

app

|--> resources

| | resursele text, imagine, mp3, video

|--> src

| | MsgAttach.java

| | MsgSOAPPublisher.java

| | MsgSOAPSubscriber.java

| | MP3Player.java

| | ShowImage.java

| logging.properties (din FMJ)

| build.xml

si cu fisierul build.xml

1 <?xml version=” 1 .0 ” encoding=”UTF−8”?>2 <p r o j e c t default=”run” based i r=” . ”>3 <property name=”mq. home” value=” d: /mq”/>4 <property name=” r e s o u r c e s . home” l o c a t i o n=”${ based i r }/ r e s o u r c e s ”/>5 <property name=” fmj . home” l o c a t i o n=” d: /JavaApp/ fmj”/>

7 <path id=” c l a s s p a t h ” >8 <pathelement path=” bu i ld / c l a s s e s ” />9 <pathelement path=”${ fmj . home}/ fmj . j a r ” />

10 < f i l e s e t d i r=”${mq. home}/ l i b ”>11 <i n c l ude name=” ∗ . j a r ”/>12 </ f< i l e s e t>13 < f i l e s e t d i r=”${ fmj . home}/ l i b ”>14 <i n c l ude name=” ∗ . j a r ”/>15 </ f i l e s e t>16 </path>

Page 118: DISTR1

118 CAPITOLUL 5. MESAJE IN JAVA

18 <t a r g e t name=” i n i t ”>19 <mkdir d i r=” bu i ld ”/>20 <mkdir d i r=” bu i ld / c l a s s e s ”/>21 </ t a r g e t>

23 <t a r g e t name=” compile ” depends=” i n i t ”>24 <javac s r c d i r=” s r c ” c l a s s p a t h r e f=” c l a s sp a t h ”25 d e s t d i r=” bu i ld / c l a s s e s ” debug=” yes ” />26 </ t a r g e t>

28 <t a r g e t name=” s e r v e r ”>29 <exec executab l e=”${mq. home}/ bin / imqbrokerd . exe ” d i r=”${mq. home}/ bin ”/>30 </ t a r g e t>

32 <t a r g e t name=”run” depends=” compile ”>33 <java classname=”MsgAttach” c l a s s p a t h r e f=” c l a s s p a t h ”34 f o rk=” yes ” f a i l o n e r r o r=” yes ”>35 <sysproper ty key=” f i l e l o c a t i o n ”36 value=”${ r e s o u r c e s . home}/ c a p i t o l . txt ”/>37 <sysproper ty key=” image l o ca t i on ”38 value=” l o c a l h o s t /${ r e s o u r c e s . home}/xml−p i c . jpg ”/>39 <sysproper ty key=” mp3 locat ion ”40 value=” l o c a l h o s t /${ r e s o u r c e s . home}/Tomjones . mp3”/>41 <sysproper ty key=” v i d e o l o c a t i o n ”42 value=” l o c a l h o s t /${ r e s o u r c e s . home}/ c l o ck . av i ”/>43 <sysproper ty key=” java . l i b r a r y . path”44 value=”${ fmj . home}/ nat ive /win32−x86”/>45 </ java>46 </ t a r g e t>

48 </ p r o j e c t>

Programul de afisare a imaginii

1 import java . awt . ∗ ;2 import java . awt . image . ∗ ;3 import javax . swing . ∗ ;4 import java . i o . ∗ ;5 import javax . imageio . ImageIO ;6 import java . net . ∗ ;

8 c l a s s MyCanvas extends Canvas{9 Image image=n u l l ;

11 MyCanvas( Image image ){12 t h i s . image=image ;13 }

15 pub l i c void pa int ( Graphics g ){16 g . drawImage ( image , 0 , 0 , t h i s ) ;17 }18 }

20 pub l i c c l a s s ShowImage{21 MyCanvas mc=n u l l ;

23 ShowImage ( Image image ){24 mc=new MyCanvas( image ) ;25 }

Page 119: DISTR1

5.6. PROGRAME JMS PRIN APACHE-QPID 119

27 pub l i c void show (){28 // I n t e r f a t a swing29 JFrame j f rame = new JFrame ( ”The r e c e i v e d image” ) ;30 j f rame . addNoti fy ( ) ;31 j f rame . getContentPane ( ) . setLayout (new BorderLayout ( ) ) ;32 j f rame . getContentPane ( ) . add (mc, BorderLayout .CENTER) ;33 j f rame . s e tDe fau l tC lo seOperat ion ( JFrame .EXIT ON CLOSE ) ;34 j f rame . s e t S i z e ( 20 0 , 20 0 ) ;35 j f rame . s e t V i s i b l e ( t rue ) ;36 }37 }

Programul pentru redarea continutului unui fisier mp3 necesita prezenta resurseijl1.0.jar din pachetul JLayer1.0, descarcabil din internet. Un program de redare este

1 import java . i o . ∗ ;2 import javazoom . j l . p l aye r . Player ;

4 pub l i c c l a s s MP3Player extends Thread{5 p r i v a t e Player p laye r ;

7 pub l i c MP3Player ( InputStream i s ) {8 t ry {9 BufferedInputStream b i s=new BufferedInputStream ( i s ) ;

10 p laye r=new Player ( b i s ) ;11 }12 catch ( Exception e ){13 System . out . p r i n t l n ( e . getMessage ( ) ) ;14 System . e x i t ( 1 ) ;15 }16 }

18 pub l i c void run ( ){19 t ry {20 p laye r . play ( ) ;21 }22 catch ( Exception e ){23 System . out . p r i n t l n ( e . getMessage ( ) ) ;24 }25 i f ( p l aye r != n u l l ) p laye r . c l o s e ( ) ;26 }27 }

5.6 Programe JMS prin apache-qpid

apache-qpid reprezinta o implementare a protocolului AMQP care poate fi folositde clienti Java, C++, C#, Pyton, Ruby. Programele dezvoltate utilizand Oracle-Sun Java System Message Queue sau apache-ActiveMQ se ruleaza (aproape) faramodificari. Acest fapt dorim sa-l prezentam ın continuare.

Instalarea serviciului de mesagerie revine la

1. Dezarhivarea fisierului descarcat;

Page 120: DISTR1

120 CAPITOLUL 5. MESAJE IN JAVA

2. Generarea unei semnaturi.

Catalogul QPID HOME\bin contine fisierul create-example-ssl-stores.bat, carese adapteaza corespunzator iar semnatura generata se depune ın catalogulQPID HOME\etc.

Urmatorul exemplu creaza semnatura data de fisierul qpid.keystore.

1 @REM Create example keys to r e f o r broker and2 @REM t r u s t s t o r e f o r c l i e n t /management conso l e .3 @REM4 @REM Use generated qpid . keys to r e as the broker s keys to r e5 @REM Use generated qpid . t r u s t s t o r e as c l i e n t / c o n s o l e s t r u s t s t o r e6 @REM Al l passwords have v a l u e : password

8 @REM Create Broker Keystore :9 keytoo l −genkey −a l i a s qpidBroker −keya lg RSA −v a l i d i t y 365

10 −keys to r e qpid . keys to r e −s t o r e p a s s password −keypass password11 −dname ”CN=unitbv , OU=cs , O=Org , L=Bv , C=R”

13 @REM Export S e l f Signed Cer t :14 keytoo l −export −a l i a s qpidBroker −keys to r e qpid . keys to r e15 − f i l e qpidBroker . c e r −s t o r e p a s s password

17 @REM Import Broker Cert Into MC Trus tS to r e :18 keytoo l −import −a l i a s qpidBrokerCert − f i l e qpidBroker . c e r19 −keys to r e qpid . t r u s t s t o r e −s t o r e p a s s password −noprompt

21 @REM Delete the c e r t22 de l qpidBroker . c e r

Eventual trebuie fixata locatia fisierului qpid.keystore ın elementul keyStorePathdin fisierul QPID HOME\etc\config.xml.

Serviciul de mesagerie se lanseaza prin

1 s e t JAVA HOME=. . .2 s e t QPID HOME=. . .3 s e t QPID WORK=. . .4 %QPID HOME%\bin \qpid−s e r v e r . bat

Catalogul QPID WORK este utilizat de serviciul de mesagerie pentru consemnarea(logging) evenimentelor, ın catalog fiind prezent un fisier de configurare log4j.xml.

Reluam aplicatiile anterioare privind transmiterea / receptia unui mesaj princomunicatie punctuala utilizand o coada si publicarea si receptionarea unui mesajprin comunicatie bazata pe subiect ıntr-o varianta independententa de suportul mid-dleware de serviciu de mesagerie folosit. Regasirea resurselor gestionate de serviciulde mesagerie sa va face utilizand JNDI. De data asta informatiile necesare regasiriiresurselor sunt dependente de serviciul de mesagerie. Datele de regasire sunt fixateıntr-un fisier jndi.properties1.

1Aplicatiile pot fi executate utilizand oricare din implementarile JMS, schimband doar fisieruljndi.properties.

Page 121: DISTR1

5.6. PROGRAME JMS PRIN APACHE-QPID 121

Comunicatia prin coada - queue

Aplicatia este alcatuita din clasele MsgHelloT, MsgSenderT, SyncMsgReceiverT,AsyncMsgReceiverT, TextListener. Fata de versiunea prezentata se modifica doarclasele MsgSenderT, SyncMsgReceiverT, AsyncMsgReceiverT.

In clasa MsgHelloT campul queueName reprezinta numele JNDI al cozii.Clasa MsgSenderT

1 import javax . jms . ∗ ;2 import javax . naming . ∗ ;3 import java . u t i l . P r o p e r t i e s ;4 import java . i o . ∗ ;

6 public class MsgSenderT extends Thread{7 f ina l St r ing CONNECTION JNDI NAME = ” ConnectionFactory ” ;8 St r ing QUEUE JNDI NAME = ”queue” ;9 private I n i t i a l C o n t e x t ctx ;

10 private int n ;

12 MsgSenderT ( St r ing queueName , int n){13 QUEUE JNDI NAME=queueName ;14 this . n=n ;15 }

17 public void run ( ){18 try{19 setupJNDI ( ) ;20 // lookup the connect ion f a c t o r y21 QueueConnectionFactory c f=22 ( QueueConnectionFactory ) ctx . lookup (CONNECTION JNDI NAME) ;23 Connection conn=c f . c reateConnect ion ( ) ;24 Se s s i on s e s s i o n=conn . c r e a t e S e s s i o n ( false , S e s s i on .AUTOACKNOWLEDGE) ;25 Dest inat i on q=( Des t inat i on ) ctx . lookup (QUEUE JNDI NAME) ;26 closeJNDI ( ) ;27 MessageProducer producer=s e s s i o n . c reateProducer ( q ) ;

29 TextMessage m=s e s s i o n . createTextMessage ( ) ;30 for ( int i =0; i<n ; i ++){31 m. setText ( ” He l lo ”+i ) ;32 producer . send (m) ;33 }34 producer . send ( s e s s i o n . createMessage ( ) ) ;35 s e s s i o n . c l o s e ( ) ;36 conn . c l o s e ( ) ;37 }38 catch ( Exception e ){39 System . out . p r i n t l n ( ”JMSException : ”+e . getMessage ( ) ) ;40 }41 System . out . p r i n t l n ( ” Sender f i n i s h e d ” ) ;42 }

44 private void setupJNDI ( ){45 // Set the p r op e r t i e s . . .46 P r o p e r t i e s p r o p e r t i e s = new P r o p e r t i e s ( ) ;47 try{48 p r o p e r t i e s . load ( this . g e tC la s s ( ) . getResourceAsStream ( ” j n d i . p r o p e r t i e s ” ) ) ;49 }50 catch ( IOException e ){

Page 122: DISTR1

122 CAPITOLUL 5. MESAJE IN JAVA

51 System . out . p r i n t l n ( ”JNDI−Prope r t i e sEr ro r : ”+e . getMessage ( ) ) ;52 }53 // Create the i n i t i a l con tex t54 try{55 ctx = new I n i t i a l C o n t e x t ( p r o p e r t i e s ) ;56 }57 catch ( NamingException e ){58 System . e r r . p r i n t l n ( ” Error Se t t i ng up JNDI Context : ” + e ) ;59 }60 }

62 private void closeJNDI ( ){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 to c l o s e JNDI Context : ” + e ) ;68 }69 }70 }

Clasa SyncMsgReceiverT

1 import javax . jms . ∗ ;2 import javax . naming . ∗ ;3 import java . u t i l . P r o p e r t i e s ;4 import java . i o . ∗ ;

6 public class SyncMsgReceiverT extends Thread{7 f ina l St r ing CONNECTION JNDI NAME = ” ConnectionFactory ” ;8 St r ing QUEUE JNDI NAME = ”queue” ;9 private I n i t i a l C o n t e x t ctx ;

11 SyncMsgReceiverT ( St r ing queueName){12 QUEUE JNDI NAME=queueName ;13 }

15 public void run ( ){16 try{17 setupJNDI ( ) ;18 // lookup the connect ion f a c t o r y19 QueueConnectionFactory c f=20 ( QueueConnectionFactory ) ctx . lookup (CONNECTION JNDI NAME) ;21 Connection conn=c f . c reateConnect ion ( ) ;22 Se s s i on s e s s i o n=conn . c r e a t e S e s s i o n ( false , S e s s i on .AUTOACKNOWLEDGE) ;23 Dest inat i on q=( Des t inat i on ) ctx . lookup (QUEUE JNDI NAME) ;24 closeJNDI ( ) ;

26 MessageConsumer consumer=s e s s i o n . createConsumer ( q ) ;

28 conn . s t a r t ( ) ;29 Message msg=null ;30 while ( ( msg=consumer . r e c e i v e ( ) ) != null ){31 i f (msg instanceof TextMessage ){32 TextMessage m=(TextMessage )msg ;33 System . out . p r i n t l n (m. getText ( ) ) ;34 }35 else {36 break ;37 }

Page 123: DISTR1

5.6. PROGRAME JMS PRIN APACHE-QPID 123

38 }39 s e s s i o n . c l o s e ( ) ;40 conn . c l o s e ( ) ;41 }42 catch ( Exception e ){43 System . out . p r i n t l n ( ”JMSException : ”+e . getMessage ( ) ) ;44 }45 System . out . p r i n t l n ( ”Consumer f i n i s h e d ” ) ;46 }

48 private void setupJNDI ( ) { . . .}

50 private void closeJNDI ( ) { . . .}

52 }

Comunicatia pe baza de subiect - topic

Aplicatia este alcatuita din clasele MsgPS, MsgPublisherT, MsgSubscriberT.Fata de versiunea prezentata se modifica doar clasele MsgPublisherT, MsgSubscrib-erT.

In clasa MsgPS campul subiect reprezinta numele JNDI atasat topic-ului.Clasa MsgPublisherT

1 import javax . jms . ∗ ;2 import javax . naming . ∗ ;3 import java . u t i l . P r o p e r t i e s ;4 import java . i o . ∗ ;

6 public class MsgPublisherT extends Thread{7 f ina l St r ing CONNECTION JNDI NAME = ” ConnectionFactory ” ;8 St r ing TOPIC JNDI NAME = ” t op i c ” ;9 private I n i t i a l C o n t e x t ctx ;

10 private int n ;

12 MsgPublisherT ( St r ing sub iec t , int n){13 this . n=n ;14 TOPIC JNDI NAME=s u b i e c t ;15 }

17 public void run ( ){18 try{19 setupJNDI ( ) ;20 // lookup the connect ion f a c t o r y21 TopicConnectionFactory c f=22 ( TopicConnectionFactory ) ctx . lookup (CONNECTION JNDI NAME) ;23 TopicConnection conn=c f . createTopicConnect ion ( ) ;24 TopicSess ion s e s s i o n=conn . c r ea t eTop i cSe s s i on ( false ,25 Se s s i on .AUTOACKNOWLEDGE) ;26 Dest inat i on t=( Des t inat i on ) ctx . lookup (TOPIC JNDI NAME ) ;27 closeJNDI ( ) ;

29 MessageProducer producer = s e s s i o n . c reateProducer ( t ) ;30 TextMessage m=s e s s i o n . createTextMessage ( ) ;31 for ( int i =0; i<n ; i ++){32 m. setText ( ”Despre JMS”+” ”+i ) ;

Page 124: DISTR1

124 CAPITOLUL 5. MESAJE IN JAVA

33 producer . send (m) ;34 }35 producer . send ( s e s s i o n . createMessage ( ) ) ;36 s e s s i o n . c l o s e ( ) ;37 conn . c l o s e ( ) ;38 }39 catch ( Exception e ){40 System . out . p r i n t l n ( ”JMSException : ”+e . getMessage ( ) ) ;41 }42 System . out . p r i n t l n ( ” Pub l i she r f i n i s h e d ” ) ;43 }

45 private void setupJNDI ( ) { . . .}

47 private void closeJNDI ( ) { . . .}

49 }

Clasa MsgSubscriberT

1 javax . jms . ∗ ;2 import javax . naming . ∗ ;3 import java . u t i l . P r o p e r t i e s ;4 import java . i o . ∗ ;

6 public class MsgSubscriberT extends Thread{7 f ina l St r ing CONNECTION JNDI NAME = ” ConnectionFactory ” ;8 St r ing TOPIC JNDI NAME = ” t op i c ” ;9 private I n i t i a l C o n t e x t ctx ;

10 private St r ing c l i e n t I D ;11 private St r ing cl ientName ;

13 MsgSubscriberT ( St r ing sub iec t , S t r ing c l i en t ID , S t r ing cl ientName ){14 TOPIC JNDI NAME=s u b i e c t ;15 this . c l i e n t I D=c l i e n t I D ;16 this . c l ientName=clientName ;17 }

19 public void run ( ){20 try{21 setupJNDI ( ) ;22 // lookup the connect ion f a c t o r y23 TopicConnectionFactory c f =(24 TopicConnectionFactory ) ctx . lookup (CONNECTION JNDI NAME) ;25 TopicConnection conn=c f . createTopicConnect ion ( ) ;26 //conn . se tC l i en t ID ( c l i en t ID ) ;27 TopicSess ion s e s s i o n=conn . c r ea t eTop i cSe s s i on ( false ,28 Se s s i on .AUTOACKNOWLEDGE) ;29 Dest inat i on t=( Des t inat i on ) ctx . lookup (TOPIC JNDI NAME ) ;30 closeJNDI ( ) ;31 //TopicSubscr iber consumer =32 s e s s i o n . c r ea t eDurab l eSubsc r ibe r ( ( Topic ) t , cl ientName ) ;33 TopicSubscr iber consumer=s e s s i o n . c r e a t e S u b s c r i b e r ( ( Topic ) t ) ;

35 conn . s t a r t ( ) ;36 Message msg=null ;37 while ( ( msg=consumer . r e c e i v e ( ) ) != null ){38 i f (msg instanceof TextMessage ){39 TextMessage m=(TextMessage )msg ;40 System . out . p r i n t l n ( cl ientName+” r e c e i v e d : ”+m. getText ( ) ) ;

Page 125: DISTR1

5.6. PROGRAME JMS PRIN APACHE-QPID 125

41 }42 else43 break ;44 }45 s e s s i o n . c l o s e ( ) ;46 conn . c l o s e ( ) ;47 }48 catch ( Exception e ){49 System . out . p r i n t l n ( ”JMSException : ”+e . getMessage ( ) ) ;50 }51 System . out . p r i n t l n ( ” Subsc r ibe r f i n i s h e d ” ) ;52 }

54 private void setupJNDI ( ) { . . .}

56 private void closeJNDI ( ) { . . .}

58 }

Fisiere JNDI cu datele de regasire

Programele sectiunii anterioare se pot utiliza cu oricare de distributiile JMSOracle-Sun Message Queue, apache-actimemq, qpid.

Fisierele jndi.properties specifice fiecarei distributii suntVarianta qpid :

1 java . naming . f a c t o r y . i n i t i a l =2 org . apache . qpid . j n d i . P r o p e r t i e s F i l e I n i t i a l C o n t e x t F a c t o r y

4 # r e g i s t e r some connect ion f a c t o r i e s5 # connec t i on f a c to ry . [ jndiname ] = [ ConnectionURL ]6 connec t i on f a c to ry . 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 ’

9 # r e g i s t e r some queues in JNDI us ing the form10 # queue . [ jndiName ] = [ physicalName ]11 queue . queue = myqueue

13 # t op i c . [ jndiName ] = [ physicalName ]14 t op i c . t o p i c = mytopic

Varianta ActiveMQ

1 java . naming . f a c t o r y . i n i t i a l =2 org . apache . activemq . j n d i . Act iveMQInit ia lContextFactory

4 # use the f o l l o w i n g property to c o n f i g u r e the d e f a u l t connector5 java . naming . prov ide r . u r l = t c p : // l o c a l h o s t : 6 1 6 1 6

7 # r e g i s t e r some queues in JNDI us ing the form8 # queue . [ jndiName ] = [ physicalName ]9 queue . queue = myqueue

11 # r e g i s t e r some t o p i c s in JNDI us ing the form12 # t op i c . [ jndiName ] = [ physicalName ]13 t op i c . t o p i c = mytopic

Page 126: DISTR1

126 CAPITOLUL 5. MESAJE IN JAVA

Varianta Oracle-Sun Java System Message Queue

1 java . naming . f a c t o r y . i n i t i a l =2 com . sun . j n d i . f s c o n t e x t . RefFSContextFactory3 java . naming . prov ide r . u r l= f i l e : /// c : /Temp

5 # use the f o l l o w i n g property to c o n f i g u r e the d e f a u l t connector

7 # r e g i s t e r some queues in JNDI us ing the form8 # queue . [ jndiName ] = [ physicalName ]9 queue . queue = myqueue

11 # r e g i s t e r some t o p i c s in JNDI us ing the form12 # t op i c . [ jndiName ] = [ physicalName ]13 t op i c . t o p i c = mytopic

In acest caz este nevoie de crearea ın prealabil a obiectelor corespunzatoare conexi-unii, a cozii (queue) si a subiectului (topic). Aceaste obiecte se creaza cu utilitarulimqobjmgr din distributia Oracle-Sun Java System Message Queue.

Obiectele se pot crea cu fisierul de comenzi:

1 s e t PATH=d: \mq\bin ;%PATH%2 imqobjmgr add −t q f − l ” ConnectionFactory ”3 −j java . naming . prov ide r . u r l= f i l e : /// c : /Temp4 −j java . 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 . RefFSContextFactory5 rem imqobjmgr add −t t f − l ” ConnectionFactory ”6 −j java . naming . prov ide r . u r l= f i l e : /// c : /Temp7 −j java . 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 . RefFSContextFactory8 imqobjmgr add −t q − l ”queue”9 −j java . naming . prov ide r . u r l= f i l e : /// c : /Temp

10 −j java . 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 . RefFSContextFactory11 rem imqobjmgr add −t t − l ” t o p i c ”12 −j java . naming . prov ide r . u r l= f i l e : /// c : /Temp13 −j java . 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

Obiectele se pot sterge cu fisierul de comenzi:

1 s e t PATH=d: \mq\bin ;%PATH%2 imqobjmgr d e l e t e −t q f − l ” ConnectionFactory ”3 −j java . naming . prov ide r . u r l= f i l e : /// c : /Temp4 −j java . 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 . RefFSContextFactory5 imqobjmgr d e l e t e −t t f − l ” ConnectionFactory ”6 −j java . naming . prov ide r . u r l= f i l e : /// c : /Temp7 −j java . 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 . RefFSContextFactory8 imqobjmgr d e l e t e −t q − l ”queue”9 −j java . naming . prov ide r . u r l= f i l e : /// c : /Temp

10 −j java . 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 . RefFSContextFactory11 imqobjmgr d e l e t e −t t − l ” t o p i c ”12 −j java . naming . prov ide r . u r l= f i l e : /// c : /Temp13 −j java . 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.7 Protocolul AMQP

Punem ın evidenta un alt model de aplicatie, specific protocolului AMQP.Modelul prevede existenta a trei entitati:

Page 127: DISTR1

5.7. PROTOCOLUL AMQP 127

• exchange – Dispecer de directionare ce primeste mesaje de la un producatorde mesaje si le distribuie unor cozi pe baza unui criteriu;

• message queue – coada ın care se pastreaza mesaje pana ce acestea sunt con-sumate de o aplicatie client.

Proprietatile unei cozi sunt:

– numele, alcatuit din litere, cifre, caracterul de subliniere, cel mult 255 decaracter.

– persistenta mesajului ın cazul ıncetarii functionarii serverului (durablemessage queue, temporary message queue).

– modul de stergere a mesajelor dupa consumarea acestora (auto-delete).

• binding – criteriul dupa care un mesaj este distribuit de dispecerul de mesajeunei cozi.

O coada comunica dispecerului de directionare o cheie denumita cheie de legare(binding key) K, ın timp ce orice mesaj va contine o cheie de rutare (routing key)R.

AMPQ defineste trei criterii de distribuire a mesajelor de catre dispecerul dedirectionare:

• distribuirea directa realizeaza o distribuire 1:1 a mesajelor:

1. o coada se leaga de dispecerul de directionare cu cheia de legare K;

2. un mesaj contine cheia de rutare R;

3. dispecerul de directionare trimite mesajul catre toate cozile care satisfacconditia R = K.

• distribuirea fanout realizeaza o distribuire 1:N a mesajelor:

1. o coada se leaga de dispecerul de directionare fara cheie de legare;

2. un mesaj nu contine cheie de rutare (eventual cheia de rutare este negli-jata);

3. dispecerul de directionare trimite neconditional mesajul catre toate cozileınregistrate.

• distribuirea publicare-abonare

1. o coada se leaga de dispecerul de directionare cu cheia de legare K;

2. un mesaj contine cheia de rutare R;

Page 128: DISTR1

128 CAPITOLUL 5. MESAJE IN JAVA

3. dispecerul de directionare trimite mesajul catre toate cozile a caror cheiede legare se potriveste cu cheia de rutare.

Cheia de legare este alcatuita din mai multe cuvinte (token) separate decaracterul ’.’ (punct). Cheia de rutare poate contine caracterele

– # - va presupune potrivirea cu un cuvant sau nu.

– * - va presupune potrivirea cu cel putin un cuvant.

Astfel *.abc se potriveste cu x.abc dar nu se potriveste cu abc, ın timpce #.abc se potriveste cu x.abc si abc.

Corespunzator celor trei criterii de distribuire a mesajelor, serverul AMQP continedispecerii de directionare

• amq.direct

• amq.fanout

• amq.topic

Un mesaj este expediat de client catre un dispecer de directionare aflat pe unserver AMQP. Preluarea unui mesaj dintr-o coada de catre un client are ca urmarestergerea mesajului ın coada.

Resursele necesare apartin pachetului org.apache.qpid.transport.

5.7.1 Crearea unei cozi

Crearea unei cozi consta din

1. Realizarea conexiunii cu serverul AMQP

Connection con = new Connection();

con.connect(broker,port,login,passworg,clientId,false);

2. Instantierea sesiunii

Session session = con.createSession(0);

3. Declararea cozii

session.queueDeclare(numeCoada, null, null);

session.exchangeBind(numeCoada, dispecerulDeDirectionare,

binding_key, null);

4. Asteptarea confirmarii actiunii de realizare a cozii

Page 129: DISTR1

5.7. PROTOCOLUL AMQP 129

session.sync();

5. Inchiderea sesiunii si a conexiunii

session.close();

con.close();

Exemplul 5.7.1 Crearea unei cozi care sa primeasca mesaje prin distribuire directasi fanout.

1 import org . apache . qpid . t r anspo r t . ∗ ;

3 public class DeclareQueue{4 public stat ic void main ( St r ing [ ] a rgs ){5 i f ( args . length <5){6 System . out . p r i n t l n ( ”Usage java DeclareQueue broker ” +7 ” port queueName exchange bindingKey ” ) ;8 System . e x i t ( 1 ) ;9 }

10 St r ing broker=args [ 0 ] ;11 int port=I n t e g e r . pa r s e In t ( args [ 1 ] ) ;12 St r ing queueName=args [ 2 ] ;13 St r ing exchange=args [ 3 ] ;14 St r ing bindingKey=args [ 4 ] ;

16 // Crearea conex iun i i17 Connection con = new Connection ( ) ;18 con . connect ( broker , port , ” t e s t ” , ” guest ” , ” guest ” , fa l se ) ;

20 // Crearea s e s i u n i i21 Se s s i on s e s s i o n = con . c r e a t e S e s s i o n ( 0 ) ;

23 // Declararea c o z i i24 s e s s i o n . queueDeclare (queueName , null , null ) ;25 s e s s i o n . exchangeBind (queueName , exchange , bindingKey , null ) ;

27 // Confirmarea c r e e r i i c o z i i28 s e s s i o n . sync ( ) ;

30 // Inch iderea s e s i u n i i s i a conex iun i i31 s e s s i o n . c l o s e ( ) ;32 con . c l o s e ( ) ;33 }34 }

5.7.2 Expedierea / publicarea unui mesaj

Expedierea / publicarea unui mesaj consta din

1. Realizarea conexiunii cu serverul AMQP

Connection con = new Connection();

con.connect(broker,port,login,passworg,clientId,false);

Page 130: DISTR1

130 CAPITOLUL 5. MESAJE IN JAVA

2. Instantierea sesiunii

Session session = con.createSession(0);

3. Precizarea (daca este nevoie) a cheii de rutare

DeliveryProperties deliveryProps = new DeliveryProperties();

deliveryProps.setRoutingKey(routing_key);

4. Crearea si expedierea mesajului

session.messageTransfer(dispecerulDeDirectionare,

MessageAcceptMode.EXPLICIT,

MessageAcquireMode.PRE_ACQUIRED,

new Header(deliveryProps),

mesaj_text);

5. Asteptarea confirmarii receptiei mesajului decatre serverul AMQP

session.sync();

6. Inchiderea sesiunii si a conexiunii

session.close();

con.close();

Exemplul 5.7.2 Expedierea unui numar de mesaje cu continut text, urmat de unmesaj fara continut, fapt care marcheaza sfarsitul trimiterii de date.

1 import org . apache . qpid . t r anspo r t . ∗ ;

3 public class Sender{4 public stat ic void main ( St r ing [ ] a rgs ){5 i f ( args . length <5){6 System . out . p r i n t l n ( ”Usage java Sender broker port ” +7 ” exchange routingKey messagesNumber” ) ;8 System . e x i t ( 1 ) ;9 }

10 St r ing broker=args [ 0 ] ;11 int port=I n t e g e r . pa r s e In t ( args [ 1 ] ) ;12 St r ing exchange=args [ 2 ] ;13 St r ing routingKey=args [ 3 ] ;14 int n=I n t e g e r . pa r s e In t ( args [ 4 ] ) ;

16 // Crearea conex iun i i17 Connection con = new Connection ( ) ;18 con . connect ( broker , port , ” t e s t ” , ” guest ” , ” guest ” , fa l se ) ;

Page 131: DISTR1

5.7. PROTOCOLUL AMQP 131

20 // Crearea s e s i u n i i21 Se s s i on s e s s i o n = con . c r e a t e S e s s i o n ( 0 ) ;

23 // Prec izarea ( daca e s t e nevoie ) a c h e i i de ru tare24 D e l i v e r y P r o p e r t i e s de l i v e ryProps = new D e l i v e r y P r o p e r t i e s ( ) ;25 de l i ve ryProps . setRoutingKey ( routingKey ) ;

27 // Formarea s i exped ierea mesaje lor28 for ( int i =0; i<n ; i ++){29 s e s s i o n . messageTransfer ( exchange ,30 MessageAcceptMode . EXPLICIT ,31 MessageAcquireMode .PRE ACQUIRED,32 new Header ( de l i v e ryProps ) ,33 ”Message ” + i ) ;34 }35 s e s s i o n . messageTransfer ( exchange ,36 MessageAcceptMode . EXPLICIT ,37 MessageAcquireMode .PRE ACQUIRED,38 new Header ( de l i v e ryProps ) ,39 ”” ) ;

41 // Confirmarea r e c e p t i e i mesaje lor42 s e s s i o n . sync ( ) ;

44 // Inch iderea s e s i u n i i s i a conex iun i i45 s e s s i o n . c l o s e ( ) ;46 con . c l o s e ( ) ;47 }48 }

5.7.3 Receptionarea mesajelor

Mesaje se receptioneaza asincron, adica de o clasa ascultatoare care implementeazainterfata SessionListener.

Interfata SessionListener declara metodele:

public void opened(Session session)

public void resumed(Session session)

public void message(Session session, MessageTransfer xfr)

public void exception(Session session, SessionException e)

public void closed(Session session)

Receptionarea de mesaje consta din

1. Realizarea conexiunii cu serverul AMQP

Connection con = new Connection();

con.connect(broker,port,login,passworg,clientId,false);

2. Instantierea sesiunii

Session session = con.createSession(0);

Page 132: DISTR1

132 CAPITOLUL 5. MESAJE IN JAVA

3. Precizarea ascultatorului de mesaje (Fie Listener o clasa care implementeazainterfata SessionListener)

Listener listener = new Listener();

session.setSessionListener(listener);

4. Crearea abonatului care urmeaza sa receptioneaze mesaje. Ascultatorul va ficaracterizat de un nume - listener destination.

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

5. Asteptarea confirmarii trimiterii tuturor mesajelor disponibile de catre serverulAMQP

session.sync();

6. Oprirea ascultatorului

session.messageCancel("listener_destination");

7. Inchiderea sesiunii si a conexiunii

session.close();

con.close();

Exemplul 5.7.3 Receptia mesajelor expediate ın clasa Sender, creata anterior. Pro-gramul se va termina ın momentul ın care ascultatorul primeste un mesaj faracontinut.

1 import org . apache . qpid . t r anspo r t . ∗ ;

3 class 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=fa l se ;

6 public void opened ( Se s s i on s e s s i o n ){}7 public void resumed ( Se s s i on s e s s i o n ){}

Page 133: DISTR1

5.7. PROTOCOLUL AMQP 133

8 public void message ( Se s s i on s e s s i on , MessageTransfer x f r ){9 System . out . p r i n t l n ( ”Message : ” + x f r ) ;

10 St r ing sMsg=x f r . t oS t r i ng ( ) ;11 i f ( sMsg . endsWith ( ”body=\”\”” ) ) s f a r s i t=true ;12 }13 public void except ion ( Se s s i on ssn , Ses s ionExcept ion e ){14 System . out . p r i n t l n ( ” Se s s i onL i s t ene rExcep t i on : ”+e . getMessage ( ) ) ;15 }16 public void c l o s e d ( Se s s i on s e s s i o n ) {}

18 public void run ( ){19 while ( ! s f a r s i t ) ;20 }21 }

23 public class Rece iver {24 public stat ic void main ( St r ing [ ] a rgs ) throws Inte r ruptedExcept ion {25 i f ( args . length <3){26 System . out . p r i n t l n ( ”Usage java Sender broker port queueName” ) ;27 System . e x i t ( 1 ) ;28 }29 St r ing broker=args [ 0 ] ;30 int port=I n t e g e r . pa r s e In t ( args [ 1 ] ) ;31 St r ing queueName=args [ 2 ] ;

33 // Crearea conex iun i i34 Connection con = new Connection ( ) ;35 con . connect ( broker , port , ” t e s t ” , ” guest ” , ” guest ” , fa l se ) ;

37 // Crearea s e s i u n i i38 Se s s i on s e s s i o n = con . c r e a t e S e s s i o n ( 0 ) ;

40 // Generarea unei i n s t an t e a a s c u l t a t o r u l u i41 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 s e s s i o n . s e t S e s s i o n L i s t e n e r ( l i s t e n e r ) ;

44 // Crearea abona tu lu i care recep t i oneaze mesaje le45 s e s s i o n . messageSubscr ibe (queueName ,46 ” l i s t e n e r d e s t i n a t i o n ” ,47 MessageAcceptMode .NONE,48 MessageAcquireMode .PRE ACQUIRED,49 null , 0 , null ) ;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 MessageCreditUnit .BYTE, Se s s i on .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 MessageCreditUnit .MESSAGE, 1 1 ) ;

55 // Confirmarea t e rminar i i t r an sm i t e r i i mesa je lor56 s e s s i o n . sync ( ) ;

58 // Abonatul a s t eap ta recep t ionarea tu turor mesaje lo59 l i s t e n e r . run ( ) ;

61 // Oprirea a s c u l t a t o r u l u i62 System . out . p r i n t l n ( ” Shutt ing 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 // Inch iderea s e s i u n i i s i a conex iun i i66 s e s s i o n . c l o s e ( ) ;

Page 134: DISTR1

134 CAPITOLUL 5. MESAJE IN JAVA

67 con . c l o s e ( ) ;68 }69 }

Utilizand clasele prezentate mai sus, prin fixarea convenabila a parametrilor sia ordinii de lansare a programelor se poate exemplifica specificul celor trei dispeceride directionare:

Codurile pentru executie prin ant sunt

• Distribuirea directa:

<target name="run" depends="compile">

<java classname="DeclareQueue" fork="yes" maxmemory="100M">

<classpath refid="qpid.classpath" />

<arg line="localhost 5672 message_queue amq.direct routing_key"/>

</java>

<sleep seconds="15" />

<java classname="Sender" fork="yes" maxmemory="100M">

<classpath refid="qpid.classpath" />

<arg line="localhost 5672 amq.direct routing_key 5"/>

</java>

<sleep seconds="5" />

<java classname="Receiver" fork="yes" maxmemory="100M">

<classpath refid="qpid.classpath" />

<arg line="localhost 5672 message_queue"/>

</java>

</target>

• 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">

Page 135: DISTR1

5.7. PROTOCOLUL AMQP 135

<classpath refid="qpid.classpath" />

<arg line="localhost 5672 q2"/>

</java>

</parallel>

</target>

• Distribuirea bazata pe publicare-abonare:

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

In cazul distribuirii fanout si a celei bazate pe publicare-abonare sunt lansate ınordine doua cozi cu cate un receptor de mesaje (Receiver) urmat de producatorulde mesaje (Sender).

Page 136: DISTR1

136 CAPITOLUL 5. MESAJE IN JAVA

Page 137: DISTR1

Capitolul 6

Servlet

Printre aplicatiile distribuite de tip client-server, ın care comunicatiile se bazeazape protocolul http, se disting

• Aplicatii Web (site): Cererea adresata serverului este lansata de o persoanaprin intermediul unui site, utilizand un program navigator: Google Chrome,Mozilla Firefox, Opera, Microsoft InternetExplorer, Apple Safari, etc.

• Servicii Web: Cererea catre server se face de un program.

Un servlet este un program Java care se excuta pe un server Web, compatibil, sieste capabil sa rapunda cererilor formulate de clienti.

Programarea si utilizarea unui servlet necesita:

• Cunoasterea marcajului html <form> pentru realizarea formularelor de in-troducere a datelor;

• Utilizarea unui server Web, container de servleti.

6.1 Marcajul <form>

Intr-un document html introducerea datelor se poate obtine utilizand marcajul<form> ...</form> .

Atribute ale marcajului <form> . Reamintim ca atributele se prezinta caperechi (nume, valoare) si se scriu ın antetul marcajului sub forma nume = valoare.

137

Page 138: DISTR1

138 CAPITOLUL 6. SERVLET

Nume Valoare Semnificatia valorii

action adresa tip URL Resursa care prelucreaza formularul.

method GET Mesajul trimis serverului Web contine dupaadresa URL numele si valorile parametrilor

introdusi. Adaugarea se face potrivit sintaxei?numeParam1=valoare&numeParam2=valoare. . .

Lungimea mesajului nu poate depasi 255 caractere.POST Transmisia datelor se face ın fluxuri de date.

Permite transferul unor fisiere de pe masinaclientului pe masina serverului.

id Parametru de identificare a formularului (optional).

name Nume atribuit formularului (optional).

onSubmit Metoda JavaScript executata ınaintea apelariiserverului Web (optional).

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

• <input>

• <option>

• <select>

• <textarea>

Atributele marcajului < input> sunt:

Nume Valoare Semnificatie

type text Se asteapta introducerea unui textpassword Se asteapta introducerea unei parolesubmit Se marcheaza sfarsitul completarii formularuluireset Se reinitializeaza formularulfile Permite selectarea unui fisierhidden Transmite mai departe un atribut fara vizualizarea lui

name numele controlului

value valoarea (initiala) a controlului

size numarul caracterelor atasat controlului

In cazul marcajului < select> utilizarea este

<select name="nume">

<option value="valoare"> Valoare

. . . . . . . . . . . . . . . .

</select>

Page 139: DISTR1

6.2. SERVER WEB - CONTAINER DE SERVLET 139

Valoarea atributului nume este data de valoarea selectata.

6.2 Server Web - container de servlet

In prezent sunt disponibile mai multe servere Web ın care poate fi instalat unservlet si un fisier JSP Java Server Pages. Se spune ca serverul Web este containerde servlet si JSP. Dintre produsele gratuite amintim

• apache-tomcat

• jetty

• Oracle-Sun Java System Application Server

Acest server Web este utilizat ın Glassfish - o implementare JEE (Java Enter-prise Edition).

• JBoss

Geronimo, o alta implementare JEE dezvoltata de apache, poate utiliza con-tainerul apache-tomcat sau jetty.

Serverul Web apache-tomcat

In continuare se va folosi serverul Web apache-tomcat, pe scurt tomcat.Serverul Web tomcat este distribuit gratuit, putand fi descarcat de la adresa

www.apache.org.

Instalarea serverului ın mediul Windows revine la dezarhivarea fisieruluidescarcat apache-tomcat-***, ıntr-un catalog TOMCAT HOME. Utilizarea serveruluinecesita fixarea a doi parametri sistem:

• CATALINA HOME= calea la catalogul ın care s-a instalat produsul - TOMCAT HOME;

• JAVA HOME=calea la distributia Java utilizata.

Pachetul contine cataloagele1: bin, common, conf, logs, server, shared, temp,

webapps, work.

Serverul se lanseaza prin comanda

TOMCAT HOME\bin\startup

si se opreste cu comanda

TOMCAT HOME\bin\shutdown1Numele si numarul cataloagelor este dependent de distributia apache-tomcat.

Page 140: DISTR1

140 CAPITOLUL 6. SERVLET

Din catalogul TOMCAT HOME, lansarea se poate obtine cu ajutorul fisierului decomenzi (*.bat)

set CATALINA_HOME=. . .

set JAVA_HOME=. . .

bin\startup

Optional se poate instala / activa managerul / administatorul serverului Web tom-cat.

Verificarea functionarii serverului Web tomcat se face apeland dintr-un navigatorpagina http://host:port unde

• host este numele calculatorului pe care ruleaza tomcat;

• Portul implicit este 8080.

Reusita este ilustrata de imaginea motanului

6.3 Realizarea unui servlet

6.3.1 Instalarea unui servlet

Pentru un servlet, ın catalogul webapps, se creaza un subcatalog, de exempluapphello continand

apphello

| |---> WEB-INF

| | |---> classes

| | | web.xml

Catalogul classes contine fisierele .class ale servletului iar fisierul web.xmlfurnizeaza serverului web informatii de acces la servlet. Astfel

1. In elementul <servlet> se leaga numele servlet-ului definit ın elementul<servlet-name> de clasa servlet-ului dat ın elementul<servlet-class> .

2. In elementul <servlet-mapping> se defineste numele sub care servlet-ul iden-tificat prin <servlet-name> nume servlet< /servlet> se invoca din pro-gramul navigator. Acest identificator - numeApel - se fixeaza ın elementul<url-pattern> . Identificatorul are ca prefix caracterul / (slash).

Page 141: DISTR1

6.3. REALIZAREA UNUI SERVLET 141

Structura unui fisier web.xml este

1 <web−app>2 <s e r v l e t>3 <s e r v l e t−name>nume se rv l e t 1</ s e r v l e t−name>4 <s e r v l e t−c l a s s>Nume clasa</ s e r v l e t−c l a s s>5 </ s e r v l e t>6 <s e r v l e t>7 <s e r v l e t−name>nume se rv l e t 2</ s e r v l e t−name>8 <s e r v l e t−c l a s s>Nume clasa</ s e r v l e t−c l a s s>9 </ s e r v l e t>

10 . . .11 <s e r v l e t−mapping>12 <s e r v l e t−name>nume se rv l e t 1</ s e r v l e t−name>13 <ur l−pattern>/numeApel 1</ ur l−pattern>14 </ s e r v l e t−mapping>15 <s e r v l e t−mapping>16 <s e r v l e t−name>nume se rv l e t 2</ s e r v l e t−name>17 <ur l−pattern>/numeApel 2</ ur l−pattern>18 </ s e r v l e t−mapping>19 . . .20 </web−app>

Optional web.xml poate contine elementul

<welcome-file-list>

<welcome-file>

fisier.html sau jsp

</welcome-file>

</welcome-file-list>

cu precizarea fisierelor html sau jsp care lanseaza servletul. Declaratia fisieruluiindex.html este implicita.

Daca servlet-ul necesa alte resurse - fisiere jar, atunci acestea se depun ıntr-unsubcatalog lib ın WEB-INF.

O alta varianta de instalare a unui servlet, de exemplu reprezentat prin clasaHelloServlet.class, ın serverul Web tomcat consta din:

1. Se creaza oriunde structura de cataloage si fisiere

apphello

| |---> WEB-INF

| | |---> classes

| | | | HelloServlet.class

| | | web.xml

2. Din catalogul apphello se realizeaza arhiva apphello.war

jar cfv apphello.war WEB-INF\∗care se copiaza ın catalogul TOMCAT HOME\webapps.

Page 142: DISTR1

142 CAPITOLUL 6. SERVLET

3. Se porneste serverul tomcat, operatie ın urma careie arhiva este dezarhivata.Astfel servlet-ul este instalat.

Daca serverul tomcat este pornit atunci arhiva se dezarhiveaza automat siservlet-ul este gata de utilizare. Aceasta instalare se numeste instalare di-namica - hot deployment.

Daca fisierul war este creat, atunci ın locul copierii, instalarea se poate face princomponenta manager a lui tomcat.

O alta posibilitate de instalare a unui servlet ın serverul web tomcat este prinintermediul produsului apache-tomcat-deployer. apache-tomcat-deployer permite in-stalarea unui servlet de la distanta cat si instalarea comandata dintr-un program.

apache-tomcat-*.*.*-deployer se instaleaza prin dezarhivarea fisierului apache-tomcat-*.*.*-deployer.Posibilitatile oferite de apache-tomcat-*.*.*-deployer se obtin ruland ant cu un fisierul build.xml din

distributia produsului. Obiectivele care pot fi atinse sunt

• compilarea unui servlet - compile

• instalarea unui servlet - deploy

• dezinstalarea unui servlet - undeploy

In prealabil trebuie completat fisierul de proprietati deployer.properties cu

• build=catalogul care va contine rezultatul compilarii si al arhivarii.

• webapp=catalogul cu sursa servlet-ului.

• path=/catalog-ul servlet-ului.

• url=url-ul aplicatiei manager din Tomcat

http://host:8080/manager

• username=numele de acces ın manager-ul din Tomcat.

• password=parola pentru manager-ul din Tomcat.

Sursa servlet-ului are structura obisnuita, precizata anterior.

6.3.2 Compilarea si apelarea unui servlet

Compilarea unui program necesita completarea variabilei de mediu classpath

cu fisierul TOMCAT HOME\. . .\servlet-api.jar din distributia tomcat. Pozitiafisierului depinde de versiunea apache-tomcat utilizata.

Un servlet se lanseaza ın executie (se apeleaza) din

• meniul File/Open a unui program navigator prin

http://host:port/context/numeApel

Page 143: DISTR1

6.3. REALIZAREA UNUI SERVLET 143

unde

– context este dat de numele catalogului ce contine servlet-ul - ın exemplulanterior acesta este apphello.

– portul implicit este 8080.

– numeApel este identificatorul fixat ın marcajul url-pattern din fisierulweb.xml.

• ca o referinta dintr-un document html

<a href="http://host:port/context/numeApel "> ...</a>

• ca valoare a atributului action ıntr-un marcaj form

<form action="http://host:port/context/numeApel” ... >

Contextul este legat de fisierul web.xml si poate contine o multime de servleti, fiecareidentificandu-se prin numeApel.

Daca context-ul servletului contine fisierul index.html atunci aplicatia se poateapela prin http:// host:port/context.

Daca este prezent elementul <welcome-file-list> ın fisierul web.xml atunciapelarea aplicatiei poate fi http:// host:port/context/fisier.html—jsp, unde fisier.htmlsau jsp este unul din fisierele declarate ıntr-un element <welcome-file> .

6.3.3 Codul unui servlet

Clasele care asigura functionalitatea servlet-ului nu fac parte din distributia JDK,ele sunt cuprinse ın distributia serverului Web.

Un servlet implementeaza interfata Servlet sau extinde una din clasele GenericServletsau HttpServlet. GenericServlet implementeaza interfata Servlet, iar HttpServletextinde clasa GenericServlet. Extinzand clasa GenericServlet nu este nevoie derescrierea tuturor metodelor abstracte ale intrefetei Servlet.

Metodele interfetei Servlet sunt

• abstract public void init(ServletConfig config)

Se apeleaza o singura data la lansarea servlet-ului.

• abstract public void service(ServletRequest req, ServletResponse res)throwsServletException,IOException

Metoda este apelata de serverul Web pentru rezolvarea cererii unui client.

Page 144: DISTR1

144 CAPITOLUL 6. SERVLET

• abstract public void destroy()

Se apeleaza o singura data la distrugerea servlet-ului.

• public String getServletInfo()

• public ServletConfig getServletConfig()

In cele ce urmeaza un servlet va fi o clasa care extinde clasa HttpServlet. Inlocul metodei service(...), programatorul suprascrie metodele doGet(...) saudoPost(...), ın functie de metoda utilizata de client la lansarea cererii.

Practic, un servlet consta din scrierea metodelor

• void init(ServletConfig config)

Aceasta metoda este optionala.

public void init(ServletConfig config) throws ServletException{

super.init(config);

// cod de initializare

}

Obiectul config are o metoda String getInitParameter(String numeParam)

cu ajutorul careia se pot recupera parametri de initializare asociati servletuluisi care se dau ın fisierul web.xml prin marcajele

<init-param>

<param-name> NumeleParametrului </param-name>

<param-value> Valoare </param-value>

</init-param>

cuprinse ın marcajul <servlet>.

• protected void doGet(HttpServletRequest req, HttpServletResponse res)throws IOException, ServletException

Trateaza o cerere trimisa cu metoda GET (vezi marcajul <form>).

• protected void doPost(HttpServletRequest req, HttpServletResponse res)throws IOException, ServletException

Trateaza o cerere trimisa cu metoda POST (vezi marcajul <form>).

Activitatile de ıntreprins ıntr-o metoda doGet() sau doPost() sunt

1. Stabilirea naturii raspunsului:res.setContentType(String tip)

unde tip specifica tipul MIME - Multipurpose Internet Mail Extensions alraspunsului:

Page 145: DISTR1

6.3. REALIZAREA UNUI SERVLET 145

• "text/html" - pagina html;

• "text/xml" - document xml;

• "text/plain" - text;

• "image/jpg" - imagine gif;

• "image/gif" - imagine jpg.

2. Se obtine o referinta catre un obiect care realizeaza transmisia datelor catrenavigatorul clientului:ServletOutputStream out = res.getOutputStream();

sauPrintWriter out=res.getWriter();

3. Se preiau datele cererii cu una din metodele:String getParameter(String numeParapetru)java.util.Enumeration getParameterNames()

4. Rezolva cererea clientului;

5. Formeaza si scrie raspunsul;

6. Inchide conexiunea obiectului prin care s-a realizat transmisia datelor catrenavigatorul clientului prin out.close().

Un utilizator lanseaza o cerere catre servlet. De obicei acest lucru se realizeazaprin completarea unui formular al unui document html. Programul navigator trimitecererea serverului Web prin intermediul caruia este lansat servlet-ul ın actiune.

Ciclul de viata al unui servlet. Cand un servlet este apelat prima data decatre serverul Web se executa metoda init. Dupa aceasta, fiecarei cereri lansate deun utilizator i se asociaza un fir de executie ın care se apeleaza metoda service.Metoda service apeleaza apoi metodele doGet(), doPost().

Exemplul 6.3.1 Servletul Hello: Clientul transmite numele servet-ului care ıi raspundecu mesajul de salut ”Hi” + nume!.

Formularul html prin care clientul introduce numele este (index.html)

1 <html>2 <head>3 <t i t l e> Serv l e t−ul He l lo </ t i t l e>4 </head>5 <body>6 <center>7 <h1> Pagina de ape l a r e a s e r v l e t u l u i H e l l o S e r v l e t </h1>8 <form method=” post ”9 action=” http :// l o c a l h o s t :8080/ apphe l l o / h e l l o ”>

10 <p>I n t r o d u c e t i numele :11 <input type=” text ” name=”name” s ize=20>

Page 146: DISTR1

146 CAPITOLUL 6. SERVLET

12 <p>13 <input type=”submit”>14 </form>15 </center>16 </body>17 </html>

Servlet-ului are codul

1 import java . i o . ∗ ;2 import javax . s e r v l e t . ∗ ;3 import javax . s e r v l e t . http . ∗ ;

5 public class H e l l o S e r v l e t extends HttpServ l e t {6 public void doGet ( HttpServ letRequest req , HttpServletResponse r e s )7 throws Serv le tExcept ion , IOException{8 r e s . setContentType ( ” text /html” ) ;9 ServletOutputStream out=r e s . getOutputStream ( ) ;

10 St r ing nume=req . getParameter ( ”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 >He l l oSe rv 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>He l l oSe rv 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 }

23 public void doPost ( HttpServ letRequest req , HttpServletResponse r e s )24 throws Serv le tExcept ion , IOException{25 doGet ( req , r e s ) ;26 }27 }

Fisierul web.xml pentru acest exemplu este

1 <?xml version=” 1 .0 ” encoding=”ISO−8859−1”?>

3 < !DOCTYPE web−app4 PUBLIC ”−//Sun Microsystems , Inc . //DTD Web Appl i ca t ion 2 .3//EN”5 ” h t tp : // java . sun . com/dtd/web−app 2 3 . dtd”>

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 <ur l−pattern>/ h e l l o</ ur l−pattern>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>index . html</welcome− f i l e>18 </welcome− f i l e − l i s t>19 </web−app>

Page 147: DISTR1

6.3. REALIZAREA UNUI SERVLET 147

Compilarea si arhivarea servlet-ului o vom realiza prin intermediul lui apache-ant. In acest scop se creaza structura:

hello

| |---> src

| | | HelloServlet.java

| |---> lib

| |---> web

| | | web.xml

| |---> web-files

| | | index.html

| build.xml

si se utilizeaza fisierul build.xml

1 <p r o j e c t ba s ed i r=” . ” default=” generate . war”>

3 <property name=”TOMCATHOME” value=” . . . / apache−tomcat −∗ .∗ .∗ ”/>4 <property name=” d i s t . name” value=” apphe l l o ” />5 <property name=” d i s t . d i r ” va lue=” d i s t ” />6 <property name=” bu i ld . d i r ” va lue=” bu i ld ”/>

8 <path id=” myclasspath ”>9 < f i l e s e t d i r=” l i b ”>

10 <i n c l ude name=” ∗ . j a r ”/>11 </ f i l e s e t>12 <pathelement path=”${TOMCATHOME}/ l i b / s e r v l e t−api . j a r ” />13 </path>

15 <t a r g e t name=” i n i t ”>16 <d e l e t e d i r=”${ d i s t . d i r }”/>17 <mkdir d i r=”${ bu i ld . d i r }”/>18 <mkdir d i r=”${ d i s t . d i r }” />19 <mkdir d i r=”${ bu i ld . d i r }/WEB−INF” />20 <mkdir d i r=”${ bu i ld . d i r }/WEB−INF/ c l a s s e s ” />21 <mkdir d i r=”${ bu i ld . d i r }/WEB−INF/ l i b ” />22 </ t a r g e t>

24 <t a r g e t name=” compile ” depends=” i n i t ”>25 <javac c l a s s p a t h r e f=” myclasspath ”26 s r c d i r=”${ based i r }/ s r c ”27 d e s t d i r=”${ bu i ld . d i r }/WEB−INF/ c l a s s e s ” />28 </ t a r g e t>

30 <t a r g e t name=” generate . war” depends=” compile ”>31 <copy t o d i r=”${ bu i ld . d i r }” >32 < f i l e s e t d i r=”${ based i r }/web− f i l e s ” >33 <i n c l ude name=” ∗ . html” />34 </ f i l e s e t>35 </copy>36 <copy t o d i r=”${ bu i ld . d i r }/WEB−INF” f i l e=”${ based i r }/web/web . xml”/>37 <copy t o d i r=”${ bu i ld . d i r }/WEB−INF/ l i b ” >38 < f i l e s e t d i r=”${ based i r }/ l i b ” >39 <i n c l ude name=” ∗ . j a r ” />40 </ f i l e s e t>41 </copy>42 < j a r d e s t f i l e=”${ d i s t . d i r }/${ d i s t . name } . war” bas ed i r=”${ bu i ld . d i r }” />43 </ t a r g e t>44 </ p r o j e c t>

Page 148: DISTR1

148 CAPITOLUL 6. SERVLET

Observatie. Valoarea parametrului dist.name trebuie sa coincida cu numele cata-logului ın atributul action a elementului form, din documentul index.html.

In cazul exemplului de fata, catalogul lib este gol. Daca aplicatia solicita resurseexterne, continute ın fisierele jar, atunci aceste fisiere se depun ın catalogul lib.

Se lanseaza ın executie serverul Web tomcat, se ıncarca servlet-ul ın serverul Websi dintr-un navigator se deschide pagina http://localhost:8080/apphello

Exemplul 6.3.2 Servlet pentru calculul celui mai mare divizor comun a doua nu-mere.

1 import java . i o . ∗ ;2 import javax . s e r v l e t . ∗ ;3 import javax . s e r v l e t . http . ∗ ;

5 public class CmmdcServlet extends HttpServ l e t {

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

9 public void doGet ( HttpServ letRequest req , HttpServletResponse r e s )10 throws Serv le tExcept ion , IOException{11 St r ing sm=req . getParameter ( ”m” ) , sn=req . getParameter ( ”n” ) ;12 St r ing t i p=req . getParameter ( ” t i p ” ) ;13 long m=Long . parseLong (sm) , n=Long . parseLong ( sn ) ;14 long x=cmmdc(m, n ) ;15 PrintWriter out=r e s . getWriter ( ) ;16 i f ( t i p . equa l s ( ” t ext /html” ) ){17 St r ing t i t l e=”CmmdcServlet” ;18 r e s . setContentType ( ” text /html” ) ;19 out . p r i n t l n ( ”<HTML><HEAD><TITLE>” ) ;20 out . p r i n t l n ( t i t l e ) ;21 out . p r i n t l n ( ”</TITLE></HEAD><BODY>” ) ;22 out . p r i n t l n ( ”<H1>”+t i t l e+”</H1>” ) ;23 out . p r i n t l n ( ”<P>Cmmdc i s ”+x ) ;24 out . p r i n t l n ( ”</BODY></HTML>” ) ;25 }26 else {27 r e s . setContentType ( ” text / p l a i n ” ) ;28 out . p r i n t l n ( x ) ;29 }30 out . c l o s e ( ) ;31 }

33 public void doPost ( HttpServ letRequest req , HttpServletResponse r e s )34 throws Serv le tExcept ion , IOException{35 doGet ( req , r e s ) ;36 }37 }

apelabil prin documentul html (index.html)

1 <html>2 <body>3 <form method=” get ”4 action=” http :// l o c a l h o s t :8080/ myserv let /cmmdc”>5 <p>Primul numar e s t e <input type=” text ” name=”m” s ize=5>

Page 149: DISTR1

6.4. FACILITATI DE PROGRAMARE CU SERVLET 149

6 <p>Al d o i l e a numar e s t e <input type=” text ” name=”n” s ize=5>7 <p><input type=”submit” value=” Calcu leaza ”>8 <input type=” hidden ” name=” t i p ” value=” text /html” >9 </form>

10 </body>11 </html>

Pentru fixarea naturii raspunsului text/html sau text/plain s-a introdus variabilatip, care ın fisierul de invocare index.html primeste pe ascuns valoarea text/html.

In cazul ın care vom apela servlet-ul dintr-un program, va fi avantajos sa primimraspunsul ca text/plain.

6.4 Facilitati de programare cu servlet

6.4.1 Program client al unui servlet

Apelarea unui servlet dintr-un program Java – adica lansarea unei cereri sireceptionarea raspunsului furnizat de servlet – se poate obtine cu produsul httpcomponents-client dezvoltat de apache.

Intr-un asemenea caz, din punctul de vedere al clientului este mai avantajos caraspunsul servlet-ului fie text/plain, ın loc de text/html.

Catalogul lib din httpcomponents-client contine, printre altele, fisierele httpcore-*.jar, httpclient-*.jar, commons-logging-*.jar.

Pentru compilare trebuie declarata ın variabila de sistem classpath referintacatre httpclient-*.jar si httpcore-*.jar dar pentru executie este nevoie si de referintacatre commons-logging-*.jar.

Dezvoltarea unui client presupune:

1. Crearea unui obiect de tip org.apache.http.client.HttpClient:

HttpClient client=new DefaultHttpClient();

DefaultHttpClient apartine pachetului org.apache.http.impl.client.

2. Declararea metodei de transmitere a datelor get, post.

• GET

HttpGet httpget = new HttpGet(uri);

unde uri este String-ul de apelare a servlet-ului, de forma

http://host:port/catalog/numeApel?numeParam=valParam&. . . ,

O solutie mai elegenta este

Page 150: DISTR1

150 CAPITOLUL 6. SERVLET

List<NameValuePair> qparams = new ArrayList<NameValuePair>();

qparams.add(new BasicNameValuePair("param_1", value_1));

qparams.add(new BasicNameValuePair("param_2", value_2));

. . .

try{

URI uri = URIUtils.createURI("http", "localhost", 8080,

"/catalog/numeApel",URLEncodedUtils.format(qparams,"UTF-8"),

null);

HttpGet httpget = new HttpGet(uri);

. . .

}

catch(. . .){. . .}

• POST

List<NameValuePair> qparams = new ArrayList<NameValuePair>();

qparams.add(new BasicNameValuePair("param_1", value_1));

qparams.add(new BasicNameValuePair("param_2", value_2));

. . .

try{

UrlEncodedFormEntity params=new UrlEncodedFormEntity(qparams,

"UTF-8");

HttpPost httppost=new HttpPost(uri);

httppost.setEntity(params);

. . .

}

catch(. . .){. . .}

cu uri=”http://host:port/catalog/numeApel”.

Clasele HttpGet, HttpPost apartin pachetuluiimport org.apache.http.client.methods.

3. Lansarea cererii.

HttpResponse response=httpclient.execute(httpget);

respectiv

HttpResponse response=httpclient.execute(httppost);

4. Preluarea raspunsului.

Page 151: DISTR1

6.4. FACILITATI 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){}

. . .

}

Exemplul 6.4.1 Dezvoltam un program client pentru servlet-ul CmmdcServlet (post).

1 import java . u t i l . Scanner ;2 import java . u t i l . L i s t ;3 import java . u t i l . ArrayList ;

5 import org . apache . http . HttpEntity ;6 import org . apache . http . HttpResponse ;7 import org . apache . http . c l i e n t . HttpCl ient ;8 import org . apache . http . c l i e n t . methods . HttpPost ;9 import org . apache . http . impl . c l i e n t . De fau l tHttpCl i ent ;

10 import org . apache . http . NameValuePair ;11 import org . apache . http . message . BasicNameValuePair ;12 import org . apache . http . c l i e n t . e n t i t y . UrlEncodedFormEntity ;

14 import java . i o . ∗ ;

16 public class ClientCmmdcServlet2{17 stat ic St r ing u r i=” http :// l o c a l h o s t :8080/ myserv let /cmmdc” ;

19 public stat ic void main ( St r ing [ ] a rgs ) {20 Scanner scanner=new Scanner ( System . in ) ;21 System . out . p r i n t l n ( ”m=” ) ;22 St r ing m=scanner . nextLine ( ) . tr im ( ) ;23 System . out . p r i n t l n ( ”n=” ) ;24 St r ing n=scanner . nextLine ( ) . tr im ( ) ;

26 // Create an ins tance o f Ht tpC l i en t .27 HttpCl ient h t t p c l i e n t = new Defau l tHttpCl i ent ( ) ;

29 // Create a method ins tance .30 List<NameValuePair> qparams = new ArrayList<NameValuePair >() ;31 qparams . add (new BasicNameValuePair ( ”m” , m) ) ;32 qparams . add (new BasicNameValuePair ( ”n” , n ) ) ;33 qparams . add (new BasicNameValuePair ( ” t i p ” , ” t ext / p l a i n ” ) ) ;34 try{35 UrlEncodedFormEntity params=new UrlEncodedFormEntity ( qparams , ”UTF−8” ) ;36 HttpPost httppost=new HttpPost ( u r i ) ;37 httppost . s e tEnt i ty ( params ) ;38 HttpResponse re sponse=h t t p c l i e n t . execute ( httppost ) ;39 HttpEntity e n t i t y=response . ge tEnt i ty ( ) ;40 i f ( e n t i t y !=null ){41 InputStream i s=e n t i t y . getContent ( ) ;42 int l ;43 byte [ ] tmp=new byte [ 2 0 4 8 ] ;44 while ( ( l=i s . read (tmp))!=−1){}

Page 152: DISTR1

152 CAPITOLUL 6. SERVLET

45 System . out . p r i n t l n ( ”Cmmdc = ”+(new St r ing (tmp ) . tr im ( ) ) ) ;46 }47 }48 catch ( Exception e ){49 System . out . p r i n t l n ( ” Exception : ”+e . getMessage ( ) ) ;50 }51 }52 }

6.4.2 Servlete ınlantuite

Un servlet apeleaza la un moment dat alt servlet. Sablonul de lucru este

RequestDispatcher dispatcher=

getServletContext().getRequestDispatcher("/url_pattern_servlet_apelat");

if(dispatcher!=null)

dispatcher.include(request,response);

Exemplul 6.4.2 Un servlet VerifServlet verifica parametri cererii. Pentru prob-lema calculului celui mai mare divizor comun a doua numere, daca cei doi parametrisunt numere ıntregi, atunci se apeleaza servletul ComputeServlet, altfel se formeazaun mesaj de eroare.

Codurile celor doua servlete sunt:VerifServlet.java

1 package cmmdc ;2 import java . i o . ∗ ;3 import javax . s e r v l e t . ∗ ;4 import javax . s e r v l e t . http . ∗ ;

6 public class V e r i f S e r v l e t extends HttpServ l e t {

8 public void doGet ( HttpServ letRequest req , HttpServletResponse r e s )9 throws Serv le tExcept ion , IOException{

10 PrintWriter out=r e s . getWriter ( ) ;11 r e s . setContentType ( ” text /html” ) ;12 St r ing sm=req . getParameter ( ”m” ) , sn=req . getParameter ( ”n” ) ;13 St r ing message=”” ;14 long m, n ;15 i f ( ( sm==null ) | | ( sm . equa l s ( ”” ) ) ){16 message=”Numar absent ” ;17 }18 else {19 try{20 m=Long . parseLong (sm ) ;21 }22 catch ( NumberFormatException e ){23 message=”Nu e s t e numar” ;24 }25 }26 i f ( ( sn==null ) | | ( sn . equa l s ( ”” ) ) ){27 message=”Numar absent ” ;

Page 153: DISTR1

6.4. FACILITATI DE PROGRAMARE CU SERVLET 153

28 }29 else {30 try{31 n=Long . parseLong ( sn ) ;32 }33 catch ( NumberFormatException e ){34 message=”Nu e s t e numar” ;35 }36 }37 out . p r i n t l n ( ”<html><body>” ) ;38 i f ( message . equa l s ( ”” ) ){39 out . p r i n t l n ( ”<h3> Rezu l ta tu l ob&#355; inut </h3>” ) ;40 RequestDispatcher d i spa t che r=41 getServ l e tContext ( ) . getRequestDispatcher ( ”/ c a l c u l ” ) ;42 i f ( d i spa t che r !=null )43 d i spa t che r . i n c lude ( req , r e s ) ;44 }45 else {46 out . p r i n t l n ( ”<h3> Date eronate </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 }

53 public void doPost ( HttpServ letRequest req , HttpServletResponse r e s )54 throws Serv le tExcept ion , IOException{55 doGet ( req , r e s ) ;56 }57 }

ComputeServlet.java

1 package cmmdc ;2 import java . i o . ∗ ;3 import javax . s e r v l e t . ∗ ;4 import javax . s e r v l e t . http . ∗ ;

6 public class ComputeServlet extends HttpServ l e t {

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

10 public void doGet ( HttpServ letRequest req , HttpServletResponse r e s )11 throws Serv le tExcept ion , IOException{12 long m=Long . parseLong ( req . getParameter ( ”m” ) ) ;13 long n=Long . parseLong ( req . getParameter ( ”n” ) ) ;14 PrintWriter out=r e s . getWriter ( ) ;15 out . p r i n t l n ( ”<H1> Cmmdc = ”+cmmdc(m, n)+”</H1>” ) ;16 }

18 public void doPost ( HttpServ letRequest req , HttpServletResponse r e s )19 throws Serv le tExcept ion , IOException{20 doGet ( req , r e s ) ;21 }22 }

Page 154: DISTR1

154 CAPITOLUL 6. SERVLET

6.4.3 Sesiune de lucru

In cazul protocolului HTTP, de fiecare data cand un client deschide sau revinela o pagina Web se deschide o noua conexiune cu serverul Web iar acesta nu retineinformatiile referitoare la client pe perioada conexiunii respective. Perioada de timpcat un client este ın conexiune cu o pagina Web se numeste sesiune.

Exista posibilitatea pastrarii unor informatii pe durata unei sesiuni (prin mecan-ismul denumit Session Tracking).

Inaintea satisfacerii unei cereri, servletul verifica existenta unui obiect HttpSession.Acest obiect se creaza la prima apelare de catre un client a servletului prin

HttpSession sesiune=request.getSession(true);

Un obiect HttpSession poate retine atribute, adica perechi de forma (nume, val-oare). Introducerea unui atribut se realizeaza prin

void setAttribute(String nume, Object valoare)

iar extragerea valorii unui atribut se obtine prin

Object getAttribute(String nume)

Metoda String nume[ ] getValueNames() returneaza numele tuturoratributelor definite.

Un atribut se elimina cu metoda void removeAttribute(String nume).

Exemplul 6.4.3 Exemplul urmator numara de cate ori se apeleaza servlet-ul ıntr-osesiune. Se defineste un atribut noAcces, care la prima apelare este initializat iarapoi este marit cu cate o unitate la fiecare noua apelare a servlet-ului.

1 import java . i o . ∗ ;2 import javax . s e r v l e t . ∗ ;3 import javax . s e r v l e t . http . ∗ ;

5 public class Ses iune extends HttpServ l e t {

7 public void doGet ( HttpServ letRequest req , HttpServletResponse r e s )8 throws Serv le tExcept ion , IOException{9 r e s . setContentType ( ” text /html” ) ;

10 St r ing mesaj ;11 PrintWriter out=r e s . getWriter ( ) ;12 HttpSess ion s e s s i o n=req . g e t S e s s i o n ( true ) ;13 I n t e g e r contor=( I n t e g e r ) s e s s i o n . ge tAt t r ibut e ( ”noAcces” ) ;14 i f ( contor==null ){15 contor=new I n t e g e r ( 1 ) ;16 mesaj=” Salut ! ” ;17 }18 else {19 contor=new I n t e g e r ( contor . intValue ( )+1) ;20 mesaj=”Bine a t i r e v e n i t ! ” ;21 }

Page 155: DISTR1

6.4. FACILITATI DE PROGRAMARE CU SERVLET 155

22 s e s s i o n . s e t A t t r i b u t e ( ”noAcces” , contor ) ;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 pag in 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 }

31 public void doPost ( HttpServ letRequest req , HttpServletResponse r e s )32 throws Serv le tExcept ion , IOException{33 doGet ( req , r e s ) ;34 }35 }

Apelarea servletului se face din

1 <html>2 <head>3 <t i t l e> Ses iune </ t i t l e>4 </head>5 <body>6 <h1> Formular de acce s </h1>7 <form method=” get ”8 action=” http :// l o c a l h o s t :8080/ myserv let / s e s i u n e ”>9 <p>

10 <input type=”submit” value=” Acceseaza ”>11 </form>12 </body>13 </html>

6.4.4 Cookie

Un Cookie este un fisier de mica dimensiune trimis de catre programul serverclientului ca parte a header-ului Http.

Acesta contine informatii despre sesiunea curenta care salvate pe disc vor puteafi accesate ın sesiuni ulterioare. Cand un navigator emite o cerere catre un server,cookie-urile anterioare primite de catre client de la serverul respectiv sunt trimisedin nou serverului ca parte a cererii formulata de client.

Cookie-urile sunt sterse automat ın momentul expirarii.

Unii clienti nu permit memorarea cookie-urilor. In acest caz, clientul este infor-mat ca acest fapt ar putea duce la imposibilitatea satisfacerii cereri sale / accesariipaginii Web. Implicit, durata de viata a unui cookie este sesiunea curenta a naviga-torului (pana se ınchide navigatorul).

Clasa Cookie

Contructor

Cookie(String nume, String valoare)

Metode

Page 156: DISTR1

156 CAPITOLUL 6. SERVLET

• void setDomain(String model)

Domeniul este o adresa URL ce restrictioneaza accesul cookie-urilor la aceldomeniu. model trebuie sa contina cel putin doua caractere ”.”.

• void setMaxAge(int durata) Fixeaza durata de existenta a cookie-ului - ınsecunde. Valoarea implicita este -1, adica cookie-ul exista pana la ınchidereaprogramului navigator.

• void setComment(String comentariu)

• void setSecure(boolean flag)

Valoarea implicita este false.

Trimiterea unui cookie clientului:public void HttpServletResponse.addCookie(Cookie cookie)

Recunoasterea cookie-urilor de catre servlet:

Cookie [ ] cookies=request.getCookies();

if(cookies!=null){

for(int i=0;i<cookies.length;i++){

String name=cookies[i].getName();

String valoare=cookies[i].getValue();

. . .

}

Exemplul 6.4.4 In exemplul urmator se numara de cate ori se apeleaza servlet-ulpe durata de viata a cookie-ului.

1 import java . i o . ∗ ;2 import javax . s e r v l e t . ∗ ;3 import javax . s e r v l e t . http . ∗ ;

5 public class Ape lar i extends HttpServ l e t {

7 public void doGet ( HttpServ letRequest req , HttpServletResponse r e s )8 throws Serv le tExcept ion , IOException{9 r e s . setContentType ( ” text /html” ) ;

10 St r ing mesaj=”” ;11 PrintWriter out=r e s . getWriter ( ) ;12 Cookie myCookie=null ;13 int contor =1;14 Cookie [ ] c oo k i e s=req . getCookies ( ) ;15 i f ( c o ok i e s !=null ){16 for ( int i =0; i<c oo k i e s . l ength ; i ++){17 St r ing name=c oo k i e s [ i ] . getName ( ) ;18 i f (name . equa l s ( ” urmar ire ” ) ){19 contor=I n t e g e r . pa r s e In t ( c oo k i e s [ i ] . getValue ( ) ) ;

Page 157: DISTR1

6.4. FACILITATI DE PROGRAMARE CU SERVLET 157

20 contor++;21 mesaj=”Bine a t i r e v e n i t ! ” ;22 }23 }24 }25 else {26 mesaj=” Salut ! ” ;27 }28 myCookie=new Cookie ( ” urmar ire ” , (new I n t e g e r ( contor ) ) . t oS t r i ng ( ) ) ;29 myCookie . setMaxAge (1000000) ;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 pag in i e s t e ”+contor ) ;34 out . p r i n t l n ( ”</body></html>” ) ;35 out . c l o s e ( ) ;36 }

38 public void doPost ( HttpServ letRequest req , HttpServletResponse r e s )39 throws Serv le tExcept ion , IOException{40 doGet ( req , r e s ) ;41 }42 }

6.4.5 Autorizarea accesului prin parola

Parolele celor ındreptatiti sa acceseze servletul sunt cuprinse ıntr-un fisier. Inservlet accesul la fisier se realizeaza prin preluarea unui parametru a carei valoareeste numele fisierului.

Servlet-ul solicita afisarea pe masina clientului a unei casute de dialog prin careclientul introduce numele si parola. Daca datele coincid cu cele ınregistrate ın fisieratunci se autorizeaza accesul la servlet.

Date transmise de client sunt codificate. Decodificarea se poate realiza cu clasaBase64Coder : www.source-code.biz, Christian d’Heureuse, Inventec Informatik AG,Switzerland.

Exemplul 6.4.5

1 import java . i o . ∗ ;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 . P r o p e r t i e s ;

6 public class ProtectedPage extends HttpServ l e t {7 private P r o p e r t i e s passwords ;8 private St r ing passwordFi le ;

10 // Paro l e l e sunt in t r−un f i s i e r ” paro l e ”11 // sub forma nume=paro la .12 public void i n i t ( Se rv l e tCon f i g c o n f i g )throws Serv l e tExcept ion {13 super . i n i t ( c o n f i g ) ;14 try {

Page 158: DISTR1

158 CAPITOLUL 6. SERVLET

15 passwordFi le = c o n f i g . ge t In i tParameter ( ” passwordFi le ” ) ;16 passwords = new P r o p e r t i e s ( ) ;17 passwords . load (new Fi leInputStream ( passwordFi le ) ) ;18 }19 catch ( IOException i o e ) {}20 }

22 public void doGet ( HttpServ letRequest request , HttpServletResponse re sponse )23 throws Serv le tExcept ion , IOException {24 re sponse . setContentType ( ” text /html” ) ;25 PrintWriter out = response . getWriter ( ) ;26 St r ing a u t h o r i z a t i o n = reques t . getHeader ( ” Author i zat ion ” ) ;27 i f ( a u t h o r i z a t i o n == null ) {28 ce rParo la ( re sponse ) ;29 }30 else {31 St r ing u s e r I n f o = a u t h o r i z a t i o n . su b s t r i n g ( 6 ) . tr im ( ) ;32 St r ing nameAndPassword = Base64Coder . decodeStr ing ( u s e r I n f o ) ;33 System . out . p r i n t l n ( nameAndPassword ) ;34 int index = nameAndPassword . indexOf ( ” : ” ) ;35 St r ing user = nameAndPassword . s ub s t r i n g (0 , index ) ;36 St r ing password = nameAndPassword . su b s t r i n g ( index +1). tr im ( ) ;37 passwords . l i s t ( System . out ) ;38 St r ing realPassword = passwords . getProperty ( user ) ;39 System . out . p r i n t l n ( user+” ”+password+” ”+realPassword ) ;40 i f ( ( rea lPassword != null)&&(realPassword . equa l s ( password ) ) ){41 St r ing t i t l e = ”Welcome to the Protected Page” ;42 out . p r i n t l n ( ”<HTML><HEAD><TITLE>”+t i t l e+”</TITLE></HEAD>” +43 ”<BODY BGCOLOR=\”#AABBAA\”>\n”+”<H1 ALIGN=CENTER>” + t i t l e +44 ”</H1>\n” + ” Aveti acce s l a pagina ”+”</BODY></HTML>” ) ;45 }46 else {47 ce rParo la ( re sponse ) ;48 }49 }50 }

52 // Cererea a f o s t fara au to r i z a r e53 private void ce rParo la ( HttpServletResponse re sponse ) {54 re sponse . s e t S t a tu s ( re sponse .SC UNAUTHORIZED) ; // Ie 40155 re sponse . setHeader ( ”WWW−Authent icate ” ,56 ”BASIC realm=\” p r i v i l e g e d−few\”” ) ;57 }

59 public void doPost ( HttpServ letRequest request , HttpServletResponse re sponse )60 throws Serv le tExcept ion , IOException {61 doGet ( request , r e sponse ) ;62 }63 }

Parolele se retin ıntr-un fisier denumit parole.properties alcatuit din ınregistraride forma nume=parola, cate o ınregistrare pe linie. Localizarea fisierului se obtineprin intermediul datelor din elementul

<init-param>

<param-name>passwordFile</param-name>

<param-value>d:\\apache-tomcat-*.*.*\\. . .\\parole.properties</param-value>

</init-param>

Page 159: DISTR1

6.4. FACILITATI DE PROGRAMARE CU SERVLET 159

Acest element apare ın corpul elementului <servlet> atasat servlet-ului. Servletulse apeleaza prin http://host:port/context/numeApel.

6.4.6 Servlet cu conexiune la o baza de date

Folosind Anexa C consideram

Exemplul 6.4.6 Consultarea unei agende de adrese e-mail. Se utilizeaza o baza dedate AgendaEMail alcatuita dintr-un singur tabel adrese (id int, nume varchar(20),numar varchar(30)).

Utilizand SGBD derby servletul este

1 import java . i o . ∗ ;2 import javax . s e r v l e t . ∗ ;3 import javax . s e r v l e t . http . ∗ ;4 import java . s q l . ∗ ;5 import java . net . ∗ ;

7 public class AgendaEMailServlet extends HttpServ l e t {8 Statement i n s t r u c t i u n e=null ;

10 public void i n i t ( Se rv l e tCon f i g c o n f i g ) throws Serv l e tExcept ion {11 super . i n i t ( c o n f i g ) ;12 // SGBD Derby13 St r ing jdbcDr iver=” org . apache . derby . jdbc . C l i en tDr ive r ” ;14 St r ing URLBazaDate=” jdbc : derby :// l o c a l h o s t :1527/ AgendaEMail” ;15 Connection con=null ;16 try{17 Class . forName ( jdbcDr iver ) . newInstance ( ) ;18 con=DriverManager . getConnect ion (URLBazaDate ) ;19 i n s t r u c t i u n e=con . createStatement ( ) ;20 }21 catch ( ClassNotFoundException e ){22 System . out . p r i n t l n ( ” Driver i n e x i s t e n t JDBC: ”+jdbcDr iver ) ;23 }24 catch ( SQLException e ){25 System . out . p r i n t l n ( ”Baza de date i n e x i s t e n t a ”+URLBazaDate ) ;26 }27 catch ( Exception e ){28 System . out . p r i n t l n ( ” Eroare : ”+e . getMessage ( ) ) ;29 }30 }

32 public void doGet ( HttpServ letRequest req , HttpServletResponse r e s )33 throws Serv le tExcept ion , IOException{34 St r ing myAtribut , myVal ;35 r e s . setContentType ( ” text /html” ) ;36 ServletOutputStream out = r e s . getOutputStream ( ) ;

38 myAtribut=req . getParameter ( ” c r i t e r i u ” ) ;39 myVal=req . getParameter ( ” termen” ) ;40 myVal=’ \ ’ ’+myVal+’ \ ’ ’ ;41 try{42 St r ing s q l=” s e l e c t ∗ from adrese where ”+ myAtribut+” = ”+myVal ;43 Resu l tSet r s=i n s t r u c t i u n e . executeQuery ( s q l ) ;

Page 160: DISTR1

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−mail </h1>” ) ;48 out . p r i n t l n ( ”<p/>” ) ;49 out . p r i n t l n ( ”<b> Nume <−−> Adresa e−mail </b>” ) ;50 out . p r i n t l n ( ”<br/>” ) ;51 while ( r s . next ( ) ){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 ( ” emai 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 . getMessage ( ) ) ;61 }62 catch ( Exception e ){63 System . out . p r i n t l n ( ” Eroare : ”+e . getMessage ( ) ) ;64 }65 }

67 public void doPost ( HttpServ letRequest req , HttpServletResponse r e s )68 throws Serv le tExcept ion , IOException{69 doGet ( req , r e s ) ;70 }71 }

Apelarea servlet-ului se face din

1 <html>2 <body>3 <h1> Cautare in baza de date AgendaEMail</h1>4 <form method=” get ”5 action=” http :// l o c a l h o s t :8080/ agendae/ adrese ”>6 <p>C r i t e r i u de cautare :7 <select name=” c r i t e r i u ” >8 <option value=”nume”>dupa Nume9 <option value=” emai l ”>dupa Email

10 </ select>11 <br>12 <p>Ent i ta tea cautata13 <input type=” text ” name=”termen” s ize=30>14 <p><input type=”submit” value=”Cauta”>15 </form>16 </body>17 </html>

Testarea aplicatiei presupune:

1. Realizarea bazei de date:

2. Testarea servlet-ului:

(a) Pornirea serverului bazei de date.

(b) Se verifica prezenta ın catalogul servlet-ului ...\WEB-INF\lib a fisieruluiderbyclient.jar sau mysql-connector-java-*.*.*-bin.jar.

Page 161: DISTR1

6.4. FACILITATI DE PROGRAMARE CU SERVLET 161

(c) Pornirea serverului tomcat sau reıncarcarea servlet-ului.

(d) Apelarea servlet-ului din pagina Web.

6.4.7 Imagini furnizate de servlet

Indicam doua modalitati prin care un client obtine o imagine furnizata de unservlet. Imaginea poate proveni dintr-un fisier extern sau poate fi creata de servlet.

• Imaginea este transmisa direct clientului ın fluxul de iesire de tipServletOutputStream, tipul MIME al raspunsului fiind

response.setContentType("image/ext");

ext∈ {gif, jpg, png, . . .}.Textul sursa al servlet-ului este:

1 import java . i o . ∗ ;2 import javax . s e r v l e t . ∗ ;3 import javax . s e r v l e t . http . ∗ ;

5 public class MyGraphG extends HttpServ l e t {6 public void doGet ( HttpServ letRequest req , HttpServletResponse r e s )7 throws Serv le tExcept ion , IOException {8 r e s . setContentType ( ” image/ g i f ” ) ;9 ServletOutputStream out = r e s . getOutputStream ( ) ;

11 // Refer in ta l a f i s i e r u l g r a f i c12 St r ing f =13 ”d :\\ apache−tomcat −6.0.20\\webapps\\myserv let \\WEB−INF\\”+14 ” c l a s s e s \\walk ing santa . g i f ” ;15 // Tranferarea f i s i e r u l u i g r a f i c16 Fi leInputStream f i s = new Fi leInputStream ( f ) ;17 BufferedInputStream b i s = new BufferedInputStream ( f i s ) ;18 byte [ ] bytes = new byte [ b i s . a v a i l a b l e ( ) ] ;19 int nread = 0 ;20 while (−1 != ( nread = b i s . read ( bytes ) ) ) {21 out . wr i t e ( bytes , 0 , nread ) ;22 }23 }24 }

• Pe calculatorul serverului Web, imaginea se salveaza ıntr-un fisier grafic, dupacare servlet-ul scrie ın fluxul de iesire un document html cu o legatura (link)catre fisierul cu imaginea creata anterior. Navigatorul clientului va descarcasi vizualiza imaginea.

Daca tipul fisierului grafic este jpg sau png atunci textul sursa al servlet-uluieste:

Page 162: DISTR1

162 CAPITOLUL 6. SERVLET

1 mport java . i o . ∗ ;2 import java . awt . ∗ ;3 import javax . s e r v l e t . ∗ ;4 import javax . s e r v l e t . http . ∗ ;5 import javax . imageio . ∗ ;6 import java . awt . image . ∗ ;7 import javax . imageio . stream . ∗ ;8 import java . u t i l . ∗ ;

10 public class MyGraphP extends HttpServ l e t {11 public void doGet ( HttpServ letRequest req , HttpServletResponse r e s )12 throws Serv le tExcept ion , IOException {13 r e s . setContentType ( ” text /html” ) ;14 PrintWriter out=r e s . getWriter ( ) ;15 St r ing f i l e R e f=”d :\\ apache−tomcat −6.0.20\\webapps\\myserv let \\” ;16 St r ing numeFis=” desen ” ;17 St r ing ext=” jpg ” ; // sau ”png”18 // Formarea imag in i i19 Frame frame = null ;20 Graphics g = null ;21 BufferedImage image=null ;22 try{23 frame = new Frame ( ) ;24 frame . addNoti fy ( ) ;25 image = ( BufferedImage ) frame . createImage (800 , 6 0 ) ;26 g = image . getGraphics ( ) ;27 // Fixarea f o n t u l u i28 g . setFont (new Font ( ” S e r i f ” , Font . ITALIC , 4 8 ) ) ;29 // Editarea unui t e x t30 g . drawString ( ” Tehno log i i d i s t r i b u i t e in Java” , 10 , 5 0 ) ;

32 // Sa lvarea imag in i i in t r−un f i s i e r jpg sau png33 F i l e f=new F i l e ( f i l e R e f+numeFis+” . ”+ext ) ;34 ImageIO . wr i t e ( image , ” jpg ” , f ) ;

36 // Raspunsul ca t re c l i e n t37 out . p r i n t l n ( ”<HTML><BODY>” ) ;38 out . p r i n t l n ( ”<h2>Imagine pre lua ta de pe s e r v e r </h2>” ) ;39 out . p r i n t l n ( ”<p><a h r e f =\”http :// l o c a l h o s t :8080/ myserv let /”+40 numeFis+” . ”+ext+”\”>” ) ;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 f ina l ly {46 // E l i b e rarea r e s u r s e l o r47 i f ( g != null ) g . d i spo s e ( ) ;48 i f ( frame != null ) frame . removeNotify ( ) ;49 }50 }51 }

Daca tipul fisierului grafic va fi gif atunci linia 34 se ınlocuieste cu

FileOutputStream fos=new FileOutputStream(f);

GifEncoder encoder = new GifEncoder(image,fos);

encoder.encode();

Page 163: DISTR1

6.4. FACILITATI DE PROGRAMARE CU SERVLET 163

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

6.4.8 Servlet cu RMI

Un servlet poate fi client al unei aplicatii RMI. Interfata la diatanta se depuneın catalogul WEB-INF\lib al servletului. Apelarea programului server RMI se faceprin

InterfataDistanta obj=(InterfataDistanta)

Naming.lookup("//"+host+":"+port+"/NumeServiciuRMI");

Exemplul 6.4.7 Client servlet pentru aplicatia RMI de calcul al celui mai maredivizor comun a doua numere naturale.

1 import java . i o . ∗ ;2 import java . rmi . ∗ ;3 import java . 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 . ∗ ;

8 public class ServletRMI extends HttpServ l e t {

10 public void doGet ( HttpServ letRequest req , HttpServletResponse r e s )11 throws Serv le tExcept ion , IOException {12 r e s . setContentType ( ” text /html” ) ;13 PrintWriter out = r e s . getWriter ( ) ;

15 St r ing sm=req . getParameter ( ”m” ) , sn=req . getParameter ( ”n” ) ;16 long m=(new Long (sm ) ) . longValue ( ) , n=(new Long ( sn ) ) . longValue ( ) ;17 long x=0;

19 St r ing host=req . getParameter ( ” host ” ) . tr im ( ) ;20 St r ing sPort=req . getParameter ( ” port ” ) ;21 int port=I n t e g e r . pa r s e In t ( sPort ) ;

23 try{24 ICmmdc obj=(ICmmdc)Naming . lookup ( ”//”+host+” : ”+port+”/CmmdcServer” ) ;25 x=obj . cmmdc(m, n ) ;26 }27 catch ( Exception e ) {28 System . out . p r i n t l n ( ”CmmdcClient except ion : ”+e . getMessage ( ) ) ;29 }30 St r ing t i t l e=”CmmdcServlet” ;31 r e s . setContentType ( ” text /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 }

Page 164: DISTR1

164 CAPITOLUL 6. SERVLET

41 public void doPost ( HttpServ letRequest req , HttpServletResponse r e s )42 throws Serv le tExcept ion , IOException{43 doGet ( req , r e s ) ;44 }45 }

6.4.9 Servlet cu JMS

De data aceasta cererea clientului se rezolva asincron:

• In prima faza se apeleaza un servlet care apeleaza un server JMS. Solutia esteretinuta de furnizorul serviciului de mesagerie pe o destinatie cu un subiectfurnizat de client. Pentru regasirea rezultatului, servlet-ul creaza clientului unabonament durabil, functie de numele subiectului.

• In faza a doua, clientul apeleaza un alt servlet, a carei functie este preluarearezultatului. Clientul trebuie sa furnizeze subiectul destinatiei rezultatului.

Exemplul 6.4.8

Codul serverului JMS

1 import javax . jms . ∗ ;2 import java . i o . ∗ ;3 import java . u t i l . S t r ingToken i ze r ;

5 public class MsgCmmdcServer{

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

9 public void s e r v i c e ( ){10 try{11 // Varianta Apache−MessageQueue12 //org . apache . act ivemq . ActiveMQConnectionFactory c f=13 // new org . apache . activemq . ActiveMQConnectionFactory (14 // ” tcp :// l o c a l h o s t :61616”) ;

16 // Varianta Oracle−Sun MessageQueue17 com . sun . messaging . TopicConnectionFactory c f=18 new com . sun . messaging . TopicConnectionFactory ( ) ;19 // c f . se tProper ty (” imqBrokerHostName” ,” hos t ” ) ;20 // c f . se tProper ty (” imqBrokerHostPort ” ,”7676”);21 TopicConnection conn=c f . createTopicConnect ion ( ) ;22 TopicSess ion s e s s i o n=23 conn . c r ea t eTop i cSe s s i on ( false , S e s s i on .AUTOACKNOWLEDGE) ;24 Dest inat i on tDate=s e s s i o n . c reateTopic ( ”Cmmdc” ) ;25 TopicSubscr iber 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=null ;28 St r ing sm=”” , sn=”” , t op i c=”” ;29 while ( true ){30 txtMsg=(TextMessage ) consumer . r e c e i v e ( ) ;31 St r ing msg=txtMsg . getText ( ) ;

Page 165: DISTR1

6.4. FACILITATI DE PROGRAMARE CU SERVLET 165

32 Str ingToken i ze r s t=new Str ingToken i ze r (msg , ” ” ) ;33 int 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+” : ”+to p i c ) ;41 long a=Long . parseLong (sm ) ;42 long b=Long . parseLong ( sn ) ;43 long c=cmmdc( a , b ) ;44 Dest inat i on tResu l t=s e s s i o n . c reateTop ic ( t op i c ) ;45 MessageProducer producer=s e s s i o n . c reateProducer ( tResu l t ) ;46 txtMsg=s e s s i o n . createTextMessage ( (new Long ( c ) ) . t oS t r i ng ( ) ) ;47 producer . send ( txtMsg ) ;48 System . out . p r i n t l n ( ” Expediat raspuns ” ) ;49 }50 }51 catch ( Exception e ){52 System . out . p r i n t l n ( ” Exception : ”+e . getMessage ( ) ) ;53 }54 System . out . p r i n t l n ( ” Server f i n i s h e d ” ) ;55 }

57 public stat ic void main ( St r ing [ ] a rgs ){58 MsgCmmdcServer s e r v e r=new MsgCmmdcServer ( ) ;59 s e r v e r . s e r v i c e ( ) ;60 }61 }

Codul servlet-ului care transmite datele problemei serverului JMS

1 package jms ;2 import javax . jms . ∗ ;3 import java . i o . ∗ ;4 import javax . s e r v l e t . ∗ ;5 import javax . s e r v l e t . http . ∗ ;

7 public class JMSSenderServlet extends HttpServ l e t {

9 public void doGet ( HttpServ letRequest req , HttpServletResponse r e s )10 throws Serv le tExcept ion , IOException {11 r e s . setContentType ( ” text /html” ) ;12 ServletOutputStream out = r e s . getOutputStream ( ) ;13 St r ing m=req . getParameter ( ”m” ) ;14 St r ing n=req . getParameter ( ”n” ) ;15 St r ing t op i c=req . getParameter ( ” t o p i c ” ) ;16 St r ing c l i e n t I D=”JMSCmmdc” ;17 St r ing cl ientName=”JMSCmmdc” ;18 try{19 // Varianta Apache−MessageQueue20 //org . apache . act ivemq . ActiveMQConnectionFactory c f=21 // new org . apache . act ivemq . ActiveMQConnectionFactory (22 // ” tcp :// l o c a l h o s t :61616”) ;

24 // Varianta Oracle−Sun MessageQueue25 com . sun . messaging . TopicConnectionFactory c f=26 new com . sun . messaging . TopicConnectionFactory ( ) ;27 // c f . se tProper ty (” imqBrokerHostName” ,” hos t ” ) ;

Page 166: DISTR1

166 CAPITOLUL 6. SERVLET

28 // c f . se tProper ty (” imqBrokerHostPort ” ,”7676”);29 TopicConnection conn=c f . createTopicConnect ion ( ) ;30 conn . s e tC l i en t ID ( c l i e n t I D ) ;31 TopicSess ion s e s s i o n=32 conn . c r ea t eTop i cSe s s i on ( false , S e s s i on .AUTOACKNOWLEDGE) ;33 Dest inat i on tResu l t=s e s s i o n . c reateTop ic ( t op i c ) ;34 TopicSubscr iber consumer=35 s e s s i o n . c r ea t eDurab l eSubsc r ibe r ( ( Topic ) tResult , cl ientName ) ;36 Dest inat i on t = s e s s i o n . c reateTop ic ( ”Cmmdc” ) ;37 MessageProducer producer = s e s s i o n . c reateProducer ( t ) ;38 TextMessage txtMsg=s e s s i o n . createTextMessage ( ) ;39 St r ing mesaj=m+” ”+n+” ”+t op i c ;40 txtMsg . setText ( mesaj ) ;41 producer . send ( txtMsg ) ;42 s e s s i o n . c l o s e ( ) ;43 conn . c l o s e ( ) ;44 out . p r i n t l n ( ”<html><body bgco lo r=\”#ccbbcc\”><center>” ) ;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 ( ” Date le au f o s t exped ia te s e r v e r u l u i ” ) ;48 out . p r i n t l n ( ”</center></body></html>” ) ;49 }50 catch ( Exception e ){51 out . p r i n t l n ( e . getMessage ( ) ) ;52 }53 out . c l o s e ( ) ;54 System . out . p r i n t l n ( ” Pub l i she r f i n i s h e d ” ) ;55 }

57 public void doPost ( HttpServ letRequest req , HttpServletResponse r e s )58 throws Serv le tExcept ion , IOException {59 doGet ( req , r e s ) ;60 }61 }

Codul servlet-ului care preia rezultatul

1 package jms ;2 import javax . jms . ∗ ;3 import java . i o . ∗ ;4 import javax . s e r v l e t . ∗ ;5 import javax . s e r v l e t . http . ∗ ;

7 public class JMSReceiverServlet extends HttpServ l e t {

9 public void doGet ( HttpServ letRequest req , HttpServletResponse r e s )10 throws Serv le tExcept ion , IOException {11 r e s . setContentType ( ” text /html” ) ;12 ServletOutputStream out = r e s . getOutputStream ( ) ;13 St r ing t op i c=req . getParameter ( ” t op i c ” ) ;14 St r ing c l i e n t I D=”JMSCmmdc” ;15 St r ing cl ientName=”JMSCmmdc” ;16 try{17 // Varianta Apache−MessageQueue18 //org . apache . act ivemq . ActiveMQConnectionFactory c f=19 // new org . apache . act ivemq . ActiveMQConnectionFactory (20 // ” tcp :// l o c a l h o s t :61616”) ;

22 // Varianta Oracle−Sun MessageQueue23 com . sun . messaging . TopicConnectionFactory c f=

Page 167: DISTR1

6.5. FILEUPLOAD 167

24 new com . sun . messaging . TopicConnectionFactory ( ) ;25 // c f . se tProper ty (” imqBrokerHostName” ,” hos t ” ) ;26 // c f . se tProper ty (” imqBrokerHostPort ” ,”7676”);27 TopicConnection conn=c f . createTopicConnect ion ( ) ;28 conn . s e tC l i en t ID ( c l i e n t I D ) ;29 TopicSess ion s e s s i o n=30 conn . c r ea t eTop i cSe s s i on ( false , S e s s i on .AUTOACKNOWLEDGE) ;31 Dest inat i on tResu l t = s e s s i o n . c reateTop ic ( t op i c ) ;32 TopicSubscr iber consumer=33 s e s s i o n . c r ea t eDurab l eSubsc r ibe r ( ( Topic ) tResult , cl ientName ) ;34 conn . s t a r t ( ) ;35 TextMessage txtMsg=(TextMessage ) consumer . r e c e i v e ( ) ;36 St r ing cmmdc=txtMsg . getText ( ) ;37 s e s s i o n . c l o s e ( ) ;38 conn . c l o s e ( ) ;39 out . p r i n t l n ( ”<html><body bgco lo r=\”#ccbbcc\”><center>” ) ;40 out . p r i n t l n ( ”<h1> JSP Cmmdc </h1>” ) ;41 out . p r i n t l n ( ”<p>” ) ;42 out . p r i n t l n ( ” Rezu l ta tu l obt inut : ”+cmmdc ) ;43 out . p r i n t l n ( ”</center></body></html>” ) ;44 }45 catch ( Exception e ){46 out . p r i n t l n ( e . getMessage ( ) ) ;47 }48 out . c l o s e ( ) ;49 System . out . p r i n t l n ( ” Subsc r ibe r f i n i s h e d ” ) ;50 }

52 public void doPost ( HttpServ letRequest req , HttpServletResponse r e s )53 throws Serv le tExcept ion , IOException {54 doGet ( req , r e s ) ;55 }56 }

In catalogul lib al servlet-ului trebuie incluse fisierele jar ale serviciului JMS folosit.

6.5 FileUpload

Deseori clientul trebuie sa furnizeze unui servlet un volum mare de date, de-pozitate ıntr-un fisier. Un produs care ne ajuta sa ındeplinim acest obiectiv estecommons-fileupload - dezvoltat de apache.

Commons-FileUpload - dezvoltat ın cadrul apache - este un produs care simplificatransferul unui fisier de la un client la programul server (file upload). Interfata deprogramare a produsului se refera la partea de server - ın cazul de fata reprezentatprin servlet.

Instalarea produsului consta din dezarhivarea fisierului descarcat din Internet.In plus este nevoie de

• commons-io

Fisierele

• commons-fileupload-*.*.jar

Page 168: DISTR1

168 CAPITOLUL 6. SERVLET

• commons-io-*.*.jar

se depun ın catalogul lib al servlet-ului.Transferarea unui fisier, din partea clientului nu ridica nici o problema. In fisierul

html de apelare, se defineste un formular

<form

action=. . .

enctype="multipart/form-data"

method="post">

iar un fisier de ıncarcat se fixeaza prin intermediul marcajului

<input type="file" name=. . . size=. . .>

Programul navigator afiseaza o fereastra de cautare, prin care clientul selecteazafisierul pe care doreste sa-l ıncarce.

Daca partea de client este un program, atunci se utilizeaza commons-httpclient.6.4.1

De partea serverului, programarea ıncarcarii revine la

1. Crearea unei fabrici pentru manipularea fisierelor pe disc

FileItemFactory factory = new DiskFileItemFactory();

2. Crearea unei unelte de ıncarcare

ServletFileUpload upload = new ServletFileUpload(factory);

3. Analiza (parsarea) mesajului furnizat de client

List fileItems = upload.parseRequest(req);

Fiecare element al listei implementeaza interfata FileItem.

Se pot fixa parametrii

• dimensiunea zonei de pe disc destinata datelor de ıncarcat

DiskFileItemFactory factory = new DiskFileItemFactory();

factory.setSizeThreshold(maxMemorySize);

• catalogul temporar de retinere a datelor de ıncarcat

factory.setRepositoryPath(tempDirectory);

sau direct

Page 169: DISTR1

6.5. FILEUPLOAD 169

DiskFileItemFactory factory = new DiskFileItemFactory(

maxMemorySize, tempDirectory);

• dimensiunea maxima a unui fisier

upload.setSizeMax(maxRequestSize);

4. Prelucrarea elementelor ıncarcate

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. In cazul unui element care nu este de tip fisier putem obtine numele si valoareaatributului furnizat de client

String name = item.getFieldName();

String value = item.getString();

6. In cazul unui fisier putem afla numele campului input, numele fisierului, di-mensiunea fisierului

String fieldName = item.getFieldName();

String fileName = item.getName();

long sizeInBytes = item.getSize();

7. Daca dorim sa salvam fisierul pe calculatorul server atunci prelucrarea este

File uploadedFile = new File(...);

item.write(uploadedFile);

8. Daca datele fisierului se ıncarca ın memoria calculatorului atunci prelucrareaeste

InputStream in = item.getInputStream();

//preluarea datelor din fluxul in

. . .

in.close();

Page 170: DISTR1

170 CAPITOLUL 6. SERVLET

Alternativ, datele se pot retine ca un sir de octeti prin

byte[] data = item.get();

Exemplul 6.5.1 Sa se obtina ın memoria serverului matricea continuta ıntr-unfisier text. In fisierul text, fiecare linie contine o linie a matricei, iar elementelesunt separate prin spatii.

Metoda getMatrix utilizata reface matricea din datele fisierului.

1 package upload ;2 import java . i o . ∗ ;3 import javax . s e r v l e t . ∗ ;4 import javax . s e r v l e t . http . ∗ ;5 import java . u t i l . ∗ ;6 import org . apache . commons . f i l e u p l o a d . d i sk . ∗ ;7 import org . apache . commons . f i l e u p l o a d . s e r v l e t . ∗ ;8 import org . apache . commons . f i l e u p l o a d . ∗ ;

10 public class Fi l eUp loadSe rv l e t extends HttpServ l e t {

12 public void doPost ( HttpServ letRequest req , HttpServletResponse r e s )13 throws Serv le tExcept ion , IOException {14 r e s . setContentType ( ” text / p l a i n ” ) ;15 ServletOutputStream out = r e s . getOutputStream ( ) ;16 try{17 boolean i s M u l t i p a r t = Serv l e tF i l eUp load . i sMult ipartContent ( req ) ;18 Fi le I temFactory f a c t o r y = new DiskFi le I temFactory ( ) ;19 Serv l e tF i l eUp load upload = new Serv l e tF i l eUp load ( f a c t o r y ) ;20 L i s t i tems = upload . parseRequest ( req ) ;21 upload . setSizeMax (1000000) ;22 I t e r a t o r i t e r=items . i t e r a t o r ( ) ;23 while ( i t e r . hasNext ( ) ) {24 Fi l e I tem item = ( Fi l e I tem ) i t e r . next ( ) ;25 i f ( ! item . isFormFie ld ( ) ) {26 St r ing f i leName = item . getName ( ) ;27 out . p r i n t l n ( f i leName ) ;28 long s i z e InByt e s = item . g e t S i z e ( ) ;29 out . p r i n t l n ( s i z e InByt e s ) ;30 InputStream in=item . getInputStream ( ) ;31 InputStreamReader i s r=new InputStreamReader ( in ) ;32 BufferedReader br=new BufferedReader ( i s r ) ;33 double [ ] [ ] matrix=getMatrix ( br ) ;34 int m=matrix . l ength ;35 int n=matrix [ 0 ] . l ength ;36 for ( int i =0; i<m; i ++){37 for ( int j =0; j<n ; j++)38 out . p r i n t ( matrix [ i ] [ j ]+” ” ) ;39 out . p r i n t l n ( ) ;40 }41 br . c l o s e ( ) ;42 i s r . c l o s e ( ) ;43 in . c l o s e ( ) ;44 out . c l o s e ( ) ;45 }46 }47 }

Page 171: DISTR1

6.5. FILEUPLOAD 171

48 catch ( Exception e ){49 System . out . p r i n t l n ( ” Exception : ”+e . getMessage ( ) ) ;50 }51 }

53 private double [ ] [ ] getMatrix ( BufferedReader br ) throws Exception {54 Vector<Double> v=new Vector<Double >(10) ;55 double [ ] [ ] matrix=null ;56 try{57 St r ing l i n e , s ;58 int m=0,n ,mn;59 do{60 l i n e=br . readLine ( ) ;61 i f ( l i n e !=null ){62 m++;63 St r ing [ ] s t=l i n e . s p l i t ( ” ” ) ;64 for ( S t r ing s : s t ){65 v . addElement (new Double ( s ) ) ;66 }67 }68 }69 while ( l i n e !=null ) ;70 i f ( v . s i z e ()>0){71 mn=v . s i z e ( ) ;72 n=mn/m;73 matrix=new double [m] [ n ] ;74 for ( int i =0; i<m; i ++){75 for ( int j =0; j<n ; j++){76 matrix [ i ] [ j ]=(( Double ) v . elementAt ( i ∗n+j ) ) . doubleValue ( ) ;77 System . out . p r i n t ( matrix [ i ] [ j ]+” ” ) ;78 }79 System . out . p r i n t l n ( ) ;80 }81 }82 }83 catch ( Exception e ){84 throw new Exception ( e . getMessage ( ) ) ;85 }86 return matrix ;87 }88 }

Pentru compilare se completeaza variabila de sistem classpath cu referinta catrefisierul commons-fileupload-*.*.jar.

Formularul clientului este

1 <html>2 <head>3 <script language=” j a v a s c r i p t ” >4 < !−−5 f unc t i on check I t (){6 var f i s=document . l i n e a r . my f i l e . value ;7 i f ( f i s==”” ){8 a l e r t (” S e l e c t a t i f i s i e r u l core spunzator mat r i c e i ” ) ;9 re turn f a l s e ;

10 }11 re turn true ;12 }13 //−−>

Page 172: DISTR1

172 CAPITOLUL 6. SERVLET

14 </ script>15 </head>16 <body>17 <h1> Inc &#259; r ca r ea unui f i &#351; i e r </h1>18 <form19 action=” http :// l o c a l h o s t :8080/ upload / upload ”20 enctype=” mult ipar t /form−data ” method=” post ”21 name=” l i n e a r ” onSubmit=” return check I t ( ) ”>22 <p>23 S e l e c t a &#355; i f i &#351; i e r u l24 <p>25 <input type=” f i l e ” name=” myf i l e ” s ize=30>26 <p>27 <input type=”submit” value=” Expediaza f i s i e r u l ”>28 </form>29 </body>30 </html>

6.6 Descarcarea unui fisier

Consideram cazul:

Exemplul 6.6.1 Fisierul ales de client dintr-o lista disponibila este descarcat fiindtransmis navigatorului.

1 import java . i o . ∗ ;2 import javax . s e r v l e t . ∗ ;3 import javax . s e r v l e t . http . ∗ ;

5 public class DownloadServlet extends HttpServ l e t {6 public void doGet ( HttpServ letRequest req , HttpServletResponse r e s )7 throws Serv le tExcept ion , IOException{8 ServletOutputStream out=r e s . getOutputStream ( ) ;9 St r ing f i l e=req . getParameter ( ” f i l e ” ) ;

10 St r ing c a l e=”webapps/download/ r e s o u r c e s /” ;11 try{12 Fi leInputStream f i s = new Fi leInputStream ( c a l e+f i l e ) ;13 BufferedInputStream b i s = new BufferedInputStream ( f i s ) ;14 byte [ ] bytes = new byte [ b i s . a v a i l a b l e ( ) ] ;15 r e s . setContentType ( ” Appl i ca t ion /Octet−stream ” ) ;16 b i s . read ( bytes ) ;17 out . wr i t e ( bytes ) ;18 b i s . c l o s e ( ) ;19 f i s . c l o s e ( ) ;20 out . c l o s e ( ) ;21 }22 catch ( Exception e ){23 r e s . setContentType ( ” text / p l a i n ” ) ;24 out . p r i n t l n ( ” Cererea d−voast ra nu poate f i s a t i s f a c u t a ” ) ;25 }26 out . c l o s e ( ) ;27 }

29 public void doPost ( HttpServ letRequest req , HttpServletResponse r e s )30 throws Serv le tExcept ion , IOException{

Page 173: DISTR1

6.7. FILTRU 173

31 doGet ( req , r e s ) ;32 }33 }

6.7 Filtru

Un filtru se asemeana unui servlet, dar activitatea ıntreprinsa vizeaza uzualcontextul, adica ansamblul servletilor care fac parte din aplicatia Web.

Un filtru se declara ın fisierul 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>

Clasa filtrului implementeaza interfata Filter, adica metodele

• public void init(FilterConfig filterConfig) throws ServletException

• public void destroy()

• public void doFilter(ServletRequest request,ServletResponse response, FilterChain filterChain)throws IOException, ServletException

Exemplul 6.7.1 Contextul myservlet contine doi servleti HelloServlet si Cmmdc-Servlet, apelabili respectiv din hello.html, cmmdc.html. Sa se programeze un filtrucare

• Redirecteaza solicitarea “/myservlet/hello” catre “/cmmdc.html”.

• Daca se cere ca natura raspunsului sa fie “text/xml” atunci invalideaza cererea.

Servletii HelloServlet si CmmdcServlet sunt cei dezvoltati la ınceputul acestuicapitol. Filtrul are codul

Page 174: DISTR1

174 CAPITOLUL 6. SERVLET

1 import java . i o . IOException ;2 import javax . s e r v l e t . ∗ ;3 import javax . s e r v l e t . http . ∗ ;

5 public class MyFi l terDispatcher 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 ;

8 public void i n i t ( F i l t e r C o n f i g f i l t e r C o n f i g ) throws Serv l e tExcept ion {9 this . f i l t e r C o n f i g = f i l t e r C o n f i g ;

10 }

12 public void dest roy ( ) {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 ( Serv l e tReques t request , Serv le tResponse response ,17 Fi l t e rCha in f i l t e r C h a i n ) throws IOException , Se rv l e tExcept ion {18 HttpServ letRequest req = ( HttpServ letRequest ) r eque s t ;19 HttpServletResponse r e s = ( HttpServletResponse ) re sponse ;20 St r ing u r i = req . getRequestURI ( ) ;21 i f ( u r i . equa l s ( ”/ myserv let ” ) | | u r i . equa l s ( ”/ myserv let /” ) )22 f i l t e r C h a i n . d o F i l t e r ( request , r e sponse ) ;23 else {24 i f ( u r i . equa l s ( ”/ myserv let / h e l l o ” ) ){25 St r ing d i spa t che rUr i=”/cmmdc . html” ;26 RequestDispatcher rd=reque s t . getRequestDispatcher ( d i spa t che rUr i ) ;27 rd . forward ( request , r e sponse ) ;28 }29 else {30 int index=u r i . l a s t IndexOf ( ” . ” ) ;31 i f ( index==−1){32 St r ing t i p=req . getParameter ( ” t i p ” ) ;33 i f ( t i p . equa l s ( ” t ext /xml” ) ){34 r e s . sendError ( HttpServletResponse .SC FORBIDDEN) ;35 }36 }37 f i l t e r C h a i n . d o F i l t e r ( request , r e sponse ) ;38 }39 }40 }41 }

Fisierul web.xml este

1 <?xml version=” 1 .0 ” encoding=”ISO−8859−1”?>2 < !DOCTYPE web−app3 PUBLIC ”−//Sun Microsystems , Inc . //DTD Web Appl i ca t ion 2 .3//EN”4 ” h t tp : // java . sun . com/dtd/web−app 2 3 . dtd”>

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>MyFi l terDispatcher</ 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 <ur l−pattern>/∗</ ur l−pattern>15 </ f i l t e r −mapping>

Page 175: DISTR1

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 <ur l−pattern>/ h e l l o</ ur l−pattern>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 <ur l−pattern>/cmmdc</ ur l−pattern>35 </ s e r v l e t−mapping>

37 </web−app>

Pentru ıntelegerea aplicatiei prezentam si codul fisierului cmmdc.html

1 <html>2 <head>3 <t i t l e>4 Cmmdc S e r v l e t5 </ t i t l e>6 </head>7 <body bgcolor=”#ccbbcc ”>8 <center>9 <h1> Cmmdc S e r v l e t </h1>

10 <form method=” get ”11 action=” http :// l o c a l h o s t :8080/ myserv let /cmmdc”>12 <table border=”1”>13 <tr>14 <td> Primul numar </td>15 <td> <input type=” text ” name=”m” s ize=10> </td>16 </ tr>17 <tr>18 <td> Al d o i l e a numar </td>19 <td> <input type=” text ” name=”n” s ize=10> </td>20 </ tr>21 <tr>22 <td> Natura ra spunsu lu i </td>23 <td> <select name=” t i p ” >24 <option value=” text /html”> t ex t /html25 <option value=” text / p l a i n ”> t ex t / p l a i n26 <option value=” text /xml”> t ex t /xml27 </ select> </td>28 </ tr>29 <tr>30 <td> <input type=”submit” value=” Calcu leaza ”> </td>31 <td></td>32 </ tr>33 </table>34 </form>35 </center>

Page 176: DISTR1

176 CAPITOLUL 6. SERVLET

36 </body>37 </html>

Page 177: DISTR1

Capitolul 7

Java Server Page – JSP

7.1 Tehnologia JSP

Tipul tehnologiei JSP este denumit procesare de sabloane (template engine). JSPeste o tehnologie similara cu PHP, ASP.NET, apache-velocity, etc. JSP permite in-cluderea de cod Java ıntr-un document html. Un asemenea document se depoziteazaıntr-un server Web, container de servlet, cu extensia jsp, eventual jspx.

Apelarea documentului JSP se realizeaza prin

• meniul File/Open a unui navigator, cu

http://host:port/cale/doc.jsp

• referinta html

<a href="http://host:port/cale/doc.jsp">

• valoare a atributului action ıntr-un marcaj form

<form action="http://host:port/cale/doc.jsp" ... >

Prin cale se ıntelege calea de la catalogul webapps pana la catalogul ce continefisierul jsp.

Vom depozita fisierele JSP ıntr-un catalog jsp din arborele

webapps

|--> JSPApp

| |--> WEB-INF

| | |--> classes

| | | web.xml

| |--> jsp

| | | doc.jsp

caz ın care cale=JSPApp/jsp.Astfel, schimband numele fisierului Hello.html

177

Page 178: DISTR1

178 CAPITOLUL 7. JAVA SERVER PAGE – JSP

1 <html>2 <body>3 Hel lo4 </body>5 </html>

ın Hello.jsp si plasandu-l ın catalogul jsp se obtine acelasi efect, dar prelucrareapaginilor / documentelor este diferita. Fisierul html este prelucrat doar de progra-mul navigator si poate fi deschis ca fisier, ın timp ce fisierul JSP este prelucrat deserverul Web cu afisarea prin intermediul navigatorului. Prelucrarea efectuata deserverul Web consta din transformarea paginii / documentului JSP ıntr-un servlet,care este compilat si lansat ın executie. Din aceastra cauza prima invocare a paginii/ documentului JSP dureaza mai mult decat apelarile ulterioare.

Apelarea paginii / documentului JSP se face prinhttp://localhost:8080/JSPApp/jsp/Hello.jsp

Exista doua moduri de a include elemente JSP ıntr-un text html:

• prin elemente specifice JSP.

Fisierul are extensia jsp si se numeste pagina JSP.

• prin marcaje xml apartinand spatiului de nume

http://java.sun.com/JSP/Page

Fisierul poate avea extensia jsp sau jspx si se numeste document JSP.

Comentariile JSP se scriu de forma

<%-- Comentariu --%>

Consideram urmatorul exemplu introductiv:

Exemplul 7.1.1 Putem afisa valoarea unei variabile Java (de exemplu data calen-daristica) prin

• Varianta paginii JSP

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 java . u t i l . Date ( ) %>

7 <p>8 <% java . u t i l . Date data1=new java . u t i l . Date ( ) ; %>9 Data c a l e n d a r i s t i c a 2 :

10 <%= data1 %>

Page 179: DISTR1

7.1. TEHNOLOGIA JSP 179

12 <p>13 <% java . u t i l . Date data2=new java . 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>

Daca se utilizeaza operatorul de afisare = atunci dupa expresia de afisat nu sepune ;.

Variabila predefinita out este de tip javax.servlet.jsp.JspWriter.

• Varianta documentului JSP

1 <?xml v e r s i o n=” 1 .0 ” encoding=”UTF−8” ?>2 <html xmlns : j s p=” http :// java . sun . com/JSP/Page”>3 <body>4 <j sp : d e c l a r a t i o n>5 java . u t i l . Date d=new java . u t i l . Date ( ) ;6 </ j sp : d e c l a r a t i o n>7 <j sp : exp r e s s i on> d </ j sp : exp r e s s i on>8 </body>9 </html>

Codul Java inglobat ıntr-un text html se numeste scriptlet. Sintaxa utilizata este

• Varianta paginii JSP

<% cod Java %>

• Varianta documentului JSP

<jsp:scriptlet> codJava </jsp:scriptlet>

Domeniul de valabilitate. Domeniul de valabilitate defineste intervalul detimp, de existenta al unui obiect, fiind definit prin valorile:

Valoare Domeniu de valabilitate

page pagina curentarequest ın pagina curenta,

ın paginile incluse siın paginile catre care se face o redirectare

session ın sesiunea curentaapplication pe durata rularii aplicatiei

In orice pagina / document JSP sunt predefinite obiectele:

Page 180: DISTR1

180 CAPITOLUL 7. JAVA SERVER PAGE – JSP

Variabila Tip/Clasa

out javax.servlet.jsp.JspWriterrequest javax.servlet.ServletRequestresponse javax.servlet.ServletResponsesession javax.servlet.http.HttpSessionpage java.lang.Object, thispageContext javax.servlet.jsp.PageContextapplication javax.servlet.ServletContext

ServletContext.getServletConfig().getContext()exception java.lang.Throwable

Astfel

String request.getParameter(String numeParametru)

furnizeaza valoarea parametrului numeParametru dintr-un formular html.

Exemplul 7.1.2 Pagina JSP Hello: Clientul transmite numele paginii care ıi raspundecu mesajul de salut ”Hi ” + nume + ” !”.

Codul paginii JPS (hello.jsp) este

1 <html>2 <head>3 <t i t l e> j s p h e l l o </ t i t l e>4 </head>5 <body>6 <center>7 <h1> Pagina de r&#259; spuns </h1>8 <p>9 <%

10 out . p r i n t l n ( ”Hi ”+reques t . getParameter ( ”name”)+” ! ” ) ;11 %>12 </center>13 </body>14 </html>

apelat din (index.html)

1 <html>2 <head>3 <t i t l e> JSP Hel lo </ t i t l e>4 </head>5 <body bgcolor=”#bbeebb”>6 <center>7 <h1> Pagina de ape l a r e JSP </h1>8 <form method=” post ”9 action=” http :// l o c a l h o s t :8080/ j s p h e l l o / j sp / h e l l o . j sp ”>

10 <p> Numele :11 <input type=” text ” name=”name” s ize=20>12 <p>13 <input type=”submit”>

Page 181: DISTR1

7.1. TEHNOLOGIA JSP 181

14 </form>15 </center>16 </body>17 </html>

Compilarea si arhivarea servlet-ului o vom realiza prin intermediul lui apache-ant. In acest scop se creaza structura:

jsphello

| |--> jsp

| | | hello.jsp

| |--> lib

| |--> src

| |--> web

| | | web.xml

| |--> web-files

| | | index.html

| build.xml

Fisierul web.xml este simplu

1 <?xml version=” 1 .0 ” encoding=”ISO−8859−1”?>

3 < !DOCTYPE web−app4 PUBLIC ”−//Sun Microsystems , Inc . //DTD Web Appl i ca t ion 2 .3//EN”5 ” h t tp : // java . sun . com/dtd/web−app 2 3 . dtd”>

7 <web−app>8 <welcome− f i l e − l i s t>9 <welcome− f i l e>index . html</welcome− f i l e>

10 <welcome− f i l e>index . j sp</welcome− f i l e>11 </welcome− f i l e − l i s t>12 </web−app>

Fisierul build.xml prelucrat de apache-ant este

1 <project based i r=” . ” d e f a u l t=” generate . war”>

3 <property name=”TOMCATHOME” value=” d: /apache−tomcat −5.5.26 ”/>4 <property name=” d i s t . name” value=” j s p h e l l o ” />5 <property name=” d i s t . d i r ” value=” d i s t ” />6 <property name=” bu i ld . d i r ” va lue=” bu i ld ”/>

8 <path id=” myclasspath ”>9 <f i l e s e t d i r=” l i b ”>

10 <include name=” ∗ . j a r ”/>11 </ f i l e s e t>12 <pathelement path=”${TOMCATHOME}/ l i b / s e r v l e t−api . j a r ” />13 </path>

15 <target name=” i n i t ”>16 <delete d i r=”${ d i s t . d i r }”/>17 <mkdir d i r=”${ bu i ld . d i r }”/>18 <mkdir d i r=”${ d i s t . d i r }” />19 <mkdir d i r=”${ bu i ld . d i r }/ j sp ” />20 <mkdir d i r=”${ bu i ld . d i r }/WEB−INF” />21 <mkdir d i r=”${ bu i ld . d i r }/WEB−INF/ c l a s s e s ” />22 <mkdir d i r=”${ bu i ld . d i r }/WEB−INF/ l i b ” />23 </target>

Page 182: DISTR1

182 CAPITOLUL 7. JAVA SERVER PAGE – JSP

25 <target name=” compile ” depends=” i n i t ”>26 <javac c l a s s p a t h r e f=” myclasspath ”27 s r c d i r=”${ based i r }/ s r c ”28 d e s t d i r=”${ bu i ld . d i r }/WEB−INF/ c l a s s e s ” />29 </target>

31 <target name=” generate . war” depends=” compile ”>32 <copy t o d i r=”${ bu i ld . d i r }” >33 <f i l e s e t d i r=”${ based i r }/web− f i l e s ” >34 <include name=” ∗ . html” />35 </ f i l e s e t>36 </copy>37 <copy t o d i r=”${ bu i ld . d i r }/ j sp ” >38 <f i l e s e t d i r=”${ based i r }/ j sp ” >39 <include name=” ∗ . j s p ” />40 <include name=” ∗ . j spx ” />41 </ f i l e s e t>42 </copy>43 <copy t o d i r=”${ bu i ld . d i r }/WEB−INF” >44 <f i l e s e t d i r=”${ based i r }/web” >45 <include name=” ∗ . xml” />46 </ f i l e s e t>47 </copy>48 <copy t o d i r=”${ bu i ld . d i r }/WEB−INF/ l i b ” >49 <f i l e s e t d i r=”${ based i r }/ l i b ” >50 <include name=” ∗ . j a r ” />51 </ f i l e s e t>52 </copy>53 <copy t o d i r=”${ bu i ld . d i r }” >54 <f i l e s e t d i r=”${ based i r }” >55 <include name=” ∗ . p r o p e r t i e s ” />56 </ f i l e s e t>57 </copy>58 <jar d e s t f i l e=”${ d i s t . d i r }/${ d i s t . name } . war” bas ed i r=”${ bu i ld . d i r }” />59 </target>60 </project>

7.1.1 Declaratii JSP

Printr-o declaratie JSP, putem defini campuri(variabile) si metode Java ce potfi apoi folosite, respectiv apelate ın documentul respectiv. O declaratie JSP sedefineste printr-un marcaj

<%! . . . %>

sau, ın format XML

<jsp:declaration> . . . </jsp:declaration>

Exemplul 7.1.3 Calculul celui mai mare divizor comun a doua numere naturalecu metoda de calcul este definita ıntr-o declaratie JSP.

Pagina JSP a aplicatiei cmmdc.jsp:

Page 183: DISTR1

7.1. TEHNOLOGIA JSP 183

1 <html>2 <body>3 <H1> CMMDC </H1>4 <%!5 long cmmdc( long m, long n){6 long c , r ;7 do{8 c=n ;9 r=m%n ;

10 m=n ;11 n=r ;12 }whi le ( r !=0) ;13 r e turn c ;14 }15 %>16 Rezu l ta tu l e s t e17 <%18 String sm=reques t . getParameter ( ”m” ) ;19 String sn=reques t . getParameter ( ”n” ) ;20 long m=Long . parseLong (sm) , n=Long . parseLong ( sn ) ;21 out . p r i n t l n (cmmdc(m, n ) ) ;22 %>23 </body>24 </html>

apelat din documentul cmmdc.html

1 <html>2 <body>3 <h1> Calcu lu l Cmmdc </h1>4 <form method=” post ”5 action=” http :// l o c a l h o s t :8080/JSPApp/ j sp /cmmdc . j sp ”>6 <p>7 Primul numar e s t e8 <input type=” text ” name=”m” value=”” s ize=5>9 <p>

10 Al d o i l e a numar e s t e11 <input type=” text ” name=”n” value=”” s ize=5>12 <p>13 <input type=”submit” value=” Calcu leaza ”>14 <input type=” r e s e t ” value=”Abandon”>15 </form>16 </body>17 </html>

Exista doua metode jspInit() - utilizata pentru initializarea datelor -, si jspDestroy()- utilizata pentru eliberarea resurselor -, care daca sunt declarate de programatoratunci sunt executate la ınceputul si la sfarsitul ciclului de executie a paginii /documentului JSP.

7.1.2 Directive JSP

Directivele JSP fixeaza informatii pentru tot documentul jsp. O directiva jsp seindica prin marcajul

<%@ directiva atribut1 atribut2 . . . %>

Page 184: DISTR1

184 CAPITOLUL 7. JAVA SERVER PAGE – JSP

sau ın format XML

<jsp:directive.directiva atribut1 atribut2 . . . />

unde fiecare atribut are sintaxa nume=valoare.

Directivele pot fi: page, include, taglib.

• Directiva page. Mentionam atributele

import= ”lista de pachete separate prin ,”info= ”text” Informatia se poate regasi apeland metoda

getServletInfo()errorPage= ”adresa url a paginii ce trateaza exceptia”isErrorPage= "true | false"

• Directiva include permite includerea unor fisiere .html sau .jsp ın document

<%@ include file=”fisier html, jsp” %>

Includerea are loc ın locul ın care apare directiva.

Referinta la fisierul html sau jsp se face relativ la catalogul paginii JSP initiale(adica cea ın care apare directiva).

• Directiva taglib indica bibliotecile de marcaje utilizate ın documentul jsp,avand atributele

uri= ”uri - Universal Resource Identifier - a bibliotecii de marcaje”prefix= ”prefixul marcajului”

7.1.3 Marcaje JSP predefinite

Un marcaj JSP defineste o actiune care se executa ın timpul procesarii paginiijsp. Sintaxa marcajelor JSP seamana cu cea a marcajelor html sau xml

<prefix : marcaj atribute />

Dintre marcajele JSP predefinite – adica cu prefixul JSP – amintim:

• <jsp : include page=”numeFisier jsp sau html” />

• <jsp : forward page=”numeFisier jsp sau html” />

Prelucrarea care urmeaza va fi cea din fisierul mentional. Diferenta dintre celedoua elemente consta ın faptul ca include prevede revenirea ın pagina JSPinitiala iar forward nu.

Referinta la fisierul html sau jsp se face relativ la catalogul paginii JSP initiale.

Page 185: DISTR1

7.1. TEHNOLOGIA JSP 185

In cazul marcajelor <jsp: include>, <jsp: forward> se pot transmiteparametri prin marcajele incluse<jsp:param name="nume" value=valoare "/>

sau<jsp:params>

<jsp:param name="nume" value=valoare "/>. . . . . .

</jsp:params>

• <jsp : useBean id=”numeComponentaJava”class=”numeClasa”scope=”domeniu” />

unde domeniu precizeaza domeniul de valabilitate al componentei Java, adicapage, request, session, application.

Creaza un obiect ”numeComponentaJava” de tip ”numeClasa” avand dome-niul de valabilitate data de ”domeniu”.

• <jsp : setProperty name=”numeComponentaJava”property=”numeProp”value=”valoare”/>

Acest marcaj este echivalent cu codul JavanumeComponentaJava.setNumeProp(valoare).

<jsp : setProperty name=”numeComponentaJava” property="*" />vizeaza toate proprietatile componentei Java, fixarea valorilor facandu-se cudatele unui formular. Numele parametrilor din formularele de introducere adatelor trebuie sa coincida cu identificatorii campurilor din componenta Javacorespunzatoare.

• <jsp : getProperty name=”numeComponentaJava”property=”numeProp”/>

Preia si afiseaza valoarea campului numeComponentaJava.numeProp.

7.1.4 Componenta Java (Java Bean)

O componenta Java este o clasa care poate interactiona cu alte componente Java,cu un document jsp, etc.

O componenta Java contine cel putin

• Un constructor fara nici un argument;

• O multime de campuri declarate private;

Page 186: DISTR1

186 CAPITOLUL 7. JAVA SERVER PAGE – JSP

• Pentru fiecare asemenea camp

private Tip xyz;

trebuie definite metodele

public void setXyz(Tip xyz){

this.xyz=xyz;

}

public Tip getXyz(){

return xyz;

}

7.1.5 Pagini JSP cu componente Java

Clasa componentei Java care se va utiliza ıntr-o pagina JSP trebuie inclusa ıntr-un pachet.

Reluam exemplul 7.1.2 cu o componenta Java corespunzatoare numelui din for-mularul index.html.

Exemplul 7.1.4

1 package j sp ;2 public class HelloBean {3 private St r ing name=”” ;4 public St r ing getName ( ) {5 return name ;6 }7 public void setName ( St r ing name) {8 this . name=name ;9 }

10 }

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

1 <j sp : useBean id=” obj ” class=” j sp . HelloBean ” scope=” reques t ”/>2 <j sp : s e tProper ty name=” obj ” property=”∗”/>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 <h1> Pagina de r&#259; spuns </h1>9 <center>

10 <%11 out . p r i n t l n ( ”Hi ”+obj . getName()+” ! ” ) ;12 %>13 </center>14 </body>15 </html>

Page 187: DISTR1

7.1. TEHNOLOGIA JSP 187

Mai mult, se poate include formularul ın pagina JSP, bineınteles stergandu-l dinfisierul html:

1 <j sp : useBean id=” obj ” class=” j sp . HelloBean ” scope=” reques t ”/>2 <j sp : s e tProper ty name=” obj ” property=”∗”/>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 &#355; i a He l lo </h1>

10 <form method=” post ”>11 <p> <h3> I n t r o d u c e t i numele : </h3>12 <input type=” text ” name=”name” s ize=20>13 <p>14 <input type=”submit”>15 </form>16 <p>17 <%18 out . p r i n t l n ( ”Hi ”+obj . getName()+” ! ” ) ;19 %>20 </center>21 </body>22 </html>

In vederea generarii arhivei war, desfasurarea aplicatiei va fi

jsphello

| |---> jsp

| | | hello.jsp

| |---> lib

| |---> src

| | |---> jsp

| | | | HelloBean.java

| |---> web

| | | web.xml

| |---> web-files

| | | index.html

| build.xml

Exemplul 7.1.5 Pagina JSP pentru calculul celui mai mare divizor comun cu metodade calcul definita ıntr-o componenta Java.

Utilizand documentului html din Exemplul 7.1.3 se defineste componenta Java

1 package cmmdc ;2 public class CmmdcBean{3 private St r ing m=”” ;4 private St r ing n=”” ;5 private St r ing cmmdc ;

7 public void setM ( St r ing m){8 this .m=m;9 }

10 public void setN ( St r ing n){11 this . n=n ;12 }

Page 188: DISTR1

188 CAPITOLUL 7. JAVA SERVER PAGE – JSP

13 public St r ing getM (){14 return m;15 }16 public St r ing getN (){17 return n ;18 }

20 public St r ing getCmmdc ( ){21 long m=Long . parseLong (getM ( ) ) ;22 long n=Long . parseLong ( getN ( ) ) ;23 return (new Long (cmmdc(m, n ) ) ) . t oS t r i ng ( ) ;24 }

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

28 }

Instantiem o componenta Java si ıi fixam proprietatile (adica ıi transmitemparametri problemei) dupa care apelam metoda ce calculeaza rezultatul dorit ınpagina JSP:

1 <j sp : useBean id=” obj ” class=”cmmdc . CmmdcBean” scope=” a p p l i c a t i o n ”/>2 <j sp : s e tProper ty name=” obj ” property=”∗”/>3 <html>4 <body>5 Cel mai mare d i v i z o r comun a l numerelor6 <p>7 <%=obj . getM ( ) %> s i <%=obj . getN ( ) %>8 e s t e <%=obj . getCmmdc ( ) %>9 </body>

10 </html>

Exemplul 7.1.6 Generarea unei exceptii (errhandler.jsp):

1 <%@ page errorPage=” er ro rpage . j sp ” %>2 <html>3 <body>4 <%5 String mater ia=reque s t . getParameter ( ” mater ia ” ) . tr im ( ) ;6 i f ( mater ia . equa l s ( ”AN” ) ) {7 out . p r i n t l n ( ”<hr><f ont c o l o r=red>Alegere co r e c ta !</ font>” ) ;8 }9 e l s e {

10 throw new Exception ( ”N−a t i f a cu t a l e g e r e a co r e c ta ” ) ;11 }12 %>13 </body>14 </html>

cu pagina de tratare a exceptiei (errorpage.jsp)

Page 189: DISTR1

7.2. JSP STANDARD TAG LIBRARY JSTL 189

1 < !−−2 Aceste comentar i i sunt f o a r t e importante in cazu l u t i l i z a r i i3 nav i g a t o ru l u i IE s i a l u i apache−tomcat −5 .∗ .∗ . / 6 .∗ .∗ . In l i p s a4 l o r nu se genereaza s a l t u l l a e x c ep t i e pr in pagina j s p .5 Rolu l comentar i i l o r e s t e marirea lung imi 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 din IE6 . . . Options sa se d e z a c t i v e z e8 opt iunea ”Show f r i e n d l y HTTP e r r o r message”

10 Cu nav i ga t o ru l F i re fox nu e x i s t a aceas ta problema .11 −−>

13 <%@ page i sErrorPage=” true ” %>14 <html>15 <body>16 <div align=” cente r ”>17 <%= except ion . getMessage ( ) %>18 </div>

20 </body>21 </html>

apelate prin

1 <html>2 <body>3 <form method=post4 action=” http :// l o c a l h o s t :8080/ myserv let / j sp / e r rhand l e r . j sp ”>5 Care e s t e mater ia p r e f e r a t a din a n i i de s tud iu u n i v e r s i t a r ?6 <p>7 Algor i tmica s i programare8 <input type=” rad io ” name=” mater ia ” value=”AP” checked>9 <p>

10 Anal iza numerica11 <input type=” rad io ” name=” mater ia ” value=”AN”>12 <p>13 I n t e l i g e n t a a r t i f i c i a l a14 <input type=” rad io ” name=” mater ia ” value=”IA”>15 <p>16 <input type=submit>17 </form>18 </body>19 </html>

7.2 JSP Standard Tag Library JSTL

JSTL este o familie de biblioteci de marcaje ce ofera o serie de facilitati activitatiide realizare a paginilor Web. JSTL ajuta la separarea activitatii de programare deaceea a proiectare (design) a paginii Web.

JSTL este alcatuita din 5 biblioteci:

Page 190: DISTR1

190 CAPITOLUL 7. JAVA SERVER PAGE – JSP

URI Descriere

http://java.sun.com/jsp/jstl/core Biblioteca de bazahttp://java.sun.com/jsp/jstl/xml Biblioteca de prelucrare

a documentelor xmlhttp://java.sun.com/jsp/jstl/fmt Biblioteca de formatare a datelorhttp://java.sun.com/jsp/jstl/sql Biblioteca de lucru cu baze de datehttp://java.sun.com/jsp/jstl/functions Biblioteca de functii ajutatoare

Instalarea bibliotecilor. Bibliotecile sunt livrate ımpreuna cu apache-tomcat-*ın catalogul apache-tomcat-*\webapps\examples\WEB-INF\lib prin fisierele jstl.jarsi standard.jar.

Utilizarea bibliotecilor. In vederea utilizarii, cele doua fisiere trebuie copiateın catalogul lib al aplicatiei care utilizeaza bibliotecile.

In pagina / documentul JSP, o biblioteca utilizata trebuie declarata printr-odirectiva taglib.

7.2.1 Biblioteca de baza

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

Marcaje din biblioteca de baza:

• c:set Fixeaza o valoare ıntr-o variabila.

Atribute ale marcajului:

Atribut Fel Descriere

var obligatoriu Numele variabilei ce va stoca valoareaexpresiei.

value optional Expresia care va fi evaluata si atribuitavariabilei

scope optional Domeniul de valabilitate al variabilei.Unul din valorile:page, request, session, application.

Referirea la o variabila se face prin sintaxa ${numeVariabila}Referirea la valoarea unui camp dintr-un formular se face prin${param.numeCamp}Alaturi de obiectul param, alte obiecte predefinite sunt cookie, header,

initParam, pageContext.

Se pot defini variabile cu acelasi nume dar avand domenii de valabilitatediferita. Referirea se face prin ${pageScope.numeVariabila},

Page 191: DISTR1

7.2. JSP STANDARD TAG LIBRARY JSTL 191

${requestScope.numeVariabila}, ${sessionScope.numeVariabila},${applicationScope.numeVariabila}.

Plasand clauza empty ınaintea unei variabile, ${empty numeVariabila}, seobtine false sau true dupa cum variabila are sau nu atribuita o valoare.

• c:remove Sterge o variabila.

Atribute ale marcajului:

Atribut Fel Descriere

var obligatoriu Numele variabilei ce se sterge.scope optional Domeniul de valabilitate al variabilei.

Unul din valorile:page, request, session, application.

• c:out Afiseaza o valoare.

Atribute ale marcajului:

Atribut Fel Descriere

value obligatoriu Valoarea ce se evalueaza si se afiseaza.default optional Cea ce se afiseaza ın cazul ın care

expresia nu poate fi evaluata.escapeXml optional true / false. Valoarea implicita este true.

Pe false interpreteaza caracterele din value

ca si cod html.

• c:if Test, verificarea unei conditii.

Atribute ale marcajului:

Atribut Fel Descriere

test obligatoriu Conditia de test.var optional Numele variabilei ce va stoca valoarea

testului.scope optional Domeniul de valabilitate al variabilei

definita anterior.

In cazul ın care conditia are valoarea true se prelucreaza corpul marcajului,ın caz contrar, acesta este ignorat.

Exemplul 7.2.1 Preluarea datelor unui formular cu campurile de intrare nume,prenume si email se face prin pagina JSP

Page 192: DISTR1

192 CAPITOLUL 7. JAVA SERVER PAGE – JSP

1 <HTML>2 <%@ t a g l i b u r i=” http :// java . sun . com/ j sp / j s t l / core ” 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 . emai l }” var=” testEmai 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 tes tEmai l }” >23 E−mail :<c : out value=”${param . emai l }” />24 </c : i f>25 </BODY>26 </HTML>

• c:choose Marcajul de selectie poate contine oricate marcaje c:when si cel multun marcaj c:otherwise. Fiecare marcaj c:when contine obligatoriu atributultest. Daca ıntr-un marcaj c:when conditia are valoarea true, atunci seprelucreaza corpul acelui marcaj. In cazul ın care toate marcajele c:when aufost evaluate cu false atunci se va prelucra marcajul c:otherwise (marcajfara atribute).

• c:forEach Ciclu.

Atribute ale marcajului:

Atribut Fel Descriere

items optional Colectia care se parcurge.var optional Numele variabilei ın care se stocheaza

valoarea elementului curent.begin optional Valoarea initiala a variabilei var.end optional Valoarea finala a variabilei var.step optional Valoarea pasului de iterare. Implicit este 1.varStatus optional Informatii despre elementul curent.

Variabila varStatus are campurile:

– index valoarea curenta a elementului dupa care se realizeaza ciclarea;

– count numarul iteratiei curente;

Page 193: DISTR1

7.2. JSP STANDARD TAG LIBRARY JSTL 193

– first are valoarea true daca este primul element al ciclului;

– last are valoarea true daca este ultimul element al ciclului;

Exemplul 7.2.2 Lista parametrilor formularului de apelare a exemplului an-terior se afiseaza prin:

<h2> Lista parametrilor din formular </h2>

<ul>

<c:forEach items="${param}" var="p">

<li>

<c:out value="${p}" />

</li>

</c:forEach>

</ul>

Exemplul 7.2.3 Lista parametrilor unui header se afiseaza prin:

<h2> Lista campurilor din antet </h2>

<ul>

<c:forEach items="${header}" var="h">

<li>

<c:out value="${h}" />

</li>

</c:forEach>

</ul>

Exemplul 7.2.4 Evidentierea fontului cu care se scriu titlurile ıntr-un docu-ment html:

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

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

</c:forEach>

• c:forTokens Asigura aceasi functionalitate ca si clasei java.util.String

Tokenizer.

Atribute ale marcajului:

Atribut Fel Descriere

value obligatoriu Valoarea ce se evalueaza si se afiseaza.expresiei.

default optional Cea ce se afiseaza ın cazul ın careexpresia nu poate fi evaluata.

escapeXml optional true / false. Valoarea implicita este true.Pe false interpreteaza caracterele din value

ca si cod html.

Page 194: DISTR1

194 CAPITOLUL 7. JAVA SERVER PAGE – JSP

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

Atribute ale marcajului:

Atribut Fel Descriere

url obligatoriu Adresa documentului importat.context optional Context-ul paginii / documentului importat.

Simbolul /, urmat de numele unei aplicatiide pe acelasi server.

var optional Numele variabilei ın care va fi stocatdocumentul importat.

scope optional Domeniul de valabilitate al variabilei var.Unul din valorile:page, request, session, application.

Cu marcajul c:param se pot fixa parametri pentru pagina importata. Acestmarcaj are doua atribute name si value. Acesti parametri se transmit cumetoda get.

• c:redirect Redirectarea activitatea catre o alta pagina.

Atribute ale marcajului:

Atribut Fel Descriere

url obligatoriu Adresa paginii catre care se face redirectarea.context optional Context-ul paginii catre care se face redirectarea.

Simbolul /, urmat de numele unei aplicatiide pe acelasi server.

Prin redirectare, parametrii nu sunt retransmisi automat mai departe.

• c:url Retine adrese URL.

Atribute ale marcajului:

Atribut Fel Descriere

value obligatoriu Adresa documentului de retinut.context optional Context-ul documentului.

Simbolul /, urmat de numele unei aplicatiide pe acelasi server.

var optional Numele variabilei ın care va fi stocataadresa documentului.

scope optional Domeniul de valabilitate al variabilei var.Unul din valorile:page, request, session, application.

Page 195: DISTR1

7.2. JSP STANDARD TAG LIBRARY JSTL 195

7.2.2 Biblioteca de lucru cu baze de date

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

Marcaje din biblioteca de baza:

• sql:setDataSource Fixeaza referinta la baza de date.

Atribute ale marcajului:

Atribut Fel Descriere

dataSource optional Referinta la baza de datedriver optional Driver-ul bazei de dateurl optional url-ul bazei de dateusername optional nume utilizatorului bazei de datepassword optional parola de acces la baza de datevar optional variabila cu referinta la baza de datescope optional Domeniul de valabilitate al variabilei var.

• sql:query O interogare a bazei de date.

Atribute ale marcajului:

Atribut Fel Descriere

sql obligatoriu Fraza sqldataSource optional Referinta la baza de datestartRow optional Linia de la care se ıncepe interogareamaxRows optional Numarul maxim de rezultate acceptatevar obligatoriu Variabila cu rezultatele interogarii

bazei de datescope optional Domeniul de valabilitate al variabilei var.

• sql:update Actualizarea a bazei de date.

Atribute ale marcajului:

Atribut Fel Descriere

sql obligatoriu Fraza sqldataSource optional Referinta la baza de date

Exemplul 7.2.5 Sa se afiseze lista din agenda telefonica creata ın exemplul dinCap. Servlet.

1 <HTML>2 <%@ t a g l i b u r i=” http :// java . sun . com/ j sp / j s t l / core ” p r e f i x=”c” %>3 <%@ t a g l i b u r i=” http :// java . sun . com/ j sp / j s t l / s q l ” p r e f i x=” s q l ” %>4 <BODY>

Page 196: DISTR1

196 CAPITOLUL 7. JAVA SERVER PAGE – JSP

5 <p>6 <s q l : setDataSource7 d r i v e r=” org . apache . derby . jdbc . C l i en tDr ive r ”8 u r l=” jdbc : derby :// l o c a l h o s t :1527/ AgendaTelefonica ”9 var=”db” />

10 <s q l : query11 dataSource=”${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 gt 0}” >15 <table>16 <tr>17 <c : forEach items=”${ r e z u l t . columnNames}” var=” c o l ”>18 <th>19 <c : out value=”${ c o l }” />20 </th>21 </c : forEach>22 </ tr>23 <c : forEach items=”${ r e z u l t . rowsByIndex}” var=” l i n e ” >24 <tr>25 <c : forEach items=”${ l i n e }” var=”elem” >26 <td>27 <c : out value=”${elem}” />28 </td>29 </c : forEach>30 </ tr>31 </c : forEach>32 </table>33 </c : i f>34 </BODY>35 </HTML>

7.3 Marcaje JSP personale

Programatorul poate crea marcaje JSP proprii care se grupeaza ın colectii numitebiblioteci de marcaje. O biblioteca de marcaje este reprezentat de o identificatordat sub forma unui URI —textitUniversal Resource Identifier).

7.3.1 Marcaje fara atribute si fara corp.

Pentru a crea unui asemenea marcaj JSP propriu este necesara definirea a patrucomponente:

1. O clasa de definitie a comportamentului marcajului JSP (tag handler class).

2. Descriptorul de biblioteca de marcaje JSP, care leaga clasa de definitie a mar-cajului cu identificatorul bibliotecii de marcaje.

3. Marcajul taglib a fisierului web.xml, care permite serverului Web sa gaseascadescriptorul bibliotecii de marcaje.

4. Fisierul JSP ce utilizeaza marcajul JSP (clientul).

Page 197: DISTR1

7.3. MARCAJE JSP PERSONALE 197

Exemplificam acesta tehnologie prin

Exemplul 7.3.1 Sa se realizeze un marcaj dateTag, a carui efect sa fie afisareadatei calendaristice.

1. Clasa de definitie a comportamentului marcajului. Programul consta din:

(a) Importul pachetelor

import javax.servlet.jsp.*;

import javax.servlet.jsp.tagext.*;

Aceste pachete se gasesc ın fisierul jsp-api.jar.

(b) Un marcaj fara atribute si fara corp trebuie sa extinda clasa TagSupport

si sa suprascrie metoda doStartTag, care defineste activitatea intreprinsacand este ıntalnit marcajul ıntr-un document jsp. Metoda trebuie sareturneze constanta SKIP BODY.

public class NumeClasa extends TagSupport{

public int doStartTag(){

. . .

return SKIP_BODY;

}

}

(c) Scrierea ın fluxul de iesire se face cu un obiect JspWriter, care se obtinecu pageContext.getOut(). Metoda print a clasei JspWriter poategenera o exceptie IOException.

Textul sursa al clasei de definitie a comportamentului marcajului dateTag este:

1 package j sp ;2 import javax . s e r v l e t . j sp . ∗ ;3 import javax . s e r v l e t . j sp . tagext . ∗ ;4 import java . i o . ∗ ;5 import java . u t i l . ∗ ;

7 public class DateTag extends TagSupport{8 public int doStartTag ( ){9 try{

10 JspWriter out=pageContext . getOut ( ) ;11 out . p r i n t l n (new Date ( ) ) ;12 }13 catch ( IOException e ){14 System . out . p r i n t l n ( ”DateTagException ”+e . getMessage ( ) ) ;15 }16 return SKIP BODY;17 }18 }

Page 198: DISTR1

198 CAPITOLUL 7. JAVA SERVER PAGE – JSP

2. Descriptorul de biblioteca de marcaje JSP este dependent de versiunea tomcatfolosita. Acest fisier trebuie sa aiba extensia tld (Taglib Language Definition).Localizarea acestui fisier este definita ın elementul taglib din web.xml. Incazul unei distributii ≥ apache-tomcat-5.*, acest fisier este (mylibtag.tld):

1 <?xml version=” 1 .0 ” encoding=”ISO−8859−1” ?>2 < !DOCTYPE t a g l i b3 PUBLIC ”−//Sun Microsystems , Inc . //DTD JSP Tag Library 1 .2//EN”4 ” h t tp : // java . sun . com/ j 2 e e /dtd/web−j s p t a g l i b r a r y 1 2 . dtd”>

6 < !−− a tag l i b r a r y d e s c r i p t o r −−>7 <t a g l i b>8 <t l i b−version> 1 .0 </ t l i b−version>9 <j sp−version> 1 .2 </ jsp−version>

10 <short−name> mytags </ short−name>11 <u r i>h t t p : // cs . unitbv . ro / mytagl ib</ u r i>12 <d e s c r i p t i o n> L i b r a r i e de marcaje </ d e s c r i p t i o n>

14 <tag>15 <name> dateTag </name>16 <tag−c l a s s> j sp . DateTag </tag−c l a s s>17 <body−content> EMPTY </body−content>18 <d e s c r i p t i o n> f u r n i z e a z a data curenta </ d e s c r i p t i o n>19 </ tag>20 </ t a g l i b>

Elementul uri contine identificatorul bibliotecii de marcaje, cs.unitbv.ro/mytaglib.

Pentru fiecare marcaj propriu se completeaza un marcaj tag. Pentru un mar-caj propriu fara atribute elementele acestui marcaj sunt

(a) name Numele simbolic al marcajului.

(b) tag-class Referinta la fisierul class al clasei de definitie a comportamen-tului marcajului propriu. Referinta se face relativ la catalogul...\WEB-INF\classes

(c) description Descrierea marcajului propriu.

(d) body-content In cazul nostru are valoarea EMPTY. In cazul unui marcajcu corp se da valoarea JSP.

3. Marcajul taglib din fisierul web.xml

<taglib>

<taglib-uri>

http://cs.unitbv.ro/mytaglib

</taglib-uri>

<taglib-location>

/WEB-INF/mylibtag.tld

</taglib-location>

</taglib>

Page 199: DISTR1

7.3. MARCAJE JSP PERSONALE 199

Elementele marcajului taglib sunt:

(a) taglib-uri Identificatorul bibliotecii de marcaje.

(b) taglib-location Locatia fisierului descriptor de biblioteca de marcaje(numele calificat al fisierului, adica alcatuit din cale plus numele fisierului).

Astfel elementele constitutive se vor gasi ın:

webapps

|--> mytag

| |--> WEB-INF

| | |--> classes

| | | |--> jsp

| | | | |--> DateTag.class

| | | web.xml

| | | mylibtag.tld

| |--> jsp

| | | dateTag.jsp

4. Marcajele proprii se utilizeaza cu sintaxa

<prefix : NumeMarcaj />

Referinta la catalogul cu toate componentele necesare marcajului si prefixulse fixeaza ın directiva taglib.

Un fisier jsp care utilizeaza marcajul realizat este (dateTag.jsp):

1 <html>2 <head>3 <t i t l e>4 Tag pentru data c a l e n d a r i s t i c a curenta5 </ t i t l e>6 </head>7 <body>8 <%@ t a g l i b u r i=” http :// cs . unitbv . ro / mytagl ib ”9 p r e f i x=”mk” %>

10 <p>11 Data curenta e s t e :12 <mk: dateTag/>13 </body>14 </html>

Page 200: DISTR1

200 CAPITOLUL 7. JAVA SERVER PAGE – JSP

7.3.2 Marcaje cu atribute si fara corp.

Realizam un marcaj ziuaTag cu un atribut ziua care va fi afisat ın momentulprelucrarii marcajului.

1. Pentru fiecare atribut clasa ce defineste actiunea marcajului trebuie sa continao metoda

public void setNumeAtribut(String value){...}

care preia valoarea atributului data de parametrul value.

Exemplul 7.3.2

Pentru exemplul enuntat aceasta clasa este

1 package j sp ;2 import javax . s e r v l e t . j sp . ∗ ;3 import javax . s e r v l e t . j sp . tagext . ∗ ;4 import java . i o . ∗ ;

6 public class ZiuaTag extends TagSupport{7 St r ing z iua ;

9 public void s e tZ iua ( S t r ing value ){10 z iua=value ;11 }

13 public int doStartTag ( ){14 try{15 JspWriter out=pageContext . getOut ( ) ;16 out . p r i n t l n ( z iua ) ;17 }18 catch ( IOException e ){19 System . out . p r i n t l n ( ” ZiuaTagException ”+e . getMessage ( ) ) ;20 }21 return SKIP BODY;22 }23 }

2. In descriptorul bibliotecii de marcaje pentru fiecare atribut se defineste unmarcaj <attribute>...< /attribute> avand incluse marcajele

Nume marcaj Semnificatie Fel

name numele atributului obligatoriu

required true | false dupa cum atributul e obligatoriuobligatoriu sau nu

rtexprvalue true | false dupa cum atributul optionalse poate utiliza ıntr-o expresie

< %= numeAtribut % >

Page 201: DISTR1

7.3. MARCAJE JSP PERSONALE 201

Marcajul <tag> din descriptorul bibliotecii de marcaje devine

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

3. Utilizarea acestui marcaj este exemplificat ın

1 <html>2 <body>3 <form method=” get ”4 action=” http :// l o c a l h o s t :8080/ mytag/ j sp /ziuaTag . j sp ”>5 <p>Astazi , e s t e6 <select name=” z iua ”>7 <option value=” l u n i ”> Luni8 <option value=” marti ”> Marti9 <option value=” mie r cur i ”> Miercur i

10 <option value=” j o i ”> Jo i11 <option value=” v i n e r i ”> Viner i12 <option value=” simbata ”> Simbata13 <option value=”duminica ”> Duminica14 </ select>15 <p><input type=”submit” value=” Af i s eaza ”>16 </form>17 </body>18 </html>

unde ziuaTag.jsp este

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=” http :// cs . unitbv . ro / mytagl ib ”7 p r e f i x=”mk” %>8 <p>9 <%

10 String z i=reques t . getParameter ( ” z iua ” ) ;11 %>12 Ziua e s t e :13 <mk: ziuaTag z iua=”<%= z i %>” />14 </body>15 </html>

Page 202: DISTR1

202 CAPITOLUL 7. JAVA SERVER PAGE – JSP

7.3.3 Marcaje cu corp.

In metoda doStartTag valoarea returnata trebuie sa fie EVAL BODY INCLUDE, ınloc de SKIP BODY.

In descriptorul bibliotecii de marcaje apare

<body-content> JSP </body-content>

ın loc de EMPTY.

Daca se doreste ca marcajul sa execute actiuni dupa interpretarea corpului,atunci acele activitati sunt definite ın metoda doEndTag. Aceasta metoda re-turneaza valoarea EVAL PAGE sau SKIP PAGE dupa cum se doreste sau nu continuareaprocesarii paginii jsp.

Exemplul 7.3.3 Fie marcajul modTag care modifica un text ın caractere mari saumici dupa valoarea atributului trans. Acest marcaj poate include ale elemente.

Codul clasei ce prelucreaza marcajul este

1 package j sp ;2 import javax . s e r v l e t . j sp . ∗ ;3 import javax . s e r v l e t . j sp . tagext . ∗ ;4 import java . i o . ∗ ;

6 public class ModTag extends TagSupport{7 St r ing text ;8 boolean toUpperCase ;

10 public void setText ( S t r ing value ){11 t ex t=value ;12 }

14 public void setTrans ( S t r ing value ){15 toUpperCase=(new Boolean ( value ) ) . booleanValue ( ) ;16 }

18 public int doStartTag ( ){19 try{20 JspWriter out=pageContext . getOut ( ) ;21 i f ( toUpperCase )22 out . p r i n t l n ( t ex t . toUpperCase ( ) ) ;23 else24 out . p r i n t l n ( t ex t . toLowerCase ( ) ) ;25 }26 catch ( IOException e ){27 System . out . p r i n t l n ( ”ModTagException ”+e . getMessage ( ) ) ;28 }29 return EVAL BODY INCLUDE;30 }31 }

Descriptorul bibliotecii de marcaje se completeaza cu

Page 203: DISTR1

7.3. MARCAJE JSP PERSONALE 203

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

O pagina de utilizare a marcajului modTag cu un corp nevid este

1 <html>2 <body>3 <form method=” get ”4 action=” http :// l o c a l h o s t :8080/ mytag/ j sp /modtextTag . j sp ”>5 Introduce o f r a z &#259;6 <input type=” text ” name=” text ” s ize=”40” >7 <p>8 Se trans form &#259; &#238;n l i t e r e9 <select name=” trans ”>

10 <option value=”upperCase”> mari11 <option value=” lowerCase ”> mici12 </ select>13 <p><input type=”submit” value=” Af i s eaza ”>14 </form>15 </body>16 </html>

ımpreuna cu modtextTag.jsp

1 <html>2 <body>3 <%@ t a g l i b u r i=” http :// cs . unitbv . ro / mytagl ib ” p r e f i x=”mk” %>4 <%5 String text=reques t . getParameter ( ” t ext ” ) ;6 String t rans=reques t . getParameter ( ” t rans ” ) ;7 String t ;8 i f ( t rans . equa l s ( ”upperCase” ) )9 t=” true ” ;

10 e l s e11 t=” f a l s e ” ;12 %>13 <p>14 <mk: modTag text=”<%= text %>” t rans=”<%=t%>”>15 <mk: dateTag/>16 </mk: modTag>17 </body>18 </html>

Page 204: DISTR1

204 CAPITOLUL 7. JAVA SERVER PAGE – JSP

Page 205: DISTR1

Capitolul 8

Portlet

Prezentarea termenului de portlet se face ımpreuna cu cea de portal. Portalulca si portletul sunt aplicatii Web. Practic, un portal accesat afiseaza portlete ınferestre distincte, portletele fiind aplicatii pe care clientul le poate folosi (Fig. 8.1,Fig. 8.2).

Figure 8.1: Portal - Portlet.

O aplicatie portlet ındeplineste standardele JSR (Java Specification Request)168 si JSR 286.

Portalul este o aplicatie Web cu functionalitatile:

• Container de portleti. Containerul este responsabil de initializarea si dis-trugerea portletilor, de transmiterea cererilor catre portleti si de colectarearaspunsurilor.

• Agregarea continuturilor (Content aggregator). Permite afisarea si gestionareamai multor portlete.

• Asigura servicii dintre care amintim:

205

Page 206: DISTR1

206 CAPITOLUL 8. PORTLET

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

– acces la portal pe baza de autentificare si autorizare. Odata autorizat,un client are acces la orice portlet.

– posibilitatea personalizarii portletelor de catre clienti.

Varietatea serviciilor variaza de la un portal la altul.

Portletul este o aplicatie Web care se aseamana cu servletul prin:

• Se instaleaza ıntr-un container.

• Genereaza continut dinamic.

• Ciclul de viata este gestionat de container.

• Interactioneaza cu clientul prin modelul request/reply.

Deosebirile unui portlet fata de un servlet sunt:

• Portletul poseda mai multe variante de tratare a cererilor.

• Prin conceptul de mod (mode) se specifica variante distincte prin care portle-tul reactioneaza. Sunt definite modurile VIEW, EDIT, HELP. Actiunile core-spunzatoare sunt definite ın metodele doView, doEdit, doHelp.

Page 207: DISTR1

8.1. APACHE-PLUTO 207

• Prin WindowState se fixeaza spatiul utilizat de portlet. Valorile variabilei Win-dowState sunt NORMAL, MAXIMIZED, MINIMIZED. In varianta MAXIMIZEDportletul ocupa ıntreaga fereastra, ın timp ce ın varianta MINIMIZED portle-tul apare ıntr-o bara de titluri.

8.1 Apache-pluto

Pentru dezvoltarea unui portlet vom folosi produsul Apache-pluto care genereazaun portal ın care se pot instala / dezinstala usor portlete.

Instalarea produsului. Daca se descarca varianta ıncorporata ın serverul Webapache-tomcat, denumita pluto-bundle, atunci instalarea la dezarhivarea fisieruluidescarcat.

Utilizarea produsului. Dintr-un navigator, portalul se apeleaza prin

http://host:8080/pluto/portal

Accesul se face cu User name = password = pluto.

Instalarea unui portlet se face ın 2 pasi:

1. Desfasurarea portlet-ului: Fisierul arhivat al portletului, avand extensia war,se depune ın catalogul PlutoDomain. Apeland managerul lui apache-tomcatdin componenta Pluto admin se obtine instalarea portletului.

Alternativ, desfasurarea portlet-lui se va obtine cu apache-ant cu utilizareaunui fisier build.xml dedicat.

2. Publicarea portlet-ului se face prin componenta Pluto admin.

8.2 Dezvoltarea unui portlet

Compilarea si arhivarea unui portlet ın vederea desfasurarii se va face ruland antcu fisierul build.xml:

1 <?xml version=” 1 .0 ” encoding=”UTF−8”?>2 <p r o j e c t name=” p o r t l e t−bu i ld ” default=” deploy ” bas ed i r=” . ”>

4 <property environment=”env”/>5 < !−−6 Set CATALINAHOME or use −Dpluto . home=/path/ to /tomcat−with−p lu t o7 on command l i n e8 −−>9 <property name=” pluto . home” value=”${ env .CATALINA HOME}”/>

10 <property f i l e=” bu i ld . p r o p e r t i e s ”/>

12 < !−−13 Al l j a r s used by your p o r t l e t need to be in l i b in add i t i on to the14 p luto−ant−t a s k s j a r15 −−>

Page 208: DISTR1

208 CAPITOLUL 8. PORTLET

16 <path id=” p r o j e c t . c l a s s p a t h ”>17 < f i l e s e t d i r=” l i b ”>18 <i n c l ude name=” ∗ . j a r ”/>19 </ f i l e s e t>20 < f i l e s e t d i r=”${ pluto . home}/ l i b ”>21 <i n c l ude name=” ∗ . j a r ”/>22 </ f i l e s e t>23 </path>

25 <t a skde f26 name=” assemble ”27 classname=” org . apache . p luto . 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 pa th ”29 />

31 <t a r g e t name=” assemble ”>32 <assemble33 webxml=”${web−i n f . d i r }/web . xml”34 por t l e txml=”${web−i n f . d i r }/ p o r t l e t . xml”35 d e s t f i l e=”${ bu i ld . d i r }/web . xml”36 />37 </ t a r g e t>

39 <t a r g e t name=” i n i t ” d e s c r i p t i o n=” Creates bu i ld d i r s ”>40 <echo message=”Ant v e r s i on = ${ ant . v e r s i on }”/>41 <mkdir d e s c r i p t i o n=” Creates bu i ld d i r e c t o r y i f needed”42 d i r=”${ bu i ld . d i r }”/>43 <mkdir d e s c r i p t i o n=” Creates war d i r e c t o r y i f needed”44 d i r=”${webbuild . d i r }”/>45 <mkdir d e s c r i p t i o n=” Creates WEB−INF d i r e c t o r y i f needed”46 d i r=”${webbuild . d i r }/WEB−INF”/>47 <mkdir d e s c r i p t i o n=” Creates WEB−INF/ c l a s s e s d i r e c t o r y i f needed”48 d i r=”${ c l a s s b u i l d . d i r }”/>49 <mkdir d e s c r i p t i o n=” Creates WEB−INF/ l i b d i r e c t o r y i f needed”50 d i r=”${webbuild . d i r }/WEB−INF/ l i b ”/>51 </ t a r g e t>

53 <t a r g e t name=” compile ” depends=” i n i t ” d e s c r i p t i o n=”Compiles source ”>54 <javac 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 ”55 f o rk=” yes ”56 debug=” true ”57 debug l eve l=” l i n e s , vars , source ”58 d e s t d i r=”${ c l a s s b u i l d . d i r }”59 s r c d i r=”${ java . s r c . d i r }”/>60 </ t a r g e t>

62 <t a r g e t name=”war” depends=” compile ”>63 < !−− Move web f i l e s exc lud ing web .xml −−>64 <copy t o d i r=”${webbuild . d i r }/”>65 < f i l e s e t d i r=”${web . d i r }” exc ludes=”∗∗/web . xml”/>66 </copy>

68 < !−− Move other neccessary l i b r a r i e s −−>69 <copy t o d i r=”${webbuild . d i r }/WEB−INF/ l i b /”>70 < f i l e s e t d i r=”${ l i b . d i r }”>71 <i n c l ude name=” ∗∗/∗ . j a r ”/>72 <exc lude name=” c a s t o r ∗ . j a r ”/>73 <exc lude name=” pluto ∗ . j a r ”/>74 <exc lude name=” p o r t l e t ∗ . j a r ”/>

Page 209: DISTR1

8.2. DEZVOLTAREA UNUI PORTLET 209

75 <exc lude name=” s e r v l e t ∗ . j a r ”/>76 <exc lude name=” j u n i t ∗ . j a r ”/>77 </ f i l e s e t>78 </copy>

80 <a n t c a l l t a r g e t=” assemble ”/>

82 < !−− Create war in deployment d i r e c t o r y −−>83 <war based i r=”${webbuild . d i r }” update=” f a l s e ”84 w a r f i l e=”${app . name } . war”85 webxml=”${ bu i ld . d i r }/web . xml”/>86 </ t a r g e t>

88 <t a r g e t name=” bu i ld ” depends=” clean , war”/>

90 <t a r g e t name=” deploy ” depends=” bu i ld ”>91 <echo message=” Deploying to p luto . home=${pluto . home}”/>92 < !−−93 Remove former deployment because sometimes94 tomcat does not f u l l y redep loy a war95 −−>96 <d e l e t e97 d i r=”${ pluto . home}/webapps/${app . name}”98 f a i l o n e r r o r=” true ”99 />

100 < !−− Deploy war f i l e −−>101 <copy102 f i l e=”${app . name } . war”103 t o d i r=”${ pluto . home}/PlutoDomain”104 ove rwr i t e=” true ”105 />106 < !−− Deploy con tex t deployment d e s c r i p t o r f o r Tomcat −−>107 <copy108 f i l e=”${ conf . d i r }/${app . name } . xml”109 t o d i r=”${ pluto . home}/ conf / Cata l ina / l o c a l h o s t ”110 ove rwr i t e=” f a l s e ”111 />

113 </ t a r g e t>

115 <t a r g e t name=” c l ean ” d e s c r i p t i o n=” Cleans bu i ld ”>116 <d e l e t e d i r=”${ bu i ld . d i r }” f a i l o n e r r o r=” f a l s e ”/>117 </ t a r g e t>

119 </ p r o j e c t>

Fisierul de proprietati build.properties este

1 #bui ld . p r o p e r t i e s2 #Standard p r o p e r t i e s f o r Ant bu i ld o f a Pluto 1 .1 p o r t l e t

4 #module name5 app . name=NumePortlet

7 #Direc tory that ho lds source code8 s r c . d i r = s r c /main9 java . s r c . d i r = ${ s r c . d i r }/ java

11 #Direc tory that ho lds documentation12 doc . d i r = docs

Page 210: DISTR1

210 CAPITOLUL 8. PORTLET

14 #Direc tory that ho lds f i l e s to be b u i l t i n to a jar , war or ear15 bu i ld . d i r = bu i ld16 webbuild . d i r = ${ bu i ld . d i r }/webapp17 c l a s s b u i l d . d i r = ${webbuild . d i r }/WEB−INF/ c l a s s e s

19 #Direc tory that ho lds c o n f i g u r a t i o n f i l e s20 conf . d i r = ${ s r c . d i r }/ r e sou r c e

22 #Direc tory that ho lds l i b r a r i e s r equ i r ed to bu i ld and run the c l a s s e s23 l i b . d i r = l i b

25 #Direc tory that ho lds webapp f i l e s26 web . d i r = ${ s r c . d i r }/webapp

28 #WEB−INF d i r e c t o r y29 web−i n f . d i r = ${web . d i r }/WEB−INF

32 #Direc tory that ho lds f i l e s to bu i ld d i s t r i b u t i o n33 d i s t . d i r = ${ bu i ld . d i r }/ d i s t

Pentru utilizarea acestui build.xml este nevoie de structura urmatoare de cat-aloage

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

Page 211: DISTR1

8.3. ELEMENTE DE PROGRAMARE 211

Fisierele castor.1.1.1.jar, pluto-descriptor-api-*.jar, pluto-descriptor-impl-*.jar, portlet-container-*.jar se copiaza din catalogul PLUTO HOME\shared\lib.

Fisierul web.xml de mai sus este

2 <?xml version=” 1 .0 ” encoding=”UTF−8”?>

4 <web−app xmlns=” ht tp : // java . sun . com/xml/ns/ j 2 e e ”5 xmlns :x s i=” h t t p : //www. w3 . org /2001/XMLSchema−i n s t ance ”6 xs i : s chemaLocat ion=” h t tp : // java . sun . com/xml/ns/ j 2 e e7 h t t p : // java . sun . com/xml/ns/ j 2 e e /web−app 2 4 . xsd”8 version=” 2 .4 ”>

10 </web−app>

Continutul final al acestui fisier rezulta ın urma obiectivului ant assemple, ıncare se preiau date din fisierul de configurare al portletului portlet.xml. Editareafisierului portlet.xml este sarcina programatorului.

Fisierul NumePortlet.xml este utilizat la desfasurarea aplicatie, fiind copiat ıncatalogul conf\Catalina\localhost al lui apache-tomcat sau Apache-pluto. Acestfisier are continutul:

1 <Context path=”NumePortlet” docBase=” . . \ PlutoDomain\NumePortlet . war”2 crossContext=” true ”/>

8.3 Elemente de programare

Orice portlet implementeaza interfata Portlet. Interfata Portlet declara 4metode

public interface Portlet{

public void init(PortletConfig config) throws PortletException;

public void processAction(ActionRequest request, ActionResponse

response) throws PortletException, java.io.IOException;

public void render(RenderRequest request, RenderResponse

response) throws PortletException, java.io.IOException;

public void destroy();

}

Metoda processAction prelucreaza cererea emisa de containerul de portlete. Lasolicitarea containerului, metoda render regenereaza continutul unui portlet.

Clasa GenericPortlet este implementarea initiala a interfetei Portlet. Ex-tinzand clasa GenericPortlet, sarcina programatorului este sa suprascrie metodele

Page 212: DISTR1

212 CAPITOLUL 8. PORTLET

• doView pentru tratarea modului VIEW;

protected void doView(RenderRequest req,RenderResponse res)throws PortletException, IOException

• doEdit pentru tratarea modului EDIT;

protected void doEdit(RenderRequest req,RenderResponse res)throws PortletException, IOException

• doHelp pentru tratarea modului HELP;

protected void doHelp(RenderRequest req,RenderResponse res)throws PortletException, IOException

• init, destroy pentru initializarea, respectiv oprirea portletului.

void init() throws PortletException

void init(PortletConfig config) throws PortletException

void destroy()

si eventual, sa defineasca continutul metodei

public void processAction(ActionRequest request,ActionResponse response)throws PortletException, java.io.IOException;

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

Exemplul 8.3.1 Portletul HelloWorld.

1 package h e l l o ;2 import java . i o . ∗ ;3 import javax . p o r t l e t . ∗ ;

5 public class Hel loWor ldPort le t extends Gener i cPor t l e t {6 protected void doView ( RenderRequest request , RenderResponse re sponse )7 throws Port le tExcept ion , IOException{8 re sponse . setContentType ( ” text /html” ) ;9 re sponse . getWriter ( ) . p r i n t l n ( ” He l lo World ! ” ) ;

10 }

12 //Alta var ian ta de programare13 /∗14 pu b l i c vo id doView(RenderRequest req , RenderResponse res )15 throws Por t l e tExcep t ion , IOException {16 res . setContentType (” t e x t /html ” ) ;17 PrintWriter out=res . getWri ter ( ) ;18 out . p r i n t l n (”<h2>”);19 out . p r i n t l n (” He l lo World ! ” ) ;20 out . p r i n t l n (”</h2>”);21 }22 ∗/23 }

Page 213: DISTR1

8.3. ELEMENTE DE PROGRAMARE 213

Fisierul portlet.xml este

1 <?xml version=” 1 .0 ” encoding=”UTF−8”?>2 <p o r t l e t−app xmlns=” ht tp : // java . sun . com/xml/ns/ p o r t l e t / p o r t l e t−app 2 0 . xsd”3 xmlns :x s i=” h t t p : //www. w3 . org /2001/XMLSchema−i n s t ance ”4 xs i : s chemaLocat ion=” h t tp : // java . sun . com/xml/ns/ p o r t l e t / p o r t l e t−app 2 0 . xsd5 h t t p : // java . sun . com/xml/ns/ p o r t l e t / p o r t l e t−app 2 0 . xsd”6 id=”myPortletApp” version=” 2 .0 ”>

8 <p o r t l e t>9 <d e s c r i p t i o n>Hel lo World as 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>Hel loWorld1Port let</ p o r t l e t−name>11 <di sp lay−name>Hel lo World P o r t l e t</ d i sp lay−name>12 <p o r t l e t−c l a s s>h e l l o . He l loWor ld1Port let</ p o r t l e t−c l a s s>13 <supports>14 <mime−type>t ex t /html</mime−type>15 <p o r t l e t−mode>VIEW</ p o r t l e t−mode>16 </ supports>17 <p o r t l e t−i n f o>18 < t i t l e>Hel lo 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>

Exemplul 8.3.2 Evidentierea modurilor VIEW, EDIT si HELP.

1 package h e l l o p l u t o ;2 import java . i o . ∗ ;3 import javax . p o r t l e t . ∗ ;

5 public class He l l oP lu toPor t l e t extends Gener i cPor t l e t {6 public void doView ( RenderRequest req , RenderResponse r e s )7 throws Port le tExcept ion , IOException {8 r e s . setContentType ( ” text /html” ) ;9 Writer out=r e s . getWriter ( ) ;

10 out . wr i t e ( ”<strong>Hel lo Pluto in view mode</strong>” ) ;11 }

13 public void doEdit ( RenderRequest req , RenderResponse r e s )14 throws Port le tExcept ion , IOException {15 r e s . setContentType ( ” text /html” ) ;16 Writer out=r e s . getWriter ( ) ;17 out . wr i t e ( ”<i>Hel lo Pluto in e d i t mode</i>” ) ;18 }

20 public void doHelp ( RenderRequest req , RenderResponse r e s )21 throws Port le tExcept ion , IOException {22 r e s . setContentType ( ” text /html” ) ;23 Writer out=r e s . getWriter ( ) ;24 out . wr i t e ( ”<u>Hel lo Pluto in he lp mode</u>” ) ;25 }26 }

Fisierul portlet.xml este

1 <?xml ve r s i o n=” 1 .0 ” encoding=”UTF−8”?>2 <p o r t l e t−app xmlns=” http :// java . sun . com/xml/ns/ p o r t l e t / p o r t l e t−app 2 0 . xsd”

Page 214: DISTR1

214 CAPITOLUL 8. PORTLET

3 xmlns : x s i=” http ://www. w3 . org /2001/XMLSchema−i n s t ance ”4 x s i : schemaLocation=” http :// java . sun . com/xml/ns/ p o r t l e t / p o r t l e t−app 2 0 . xsd5 http :// java . sun . com/xml/ns/ p o r t l e t / p o r t l e t−app 2 0 . xsd”6 id=”myPortletApp” v e r s i o n=” 2 .0 ”>

8 <p o r t l e t >9 <d e s c r i p t i o n >Hel lo Pluto as 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>Hel l oP lutoPor t l e t </p o r t l e t−name>11 <di sp lay−name>Hel lo Pluto</d i sp lay−name>12 <p o r t l e t−class>h e l l o p l u t o . He l l oP lutoPor t l e t </p o r t l e t−class>13 <supports>14 <mime−type>t ex 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 </supports>19 <p o r t l e t−i n fo>20 <t i t l e >Hel lo Pluto Port l e t </ t i t l e >21 </p o r t l e t−i n fo>22 </p o r t l e t >23 </p o r t l e t−app>

Exemplul 8.3.3 Portletul Hello. Portletul afiseaza o zona text de introducere aunui nume si un buton. Odata introdus numele, la apasarea butonului se afisaezatextul Hello nume si un buton de reluare.

1 package hel loname ;

3 import java . i o . ∗ ;4 import javax . p o r t l e t . ∗ ;5 import java . u t i l . Enumeration ;

7 public class HelloNamePortlet extends Gener i cPor t l e t {

9 public void doView ( RenderRequest req , RenderResponse r e s )10 throws Port le tExcept ion , IOException {11 r e s . setContentType ( ” text /html” ) ;12 St r ing nume=( St r ing ) req . getParameter ( ”name” ) ;13 Port l e tReques tDi spatcher prd=null ;14 i f (nume==null ){15 prd=getPort l e tContext ( ) . getRequestDispatcher ( ”/ j sp / input . j sp ” ) ;16 prd . i n c lude ( req , r e s ) ;17 }18 else {19 // Varianta cu a f i s a r e pr in View20 /∗21 Writer out=res . getWri ter ( ) ;22 out . wr i t e (” He l lo ”+ nume ) ;23 PortletURL renderURL=res . createRenderURL ( ) ;24 renderURL . setPort le tMode ( PortletMode .VIEW) ;25 renderURL . setWindowState (WindowState .NORMAL) ;26 out . wr i t e (”<p><a hre f=\””+renderURL . t oS t r i n g ()+”\”> Reluare </a>”);27 ∗/28 // Varianta cu a f i s a r e pr in t r−un f i s i e r j s p29 prd=getPort l e tContext ( ) . getRequestDispatcher ( ”/ j sp / output . j sp ” ) ;30 prd . i n c lude ( req , r e s ) ;

Page 215: DISTR1

8.3. ELEMENTE DE PROGRAMARE 215

31 }32 }

34 public void proces sAct ion ( ActionRequest req , ActionResponse r e s )35 throws IOException , Por t l e tExcept ion {36 // Preia parametr i i s i l e t r im i t e c e l u i care a emis cererea37 Enumeration params=req . getParameterNames ( ) ;38 while ( params . hasMoreElements ( ) ){39 St r ing parameterName = ( St r ing ) params . nextElement ( ) ;40 St r ing parameterValue=req . getParameter ( parameterName ) ;41 r e s . setRenderParameter ( parameterName , parameterValue ) ;42 }43 }44 }

Fisierele input.jsp si putput.jsp au codurile

1 <%@ t a g l i b u r i=” http :// java . 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 eOb j e c t s />3 <div align=” cente r ”>4 Introduce &#355; i numele :5 <br/>6 <form action=”<p o r t l e t : actionURL />”7 method=”POST”>8 <br>9 <input type=” text ” name=”name”/>

10 <br>11 <input type=”submit” name=”submitButton” value=”Apasa−ma” />12 </form>13 </div>

si respectiv

1 <%@ t a g l i b u r i=” ht t p : // java . 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 St r ing r e s u l t=” He l lo ”+renderRequest . getParameter ( ”name”)+” ! ” ;6 out . p r i n t l n ( r e s u l t ) ;7 %>8 <p><a h r e f=”<port let : renderURL portletMode=”view” windowState=”normal” />”>9 Reluare

10 </a> .

Exemplul 8.3.4 Cel mai mare divizor comun a doua numere naturale ıntr-un port-let.

Varianta ın care calculul este programat ın portlet.

1 package cmmdc ;

3 import java . i o . ∗ ;4 import javax . p o r t l e t . ∗ ;5 import java . u t i l . Enumeration ;

7 public class CmmdcPortlet extends Gener i cPor t l e t {

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

Page 216: DISTR1

216 CAPITOLUL 8. PORTLET

10 throws Port le tExcept ion , IOException {11 r e s . setContentType ( ” text /html” ) ;12 Port l e tReques tDi spatcher prd=null ;13 St r ing rez=req . getParameter ( ” r ez ” ) ;14 i f ( r e z==null ){15 prd=getPort l e tContext ( ) . getRequestDispatcher ( ”/ j sp / input . j sp ” ) ;16 prd . i n c lude ( req , r e s ) ;17 }18 else {19 prd=getPort l e tContext ( ) . getRequestDispatcher ( ”/ j sp / output . j sp ” ) ;20 prd . i n c lude ( req , r e s ) ;21 }22 }

24 public void proces sAct ion ( ActionRequest req , ActionResponse r e s )25 throws IOException , Por t l e tExcept ion {26 // Preia parametr i i s i l e t r im i t e c e l u i care a emis cererea27 St r ing sm=req . getParameter ( ”m” ) ;28 St r ing sn=req . getParameter ( ”n” ) ;29 long m=Long . parseLong (sm ) ;30 long n=Long . parseLong ( sn ) ;31 long c=cmmdc(m, n ) ;32 r e s . setRenderParameter ( ” r ez ” , (new Long ( c ) ) . t oS t r i ng ( ) ) ;33 }

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

37 }

Fisierele inputCmmdc.jsp si outputCmmdc.jsp au codurile

1 <%@ t a g l i b u r i=” http :// java . 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 eOb j e c t s />3 <div align=” cente r ”>4 <form action=”<p o r t l e t : actionURL />”5 method=”POST”>6 <table border=”1” >7 <tr>8 <td> Primul num&#259; r </td>9 <td> <input type=” text ” name=”m”/> </td>

10 </ tr>11 <tr>12 <td> Al d o i l e a num&#259; r </td>13 <td> <input type=” text ” name=”n”/> </td>14 </ tr>15 <tr>16 <td>17 <input type=”submit” name=”submitButton” value=” Calcu leaza ” />18 </td>19 </ tr>20 </table>21 </form>

23 </div>

si respectiv

1 <%@ t a g l i b u r i=” http :// java . 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 eOb j e c t s />

Page 217: DISTR1

8.3. ELEMENTE DE PROGRAMARE 217

4 <P>5 <%6 String r e s u l t=”Cmmdc ”+renderRequest . getParameter ( ” r ez ”)+” ! ” ;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 portletMode=”view” windowState=”normal” />”>12 Reluare13 </a>

Varianta ın care calculul este programat ıntr-o componenta Java (bean)si care este apelat ın pagina jsp de afisare a rezultatului.

1 package cmmdc ;

3 import java . i o . ∗ ;4 import javax . p o r t l e t . ∗ ;5 import java . u t i l . Enumeration ;

7 public class CmmdcPortlet extends Gener i cPor t l e t {

9 public void doView ( RenderRequest req , RenderResponse r e s )10 throws Port le tExcept ion , IOException {11 r e s . setContentType ( ” text /html” ) ;12 Port l e tReques tDi spatcher prd=null ;13 St r ing sb=req . getParameter ( ” submitButton” ) ;14 i f ( sb==null ){15 prd=getPort l e tContext ( ) . getRequestDispatcher ( ”/ j sp /inputCmmdc . j sp ” ) ;16 prd . i n c lude ( req , r e s ) ;17 }18 else {19 prd=getPort l e tContext ( ) . getRequestDispatcher ( ”/ j sp /outputCmmdc . j sp ” ) ;20 prd . i n c lude ( req , r e s ) ;21 }22 }

24 public void proces sAct ion ( ActionRequest req , ActionResponse r e s )25 throws IOException , Por t l e tExcept ion {26 // Preia parametr i i s i l e t r im i t e c e l u i care a emis cererea27 Enumeration params=req . getParameterNames ( ) ;28 while ( params . hasMoreElements ( ) ) {29 St r ing parameterName = ( St r ing ) params . nextElement ( ) ;30 St r ing parameterValue=req . getParameter ( parameterName ) ;31 System . out . p r i n t l n ( ” >> parameterName = ” + parameterName +32 ” <=> parameterValue = ” + parameterValue ) ;33 r e s . setRenderParameter ( parameterName , parameterValue ) ;34 }35 }36 }

Codul componentei Java

1 public class CmmdcBean{

3 private St r ing m=”” ;4 private St r ing n=”” ;

6 public void setM ( St r ing m){

Page 218: DISTR1

218 CAPITOLUL 8. PORTLET

7 this .m=m;8 }9 public void setN ( St r ing n){

10 this . n=n ;11 }12 public St r ing getM (){13 return m;14 }15 public St r ing getN (){16 return n ;17 }18 public St r ing cmmdc( ){19 long m0=Long . parseLong (m) ;20 long n0=Long . parseLong (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 oS t r i ng ( ) ;30 }31 }

Pagina outputCmmdc.jsp

1 <%@ t a g l i b u r i=” http :// java . sun . com/ p o r t l e t ” p r e f i x=” p o r t l e t ” %>2 <j sp : useBean id=”myCmmdcBean” class=”cmmdc . CmmdcBean” scope=” s e s s i o n ”/>3 <j sp : s e tProper ty name=”myCmmdcBean” property=”∗”/>

5 <p o r t l e t : d e f i n eOb 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 portletMode=”view” windowState=”normal” />”>14 Reluare15 </a>

Varianta ın care care calculul este programat ıntr-un servlet. Servletulutilizat este cel prezentat ın capitolul Servlet, (6.3.2), dar inclus ın pachetul portlet-ului. Fisierul inputCmmdc.jsp are ın plus linia

<input type="hidden" name="tip" value="text/html"/>

iar ın codul clasei CmmdcPortlet, ın locul liniei

prd=getPortletContext().getRequestDispatcher("/jsp/outputCmmdc.jsp");

apare

prd=getPortletContext().getRequestDispatcher("/cmmdc");

Page 219: DISTR1

8.3. ELEMENTE DE PROGRAMARE 219

adica ın locul invocarii paginii JSP, dispecerul apeleaza servletul. In servlet esteesentiala furnizarea rezultatului ın format html. Pagina html generata se ıncarca ınfereastra portlet-ului.

Fisierul web.xml, ınaintea completarii prin ant, este

1 <?xml version=” 1 .0 ” encoding=”UTF−8”?>

3 <web−app xmlns=” ht tp : // java . sun . com/xml/ns/ j 2 e e ”4 xmlns :x s i=” h t t p : //www. w3 . org /2001/XMLSchema−i n s t ance ”5 xs i : s chemaLocat ion=” h t tp : // java . sun . com/xml/ns/ j 2 e e6 h t t p : // java . sun . com/xml/ns/ j 2 e e /web−app 2 4 . xsd”7 version=” 2 .4 ”>

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 <ur l−pattern>/cmmdc</ ur l−pattern>17 </ s e r v l e t−mapping>18 </web−app>

Interfata PortletPreferences

Atribute, adica perechi de tip String (nume,valoare) definite ın fisierul portlet.xmlprin

<portlet-preferences>

<preference>

<name>nume_atribut</name>

<value>valoare_atribut</value>

<read-only>true|false</read-only>

</preference>

. . .

</portlet-preferences>

Atributele se transmit metodelor doView, doEdit si doHelp. Suportul esteoferit prin interfata PortletPreferences.

Metode

• String getValue(String key, String def )

Returneaza valoarea primului atribut avand numele key. In lipsa atributuluisau a valorii returneaza valoarea def.

• String[] getValues(String key, String[] def )

Returneaza toate valorile atributului key.

Page 220: DISTR1

220 CAPITOLUL 8. PORTLET

• Enumeration<String> getNames()

Suport pentru acces la numele atributelor care au valoare.

• Map<String,String[]> getMap()

Suport pentru acces la atribute.

Un obiect care implementeaza interfata PortletPreferences se obtine prinmetoda getPreferences() a clasei RenderRequest.

Exemplul 8.3.5 Portlet ın care se preiau si se afiseaza valori ale atributelor.

Codul portletului este

1 package p r e f ;

3 import java . i o . ∗ ;4 import javax . p o r t l e t . ∗ ;

6 public class P r e f P o r t l e t extends Gener i cPor t l e t {

8 public void doView ( RenderRequest req , RenderResponse r e s )9 throws Port le tExcept ion , IOException {

10 P o r t l e t P r e f e r e n c e s p r e f s = req . g e t P r e f e r e n c e s ( ) ;11 St r ing a t t r 1 = p r e f s . getValue ( ”ATTR1” , ” a t t r 1 ” ) ;12 St r ing a t t r 2 = p r e f s . getValue ( ”ATTR2” , ” a t t r 2 ” ) ;13 r e s . setContentType ( ” text /html” ) ;14 Writer out=r e s . getWriter ( ) ;15 out . wr i t e ( ”<strong>”+at t r 1+” <−−> ”+at t r 2+”</strong>” ) ;16 }17 }

iar atributele din fisierul portlet.xml sunt

<portlet-preferences>

<preference>

<name>ATTR1</name>

<value>Programare distribuita</value>

<read-only>true</read-only>

</preference>

<preference>

<name>ATTR2</name>

<!--

<value>Analiza numerica</value>

-->

<read-only>true</read-only>

</preference>

</portlet-preferences>

Al doilea atribut nu are valoare.Portletul afiseaza textul Programare distribuita <–>attr2.

Page 221: DISTR1

8.4. PRODUSE PORTAL 221

8.4 Produse Portal

Termenul portal va desemna

• aplicatia informatica prin care o institutie comunica cu lumea exterioara

• produsul informatic care realizeaza aplicatia amintita la pct. anterior

In cele ce urmeaza ne vom referi doar la produse portal care sunt containere deportlete.

Dezvoltarea unui portal al unei organizatii se face pe produse specializate acestuiscop. 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 SpecialInterest Group) si a fost utilizat de mai multe universitati ca suport ın constructiaportalului specific.

Instalarea produsului. Distributia produsului se face ın doua variante

• uPortal-*.*.* - uPortal-only ;

• uPortal-*.*.*-quick-start care ınglobeaza toate resursele necesare functionarii(apache-ant, apache-tomcat, apache-maven, HypersonicSQLDB).

In cele ce urmeaza utilizam varianta uPortal-quick-start. Instalarea produsuluirevine la dezarhivarea fisierului descarcat.

Lansarea portalului. In urma dezarhivarii, ın catalogul uPortal HOME segaseste un fisier build.xml, ale carei obiective asigura lansarea portalului1.

Se completeaza fisierul ant.bat cu referinta set JAVA HOME=...

Lansarea portalului consta ın executarea comenzii

ant start

De fapt se porneste SGBD HypersonicSQLDB si serverul Web apache-tomcat.Oprirea portalului se face prin executarea comenzii

1La prima executare a unei operatii asupra portalului, calculatorul trebuie sa fie conectat lainternet, deoarece mai multe resurse sunt descarcate prin apache-maven. Aceste resurse se depunın c:\Documents and Settings\adminName\.m2\repository.

Page 222: DISTR1

222 CAPITOLUL 8. PORTLET

ant stop

Dintr-un navigator, portalul se acceseaza prin

http://host:8080/uPortal

Accesarea portalului se poate face doar de detinatorii unui cont (UserName,Password). Administratorul (UserName=Password=admin) poate crea conturi noi.

Instalarea unui portlet consta ın desfasurarea si publicarea lui.Compilarea si arhivarea portletului se poate face cu apache-ant In acest scop se

creaza structura

|--> lib

| | portlet-api-1.0.jar

|--> pachetul portlet-ului

| |--> jsp

| | | *.jsp

| |--> WEB-INF

| | |--> classes

| | | | *.java

| | | web.xml

| | | portlet.xml

| build.xml

cu fisierele *.java, *.jsp si portlet.xml corespunzatoare portletului iar web.xml estegeneric

1 <?xml version=” 1 .0 ” encoding=”ISO−8859−1”?>2 < !DOCTYPE web−app PUBLIC3 ”−//Sun Microsystems , Inc . //DTD Web Appl i ca t ion 2 .3//EN”4 ” h t tp : // java . sun . com/dtd/web−app 2 3 . dtd”>5 <web−app>6 </web−app>

Fisierul build.xml, compilare si arhivare este

1 <p r o j e c t name=” p o r t l e t−bu i ld ” default=”war” based i r=” . ”>

3 <property name=” package ” value=” h e l l o ” />4 <property name=” p o r t l e t . name” value=” HelloNamePortlet ” />5 <property name=” bu i ld . d i r ” va lue=” bu i ld ” />

7 <path id=” p r o j e c t . c l a s s p a t h ”>8 < f i l e s e t d i r=” l i b ”>9 <i n c l ude name=” ∗ . j a r ”/>

10 </ f i l e s e t>11 </path>

13 <t a r g e t name=” i n i t ” >14 <d e l e t e d i r=”${package }/${ bu i ld . d i r }” />15 <mkdir d i r=”${package }/${ bu i ld . d i r }” />16 <mkdir d i r=”${package }/${ bu i ld . d i r }/ j sp ” />17 <mkdir d i r=”${package }/${ bu i ld . d i r }/WEB−INF” />18 <mkdir d i r=”${package }/${ bu i ld . d i r }/WEB−INF/ c l a s s e s ” />19 </ t a r g e t>

21 <t a r g e t name=” compile ” depends=” i n i t ” d e s c r i p t i o n=”Compiles source ”>

Page 223: DISTR1

8.4. PRODUSE PORTAL 223

22 <javac 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 }/${ bu i ld . 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>

27 <t a r g e t name=”war” depends=” compile ”>28 <copy t o d i r=”${package }/${ bu i ld . d i r }/WEB−INF/”29 f i l e=”${package }/WEB−INF/ p o r t l e t . xml” />30 <copy t o d i r=”${package }/${ bu i ld . d i r }/ j sp ”>31 < f i l e s e t d i r=”${package }/ j sp ”>32 <i n c l ude name=” ∗ . j s p ”/>33 </ f i l e s e t>34 </copy>

36 <war based i r=”${package }/${ bu i ld . d i r }” update=” f a l s e ”37 w a r f i l e=”${ p o r t l e t . name } . war”38 webxml=”${package }/WEB−INF/web . xml”/>39 </ t a r g e t>

41 <t a r g e t name=” bu i ld ” depends=” clean , war”/>

43 <t a r g e t name=” c l ean ” d e s c r i p t i o n=” Cleans bu i ld ”>44 <d e l e t e d i r=”${ bu i ld . d i r }” f a i l o n e r r o r=” f a l s e ”/>45 </ t a r g e t>

47 </ p r o j e c t>

Desfasurarea portlet-ului se face cu apache-ant utilizand fisierul build.xml dinuPortal HOME\uPortal-*.*.* prin

ant deployPortletApp -DportletApp=arhiva portlet-ului.war

In urma acestei operatii, portlet-ul se dezarhiveaza ın uPortal HOME\apache-tomcat-*.*.*\webapps iar fisierul web.xml este actualizat.

Publicarea portlet-ului se face cu rolul de administrator. Dupa conectare lauPortal

1. AdminTools → Portlet Manager → Publish a new channel

2. Se parcurg meniurile Channel Manager

(a) Din meniul Channel Type se selecteaza optiunea Portlet. Clic Next.

(b) In meniul General Settings se fixeaza toti parametrii indicati. Clic Next.

(c) In meniul Portlet Descriptor se fixeaza

• Contextul portlet-ului, adica catalogul din webapps care contine portlet-ul. In mod obligatoriu primul caracter este / (slash) Pentru fixareaacestui parametru se va consulta fisierul web.xml.

• Numele portlet-ului asa cum este definit ın fisierul portlet.xml.

Clic Next.

(d) In meniul Portlet Preferences, clic Next.

Page 224: DISTR1

224 CAPITOLUL 8. PORTLET

(e) In meniul Display Settings, clic Next.

(f) In meniul Channel Controls, clic Next.

(g) In meniul Categories se fixeaza categoria canalului si cel putin un mem-bru.

Select Marked → Next.

(h) In meniul Groups se fixeaza grupul si cel putin un membru.

Select Marked → Next

Grupul desemneaza clientii care pot publica portlet-ul.

(i) In meniul Review, clic Finish.

Canalul portlet-ului apare ın lista afisata.

3. Fiecare client care poate utiliza portlet-ul - adica cei din grupul selectat, ılpublica prin componenta Add Content.

Pentru administrator: AdminTools → Customize urmat de

(a) Clic pe un buton Add Channel corespunzator locului unde vrem sa fiepozitionat portlet-ul.

(b) In User Preferences,

i. se alege categoria portlet-ului, clic go;

ii. se alege numele portlet-ului, clic Add Channel.

(c) Clic pe numele canalului corespunzator portlet-ului. Canalul este afisatın meniul Welcome.

(d) Clic pe numele canalului din meniul Welcome lanseaza portlet-ul.

Un client elimina un portlet prin clic pe butonul Remove din fereastra portlet-ului.

Administratorul portalului sterge un portlet prin clic pe butonul de ınchidereın lista portlet-elor publicate din AdminTools → Portlet Manager → Modify a

currently published channel.

Asemanator, se pot publica ın uPortal aplicatii Web. Deosebirea esentiala esteca 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 executa ruland distributia jetspeed-2.*.*-installer.jar.

Versiunea instalata a platformei jetspeed este construita peste o distributieapache-tomcat-*. Astfel, lansarea se face apeland bin\startup.bat.

Portalul se acceseaza, dintr-un navigator, prin

Page 225: DISTR1

8.4. PRODUSE PORTAL 225

http://localhost:8080/jetspeed

Desfasurarea unui portlet consta ın copierea arhivei war corespunzatoare, re-alizat ın 8.4.1, ın catalogul

Jetspeed HOME\webapps\jetspeed\WEB-INF\deploy

Pe rol de admin (acces cu valorile initiale username=password=admin), publi-carea portlet-ului presupune

1. Clic pe icon-ul butonului Edit - aflat sub butonul logout.

2. Clic pe butonul Add Portlet, aflat sub butonul Edit.

3. Clic pe butonul Add al portlet-ului care se doreste publicat.

4. Clic pe sageata de reıntoarcere, urmat de clic pe iconul butonului View - aflatpe pozitia butonului Edit.

Pentru a sterge un portlet, dupa primul pas anterior, se apasa butonul deınchidere din zona portlet-ului.

Page 226: DISTR1

226 CAPITOLUL 8. PORTLET

Page 227: DISTR1

Capitolul 9

Java Web Start

9.1 Java Web Start

O aplicatie Java destinata a fi utilizata pe un calculator poate fi valorificatasi ıntr-o retea, pe baza protocolului Java Network Launching Protocol - JNLP.Tehnologia poarta numele de Java Web Start.

Aplicatia Java trebuie sa satisfaca o serie de restrictii:

• Aplicatia trebuie arhivata cu jar;

• Eventualele date necesare aplicatiei se introduc prin intermediul unei interfetegrafice (swing, SWT, apache-pivot);

• Acces limitat la proprietatile si resursele sistemului client.

Aplicatiei i se ataseaza un fisier xml, dar cu extensia jnlp, care se va apeladintr-un navigator. Pentru acest fisier folosim terminologia de fisier jnlp.

Fisierul jnlp fixeaza:

• referinta URL a aplicatie (prin atributul codebase);

• arhivele jar utilizate (prin atributul href);

• clasa cu metoda main (prin atributul main-class).

Ansamblul de resurse formeaza o aplicatie Web care poate fi desfasurata ıntr-un server Web (Microsoft Internet Information Service (IIS), apache) sau poate fiincorporat ıntr-un servlet, caz ın care desfasurarea va fi ıntr-un server Web containerde servlet.

Aratam activitatile care trebuie ıntreprinse ın cazul unui exemplu simplu dat declasa VisualCmmdc.java.

227

Page 228: DISTR1

228 CAPITOLUL 9. JAVA WEB START

1 public class VisualCmmdc extends javax . swing . JFrame {2 public VisualCmmdc ( ){3 initComponents ( ) ;4 }

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

8 private void initComponents ( ) {9 // cod generat de Netbeans

10 }

12 private void cmmdcButtonMouseClicked ( java . awt . event . MouseEvent evt ){13 try{14 St r ing sm=mTextField . getText ( ) ;15 St r ing sn=nTextField . getText ( ) ;16 long m=Long . parseLong (sm ) ;17 long n=Long . parseLong ( sn ) ;18 long c=cmmdc(m, n ) ;19 St r ing s=(new Long ( c ) ) . t oS t r i ng ( ) ;20 cmmdcTextField . setText ( s ) ;21 }22 catch ( Exception e ){23 System . e r r . p r i n t l n ( ” Exception : ”+e . getMessage ( ) ) ;24 }25 }

27 private void exitForm ( java . awt . event . WindowEvent evt ){28 System . e x i t ( 0 ) ;29 }

31 public stat ic void main ( St r ing args [ ] ) {32 new VisualCmmdc ( ) . s e t V i s i b l e ( true ) ;33 }

35 private javax . swing . JButton cmmdcButton ;36 private javax . swing . JLabel mLabel ;37 private javax . swing . JLabel nLabel ;38 private javax . swing . JTextFie ld mTextField ;39 private javax . swing . JTextFie ld nTextField ;40 private javax . swing . JTextFie ld cmmdcTextField ;41 }

Interfata grafica a programului este ilustrata ın Fig. 9.1

Figure 9.1: Interfata grafica pentru rezolvarea ecuatiei algebrice.

Page 229: DISTR1

9.1. JAVA WEB START 229

Instalare ıntr-un server Web

Pentru instalarea aplicatiei ıntr-un server Web, se parcurg pasii:

1. Se arhiveaza aplicatia

jar cfv cmmdc.jar *.class

2. Se editeaza fisierul launch.jnlp

1 <?xml version=” 1 .0 ” encoding=”UTF−8”?>2 <j n l p codebase=” h t t p : // host /cmmdc”>3 <i n fo rmat ion>4 < t i t l e> . . . </ t i t l e>5 <vendor> . . . </ vendor>6 <d e s c r i p t i o n> . . . </ d e s c r i p t i o n>7 </ in fo rmat ion>8 <r e s o u r c e s>9 < j 2 s e version=”1.2+”/>

10 < j a r h r e f=”cmmdc . j a r ”/>11 </ r e s o u r c e s>12 <app l i c a t i on−desc main−c l a s s=”VisualCmmdc”/>13 </ j n l p>

host se ınlocuieste cu numele calculatorului care gazduieste serverul Web.

3. Se creaza fisier de apelare a aplicatiei (cmmdc.html)

1 <html>2 <body bgcolor=”#AAEEAA”>3 <center>4 <h3>Visua l Cmmdc Appl i ca t ion </h3>5 <a href=” http :// host /cmmdc/ launch . j n l p ”>6 Launch the a p p l i c a t i o n </a>7 </center>8 </body>9 </html>

4. Ansamblul

cmmdc

| cmmdc.jar

| cmmdc.html

| launch.jnlp

se copiaza ın serverul Web (ın cazul IIS acest loc este catalogulInetPub\wwwroot).

Dintr-un navigator, apelarea aplicatiei este http://host/cmmdc/cmmdc.html.

Page 230: DISTR1

230 CAPITOLUL 9. JAVA WEB START

Aplicatia Java ca servlet

Pentru includerea aplicatie Java ıntr-un servlet, primii trei pasi prezentati maisus coincid. Singura diferenta consta ın continutul referintelor, dupa host va apareportul utilizat de serverul Web container de servlet, uzual host:8080.

4. Intr-un catalog de lucru se creaza structura de cataloage si fisiere:

app

|--- cmmdc.jar

|--- launch.jnlp

WEB-INF

|--- lib

| |--- jnlp-servlet.jar

|--- web.xml

cmmdc.html

Fisierul jnlp-servlet.jar se preia din distributia JDK, din catalogul sam-ple/jnlp/servlet.

Fisierul web.xml este

1 ?xml v e r s i on=” 1 .0 ” encoding=” i so −8859−1”?>2 < !DOCTYPE web−app3 PUBLIC ”−//Sun Microsystems , Inc . //DTD Web Appl i ca t ion 2 .3//EN”4 ” h t tp : // java . sun . com/dtd/web−app 2 3 . dtd”>5 <web−app>6 < !−− Standard Action S e r v l e t Conf igurat ion ( with debugging ) −−>7 <web−app>8 <s e r v l e t>9 <s e r v l e t−name>JnlpDownloadServlet</ s e r v l e t−name>

10 <s e r v l e t−c l a s s>11 j n l p . sample . s e r v l e t . JnlpDownloadServlet12 </ s e r v l e t−c l a s s>13 </ 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>JnlpDownloadServlet</ s e r v l e t−name>16 <ur l−pattern>∗ . j n l p</ ur l−pattern>17 </ s e r v l e t−mapping>18 </web−app>19 </web−app>

5. Continutul catalogului de lucru se arhiveaza ıntr-un fisier war.

jar cfv cmmdc.war app/* WEB-INF/* cmmdc.html

6. Utilizand apache-tomcat sau jetty, de exemplu, fisierul war se copiaza ın cat-alogul webapps al serverului web.

Dintr-un navigator, apelarea aplicatiei se obtine prinhttp://host:8080/cmmdc/cmmdc.html.

Page 231: DISTR1

9.1. JAVA WEB START 231

Daca aplicatia Java utilizeaza imagini grafice acestea trebuie arhivate ımpreunacu aplicatia, de exemplu ıntr-un catalog images.

Incarcarea si afisarea unei imagini programandu-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);

Daca aplicatia Java utilizeaza resurse externe date prin fisiere jar atunci:

1. Toate fisierele jar se certifica.

Certificarea resurselor se realizeaza ruland succesiv

(a) keytool -genkey -keystore myKeystore -alias myself

(b) keytool -selfcert -alias myself -keystore myKeystore

(c) jarsigner -keystore myKeystore resource.jar myself

keytool.exe si jarsigner.exe se gasesc ın distributia jdk.

Primele doua actiuni au ca rezultat obtinerea certificatului myKeystore iarultima actiune reprezinta ınglobarea certificarii ın arhiva resource.jar.

Toate fisierele jar trebuie sa poarte aceasi certificare.

2. Fisierele jar certificate se depun ın catalogul app\lib.

3. In fisierul jnlp, ın elementul resources, pentru fiecare fisier jar utilizat seintroduce declaratia

<jar href=”lib/resource.jar”/>

4. In plus, fisierul jnlp atasat aplicatiei contine elementele

<security>

<all-permissions />

</security>

Daca arhiva jar a aplicatiei Java este executabila atunci, ın fisierul jnlp, elemen-tul application-desc poate lipsi.

Intr-o arhiva jar executabila, fisierul MANIFEST.MF indica clasa cu metoda mainsi eventualele resurse externe utilizate (fisiere jar) prin proprietatile

Main-class: numeClasa

Class-path: lib/resursa1.jar lib/resursa2.jar . . .

Pentru a obtine fisierul MANIFEST.MF cu aceste proprietati se editeaza un fisier textcu continutul de mai sus, denumit de exemplu myManifest.mf, si se arhiveaza prin

jar cfvm numeArhiva.jar myManifest.mf *.class lib

Page 232: DISTR1

232 CAPITOLUL 9. JAVA WEB START

Page 233: DISTR1

Capitolul 10

Java Management Extensions

Java Management Extensions (JMX) face posibila ca un obiect Java sa permitagestionarea metodelor si a anumitor campuri de catre alte obiecte. Obiectele Javacare ısi expun astfel resursele se numesc MBean - uri si formeaza temelia cadruluide lucru JMX.

Exista mai multe tipuri de MBean-uri:

• Standard MBean;

• Dynamic MBean;

• Open MBean;

• Model MBean;

• MXBean;

Un obiect care gestioneaza resursele unui MBean se numeste agent sau server MBean.Agentul dispune de mijloace care interactioneaza cu un MBean, permitandu-i:

• accesul la valorile unui camp si la modificarea lor;

• invocarea metodelor.

In general, un agent poate fi definit ca

• autorul unei actiuni;

• factor care provoaca actiuni;

• reprezentant al unei institutii ınsarcinat cu ındeplinirea unor actiuni.

Terminologia server MBean se justifica prin faptul ca poate fi invocat de unprogram client. In aceasta ipostaza, serverul MBean are rolul unui container deMBean-uri si de gestionare si executie a apelurilor clientilor.

Structura unei aplicatii JMX contine doua nivele:

233

Page 234: DISTR1

234 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS

• componentele MBean;

• agentul (serverul MBean).

10.1 Standard MBean

10.1.1 Crearea unui Standard MBean

O componenta MBean este alcatuita dintr-o interfata si o clasa care imple-menteaza interfata satisfacand urmatoarele restrictii:

1. interfata are numele clasei care o implementeaza avand ın plus sufixul MBean;

2. Interfata si clasa care o implementeaza apartin aceluiasi pachet;

3. constructorii si metodele expuse trebuie sa fie publice.

In continuare campurile si metodele destinate expunerii se vor denumi atribute,respectiv operatii. Fiecarui atribut xxx i se ataseaza cel putin una din metodele

public void setXxx(tip xxx){

this.xxx=xxx;

}

si / sau

public tip getXxx(){

return xxx;

}

Un atribut se precizeaza doar prin aceste metode, fara definirea / declararea campuluicorespunzator. Campul se defineste ın clasa ce implementeaza interfata MBean-ului.

Astfel, un MBean este caracterizat de

• atribute

care pot fi consultate (citite), modificate (scrise) sau cu ambele optiuni.

• operatii

• notificari

cu evidenta modificarilor suferite de atribute.

Exemplul 10.1.1

Construim un MBean cu

Page 235: DISTR1

10.1. STANDARD MBEAN 235

• atributele

– label

ce poate fi numai citit;

– cursEuro

care poate fi consultat si modificat;

• operatiile

– public String sayHello()

afiseaza un mesaj;

– public long cmmdc(long m, long n);

de calcul a celui mai mare divizor comun a doua numere naturale.

Interfata IntroMBean este

1 package bas i c ;

3 public interface IntroMBean {4 // Opera t i i5 public St r ing sayHe l lo ( ) ;6 public long cmmdc( long m, long n ) ;

8 // Atr i bu te9 // read−only

10 public St r ing getLabe l ( ) ;11 // read−wr i t e12 public double getCursEuro ( ) ;13 public void setCursEuro (double cursEuro ) ;14 }

fiind implementat de clasa Intro

1 package bas i c ;2 import javax . management . ∗ ;

4 public class In t ro implements IntroMBean {

6 //Atr i bu te7 private f ina l St r ing label = ”Fac . Matematica s i In fo rmat i ca ” ;8 private double cursEuro = 3 . 5 0 ;

10 public St r ing getLabe l ( ) {11 return label ;12 }

14 public double getCursEuro ( ) {15 return cursEuro ;16 }

18 public synchronized void setCursEuro (double cursEuro ) {19 this . cursEuro = cursEuro ;20 }

Page 236: DISTR1

236 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS

22 //Opera t i i23 public St r ing sayHe l lo ( ) {24 St r ing message=” He l lo World ! ” ;25 System . out . p r i n t l n ( message ) ;26 return message ;27 }

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

In acest caz nu s-a implementat posibilitatea notificarilor atributului cursEuro.

10.1.2 Crearea unui MBeanServer

Un agent sau MBean server implementeaza interfata MBeanServer. Un aseme-nea obiect se obtine printr-una din metodele statice

• static MBeanServer ManagementFactory.getPlatformMBeanServer()

Utilitarul jconsole permite conectarea la serverul MBean.

• static MBeanServer MBeanServerFactory.createMBeanServer()

In agent se ınregistreaza componente MBean. Un obiect MBean este caracterizatde un nume, un obiect de tip ObjectName. Inregistrarea si / sau crearea uneicomponente MBean necesita definirea ın prealabil a acestui nume. Structura uneinume este

domeniu : numeAtribut=valAtribut ,numeAtribut=valAtribut . . .

unde

• domeniu

este un nume simbolic (String). Daca domeniul este stringul vid atunci seconsidera valoarea implicita DefaultDomain.

• atribute uzuale:

– type=numele MBean-ului

– index=numar de identificare a MBean-ului

Cel putin un atribut este obligatoriu.

Clasa ObjectName

Constructori

• ObjectName(String nume)

Parametrul nume are structura descrisa mai sus.

Page 237: DISTR1

10.1. STANDARD MBEAN 237

• ObjectName(String domeniu, Hashtable<String,String> tabel)

• ObjectName(String domeniu, String numeAtribut, String

valAtribut)

Metode

• static ObjectName getInstance(String nume)

Inregistrarea si utilizarea MBean-ului face apel la metodele interfetei MBeanServer.

ObjectInstance

Un obiect de tip ObjectInstance este folosit pentru reprezentarea ansamblu-lui alcatuit de un obiect ObjectName asociat unui MBean si numele clasei core-spunzatoare.

Interfata MBeanServer

Metode

• ObjectInstance registerMBean(Object obj, ObjectName nume)

Inregistreaza pe platforma, instanta obj a unui MBean avand numele nume.

• void unregister(ObjectName nume)

• ObjectInstance createMBean(String numeClasa, ObjectName nume)

Creaza si ınregistreaza un MBean de clasa numeClasa si de nume nume.

• ObjectInstance createMBean(String numeClasa, ObjectName nume, Object[]

param, String[] sign)

In plus, sirul param contine parametri constructorului, de tip, respectiv sign.

• String getDefaultDomain()

• Object invoke(ObjectName mbeanName, String operationName, Object[]

param, String[] paramTip)

Se invoca operatia operationName a MBean-ului mbeanName. Parametri nece-sari operatiei ımpreuna cu tipurile corespunzatoare sunt dati ın variabileleparam si respectiv paramTip.

• Object getAttribute(ObjectName mbeanName,String atribut)

Returneaza valoarea atributului atribut a mbean-ului mbeanName.

Page 238: DISTR1

238 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS

• void setAttribute(ObjectName mbeanName,Attribute atribut)

Fixeaza valoarea atributului atribut a MBean-ului mbeanName. Retinem doarconstructorul clasei Attribute prin

Attribute(String nume, Object valoare)

• MBeanInfo getMBeanInfo(ObjectName mbeanName)

Returneaza un obiect de tip MBeanInfo util inspectarii resurselor unui MBean.

Exista mai multe sabloane de programare a ınregistrarii unei componente MBean.

Exemplul 10.1.2 Se creaza doua componente MBean de tip Intro care vor fi in-spectate prin intermediul utilitarului jconsole1 - distributia jdk .

Utilitarul jconsole permite apelarea operatiilor, modificarea atributelor si sem-naleaza notificarile.

1 package bas i c ;2 import java . lang . management . ∗ ;3 import javax . management . ∗ ;

5 public class Main{6 public stat ic void main ( St r ing [ ] a rgs ){7 St r ing domeniu=”” ;8 i f ( args . length >0) domeniu=args [ 0 ] ;9 try{

10 // Serveru l p l a t f o rme i11 MBeanServer mbs = ManagementFactory . getPlatformMBeanServer ( ) ;

13 //Varianta 114 // Construirea ObjectName corespunzator MBean−u l u i15 ObjectName mbeanObjectName =16 new ObjectName ( domeniu+” : type=Intro , index=1” ) ;

18 // Crearea MBean−u l u i19 In t ro mbean = new In t ro ( ) ;

21 // In r e g i s t r a r e a MBean−u l u i22 mbs . registerMBean (mbean , mbeanObjectName ) ;

24 //Varianta 225 mbeanObjectName=new ObjectName ( domeniu+” : type=Intro , index=2” ) ;26 mbs . createMBean ( ” ba s i c . In t ro ” , mbeanObjectName ) ;

28 // Asteptare n ed e f i n i t a29 System . out . p r i n t l n ( ”Waiting f o r e v e r . . . ” ) ;30 while ( true ) ;31 }32 catch ( Exception e ){33 System . e r r . p r i n t l n ( ” Exception : ”+e . getMessage ( ) ) ;34 }35 }36 }

1In acest caz, este nevoie ca variabilele de tip clasa acoperitoare Double, Long sa fie ınlocuiteprin tipuri predefinite.

Page 239: DISTR1

10.1. STANDARD MBEAN 239

Executarea aplicatiei revine la

1. Intr-o fereastra DOS se lanseaza agentul Main prinjava -Dcom.sun.manager.jmxremote basic.Main

2. Intr-o alta fereastra DOS se lanseazajconsole

pornind utilitarul jconsole.

3. In fereastra de dialog jconsole:Connect to Agent se da clic pe Connect.

4. In panoul Tree gasim domeniul dat. Prin clic pe domeniu apar MBean-urilede indice 1 si 2.

5. Prin clic pe unul din aceste MBean-uri, ın panoul central avem acces la atributelesi la operatiile lor.

Rezultatul unei operatii apare ıntr-o fereastra de informare (Fig. 10.1).

10.1.3 Notificari

Pentru implementarea retinerii de catre un agent MBean a notificarilor, clasace implementeaza interfata MBean-ului trebuie sa extinda clasa Notification-

BroadcasterSupport.

Modificarile unui atribut se retin ıntr-un obiect de tip Notification si estetransmis prin metoda

sendNotification(Notification notification)

a clasei NotificationBroadcasterSupport.

Suplimentar se defineste metoda

public MBeanNotificationInfo[] getNotificationInfo()

ın care se precizeaza

• tipul notificarii - (constanta definita de clasa AttributeChangeNotification);

• clasa ın care s-a generat notificarea

String name = AttributeChangeNotification.class.getName();

• o descriere a modificarii.

Astfel, introducerea notificarilor presupune familiarizarea cu clasele

Page 240: DISTR1

240 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS

Figure 10.1: Rezultatele furnizate de jcluster.

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

Page 241: DISTR1

10.1. STANDARD MBEAN 241

– Notification(String type, Object source, long sequenceNumber, long

timeStamp, String mesaj)

– Notification(String type, Object source, long sequenceNumber, String

mesaj)

Metode

– public void setUserData(Object userData)

– public Object getUserData()

• AttributeChangeNotification extends Notification

Constructori

– AttributeChangeNotification(Object source, long sequenceNumber,long timeStamp, String msg, String attributeName, String attribute-Type, Object oldValue, Object newValuE)

Campuri

– static String ATTRIBUTE CHANGE

Semnaleaza schimbarea atributului

Exemplul 10.1.3 Extinderea MBean-ului Intro cu notificarea modificarilor atributelorın jconsole.

Implementarea notificarilor ın clasa Intro presupune modificarea metodei setCursEuro.Totodata se adauga metoda getNotificationInfo, ce furnizeaza informatii referitoarela modificarea aparuta. Codul clasei care implementeaza interfata devine

1 package agentn ;2 import javax . management . ∗ ;

4 public class IntroN extends Not i f i c a t i onBroadcas t e rSuppor t5 implements IntroNMBean{6 private long sequenceNumber=1;

8 //Atr i bu te9 private f ina l St r ing label = ”Fac . Matematica s i In fo rmat i ca ” ;

10 private double cursEuro = 3 . 5 0 ;

12 public St r ing getLabe l ( ) { . . .}

14 public double getCursEuro ( ) { . . .}

16 public synchronized void setCursEuro (double cursEuro ) {17 double oldCursEuro=this . cursEuro ;18 this . cursEuro = cursEuro ;19 //System . out . p r i n t l n (”Curs de schimb euro : ” + euro+” ron . ” ) ;20 N o t i f i c a t i o n n=new Attr ibuteChangeNot i f i ca t i on (21 this ,

Page 242: DISTR1

242 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS

22 sequenceNumber++,23 System . cur r entT imeMi l l i s ( ) ,24 ”Schimbarea c u r s u l u i Euro” ,25 ” cursEuro ” ,26 ” double ” ,27 oldCursEuro ,28 cursEuro ) ;29 s e n d N o t i f i c a t i o n (n ) ;30 }

32 public MBeanNot i f i cat ionInfo [ ] g e t N o t i f i c a t i o n I n f o ( ) {33 St r ing [ ] types = new St r ing [ ] {34 Attr ibuteChangeNot i f i ca t i on .ATTRIBUTE CHANGE35 } ;36 St r ing name = Att r ibuteChangeNot i f i ca t i on . class . getName ( ) ;37 St r ing 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 MBeanNot i f i cat ionInfo i n f o =39 new MBeanNot i f i cat ionInfo ( types , name , d e s c r i p t i o n ) ;40 return new MBeanNot i f i cat ionInfo [ ] { i n f o } ;41 }

43 // Opera t i i44 public St r ing sayHe l lo ( ) { . . .}

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

In jconsole pentru notificare, ın prealabil este nevoie de subscriere.

10.1.4 Agent MBean

In exemplelele anterioare rezursele unui MBean au fost utilizate prin jconsole.Valorificarea resurselor unui MBean Intro, dintr-un MBeanServer (agent) se pro-grameaza prin

Exemplul 10.1.4

1 package agent ;2 import java . i o . IOException ;3 import javax . management . ∗ ;4 import javax . management . remote . ∗ ;5 import java . u t i l . Scanner ;

7 public class Agent{8 public stat ic void main ( St r ing [ ] a rgs ) {9 try {

10 // Crearea Agentu lu i − MBeanServer11 MBeanServer mbs = MBeanServerFactory . createMBeanServer ( ) ;

13 // Crearea unui MBean14 St r ing domain = mbs . getDefaultDomain ( ) ;15 St r ing className=” agent . In t ro ” ;16 St r ing sObjectName=domain+” : type=”+className ;17 ObjectName mbeanObjectName = new ObjectName ( sObjectName ) ;18 mbs . createMBean ( className , mbeanObjectName ) ;

Page 243: DISTR1

10.1. STANDARD MBEAN 243

20 // U t i l i z a r e a MBean−u l u i21 // Apelarea o p e r a t i i l o r22 St r ing ope ra t i a=” sayHe l lo ” ;23 mbs . invoke ( mbeanObjectName , operat ia , null , null ) ;

25 ope ra t i a=”cmmdc” ;26 System . out . p r i n t l n ( ”Cmmdc a l numerelor : ” ) ;27 Scanner scanner=new Scanner ( System . in ) ;28 System . out . p r i n t l n ( ”Primul numar : ” ) ;29 long m=scanner . nextLong ( ) ;30 System . out . p r i n t l n ( ”Al d o i l e a numar : ” ) ;31 long n=scanner . nextLong ( ) ;32 Object [ ] param={m, n } ;33 St r ing [ ] s i gn={” long ” , ” long ” } ;34 Long r=(Long )mbs . invoke ( mbeanObjectName , operat ia , param , s i gn ) ;35 System . out . p r i n t l n ( ”cmmdc=”+r . t oS t r i ng ( ) ) ;

37 // U t i l i z a r e a A t r i b u t e l o r38 St r ing label=( St r ing )mbs . ge tAt t r ibut e ( mbeanObjectName , ” Label ” ) ;39 System . out . p r i n t l n ( ” Valoarea a t r i b u t u l u i l a b e l : ”+label ) ;

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 euro ” ) ;42 double cursEuro=scanner . nextDouble ( ) ;43 Attr ibute curs=new Attr ibute ( ”CursEuro” , cursEuro ) ;44 mbs . s e t A t t r i b u t e ( mbeanObjectName , curs ) ;45 Double euro=(Double )mbs . ge tAt t r ibut e ( mbeanObjectName , ”CursEuro” ) ;46 System . out . p r i n t l n ( ” Valoarea a t r i b u t u l u i cursEuro : ”+euro ) ;47 }48 catch ( Exception e ){49 System . out . p r i n t l n ( e . getMessage ( ) ) ;50 }51 }52 }

10.1.5 Invocarea la distanta

Din punct de vedere al programarii distribuite, cazul interesant este cel ın careclasa ce implementeaza MBean-ul si clientul (agentul MBean) care o utilizeaza seafla pe calculatoare diferite.

In acest caz:

• Este nevoie de o clasa server (agent) al carui rol este

– Instantierea unui MBeanServer

– Instantiarea unui server de conexiune, obiect de tip MBeanServerConnection.

Bazat pe tehnologia RMI sau RMI-IIOP, acest obiect gestioneaza comunicatiadintre un client si serverul MBeanServer. Serverul de conexiune si serverulMBeanServer apartin aceleiacsi clase.

– Lansarea ın executie a serverului de conexiune.

• Clientul dispune de interfata MBeanu-ului.

Page 244: DISTR1

244 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS

Interfata MBeanServerConnection este implementata de clasa MBeanServer Sablonulde programare pentru instantierea obiectului de tip MBeanServerConnection silansarea sa ın executie poate fi:

String surl="service:jmx:rmi:///jndi/rmi://host:port/numeServer"

// String surl="service:jmx:iiop:///jndi/iiop://host:port/numeServer";

// Crearea unui RMI server-conector

JMXServiceURL url = new JMXServiceURL(surl);

JMXConnectorServer cs =

JMXConnectorServerFactory.newJMXConnectorServer(url,null,MBeanServer);

//

// Pornirea server-conectorului RMI

cs.start();

System.out.println("Press Enter to finish !");

System.in.read();

cs.stop();

Serverul de conexiune are un nume, numeServer care trebuie cunoscut de catreclient.

Lansarea ın executie a serverului este precedata de pornirea registrului rmireg-istry, respectiv orbd.

Exemplul 10.1.5

1 package s e r v e r ;2 import java . i o . IOException ;3 import javax . management . ∗ ;4 import javax . management . remote . ∗ ;

6 public class MBServer{7 public stat ic void main ( St r ing [ ] a rgs ) {8 St r ing host=” l o c a l h o s t ” ;9 St r ing port=”1099” ;

10 i f ( args . l ength==0){11 System . out . p r i n t l n ( ”The name o f the s e r v e r i s r equ i r ed ” ) ;12 System . e x i t ( 0 ) ;13 }14 i f ( args . length >=2)15 host=args [ 1 ] ;16 i f ( args . length >=3)17 port=args [ 2 ] ;18 try {19 // Crearea MBeanServer20 MBeanServer mbs = MBeanServerFactory . createMBeanServer ( ) ;

22 // Crearea unui RMI server−conector23 St r ing s u r l=” s e r v i c e : jmx : rmi :/// j n d i /rmi : // ”+24 host+” : ”+port+”/”+args [ 0 ] ;25 // S t r ing s u r l=”s e r v i c e : jmx : i i o p :/// jnd i / i i o p ://”+26 // hos t+”:”+port+”/”+args [ 0 ] ;27 JMXServiceURL u r l=new JMXServiceURL( s u r l ) ;28 JMXConnectorServer cs=29 JMXConnectorServerFactory . newJMXConnectorServer ( ur l , null , mbs ) ;

Page 245: DISTR1

10.1. STANDARD MBEAN 245

31 // Pornirea server−conec to ru lu i RMI32 cs . s t a r t ( ) ;33 System . out . p r i n t l n ( ” Press Enter to f i n i s h ! ” ) ;34 System . in . read ( ) ;35 cs . stop ( ) ;36 }37 catch ( Exception e ){38 System . out . p r i n t l n ( e . getMessage ( ) ) ;39 e . pr intStackTrace ( ) ;40 }41 }42 }

Primul argument care trebuie furnizat programului anterior (args[0]) este numeleserverului.

Clientul, la randul lui, este nevoit sa creeze un conector RMI catre server (agent),prin intermediul caruia obtine un obiect ce implementeaza interfata MBeanServerConnection.Prin acest obiect, clientul va putea crea MBean-uri - ın agent - si le va putea utilizaresursele.

Sablonul de programare pentru crearea obiectului MBeanServerConnection poatefi

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

Resursele unui MBean se poate invoca prin

• metoda invoke(mbeanObjectName,operationName,param,sign) a interfeteiMBeanServerConnection.

• crearea unui reprezentant local al MBean-ului prin metoda statica

mbeanClass proxy =(mbeanClass)MBeanServerInvocationHandler.newProxyInstance(mbeanServerConnection,mbeanObjectName,mbeanClass.class,true);

In final, MBean-ul se sterge din serverul de conexiune, princs.unregisterMBean(mbeanObjectName).

Exemplul 10.1.6 Client ce utilizeaza un MBean Intro, definit ın Exemplul 10.1.1

1 package c l i e n t ;2 import java . i o . IOException ;3 import java . u t i l . ∗ ;4 import javax . management . ∗ ;5 import javax . management . remote . ∗ ;

Page 246: DISTR1

246 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS

7 public class Cl i en t {8 public stat ic void main ( St r ing [ ] a rgs ) {9 St r ing host=” l o c a l h o s t ” ;

10 St r ing port=”1099” ;11 i f ( args . length <=1){12 System . out . p r i n t l n ( ”The s e r v e r and domain names are r equ i r ed ” ) ;13 System . e x i t ( 0 ) ;14 }15 St r ing serverName=args [ 0 ] ;16 St r ing domain=args [ 1 ] ;17 i f ( args . length >=3) host=args [ 2 ] ;18 i f ( args . length >=4) port=args [ 4 ] ;19 Scanner scanner=new Scanner ( System . in ) ;20 try {21 //Crearea unui conector RMI s i a o b i e c t u l u i de t i p MBeanServercsection22 St r ing s u r l=” s e r v i c e : jmx : rmi :/// j n d i /rmi : // ”+23 host+” : ”+port+”/”+args [ 0 ] ;24 // S t r ing s u r l=”s e r v i c e : jmx : i i o p :/// jnd i / i i o p ://”+25 // hos t+”:”+port+”/”+args [ 0 ] ;26 JMXServiceURL u r l = new JMXServiceURL( s u r l ) ;27 JMXConnector jmxc = JMXConnectorFactory . connect ( ur l , null ) ;28 MBeanServerConnection cs = jmxc . getMBeanServerConnection ( ) ;

30 // Domeniile a g en tu l u i sunt31 System . out . p r i n t l n ( ”Domains : ” ) ;32 St r ing domains [ ] = cs . getDomains ( ) ;33 for ( int i = 0 ; i < domains . l ength ; i++) {34 System . out . p r i n t l n ( ”\tDomain [ ” + i + ” ] = ” + domains [ i ] ) ;35 }

37 // ia r domeniul imp l i c i t38 System . out . p r i n t l n ( ”DefaultDomain : ” +cs . getDefaultDomain ( ) ) ;39 System . out . p r i n t l n ( ”Domain : ” +domain ) ;

41 // Crearea unui MBean Intro42 St r ing className=” bas i c . In t ro ” ;43 St r ing sObjectName=domain+” : type=”+className ;44 ObjectName mbeanObjectName = new ObjectName ( sObjectName ) ;45 cs . createMBean ( className , mbeanObjectName , null , null ) ;

47 double cursEuro ;48 long m, n ;

50 // U t i l i z a r e a MBean−u l u i51 // Varianta 1 de invocare pr in proxy52 System . out . p r i n t l n ( ” Varianta de invocare pr in prox i ” ) ;53 IntroMBean proxy=54 ( IntroMBean ) MBeanServerInvocationHandler . newProxyInstance (55 cs ,56 mbeanObjectName ,57 c l i e n t . IntroMBean . class ,58 true ) ;

60 // U t i l i z a r e a o p e r a t i i l o r61 // opera t i a ” sayHe l lo ”62 proxy . sayHe l lo ( ) ;

64 // opera t i a cmmdc65 System . out . p r i n t l n ( ”Cmmdc a l numerelor : ” ) ;

Page 247: DISTR1

10.1. STANDARD MBEAN 247

66 System . out . p r i n t l n ( ”Primul numar : ” ) ;67 m=scanner . nextLong ( ) ;68 System . out . p r i n t l n ( ”Al d o i l e a numar : ” ) ;69 n=scanner . nextLong ( ) ;70 System . out . p r i n t l n ( ”Cmmdc=”+proxy . cmmdc(m, n ) ) ;

72 // U t i l i z a r e a a t r i b u t e l o r73 System . out . p r i n t l n ( ”Numele : ”+proxy . getLabe 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 euro ” ) ;75 cursEuro=scanner . nextDouble ( ) ;76 proxy . setCursEuro ( cursEuro ) ;77 System . out . p r i n t l n ( ”Euro : ”+proxy . getCursEuro ( ) ) ;

79 // Varianta 2 de invocare pr in conexiune80 System . out . p r i n t l n ( ” Varianta de invocare pr in conexiune ” ) ;81 // Apelarea o p e r a t i i l o r82 St r ing ope ra t i a=” sayHe l lo ” ;83 cs . invoke ( mbeanObjectName , operat ia , null , null ) ;84 ope ra t i a=”cmmdc” ;85 System . out . p r i n t l n ( ”Cmmdc a l numerelor : ” ) ;86 System . out . p r i n t l n ( ”Primul numar : ” ) ;87 m=scanner . nextLong ( ) ;88 System . out . p r i n t l n ( ”Al d o i l e a numar : ” ) ;89 n=scanner . nextLong ( ) ;90 Object [ ] param={m, n } ;91 St r ing [ ] s i gn={” long ” , ” long ” } ;92 Long r=(Long ) cs . invoke ( mbeanObjectName , operat ia , param , s i gn ) ;93 System . out . p r i n t l n ( ”Cmmdc=”+r . t oS t r i ng ( ) ) ;

95 // U t i l i z a r e a A t r i b u t e l o r96 St r ing label=( St r ing ) cs . g e tAt t r ibut e ( mbeanObjectName , ” Label ” ) ;97 System . out . p r i n t l n ( ” Valoarea a t r i b u t u l u i l a b e l : ”+label ) ;

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 euro ” ) ;100 cursEuro=scanner . nextDouble ( ) ;101 Attr ibute curs=new Attr ibute ( ”CursEuro” , cursEuro ) ;102 cs . s e t A t t r i b u t e ( mbeanObjectName , curs ) ;103 Double newEuro=(Double ) cs . g e tAt t r ibute ( mbeanObjectName , ”CursEuro” ) ;104 System . out . p r i n t l n ( ” Valoarea a t r i b u t u l u i euro : ”+newEuro ) ;105 cs . unregisterMBean ( mbeanObjectName ) ;106 }107 catch ( Exception e ) {108 System . out . p r i n t l n ( e . getMessage ( ) ) ;109 }110 }111 }

Inspectarea si valorificarea resurselor unei componente MBean se poateface si prin intermediul metodei

1 private stat ic void getMBeanResources ( MBeanInfo i n f o ){2 System . out . p r i n t l n ( ”CLASA: \ t ” + i n f o . getClassName ( ) ) ;3 System . out . p r i n t l n ( ”DESCR: \ t ” + i n f o . g e tDe s c r i p t i on ( ) ) ;4 System . out . p r i n t l n ( ”ATTRIBUTE” ) ;5 MBeanAttributeInfo [ ] a t t r I n f o = i n f o . g e tAt t r i bu t e s ( ) ;6 i f ( a t t r I n f o . l ength > 0) {7 for ( int i = 0 ; i < a t t r I n f o . l ength ; i++) {8 System . out . p r i n t l n ( ”\tNUME: \ t ” + a t t r I n f o [ i ] . getName ( ) ) ;9 System . out . p r i n t l n ( ”\tDESC : \ t ” + a t t r I n f o [ i ] . g e tDe s c r i p t i on ( ) ) ;

Page 248: DISTR1

248 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS

10 System . out . p r i n t l n ( ”\tTIP : \ t ” + a t t r I n f o [ i ] . getType ( ) +11 ” READ: ”+ a t t r I n f o [ i ] . i sReadable ( ) +12 ” WRITE: ”+ a t t r I n f o [ i ] . i sWr i tab l e ( ) ) ;13 }14 }15 else16 System . out . p r i n t l n ( ”\ tFara a t r i b u t e ! ” ) ;17 System . out . p r i n t l n ( ”CONSTRUCTORI” ) ;18 MBeanConstructorInfo [ ] c o n s t r I n f o = i n f o . ge tConst ruc tor s ( ) ;19 for ( int i =0; i<c o n s t r I n f o . l ength ; i++) {20 System . out . p r i n t l n ( ”\tNUME: \ t ” + c o n s t r I n f o [ i ] . getName ( ) ) ;21 System . out . p r i n t l n ( ”\tDESCR: \ t ” + c o n s t r I n f o [ i ] . g e tDe s c r i p t i on ( ) ) ;22 System . out . p r i n t l n ( ”\tPARAM: \ t ” +23 c o n s t r I n f o [ i ] . g e tS ignature ( ) . l ength +” parametr i ” ) ;24 }25 System . out . p r i n t l n ( ”OPERATII” ) ;26 MBeanOperationInfo [ ] opInfo = i n f o . getOperat ions ( ) ;27 i f ( opInfo . l ength > 0) {28 for ( int i = 0 ; i < opInfo . l ength ; i++) {29 System . out . p r i n t l n ( ”\tNUME: \ t ” + opInfo [ i ] . getName ( ) ) ;30 System . out . p r i n t l n ( ”\tDESCR: \ t ” + opInfo [ i ] . g e tDe s c r i p t i on ( ) ) ;31 System . out . p r i n t l n ( ”\tPARAM: \ t ” +32 opInfo [ i ] . g e tS ignature ( ) . l ength +” parametr i ” ) ;33 }34 }35 else36 System . out . p r i n t l n ( ”\ tFara o p e r a t i i ” ) ;37 System . out . p r i n t l n ( ”NOTIFICARI” ) ;38 MBeanNot i f i cat ionInfo [ ] n o t i f I n f o = i n f o . g e t N o t i f i c a t i o n s ( ) ;39 i f ( n o t i f I n f o . l ength > 0) {40 for ( int i = 0 ; i < n o t i f I n f o . l ength ; i++) {41 System . out . p r i n t l n ( ”\tNUME: ” + n o t i f I n f o [ i ] . getName ( ) ) ;42 System . out . p r i n t l n ( ”\tDESCR: ” + n o t i f I n f o [ i ] . g e tDe s c r i p t i on ( ) ) ;43 St r ing not i fTypes [ ] = n o t i f I n f o [ i ] . getNot i fTypes ( ) ;44 for ( int j = 0 ; j < not i fTypes . l ength ; j++) {45 System . out . p r i n t l n ( ”\tTIP : ” + not i fTypes [ j ] ) ;46 }47 }48 }49 else50 System . out . p r i n t l n ( ”\ tFara n o t i f i c a r i ” ) ;51 }

Aceasta metoda poate fi inserata ın oricare din programele agent sau client.

Notificarea la distanta

Notificarea la distanta presupune utilizarea unui MBean posedand aceasta fa-cilitate. Pe partea de client trebuie implementat interfata NotificationListener

care declara metoda

public void handleNotification(Notification notification, Object

handback)

Atasarea si disponibilizarea clasei ce implementeaza interfata Notification

Listener se obtin prin metodele interfetei MBeanServerConnection:

Page 249: DISTR1

10.1. STANDARD MBEAN 249

• void addNotificationListener(ObjectName name, NotificationListener

listener, NotificationFilter filter, Object handback )throws Instance-

NotFoundException, IOException

• void removeNotificationListener(ObjectName name, ObjectName listener)throws InstanceNotFoundException, ListenerNotFoundException, IOException

Exemplul 10.1.7 Folosind exemplul 10.1.6 - dar cu MBean-ul creat pentru 10.1.3se creaza un client cu notificare, care sesiseaza modificarea valoarii atributului cursEuroa MBean-ului IntroN.

Implementarea interfetei NotificationListener este

1 package c l i e n t ;2 import javax . management . N o t i f i c a t i o n ;3 import javax . management . N o t i f i c a t i o n L i s t e n e r ;4 import javax . management . At t r ibuteChangeNot i f i ca t i on ;

6 public class 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 Object handback ) {9 System . out . p r i n t l n ( ”\nReceived 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 Attr ibuteChangeNot i f i ca t i on myNotif=11 ( Att r ibuteChangeNot i f i ca t i on ) n o t i f i c a t i o n ;12 System . out . p r i n t l n ( ”Curs i n i t i a l : ” +13 myNotif . getOldValue ( ) . t oS t r i ng ( ) ) ;14 System . out . p r i n t l n ( ”Curs curent : ” +15 myNotif . getNewValue ( ) . t oS t r i ng ( ) ) ;16 }17 }

Codul clasei client este

1 package c l i e n t ;2 import java . i o . IOException ;3 import javax . management . ∗ ;4 import javax . management . remote . ∗ ;

6 public class C l i e n t N o t i f {7 public stat ic void main ( St r ing [ ] a rgs ) {8 St r ing host=” l o c a l h o s t ” ;9 St r ing port=”1099” ;

10 i f ( args . length <=1){11 System . out . p r i n t l n ( ”The s e r v e r and domain names are r equ i r ed ” ) ;12 System . e x i t ( 0 ) ;13 }14 St r ing serverName=args [ 0 ] ;15 St r ing domain=args [ 1 ] ;16 i f ( args . length >=3) host=args [ 2 ] ;17 i f ( args . length >=4) port=args [ 3 ] ;18 C l i e n t N o t i f obj=new C l i e n t N o t i f ( ) ;19 try {20 // Crearea unui conector RMI s i a o b i e c t u l u i21 // de t i p MBeanServerConnection22 St r ing s u r l=” s e r v i c e : jmx : rmi :/// j n d i /rmi : // ” +23 host+” : ”+port+”/”+args [ 0 ] ;

Page 250: DISTR1

250 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS

24 JMXServiceURL u r l = new JMXServiceURL( s u r l ) ;25 JMXConnector jmxc = JMXConnectorFactory . connect ( ur l , null ) ;26 MBeanServerConnection cs = jmxc . getMBeanServerConnection ( ) ;

28 // Crearea unui MBean Intro29 St r ing className=” bas i cn . IntroN ” ;30 St r ing sObjectName=domain+” : type=”+className ;31 ObjectName mbeanObjectName = new ObjectName ( sObjectName ) ;

33 MBeanInfo i n f o=cs . getMBeanInfo ( mbeanObjectName ) ;34 getMBeanResources ( i n f o ) ;

36 // U t i l i z a r e a n o t i f i c a r i i37 // Crearea unui a s c u l t a t o r38 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 // Act ivarea n o t i f i c a t o r u l u i40 cs . 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 , obj ) ;

42 Thread . s l e e p ( 5 0 0 ) ;43 // D i s pon 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 i44 System . out . p r i n t l n ( ” Press Enter to f i n i s h ! ” ) ;45 try{46 System . in . read ( ) ;47 }48 catch ( java . i o . IOException e ){}49 cs . 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 pon i b i l i z a r e a o b i e c t u l u i MBeanObjectName51 cs . unregisterMBean ( mbeanObjectName ) ;52 }53 catch ( Exception e ) {54 System . out . p r i n t l n ( e . getMessage ( ) ) ;55 e . pr intStackTrace ( ) ;56 }57 }

59 private stat ic void getMBeanResources ( MBeanInfo i n f o ) { . . .}

61 }

Clasa Client care creaza MBean-ul trebuie lansata ınaintea clasei ClientNotif. Acestedoua clase pot rula pe calculatoare distincte.

Exemplul 10.1.8 O aplicatie servlet ıntretine un cont. Actiunile ce pot fi ıntreprinsesunt: depunerea unei sume, extragerea unei sume ın limita soldului si consultareacontului. Contul este implementat ca un MBean standard. Se cere urmarirea ladistanta a modificarilor suferite de cont.

Interfata contului (a MBean-ului) este

1 public interface ContMBean {2 // Atr i bu te3 // read−wr i t e4 public double getCont ( ) ;5 public void setCont (double cont ) ;6 }

implementat prin

Page 251: DISTR1

10.1. STANDARD MBEAN 251

1 import javax . management . ∗ ;

3 public class Cont extends Not i f i c a t i onBroadcas t e rSuppor t4 implements ContMBean{5 private long sequenceNumber=1;6 private double cont ;

8 public synchronized double getCont ( ) {9 return cont ;

10 }

12 public synchronized void setCont (double cont ) {13 double oldCont=this . cont ;14 this . cont=cont ;15 N o t i f i c a t i o n n=new Attr ibuteChangeNot i f i ca t i on (16 this ,17 sequenceNumber++,18 System . cur r entT imeMi l l i s ( ) ,19 ”Schimbarea Cont” ,20 ” cont ” ,21 ” double ” ,22 oldCont ,23 cont ) ;24 s e n d N o t i f i c a t i o n (n ) ;25 }

27 public MBeanNot i f i cat ionInfo [ ] g e t N o t i f i c a t i o n I n f o ( ) {28 St r ing [ ] types = new St r ing [ ] {29 Attr ibuteChangeNot i f i ca t i on .ATTRIBUTE CHANGE30 } ;31 St r ing name = Att r ibuteChangeNot i f i ca t i on . class . getName ( ) ;32 St r ing 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 MBeanNot i f i cat ionInfo i n f o =34 new MBeanNot i f i cat ionInfo ( types , name , d e s c r i p t i o n ) ;35 return new MBeanNot i f i cat ionInfo [ ] { i n f o } ;36 }37 }

Codul servletului este

1 mport java . i o . ∗ ;2 import javax . s e r v l e t . ∗ ;3 import javax . s e r v l e t . http . ∗ ;4 import javax . management . ∗ ;5 import javax . management . remote . ∗ ;

7 public class Depoz i tSe rv l e t extends HttpServ l e t {8 MBeanServerConnection cs=null ;9 ObjectName mbeanObjectName=null ;

10 St r ing host ;11 St r ing port=”1099” ;12 St r ing s e r v e r=” s e r v e r ” ;

14 public void i n i t ( Se rv l e tCon f i g c o n f i g ) {15 try {16 super . i n i t ( c o n f i g ) ;17 host=c o n f i g . ge t In i tParameter ( ” jmxServerHost ” ) ;18 St r ing s u r l=” s e r v i c e : jmx : rmi :/// j n d i /rmi : // ”+host+” : ”+port+”/”+s e r v e r ;19 // S t r ing s u r l=”s e r v i c e : jmx : i i o p :/// jnd i / i i o p ://”+ hos t+”:”+port+”/”+serve r ;

Page 252: DISTR1

252 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS

20 JMXServiceURL u r l = new JMXServiceURL( s u r l ) ;21 JMXConnector jmxc = JMXConnectorFactory . connect ( ur l , null ) ;22 cs = jmxc . getMBeanServerConnection ( ) ;23 St r ing domain = cs . getDefaultDomain ( ) ;24 St r ing className=”Cont” ;25 St r ing sObjectName=domain+” : type=”+className ;26 mbeanObjectName = new ObjectName ( sObjectName ) ;27 cs . createMBean ( className , mbeanObjectName , null , null ) ;28 }29 catch ( Exception e ){30 System . out . p r i n t l n ( e . getMessage ( ) ) ;31 System . e x i t ( 0 ) ;32 }33 }

35 public void doGet ( HttpServ letRequest req , HttpServletResponse r e s )36 throws Serv le tExcept ion , IOException{37 ServletOutputStream out=r e s . getOutputStream ( ) ;38 St r ing oper=req . getParameter ( ” oper ” ) ;39 St r ing message=”” ;40 double suma=0;41 i f ( ! oper . equa l s ( ”con” ) ){42 St r ing s=req . getParameter ( ”suma” ) ;43 suma=Double . parseDouble ( s ) ;44 }45 Double objValue=null ;46 try{47 objValue=(Double ) cs . g e tAt t r ibute ( mbeanObjectName , ”Cont” ) ;48 }49 catch ( Exception e ){50 message=”JMX−Error : ”+e . getMessage ( ) ;51 }52 double value=objValue . doubleValue ( ) ;53 int index=−1;54 i f ( oper . equa l s ( ”dep” ) ) index =0;55 i f ( oper . equa l s ( ” ext ” ) ) index =1;56 i f ( oper . equa l s ( ”con” ) ) index =2;57 double x ;58 Attr ibute curs=null ;59 switch ( index ){60 case 0 :61 x=value+suma ;62 curs=new Attr ibute ( ”Cont” , x ) ;63 try{64 cs . s e t A t t r i b u t e ( mbeanObjectName , curs ) ;65 message=”S−a depus suma” ;66 }67 catch ( Exception e ){68 message=”JMX−Error : ”+e . getMessage ( ) ;69 }70 break ;71 case 1 :72 i f ( value>=suma){73 x=value−suma ;74 curs=new Attr ibute ( ”Cont” , x ) ;75 try{76 cs . s e t A t t r i b u t e ( mbeanObjectName , curs ) ;77 message=”S−a ex t ra s suma” ;78 }

Page 253: DISTR1

10.1. STANDARD MBEAN 253

79 catch ( Exception e ){80 message=”JMX−Error : ”+e . getMessage ( ) ;81 }82 }83 else {84 message=” Cererea nu poate f i i n d e p l i n i t a ” ;85 }86 break ;87 case 2 :88 message=”Suma din cont e s t e ”+value+” un i t . ” ;89 break ;90 }91 r e s . setContentType ( ” text /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>Operat iuni 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 }

103 public void doPost ( HttpServ letRequest req , HttpServletResponse r e s )104 throws Serv le tExcept ion , IOException{105 doGet ( req , r e s ) ;106 }107 }

Pagina de apelare a servletului fiind (index.html)

1 <html>2 <head>3 <t i t l e> Serv l e t−ul He l lo </ t i t l e>4 </head>5 <body bgcolor=”#aaeeaa ”>6 <center>7 <h1> Pagina de &#238; nt re &#355; i n e r e a d e p o z i t u l u i </h1>8 <form method=” post ”9 action=” http :// l o c a l h o s t :8080/ appcont/ appdepozit ”>

10 <p>Introduce &#355; i :11 <p>Opera&#355; i a : <select name=” oper ” >12 <option value=”dep”>Depunere13 <option value=” ext ”>Extragere14 <option value=”con”>Consultare15 </ select>16 <p>17 <input type=” text ” name=”suma” value=”0”>18 <p>19 <input type=”submit” value=”Executa”>20 </form>21 </center>22 </body>23 </html>

Serverul MBean este cel prezentat ın Exemplul 10.1.5. Clientlul care urmareste dela distanta contul are codul

Page 254: DISTR1

254 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS

1 import java . i o . IOException ;2 import javax . management . ∗ ;3 import javax . management . remote . ∗ ;

5 public class C l i e n t N o t i f {6 public stat ic void main ( St r ing [ ] a rgs ) {7 St r ing host=” l o c a l h o s t ” ;8 St r ing port=”1099” ;9 i f ( args . l ength==0){

10 System . out . p r i n t l n ( ”The Server name i s r equ i r ed ” ) ;11 System . e x i t ( 0 ) ;12 }13 i f ( args . length >=2) host=args [ 1 ] ;14 i f ( args . length >=3) port=args [ 2 ] ;15 C l i e n t N o t i f obj=new C l i e n t N o t i f ( ) ;16 try {17 // Crearea unui conector RMI s i a o b i e c t u l u i de18 // t i p MBeanServerConnection19 St r ing s u r l=” s e r v i c e : jmx : rmi :/// j n d i /rmi : // ” +20 host+” : ”+port+”/”+args [ 0 ] ;21 JMXServiceURL u r l = new JMXServiceURL( s u r l ) ;22 JMXConnector jmxc = JMXConnectorFactory . connect ( ur l , null ) ;23 MBeanServerConnection cs = jmxc . getMBeanServerConnection ( ) ;

25 St r ing domain = cs . getDefaultDomain ( ) ;26 System . out . p r i n t l n ( ”DefaultDomain : ” +domain ) ;27 // Crearea unui MBean Intro28 St r ing className=”Cont” ;29 St r ing sObjectName=domain+” : type=”+className ;30 ObjectName mbeanObjectName = new ObjectName ( sObjectName ) ;

32 MBeanInfo i n f o=cs . getMBeanInfo ( mbeanObjectName ) ;33 getMBeanResources ( i n f o ) ;

35 // U t i l i z a r e a n o t i f i c a r i i36 // Crearea unui a s c u l t a t o r37 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 // Act ivarea n o t i f i c a t o r u l u i39 cs . 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 , obj ) ;

41 Thread . s l e e p ( 5 0 0 ) ;42 // D i s pon 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 i43 System . out . p r i n t l n ( ” Press Enter to f i n i s h ! ” ) ;44 try{45 System . in . read ( ) ;46 }47 catch ( java . i o . IOException e ){}48 cs . 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 pon i b i l i z a r e a o b i e c t u l u i MBeanObjectName50 cs . unregisterMBean ( mbeanObjectName ) ;51 }52 catch ( Exception e ) {53 System . out . p r i n t l n ( e . getMessage ( ) ) ;54 e . pr intStackTrace ( ) ;55 }56 }

58 private stat ic void getMBeanResources ( MBeanInfo i n f o ) { . . .}59 }

Page 255: DISTR1

10.1. STANDARD MBEAN 255

61 class 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 Object handback ){64 System . out . p r i n t l n ( ”\nReceived 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 Attr ibuteChangeNot i f i ca t i on myNotif=66 ( Att r ibuteChangeNot i f i ca t i on ) n o t i f i c a t i o n ;67 System . out . p r i n t l n ( ” Sold i n i t i a l : ” +68 myNotif . getOldValue ( ) . t oS t r i ng ( ) ) ;69 System . out . p r i n t l n ( ” Sold curent : ” +70 myNotif . getNewValue ( ) . t oS t r i ng ( ) ) ;71 }72 }

Serverul MBean este cel utilizat ın exemplele anterioare.Serverul MBean este plasat ın servlet (ın catalogul WEB-INF/classes al aplicatiei)

iar clientul care urmareste de la distanta se poate afla oriunde.Dupa instalarea servlet-ului se lanseaza pe masina acestuia server-ul MBean.

Deoarece notificarea presupune existenta MBean-ului, iar acesta se instanteaza prinmetoda init a servlet-ului este nevoie de apelarea servlet-ului, depunand 0 unitati.Dupa aceasta operatie se lanseaza ın executie programul ClientNotif.

Page 256: DISTR1

256 CAPITOLUL 10. JAVA MANAGEMENT EXTENSIONS

Page 257: DISTR1

Capitolul 11

Teme de laborator

11.1 Probleme propuse

1. Sa se realizeze conversia temperaturii exprimata ın grade Celsius ın gradeFahrenheit si invers. Formula de transformare este

tF = 1.8tC + 32oF

In RMI, programul server implementeaza interfata (la distanta)

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. Sa se realizeze conversia a unei sume de bani ıntre USD, EURO si RON.

Programul server (RMI) implementeaza interfata

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

Page 258: DISTR1

258 CAPITOLUL 11. TEME DE LABORATOR

Rata zilnica de schimb preia dinamic sub forma unui fisier xml, apelandhttp://www.bnr.ro/nbrfxrates.xml.

3. Sa se realizeze conversia unui numar natural, din cifre arabe ın cifre romanesi invers.

Pentru numere x ∈ (3999, 3999999], x = a ∗ 1000 + b se va folosi scrierea subforma (A)B, unde A,B reprezinta conversiile lui a, respectiv b.

Exemplu: Conversia numarului 2289463 este (MMCCLXXXIX)CDLXIII.

Pentru numere x ∈ (4000000, 3999999999], x = a ∗ 1000000 + b ∗ 1000 + c seva folosi scrierea sub forma [A](B)C, unde A,B,C reprezinta conversiile luia, b, c.

4. Sa se realizeze conversia unui numar dintr-o baza ın alta.

5. Un server aduna la un numar (initializat cu 0) o valoare trimisa de un clientreturnand rezultatul. Exista o singura instanta a numarului, acelasi pentruorice client.

Sa se programeze serviciul descris mai sus.

6. Aplicatia producator – consumator.

Fie un sistem format din doua procese P1 si P2, primul producand niste datecare apoi vor fi preluate de cel de al doilea. Comunicarea ıntre cele douaprocese se realizeaza prin intermediul unei zone de memorie – tampon, – de oanumita dimensiune, ın care procesul P1 introduce informatii (sub forma unorınregistrari), pe care apoi P2 le extrage.

Procesul P2 nu este nevoit sa astepte pentru fiecare ınregistrare ın parte, iarP1 nu astepta pana ce P2 este gata sa receptioneze ınregistrarea produsa.Procesele evolueaza independent unul de celalat, P1 introducand ın tamponınregistrarea produsa, de unde P2 o va extrage la nevoie.

Se impun urmatoarele restrictii:

• Procesul P1 ıncearca sa introduca o ınregistrare ın tampon si constataca acesta s-a umplut. In acest caz, el va trebui sa astepte pana ce seiveste un loc ın tampon (ceea ce se va ıntampla ca urmare a extrageriunei ınregistrari de catre P2).

• Procesul P2 ıncearca sa extraga o ınregistrare si constata ca tamponuleste gol. In acest caz el va trebui sa astepte pana ce apare o ınregistrareca urmare a introduceri unei ınregistrari ın tampon de catre P1.

Se defineste interfata RMI

Page 259: DISTR1

11.1. PROBLEME PROPUSE 259

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:

(a) Implementarea interfetei IBoundedBuffer.

(b) Realizarea a doua programe client Producator, care introduce obiecte ıntampon si Consumator pentru extragerea lor.

7. Aplicatie de e-mail.

Un e-mail este definit printr-un ansamblu de 4 variabile de tip String

(de la (from), catre (to), subiect (subject), mesaj (body)).

package iemail;

import java.io.Serializable;

public class Email implements Serializable {

public String from = "";

public String subject = "";

public String to = "";

public String body = "";

public Email() {}

public Email(String from, String to, String subject, String body) {

this.from =from;

this.subject =subject;

this.to =to;

this.body =body;

}

}

Interfata aplicatiei RMI IEmailServer este

package iemail;

import java.rmi.*;

public interface IEmailServer extends Remote {

public boolean login(String name, String password)

throws RemoteException;

public void createUser(String name, String password)

throws RemoteException;

public void writeEmail(String from, String to,

String subject, String body) throws RemoteException,

UnknownUserException;

public void readEmail(String userName,ICallbackEmail ce)

throws RemoteException;

}

Page 260: DISTR1

260 CAPITOLUL 11. TEME DE LABORATOR

Un client / utilizator al serviciului sau serverului de e-mail este o instanta aclasei User.

package email;

import java.util.*;

import iemail.*;

public class User implements java.io.Serializable{

String name, password;

Vector emails = new Vector();

public User(String name, String password) {

this.name = name;

this.password = password;

}

public void addEmail(Email email) {

emails.addElement(email);

}

}

Pentru a putea folosi serverul de e-mail, un client trebuie ın prealabil sa seınregistreze (createUser).

Un client ınregistrat se poate conecta la serverul de e-mail (login) dupa carepoate scrie (trimite) sau citi (receptiona) mesaje.

Se cere ca la adagarea unui mesaj (deci ınaintea apelarii metodei User.addEmail)sa se verifice daca emitentul este conectat si daca destinatarul este ınregistrat.ın caz contrar se genereaza exceptia UnknownUserException

package iemail;

public class UnknownUserException extends Exception {

public UnknownUserException() {

super();

}

public UnknownUserException(String exception) {

super(exception);

}

}

Citirea mesajelor este lasata la latitudinea clientilor ın sensul ca clientul im-plementeaza metoda printEmail al interfetei ICallbackEmail.

package iemail;

import java.rmi.*;

import java.rmi.server.*;

public interface ICallbackEmail extends Remote {

public void printEmail(Email email) throws RemoteException;

}

Page 261: DISTR1

11.1. PROBLEME PROPUSE 261

Solicitarea receptionarii mesajelor se realizeaza de catre server prin apelareametodei printEmail pentru fiecare mesaj primit de client.

Se cere:

(a) Implementarea interfetei IEmailServer.

(b) Realizarea a doua programe client AddClient pentru ınregistrarea utiliza-torilor si ClientEmail pentru exploatarea serviciului de e-mail. Fiecaredin cele doua programe are ca parametri numele (identificatorul) clientu-lui, parola si referinta serverului.

8. Integrare numerica.

Scopul aplicatiei este calculul unei integrale de un program server cu functiade integrat detinuta de catre client. In cazul aplicatiei RMI, evaluarile functieicerute de formula de integrare numerica se vor realiza prin apel invers. Inte-grarea numerica va fi executat de un server disponibil clientilor prin mecanis-mul de fabrica de obiecte.

Interfata fabricii de obiecte este

package integ;

import java.rmi.*;

public interface IFabIntegrator extends Remote{

IIntegrator getIntegrator() throws RemoteException;

}

iar interfata IIntegrator este

package integ;

import java.rmi.*;

public interface IIntegrator extends Remote{

double adaptiveSimpson(double leftEnd, double rightEnd,

double epsilon, int initParam) throws RemoteException;

}

declara o metoda ce calculeaza un sir (Imk)k pana ın momentul |Imk

−Imk−1| <

ε.

Propunem utilizarea formulei lui Simpson

∫ b

af(x)dx ≈ Im =

b− a

6m[f(a) + 2

m−1∑i=1

f(a2i) + 4m−1∑i=0

f(a2i+1) + f(b)]

unde ai = a + i b−a2m .

Sirul (mk)k este definit prin mk = 2km0.

Semnificatia parametrilor metodei adaptiveSimpson este

Page 262: DISTR1

262 CAPITOLUL 11. TEME DE LABORATOR

leftEnd arightEnd bepsilon εinitParam m0

Interfata apelului invers este

package integ;

import java.rmi.*;

double function(double x)throws RemoteException;

}

Se cere implementarea aplicatiei cu minimizarea numarului de apelari a metodeifunction.

9. Agenda telefonica.

Pentru crearea si ıntretinerea unei agende telefonice utilizand RMI consideram:

Un ServerCarteTelefon realizeaza urmatoarele operatii:

• adauga o ınregisrare ın agenda telefonica;

O ınregistrare este alcatuita dintr-o pereche (nume, numar).

package itelef;

import java.io.Serializable;

public class Entry implements Serializable{

public String nume,numar;

public Entry(String nume,String numar){

this.nume=nume;

this.numar=numar;

}

}

• sterge ınregistrarea corespunzatoare unui nume din agenda telefonica.

• interogarea agendei: furnizeaza numarul de telefon al unui nume;

• modificarea numarului de telefon corespunzator unui nume;

• afisarea ınregistrarilor;

• salvarea ınregistrarilor ıntr-un fisier;

• restaurarea ınregistrarilor dintr-un fisier.

Interfata corespunzatoare ICarteTelefon este

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;

Page 263: DISTR1

11.1. PROBLEME PROPUSE 263

Entry[] list() throws RemoteException;

void save(String file)throws RemoteException;

void restore(String file)throws RemoteException,ClassNotFoundException;

void modifyEntry(Entry e)throws RemoteException;

}

Interfata fabricii de obiecte IFabCarteTelefon este

package itelef;

import java.rmi.*;

public interface IFabCarteTelefon extends Remote{

ICarteTelefon getCarteTelefon() throws RemoteException;

}

Se cere implementarea aplicatiei de creare si ıntretinere a agendei telefonice.

Se extinde aplicatia anterioara cu functiunea suplimentara a serverului de aretine toate modificarile efectuate de catre un client si care la solicitare pot fiafisate.

Modificarile se retin ıntr-o variabila mod de tip Vector. La solicitarea clien-tului, pentru fiecare modificare memorata, programul server apeleaza metodaschimbStare declarata ın interfata

package itelef;

import java.rmi.*;

public interface IApelInvers extends Remote{

void schimbStare(Entry e) throws RemoteException;

}

Metoda schimbStare(Entry e) nu face altceva decat afiseaza campurile vari-abilei e.

Interfata ICarteTelefon declara ın plus metoda

void apelInvers(IApelInvers obj)throws RemoteException;

Aceasta metoda va fi implementata ın programul ServerCarteTelefon.java.Elementelor retinute ın vectorul mod li se aplica metoda schimbStare().

Sa se implementeze acesta functiune utilizand tehnica apelului invers.

Se poate utiliza baza de date AGENDATELEFONICA formata din tabelul

TELEF

ID

NUME

NUMAR

Page 264: DISTR1

264 CAPITOLUL 11. TEME DE LABORATOR

10. Sa se realizeze programe client avand o interfata grafica. Recomandam uti-lizarea produsului NetBeans.

R. Exemplu de client pentru problema calculului celui mai mare divizor comuna doua numere cu soclu TCP.

import java.net.*;

import java.io.*;

public class VisualCmmdcClient extends javax.swing.JFrame {

public VisualCmmdcClient() {

initComponents();

}

private void initComponents(){

// cod generat de Netbeans

}

private void jButton1MouseClicked(java.awt.event.MouseEvent evt){

long m=(new Long(jTextField1.getText())).longValue();

long n=(new Long(jTextField2.getText())).longValue();

String host=jTextField4.getText();

int port=(new Integer(jTextField5.getText())).intValue();

Socket cmmdcSocket = null;

DataInputStream in=null;

DataOutputStream out=null;

try {

cmmdcSocket = new Socket(host, port);

out=new DataOutputStream(cmmdcSocket.getOutputStream());

in=new DataInputStream(cmmdcSocket.getInputStream());

}

catch(UnknownHostException e) {

System.err.println("Server necunoscut: "+host);

System.exit(1);

}

catch (IOException e) {

System.err.println("Eroare I/O : "+host+" la portul "+port);

System.exit(1);

}

try{

out.writeLong(m);

out.writeLong(n);

long r=in.readLong();

jTextField3.setText(new Long(r).toString());

out.close();

in.close();

cmmdcSocket.close();

}

catch(IOException e){

System.err.println("Imposibilitate de comunicare");

}

}

private void exitForm(java.awt.event.WindowEvent evt) {

System.exit(0);

}

public static void main(String args[]) {

Page 265: DISTR1

11.1. PROBLEME PROPUSE 265

new VisualCmmdcClient().setVisible(true);

}

private javax.swing.JButton jButton1;

private javax.swing.JLabel jLabel1;

private javax.swing.JLabel jLabel2;

private javax.swing.JLabel jLabel3;

private javax.swing.JLabel jLabel4;

private javax.swing.JTextField jTextField1;

private javax.swing.JTextField jTextField2;

private javax.swing.JTextField jTextField3;

private javax.swing.JTextField jTextField4;

private javax.swing.JTextField jTextField5;

}

11. Sa se determine zodia (chinezeasca) corespunzatoare unei date calendaristice.Obs. Inceputul anului nou chinezesc nu coincide cu ınceputul anului nou cal-endaristic.

Se va crea baza de date AN CHINEZESC alcatuita din tabelul

INCEPUT

AN

LUNA

ZI

12. Se considera baza de date UNITATI DE MASURA formata din tabelul

CONVERSIE

UM SI

UM SIMBOL

DENUMIRE (ROM)

VAL

Exemplu:

1 M INCH Tol 0.02542 M FEET (FT) Picior 0.30483 KG UK ONCE Uncie (UK) 0.0311034 KG UK POUND Livra (UK) 0.373

Sa se realizeze o aplicatie pentru conversia unitatilor de masura extinzandcontinutul bazei de date.

13. Se considera baza de date NORME-DIDACTICE formata din tabelele

CADRU-DIDACTIC MATERIA CURSURI

COD-CADRU-DIDACTIC COD-MATERIE COD-CURS

NUME DENUMIRE COD-CADRU-DIDACTIC

COD-MATERIE

Page 266: DISTR1

266 CAPITOLUL 11. TEME DE LABORATOR

Sa se elaboreze programe de ıntretinere si interogare a bazei de date.

14. Se considera baza de date APROVIZIONARE formata din tabelele

RESURSA FURNIZOR CONTRACT

COD-RESURSA COD-FURNIZOR COD-CONTRACT

DENUMIRE NUME COD-FURNIZOR

CANTITATE COD-RESURSA

CANTITATE

Sa se elaboreze programe de ıntretinere si interogare a bazei de date.

15. Se considera baza de date DESFACERE formata din tabelele

PRODUSE BENEFICIAR CONTRACT

COD-PRODUS COD-BENEFICIAR COD-CONTRACT

DENUMIRE NUME COD-BENEFICIAR

CANTITATE COD-PRODUS

CANTITATE

Sa se elaboreze programe de ıntretinere si interogare a bazei de date.

16. Validarea codului numeric personal.

Codul Numeric Personal (CNP) constituie numarul de ordine atribuit de Evidenta

populatiei unei persoane la nastere, de cetatenie romana, care se ınscrie ın actele si

certificatele de stare civila si se preia ın celelate acte cu caracter oficial.

Structura unui CMP este

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

Page 267: DISTR1

11.1. PROBLEME PROPUSE 267

Verificarea cifrei de control: Se foloseste cheia de testare 279146358279. Primele12 cifre ale CNP se ınmultesc pe rand de la staga spre dreapta cu cifra core-spunzatoare a cheii de testare. Cele 12 produse se aduna, iar suma se ımpartela 11. Daca restul ımpartirii este mai mic decat 10, atunci acesta va fi cifra decontrol. Daca restul ımpartirii este 10 atunci cifra de control este 1.

Sa se elaboreze un program pentru verificarea CNP.

17. Informatiile unui aeroport civil privind decolarile(plecari) si aterizari(sosiri)pe parcursul unei perioade sunt cuprinse ın tabelul activitate al bazei de dateaeroport

ACTIVITATE

IDFEL aterizare/decolareZITIMP ora/minutCOMPANIEOBSERVATIE

Sa se realizeze o aplicatie de furnizare a datelor catre clienti.

Page 268: DISTR1

268 CAPITOLUL 11. TEME DE LABORATOR

Page 269: DISTR1

Appendix A

Unealta de dezvoltareapache-ant

Incepem aceasta sectiune prin a introduce cateva elemente privind sintaxa ıntr-un document xml pentru ca apache-ant va face apel la un fisier xml.

XML

EXtensible Markup Language (XML) reprezinta un limbaj pentru definirea mar-cajelor de semantica, care ımpart un document ın parti identificabile ın document.Din 1998, XML este un standard World Wide Web Consortium (W3C).

Totodata XML este un meta-limbaj pentru definirea sintaxei de utilizat ın altedomenii.

XML descrie structura si semantica si nu formatarea.

Structura unui document XML este

<?xml version="1.0" encoding="tip_codare" [standalone="yes"]?>

corpul documentului alcatuit din elemente

Prima linie - preambulul - reprezinta declaratia de document XML. Tipul codariipoate fi utf-8, iso-8859-1.

Corpul documentului este alcatuit din elemente. Inceputul unui element esteindicat printr-un marcaj. Textul marcajului constituie denumirea elementului. El-ementele pot fi cu corp, alcatuit din alte elemente, avand sintaxa

<marcaj>

corpul elementului

</marcaj>

sau fara corp, caz ın care sintaxa este

269

Page 270: DISTR1

270 APPENDIX A. UNEALTA DE DEZVOLTARE APACHE-ANT

<marcaj/>

Un marcaj poate avea atribute date prin sintaxa

numeAtribut="valoareAtribut"

Valoarea unui atribut este cuprinsa ıntre ghilimele (””).

<marcaj numeAtribut="valoareAtribut" . . .>

corpul elementului

</marcaj>

Exista un singur element radacina. Elementele unui document XML formeazaun arbore. Fiecarui marcaj de ınceput al unui element trebuie sa-i corespunda unmarcaj de sfarsit. Caracterele mari si mici din denumirea unui element sunt distincte(case sensitive).

Elementele ıncuibarite (nested)- incluse ıntr-un alt element - nu se pot amesteca,adica un marcaj de sfarsit corespunde ultimului marcaj de ınceput.

Un comentariu se indica prin

<!--

Text comentariu

-->

Exemplul A.0.1 Fisier XML - denumirile elementelor si continutul lor permit ıntelegereasimpla a semanticii introduse ın document.

1 <?xml version=” 1 .0 ” encoding=” utf−8”?>2 <c u r s u r i>3 <d i s c i p l i n a f e l=” o b l i g a t o r i u ”>4 <nume> Anal iza numerica </nume>5 <fond−de−timp>6 <curs> 2 </ curs>7 <seminar> 1 </ seminar>8 <l a b o r a t o r> 1 </ l a b o r a t o r>9 </ fond−de−timp>

10 </ d i s c i p l i n a>11 <d i s c i p l i n a f e l=” o b l i g a t o r i u ”>12 <nume> Programare d i s t r i b u i t a </nume>13 <fond−de−timp>14 <curs> 2 </ curs>15 <seminar> 0 </ seminar>16 <l a b o r a t o r> 2 </ l a b o r a t o r>17 </ fond−de−timp>18 </ d i s c i p l i n a>19 <d i s c i p l i n a f e l=” o b l i g a t o r i u ”>20 <nume> So f t matematic </nume>21 <fond−de−timp>22 <curs> 2 </ curs>23 <seminar> 0 </ seminar>24 <l a b o r a t o r> 1 </ l a b o r a t o r>25 </ fond−de−timp>26 </ d i s c i p l i n a>27 </ c u r s u r i>

Page 271: DISTR1

271

Un document XML este bine formatat daca:

• exista preambul;

• fiecare element este ınchis sau ıi corespunde un marcaj de inchidere;

• marcajele ıncuibarite nu se amesteca.

Un document XML este valid daca

• este bine formatat;

• ın cazul ca exista o referinta catre XML Schema atunci documentul XML esteconform schemei.

Prelucrarea unui document XML ın Java se poate face pe baza interfetelor deprogramare:

• Document Object Model - DOM;

• Simple API for XML - SAX;

• Stream API for XML - StAX;

• Java Architecture for XML Binding - JAXB.

Se recomanda utilizarea interfetelor de programare StAX si JAXB.

Amintim faptul ca reprezentarea obiectelor matematice prin elemente XML con-stituie subiectul a doua proiecte MathML si OpenMath. Obiectivul limbajului MathMLeste reprezentarea unui text matematic ıntr-un document HTML, ın timp ce obiec-tivul proiectului OpenMath este reprezentarea semantica a datelor matematice pen-tru realizarea de aplicatii cooperante ıntre sisteme de calcul simbolic - CAS (Com-puter Algebra System).

apache-ant

Utilitarul apache-ant asigura executarea unui sir de comenzi de operare. Acestecomenzi se ınregistreaza ıntr-un fisier de tip xml, cu denumirea build.xml. Astfel,apache-ant se substituie unui fisier de comenzi bat ın Windows sau unui script shelldin Linux/Unix. Avantajul obtinut consta ın independenta fata de platforma decalcul (Windows, Linux).

Instalarea consta ın dezarhivarea fisierului descarcat din Internet.

Lansarea ın executie necesita fixarea variabilei de mediu JAVA HOME, ce continecalea la distributia Java. Lansarea se poate face prin urmatorul fisier de comenzi

Page 272: DISTR1

272 APPENDIX A. UNEALTA DE DEZVOLTARE APACHE-ANT

set JAVA_HOME=. . .

set ANT_HOME=. . .

%ANT_HOME%\bin\ant.bat %1

Parametrul %1 acestui fisier de comenzi reprezinta obiectivul care se doreste afi atins. Daca se modifica denumirea sau locatia fisierului build.xml atunci fisierulde comenzi se invoca cu optiunea -buildfile.

Un fisier build.xml corespunde unui proiect (project), alcatuit din unul sau maimulte obiective (target). Atingerea fiecararui obiectiv consta din ındeplinirea uneiasau mai multor sarcini (task). Apache-ant contine o familie predefinita de sarcini.Programatorul are datoria fixarii atributelor sarcinilor. Manualul din documentatiaprodusului contine descrierea atributelor cat si exemple. In general, o sarcinareprezinta o operatie executata uzual ın linia de comanda.

Atributele se dau, respectand sintaxa XML

numeAtribut = ”valoareAtribut”

Astfel, un proiect apare sub forma

<project name="numeProiect"

default="obiectiv"

basedir="catalogDeReferinta">

<target name="numeObiectiv">

sarcini

</target>

. . . . . . .

</project>

Daca la apelarea lui Apache-ant lipseste parametrul optional atunci se va executaobiectivul default.

Intr-un proiect se pot defini variabile prin marcajul

<property name=”numeVariabila” value=”valoareVariabila” />

O variabila definita se va utiliza cu sintaxa ${numeVariabila}.

Exemplul A.0.2 Fisierul build pentru executia programelor din §1.2.

1 <p r o j e c t name=” Socket ” default=” Server ” ba s ed i r=” . ”>2 <d e s c r i p t i o n> S o c l u r i TCP </ d e s c r i p t i o n>

4 < !−− s e t g l o b a l p r op e r t i e s f o r t h i s b u i l d −−>5 <property name=” bu i ld ” l o c a t i o n=”work”/>6 <property name=” s r c ” l o c a t i o n=” . ” />

8 <t a r g e t name=” i n i t ”>

Page 273: DISTR1

273

9 < !−− Create the time stamp −−>10 <tstamp/>11 < !−− Create the b u i l d d i r e c t o r y s t r u c t u r e used by compile −−>12 <d e l e t e d i r=”${ bu i ld }”/>13 <mkdir d i r=”${ bu i ld }”/>14 </ t a r g e t>

16 <t a r g e t name=”Compile” depends=” i n i t ” d e s c r i p t i o n=” compile the source ” >17 <javac s r c d i r=”${ s r c }” d e s t d i r=”${ bu i ld }” inc ludeantrunt ime=” f a l s e ”/>18 </ t a r g e t>

20 <t a r g e t name=” Server ” depends=”Compile”>21 <java classname=”MyMServer” c l a s s pa th=”${ bu i ld }” f o rk=” true ”/>22 </ t a r g e t>

24 <t a r g e t name=” Cl i en t ”>25 <java classname=”VisualCmmdcClient” c l a s sp a t h=”${ bu i ld }” f o rk=” true ”/>26 </ t a r g e t>27 </ p r o j e c t>

Utilizarea lui apache-ant presupune ca toate resursele utilizate, cuprinse uzualın fisiere cu extensia jar (j ava arhive) sunt disponibile pe calculatorul local. Dacacalculatorul este conectat la Internet, atunci resursele publice pot fi descarcateımpreuna cu toate dependintele si utilizate prin apache-ant, folosind suplimentarapache-ivy 1.

In vederea utilizarii lui apache-ivy se copiaza fisierul ivy-*.jar din distributiaapache-ivy ın ANT HOME\lib.

Fisierul build.xml contine ın plus

<project name="Proiect" basedir="." default="obiectiv_final"

xmlns:ivy="antlib:org.apache.ivy.ant">

. . .

<!-- =================================

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

1Asemanator cu maven, un alt produs de dezvoltare.

Page 274: DISTR1

274 APPENDIX A. UNEALTA DE DEZVOLTARE APACHE-ANT

<ivy:report todir="${report.dir}"/>

</target>

. . .

</project>

la care se adauga un fisier ivy.xml, cu dependintele necesare aplicatiei care urmeazaa fi preluate dintr-unul din depozitele ivy - local, shared, public

<ivy-module version="2.0">

<info organisation="cs.unitbv.ro" module="Biblioteca-Ivy"/>

<dependencies>

<dependency org="commons-fileupload" name="commons-fileupload" rev="1.2"/>

. . .

</dependencies>

</ivy-module>

Page 275: DISTR1

Appendix B

Utilizarea SGBD ın Java

Scopul acestei anexe este prezentarea bazelor utilizarii unui Sistem de Gestiunea Bazelor de Date (SGBD - Data Bases Management System - DBMS) din Java.Exemplificam modul de operare si utilizare pentru crearea si exploatarea unei bazede date corespunzatoare unei agende telefonice.

B.1 Derby / Javadb

Instalarea produsului consta ın dezarhivarea fisierului descarcat.Utilizarea produsului. Va fi utilizata varianta de retea bazata pe un server al

SGBD care utilizeaza implicit portul 1527.Se ıntreprind urmatoarele operatii:

1. Lansarea serverului Derby / Javadb:

set JAVA_HOME=. . .

set DB_HOME=. . .

set PATH=%DB_HOME%\bin;%PATH%

startNetworkServer.bat

2. Crearea bazei de date se va face utilizand utilitarul ij din distributia Derby /Javadb. Acesta se lanseaza prin:

set JAVA_HOME=. . .

set DB_HOME=. . .

set PATH=%DB_HOME%\bin;%PATH%

ij.bat

Exemplul B.1.1

Baza de date AgendaEMail se creaza executand

run ’CreateAgendaE.sql’;

unde fisierul CreateAgendaE.sql este

275

Page 276: DISTR1

276 APPENDIX B. UTILIZAREA SGBD IN JAVA

1 connect ’ jdbc : derby : AgendaEMail ; c r e a t e=true ’ ;2 create table adrese (3 id int generated always as identity ( s t a r t with 1 , increment by 1)4 primary key ,5 nume char (20) not null ,6 emai l char (30) not null7 ) ;

si ıncarcarea cu date

run ’ValuesAgendaE.sql’;

cu fisierul ValuesAgendaE.sql

1 insert into adrese (nume , emai l ) values ( ’ aaa ’ , ’ aaa@yahoo . com ’ ) ,2 ( ’ bbb ’ , ’ bbb@gmail . com ’ ) , ( ’ ccc ’ , ’ ccc@unitbv . ro ’ ) ,3 ( ’ aaa ’ , ’ xyz@unitbv . ro ’ ) ;

Putem crea tabele si le ıncarca cu valori prin ant. In acest caz, ın prealabiltrebuie creata baza de date prin intermediul utilitarului ij:

connect ’jdbc:derby:AgendaEMail;create=true’;

Fisierul build.xml are codul

<?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"/>

Page 277: DISTR1

B.2. MYSQL 277

DROP TABLE adrese;

</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"/>

SELECT * FROM adrese;

</sql>

</target>

</project>

Resursele externe utilizate se fixeaza ın fisierul de proprietati build.properties

db.driver=org.apache.derby.jdbc.ClientDriver

db.url=jdbc:derby://localhost:1527/AgendaEMail

db.user=. . .

db.pw=. . .

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 descarcat varianta fara instalareautomata mysql-noinstall-*.*.*-win32.zip. Acest fisier se dezarhiveaza ıntr-un cata-log MYSQL HOME.

Implicit, serverul mysql utilizeaza portul 3306, iar fisierele bazelor de date vor figazduite ın catalogul MYSQL HOME\data.

Pentru utilizarea ın aplicatii Java trebuie descarcat un conector mysql-connector-java-*.*.*.tar.gz, continand fisierul mysql-connector-java-*.*.*-bin.jar.

Page 278: DISTR1

278 APPENDIX B. UTILIZAREA SGBD IN JAVA

Utilizarea produsului.Se ıntreprind urmatoarele operatii:

1. Lansarea serverului mysql :

set MYSQL_HOME=. . .

set PATH=%MYSQL_HOME%\bin;%PATH%

mysqld

2. Unui utilizator i se poate atasa o parola, executand ıntr-o sesiune mysql comen-zile

set password for ’root’@’localhost’=password(’parola’);

set password for ’root’@’127.0.01’=password(’parola’);

Parola se sterge prin

set password for ’root’@’localhost’=password(’’);

set password for ’root’@’127.0.01’=password(’’);

Daca utilizatorul are o parola atunci la apelarea utilitarului mysql va fi prezentasi optiunea -p.

3. Exemplul B.2.1

Crearea bazei de date AgendaEMail se va face prin intermediul fisierului decomenzi

set MYSQL_HOME=d:\mysql-*-win32\bin

set path=%MYSQL_HOME%;%PATH%

mysql -u root < CreateAgendaE.sql

mysql -u root < ValuesAgendaE.sql

unde scriptul CreateAgendaE.sql este

1 create database AgendaEMail ;2 use AgendaEMail ;

4 create table adrese (5 id int primary key auto increment not null ,6 nume char (20) not null ,7 emai l char (30) not null8 ) ;

iar scriptul de populare cu date (ValuesAgendaE.sql) este

1 use AgendaEMail ;2 insert adrese values (1 , ”aaa” , ”aaa@yahoo . com” ) ;3 insert adrese values (2 , ”bbb” , ”bbb@gmail . com” ) ;4 insert adrese values (3 , ” ccc ” , ” ccc@unitbv . ro ” ) ;5 insert adrese values (1 , ”aaa” , ”xyz@unitbv . ro ” ) ;

4. Serverul mysql se opreste prin

set MYSQL_HOME=d:\mysql-*-win32

set PATH=%MYSQL_HOME%\bin;%PATH%

mysqladmin -u root shutdown

Page 279: DISTR1

B.3. POSTGRESQL 279

B.3 PostgreSQL

Instalarea produsului. PostgreSQL este distribuit gratuit. Vom folosi o ver-siune fara instalare automata, care se dezarhiveaza ın catalogul ...\pgsql.

Comunicatia cu acest server se face prin portul 5432.Pentru utilizarea ın aplicatii Java trebuie descarcat un conector postgresql-*.*-

*.jdbc4.jar.Utilizarea produsului.

• Crearea bazei de date a SGBD (initpg.bat)

set PG_HOME=. . .\pgsql

%PG_HOME%\bin\initdb -D %PG_HOME%\Data

• Lansarea serverului postgresql (server.bat)

set PG_HOME=. . .\pgsql

%PG_HOME%\bin\pg_ctl -D %PG_HOME%\Data start

Serverul se opreste tastand Ctrl+c.

• Crearea unui utilizator (inituser.bat)

set PG_HOME=d:\pgsql

%PG_HOME%\bin\createuser

In cele ce urmeaza vom presupune ca utilizatorul are numele postgres. Nu-mele utilizatorul postgres este predefinit. Daca se alege alt nume atunci se vaexecuta suplimentar

%PG_HOME%\bin\createdb nume_utilizator

• Exemplul B.3.1

Crearea aceleiasi baze de date AgendaTelefonica se face cu fisierul 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

Script-urile sql sunt

createdb.sql

create database "AgendaEMail" owner postgres;

createtable.sql

Page 280: DISTR1

280 APPENDIX B. UTILIZAREA SGBD IN JAVA

create table adrese(id int4 primary key,

nume varchar(20) not null, email varchar(30) not null);

insertvalues.sql

insert adrese values(1,"aaa","[email protected]");

insert adrese values(2,"bbb","[email protected]");

insert adrese values(3,"ccc","[email protected]");

insert adrese values(1,"aaa","[email protected]");

B.4 HyperSQL

Instalarea produsului. Instalarea consta din dezarhivarea fisierului descarcatıntr-un catalog pe care-l notam HSQL HOME. HypereSQL se distribuie gratuit.

Comunicatia cu acest serverul se face prin portul 9001.

Conectorul Java este continut ın distributia produsului si este fisierul hsqldb.jar.

Utilizarea produsului.

• Pornirea serverului si crearea bazei de date AgendaTelefonica

set HSQL_HOME=. . .\hsqldb

set JAVA_HOME=. . .

java -cp %HSQL_HOME%/lib/hsqldb.jar org.hsqldb.server.Server

--database.0 file:AgendaEMail --dbname.0 AgendaEMail

• Crearea tabelei telef si inserarea valorilor initiale

set HSQL_HOME=. . .\hsqldb

set JAVA_HOME=. . .

java -cp %HSQL_HOME%/lib/sqltool.jar org.hsqldb.cmdline.SqlTool

--inlineRc URL=jdbc:hsqldb:hsql://localhost/AgendaEMail,

USER=SA,password= CreateTable.sql

java -cp %HSQL_HOME%/lib/sqltool.jar org.hsqldb.cmdline.SqlTool

--inlineRc URL=jdbc:hsqldb:hsql://localhost/AgendaEMail,

USER=SA,password= InsertValues.sql

unde script-urile sql sunt

CreateTable.sql

\c true

DROP TABLE adrese;

\c false

\p Creating Table adrese

create table adrese(

id integer primary key not null,

nume varchar(20) not null,

email varchar(30) not null

);

Page 281: DISTR1

B.5. ORACLE XE 10G 281

InsertValues.sql

\p Interting values into telef

insert INTO adrese ("ID","NUME","EMAIL") values(1,’aaa’,’[email protected]’);

insert INTO adrese ("ID","NUME","EMAIL") values(2,’bbb’,’[email protected]’);

insert INTO adrese ("ID","NUME","EMAIL") values(3,’ccc’,’[email protected]’);

insert INTO adrese ("ID","NUME","EMAIL") values(4,’aaa’,’[email protected]’);

commit;

B.5 Oracle XE 10g

Utilizarea produsului ın linie de comanda:

• Intr-o fereastra DOS se lanseaza sqlplus.

• Start → Programs → Oracle Database 10g Express Edition → Run SQL Com-mand Line. In fereastra DOS se lanseaza connect.

Ca user : system putem schimba portul HTTP din 8080 ın 9090(de exemplu),prin

exec dbms_xdb.sethttpport(9090)

Exemplul B.5.1

Baza de date AgendaEMail se creaza executand

1. @CreateAgendaE.sql

unde fisierul CreateAgendaE.sql este

1 create table adrese (2 id int primary key ,3 nume varchar2 ( 20 ) ,4 emai l varchar2 (30)5 ) ;

si ıncarcarea cu date

2. @ValuesAgendaE.sql

cu fisierul ValuesAgendaE.sql

1 insert into adrese values (1 , ’ aaa ’ , ’ aaa@unitbv . ro ’ ) ;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 ’ ) ;

Page 282: DISTR1

282 APPENDIX B. UTILIZAREA SGBD IN JAVA

B.6 Sablonul de utilizare a unei baze de date ıntr-unprogram Java

Interactiunea cu baze de date relationale implica:

1. Stabilirea corespondentei dintre date aflate ın obiecte si atribute / tabele (ob-ject to relational database mapping).

2. Apelarea actiunilor CRUD (Create, Read, Update, Delete).

Pentru realizarea acestor activitati sunt cunoscute mai multe modele:

• Data Access Object DAO

• Java Data Object JDO

Limbajul SQL (Structured Query Language) este dependent de SGBD utilizat.Dezvoltarea modelelor de interactiune dintre un program Java cu o baza de datedintr-un SGBD s-a nascut din dorinta de a asigura independenta stratului Java deSGBD. Solutia gasita consta ın introducerea unui strat suplimentar, ıntre Java siSGBD care asigura corespondenta ıntre obiectele Java cu tabelele unei baze de datesi permite o configurare simpla la schimbarea SGBD.

Materializarea acestor idei (Object Relational Mapping - ORM) se afla ın

• interfata de programare (API) Java Persistence API (JPA);

• produsul Hibernate.

Pentru ınceput vom face abstractie de modelele mentionate anterior si vom trataın modul cel mai simplu realizarea unei aplicatii care interactioneaza cu o baza dedate gestionata de un SGBD.

Pentru a avea acces la o baza de date trebuie stabilita o conexiune la acea bazade date. In acest sens este necesar cunoasterea:

• driver-ului de acces la sistemul de gestiune a bazei de date (SGBD) (StringjdbcDriver)

Tip SGBD Driver Fisieruldriver-ului

access sun.jdbc.odbc.JdbcOdbcDrivermysql com.mysql.jdbc.Driver mysql-connector-java-*.*.*-bin.jar

(www.mysql.com)derby org.apache.derby.jdbc.ClientDriver derbyclient.jarjavadb

(distributia derby)postgresql org.postgresql.Driver postgresql-*.*-*.jdbc4.jarhypeqsql org.hsqldb.jdbcDriver hsqldb.jaroraclexe oracle.jdbc.driver.OracleDriver ojdbc14.jar

Daca ıntr-un servlet se realizeaza o conexiune la o baza de date atunci fisieruldriver-ului trebuie copiat ın catalogul lib al aplicatiei.

Page 283: DISTR1

B.6. SABLONUL DE UTILIZARE A UNEI BAZE DE DATE 283

• adresa URL a bazei de date (String URLBazaDate), sub forma

Tip SGBD Referinta Baza de Date

mysql jdbc:mysql://host:3306/numeBazaDatederby / javadb jdbc:derby://host:1527/numeBazaDate

postgresql jdbc:postgresql://host:5432/numeBazaDatehypersql jdbc:hsqldb:hsql://host/numeBazaDate

oracle jdbc:oracle:thin:@host:1521:XE

Sablonul de prelucrare este

String jdbcDriver=. . .

String URLBazaDate=. . .

Connection con=null;

try{

Class.forName(jdbcDriver).newInstance();

con=DriverManager.getConnection(URLBazaDate);

...

}

catch(ClassNotFoundException e){. . .}

catch(SQLException e){. . .}

Odata conexiunea cu baza de date stabilita se genereaza un obiect de tip Statement

prin intermediul caruia se executa interogarea SQL.

Statement instructiune=con.createStatement();

String sql=. . . //fraza select;

Rezultatele interogarii bazei de date se obtine prin

try{

ResultSet rs=instructiune.executeQuery(sql);

while(rs.next()){

prelucrarea rezultatului

}

}

catch(SQLException e){...}

Exemplul B.6.1

O interogare simpla a bazei de date AgendaEMail se realizeaza cu programul

1 import java . i o . ∗ ;2 import java . s q l . ∗ ;3 import java . net . ∗ ;

Page 284: DISTR1

284 APPENDIX B. UTILIZAREA SGBD IN JAVA

4 import java . u t i l . ∗ ;

6 public class AgendaE {7 Statement i n s t r u c t i u n e=null ;

9 public void i n i t ( S t r ing username , S t r ing password ){10 // SGBD Derby11 St r ing jdbcDr iver=” org . apache . derby . jdbc . C l i en tDr ive r ” ;12 St r ing URLBazaDate=” jdbc : derby :// l o c a l h o s t :1527/ AgendaEMail” ;

14 // SGBD mysql15 /∗16 St r ing jdbcDr iver=”com. mysql . j dbc . Driver ” ;17 St r ing URLBazaDate=”jdbc : mysql :// l o c a l h o s t :3306/AgendaEMail? user=root ” ;18 ∗/

20 // PostgreSQL21 /∗22 St r ing jdbcDr iver=”org . p o s t g r e s q l . Driver ” ;23 St r ing URLBazaDate=”jdbc : p o s t g r e s q l :// l o c a l h o s t :5432/AgendaEMail ” ;24 // S t r ing username=pos t g r e s ” ;25 // S t r ing password=”;26 ∗/

28 // HyperSQL29 /∗30 St r ing jdbcDr iver=”org . h s q l d b . jdbcDr iver ” ;31 St r ing URLBazaDate=”jdbc : h s q l d b : h s q l :// l o c a l h o s t /AgendaEMail ” ;32 // S t r ing username=”SA”;33 // S t r ing password=””;34 ∗/

36 // Oracle 10g Express Edi t ion37 /∗38 St r ing jdbcDr iver=”orac l e . j dbc . d r i v e r . OracleDriver ” ;39 St r ing URLBazaDate=”jdbc : o rac l e : t h in : @ loca lhos t : 1521 :XE”;40 ∗/

42 Connection con=null ;43 try{44 Class . forName ( jdbcDr iver ) . newInstance ( ) ;45 i f ( username!=null )46 con = DriverManager . getConnect ion (URLBazaDate , username , password ) ;47 else48 con = DriverManager . getConnect ion (URLBazaDate ) ;49 i n s t r u c t i u n e=con . createStatement ( ) ;50 }51 catch ( ClassNotFoundException e ){52 System . out . p r i n t l n ( ” Driver i n e x i s t e n t JDBC: ”+jdbcDr iver ) ;53 }54 catch ( SQLException e ){55 System . out . p r i n t l n ( ”Baza de date i n e x i s t e n t a ”+URLBazaDate ) ;56 }57 catch ( Exception e ){58 System . out . p r i n t l n ( ” Eroare : ”+e . getMessage ( ) ) ;59 }60 }

62 public stat ic void main ( St r ing [ ] a rgs ) {

Page 285: DISTR1

B.6. SABLONUL DE UTILIZARE A UNEI BAZE DE DATE 285

63 AgendaE agenda=new AgendaE ( ) ;64 i f ( args . length >0)65 agenda . i n i t ( args [ 0 ] , a rgs [ 1 ] ) ;66 else67 agenda . i n i t (null , null ) ;68 Scanner scanner=new Scanner ( System . in ) ;69 int pre l , no ;70 St r ing ch=”Y” ,nume=”” , emai l=”” , s q l=”” ;71 Resu l tSet r s=null ;72 try{73 while ( ch . s tartsWith ( ”Y” ) ){74 do{75 System . out . p r i n t l n ( ” Continue ? (Y/N) ” ) ;76 ch=scanner . next ( ) . toUpperCase ( ) ;77 }78 while ( ( ! ch . s tartsWith ( ”Y”))&&(! ch . s tartsWith ( ”N” ) ) ) ;79 i f ( ch . s tartsWith ( ”Y” ) ){80 System . out . p r i n t l n ( ”Natura i n t e r o g a r i i ?” ) ;81 System . out . p r i n t l n ( ” (Dupa nume : 1 , Dupa emai l : 2 ) ” ) ;82 do{83 p r e l =0;84 try{85 p r e l=scanner . next Int ( ) ;86 }87 catch ( InputMismatchException e ){}88 }89 while ( ( pre l <1)&&(pre l >2)) ;90 switch ( p r e l ){91 case 1 :92 System . out . p r i n t l n ( ”Numele” ) ;93 nume=’ \ ’ ’+scanner . next ( ) . tr im ()+ ’ \ ’ ’ ;94 s q l=” s e l e c t ∗ from adrese where nume=”+nume ;95 r s=agenda . i n s t r u c t i u n e . executeQuery ( s q l ) ;96 i f ( r s !=null ){97 System . out . p r i n t l n ( ”S−au g a s i t a d r e s e l e de e−mail : ” ) ;98 while ( r s . next ( ) ){99 System . out . p r i n t l n ( r s . g e t S t r i n g ( ” emai l ” ) ) ;

100 }101 }102 else {103 System . out . p r i n t l n ( ”Fara adresa de e−mail ! ” ) ;104 }105 break ;106 case 2 :107 System . out . p r i n t l n ( ”Email” ) ;108 emai l=’ \ ’ ’+scanner . next ( ) . tr im ()+ ’ \ ’ ’ ;109 s q l=” s e l e c t ∗ from adrese where emai l=”+emai l ;110 r s=agenda . i n s t r u c t i u n e . executeQuery ( s q l ) ;111 i f ( r s !=null ){112 System . out . p r i n t l n ( ”S−a g a s i t numele” +113 ” : ” ) ;114 while ( r s . next ( ) ){115 System . out . p r i n t l n ( r s . g e t S t r i n g ( ”nume” ) ) ;116 }117 }118 else {119 System . out . p r i n t l n ( ”Numar i n e x i s t e n t ! ” ) ;120 }121 break ;

Page 286: DISTR1

286 APPENDIX B. UTILIZAREA SGBD IN JAVA

122 default : System . out . p r i n t l n ( ”Comanda eronata ” ) ;123 }124 }125 }126 }127 catch ( Exception e ){128 System . out . p r i n t l n ( ” Cl i entExcept ion : ”+e . getMessage ( ) ) ;129 }130 }131 }

Fraza select si interogarea se mai putea programa prin

String sql="select * from adrese where nume =?";

PreparedStatement prepStmt=con.prepareStatement(sql);

prepStmt.setString(1,nume);

RezultSet rs=prepStmt.executeQuery();

. . .

prepStmt.close();

In acest caz, valoarea variabilei nume este fara apostroafe.

Compilarea si executia programului necesita declararea ın variabila classpath

a fisierelor

• 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

Executia programului presupune serverul SGBD activ.

B.7 Modelul DAO

Prezentarea va exemplifica modelul DAO ın cazul bazei de date amintite anterior(AgendaEMail): o agenda de adrese e-mail alcatuita dintr-un singur tabel adrese,cu atributele

id: int, cheia primara

nume: String

email: String

Conexiunea cu baza de date se separa de activitatile care se ıntreprind asuprabazei de date. Pentru stabilirea conexiunii este nevoie doar de adresa URI a bazeide date. Alegem solutia simpla:

Page 287: DISTR1

B.7. MODELUL DAO 287

1 package agendae . dao ;2 import java . s q l . Connection ;3 import java . s q l . SQLException ;4 import java . s q l . DriverManager ;5 public class DAOBase{6 public Connection getConnect ion ( ) throws Exception {7 St r ing URLDB=” jdbc : derby :// l o c a l h o s t :1527/ AgendaEMail” ;8 Connection connect ion = null ;9 try {

10 connect ion=DriverManager . getConnect ion (URLDB) ;11 }12 catch ( SQLException e ) {13 throw new Exception ( ” Connection Error : ”+e . getMessage ( ) ) ;14 }15 return connect ion ;16 }17 }

Fiecarui tabel al bazei de date i se asociaza:

• O componenta Java (bean) a carei instanta retine (total sau partial) datelecorespunzatoare unei linii a tabelei.

1 package agendae . dao ;2 import java . i o . S e r i a l i z a b l e ;

4 public class Adrese implements S e r i a l i z a b l e {5 private int id ;6 private St r ing nume ;7 private St r ing emai l ;

9 public Adrese ( ){}

11 public Adrese ( int id , S t r ing nume , S t r ing emai l ) {12 this . id = id ;13 this . nume = nume ;14 this . emai l = emai l ;15 }16 public St r ing getNume ( ) {17 return nume ;18 }19 public void setNume ( St r ing nume) {20 this . nume = nume ;21 }22 public St r ing getEmail ( ) {23 return emai l ;24 }25 public void setEmai l ( S t r ing emai l ) {26 this . emai l = emai l ;27 }28 public int get Id ( ) {29 return id ;30 }31 public void s e t I d ( int id ) {32 this . id = id ;33 }34 }

Page 288: DISTR1

288 APPENDIX B. UTILIZAREA SGBD IN JAVA

• O interfata Java cu actiunile care se ıntreprind asupra tabelei respective.Uzual, daca tabela are numele xyz atunci numele interfetei va fi XyzDAO.java.Prentru cazul exemplificat consideram interfata

1 package agendae . dao ;2 import java . u t i l . L i s t ;

4 public interface AdreseDAO {5 public void createAdrese ( Adrese i n r eg ) throws Exception ;6 public void updateAdrese ( Adrese i n r eg ) throws Exception ;7 public Adrese readAdrese ( int i n r e g I d ) throws Exception ;8 public void de l e t eAdrese ( int i n r e g I d ) throws Exception ;9 public List<Adrese> searchAdrese ( 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 Exception ;11 }

Cautarea unei ınregistrari se poate face dupa nume sau dupa adresa de email.Unui nume ıi pot corespunde mai multe adrese de email, iar dintr-o adresa nuputem sti cui ıi apartine. Clasa SearchCriteria este o componenta prin care sefixeaza criteriul de catare.

1 package agendae . dao ;2 import java . i o . S e r i a l i z a b l e ;

4 public class 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 St r ing nume=null ;6 private St r ing emai l=null ;

8 public St r ing getNume ( ) {9 return nume ;

10 }11 public void setNume ( St r ing nume) {12 this . nume = nume ;13 }14 public St r ing getEmail ( ) {15 return emai l ;16 }17 public void setEmai l ( S t r ing emai l ) {18 this . emai l = emai l ;19 }20 }

Daca nume=null atunci se cere lista numelor care corespund la o adresa email,iar daca email=null atunci se cere lista adreselor de email corespunzatoareunui nume.

Deoarece fiecare SGBD are propriul dialect SQL clasa ce implementeaza interfataDAO este specifica SGBD-ului. Utilizand Derby / JavaDB codul implementariiAdreseDAODerbyImpl este

1 package agendae . dao ;2 import java . s q l . SQLException ;3 import java . s q l . Connection ;4 import java . s q l . PreparedStatement ;5 import java . s q l . Resu l tSet ;6 import java . s q l . Statement ;

Page 289: DISTR1

B.7. MODELUL DAO 289

7 import java . u t i l . ArrayList ;8 import java . u t i l . L i s t ;

10 public class AdreseDAODerbyImpl extends DAOBase implements AdreseDAO {11 private stat ic f ina l St r ing CREATE Adrese SQL =12 ”INSERT INTO adrese (nume , emai l ) VALUES (? , ?) ” ;13 public void createAdrese ( Adrese i n r eg )throws Exception {14 Connection connect ion = null ;15 PreparedStatement pStatement = null ;16 try {17 connect ion = getConnect ion ( ) ;18 pStatement = connect ion . prepareStatement (CREATE Adrese SQL ) ;19 pStatement . s e t S t r i n g (1 , i n r eg . getNume ( ) ) ;20 pStatement . s e t S t r i n g (2 , i n r eg . getEmail ( ) ) ;21 pStatement . executeUpdate ( ) ;22 pStatement . c l o s e ( ) ;23 }24 catch ( Exception e ) {25 throw new Exception ( ”AdreseDAODerbyImpl : ”+e . getMessage ( ) ) ;26 }27 f ina l ly {28 try{29 connect ion . c l o s e ( ) ;30 }31 catch ( SQLException ex ) {}32 }33 }

35 private stat ic f ina l St r ing UPDATE Adrese SQL =36 ”UPDATE adrese SET nume=?, emai l=? WHERE id = ?” ;37 public void updateAdrese ( Adrese i n r eg ) throws Exception {38 Connection connect ion = null ;39 PreparedStatement pStatement = null ;40 try{41 connect ion = getConnect ion ( ) ;42 pStatement = connect ion . prepareStatement (UPDATE Adrese SQL ) ;43 pStatement . s e t S t r i n g (1 , i n r eg . getNume ( ) ) ;44 pStatement . s e t S t r i n g (2 , i n r eg . getEmail ( ) ) ;45 pStatement . s e t I n t (3 , i n r e g . ge t Id ( ) ) ;46 pStatement . executeUpdate ( ) ;47 pStatement . c l o s e ( ) ;48 }49 catch ( SQLException e ) {50 throw new Exception ( ”AdreseDAODerbyImpl : ”+e . getMessage ( ) ) ;51 }52 f ina l ly {53 try {54 connect ion . c l o s e ( ) ;55 }56 catch ( SQLException ex ) {}57 }58 }

60 private stat ic f ina l St r ing READ Adrese SQL =61 ”SELECT nume , emai l FROM adrese WHERE id = ?” ;62 public Adrese readAdrese ( int i n r e g I d ) throws Exception {63 Connection connect ion = null ;64 PreparedStatement pStatement = null ;65 Resu l tSet r s = null ;

Page 290: DISTR1

290 APPENDIX B. UTILIZAREA SGBD IN JAVA

66 Adrese i n r e g = new Adrese ( ) ;67 try {68 connect ion = getConnect ion ( ) ;69 pStatement = connect ion . prepareStatement (READ Adrese SQL ) ;70 pStatement . s e t I n t (1 , i n r e g I d ) ;71 r s = pStatement . executeQuery ( ) ;72 i f ( r s . next ( ) ) {73 i n r e g . setNume ( r s . g e t S t r i n g ( ”nume” ) ) ;74 i n r e g . setEmai l ( r s . g e t S t r i n g ( ” emai l ” ) ) ;75 i n r e g . s e t I d ( i n r e g I d ) ;76 }77 r s . c l o s e ( ) ;78 pStatement . c l o s e ( ) ;79 }80 catch ( SQLException e ) {81 throw new Exception ( ”AdreseDAODerbyImpl : ”+e . getMessage ( ) ) ;82 }83 f ina l ly {84 try {85 connect ion . c l o s e ( ) ;86 } catch ( SQLException ex ) {}87 }88 return i n r e g ;89 }

91 private stat ic f ina l St r ing DELETE Adrese SQL =92 ”DELETE FROM adrese WHERE id = ?” ;93 public void de l e t eAdre se ( int i n r e g I d ) throws Exception {94 Connection connect ion = null ;95 PreparedStatement pStatement = null ;96 try {97 connect ion = getConnect ion ( ) ;98 pStatement = connect ion . prepareStatement (DELETE Adrese SQL ) ;99 pStatement . s e t I n t (1 , i n r e g I d ) ;

100 pStatement . executeUpdate ( ) ;101 pStatement . c l o s e ( ) ;102 }103 catch ( SQLException e ) {104 throw new Exception ( ”AdreseDAODerbyImpl : ”+e . getMessage ( ) ) ;105 }106 f ina l ly {107 try {108 connect ion . c l o s e ( ) ;109 }110 catch ( SQLException ex ) {}111 }112 }

114 private stat ic f ina l St r ing SEARCH Adrese SQL =115 ”SELECT id , nume , emai l FROM adrese WHERE ” ;116 public List<Adrese> searchAdrese ( 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 )117 throws Exception {118 List<Adrese> l i s t = new ArrayList<Adrese >() ;119 Connection connect ion = null ;120 Statement statement = null ;121 Resu l tSet r e s u l t S e t = null ;122 St r ing searchSQL ;123 St r ing nume=s e a r c h C r i t e r i a . getNume ( ) ;124 St r ing emai l=s e a r c h C r i t e r i a . getEmail ( ) ;

Page 291: DISTR1

B.7. MODELUL DAO 291

125 //System . out . p r i n t l n (” Cr i t e r i a : ”+nume+” ”+email ) ;126 i f (nume==null ){127 searchSQL=SEARCH Adrese SQL+” emai l=”+’ \ ’ ’+emai l+’ \ ’ ’ ;128 }129 else {130 searchSQL=SEARCH Adrese SQL+”nume=”+’ \ ’ ’+nume+’ \ ’ ’ ;131 }132 //System . out . p r i n t l n ( searchSQL ) ;133 try {134 connect ion = getConnect ion ( ) ;135 statement = connect ion . createStatement ( ) ;136 r e s u l t S e t = statement . executeQuery ( searchSQL ) ;137 while ( r e s u l t S e t . next ( ) ) {138 Adrese i n r e g = new Adrese ( ) ;139 i n r e g . s e t I d ( r e s u l t S e t . g e t In t ( ” id ” ) ) ;140 i n r e g . setNume ( r e s u l t S e t . g e t S t r i n g ( ”nume” ) ) ;141 i n r e g . setEmai l ( r e s u l t S e t . g e t S t r i n g ( ” emai l ” ) ) ;142 l i s t . add ( i n r e g ) ;143 }144 r e s u l t S e t . c l o s e ( ) ;145 statement . c l o s e ( ) ;146 }147 catch ( SQLException e ) {148 throw new Exception ( ”AdreseDAODerbyImpl : ”+e . getMessage ( ) ) ;149 }150 f ina l ly {151 try {152 connect ion . c l o s e ( ) ;153 }154 catch ( SQLException ex ) {}155 }156 return l i s t ;157 }158 }

Apelarea unei atiuni CRUD necesita o instanta a clasei AdreseDAODerbyImpl.Crearea acestei instante va fi facuta utilizand sablonul singleton, prin clasa

1 package agendae . dao ;

3 public class DAOFactory {4 private stat ic DAOFactory in s t ance ;5 private stat ic AdreseDAODerbyImpl adreseDAODerbyImpl=null ;6 stat ic {7 i n s t ance = new DAOFactory ( ) ;8 }9 private DAOFactory ( ){

10 adreseDAODerbyImpl=new AdreseDAODerbyImpl ( ) ;11 }12 public stat ic DAOFactory ge t In s tance ( ) {13 return i n s t ance ;14 }

16 public AdreseDAO getAdreseDAO ( ) {17 return adreseDAODerbyImpl ;18 }19 }

Un client fara interfataa grafica este

Page 292: DISTR1

292 APPENDIX B. UTILIZAREA SGBD IN JAVA

1 package agendae ;2 import java . u t i l . ∗ ;3 import agendae . dao . ∗ ;

5 public class AgendaEClient{6 public stat ic void main ( St r ing [ ] a rgs ) {7 AdreseDAO dao=DAOFactory . g e t In s tance ( ) . getAdreseDAO ( ) ;8 Adrese e n t i t y=null ;9 List<Adrese> l i s t=null ;

10 I t e r a t o r <Adrese> i t e r a t o r=null ;11 S e a r c h C r i t e r i a sc=null ;12 St r ing ch=”Y” ;13 int p r e l ;14 Scanner scanner=new Scanner ( System . in ) ;15 while ( ch . s tartsWith ( ”Y” ) ){16 do{17 System . out . p r i n t l n ( ” Continue ? (Y/N) ” ) ;18 ch=scanner . next ( ) . toUpperCase ( ) ;19 }20 while ( ( ! ch . s tartsWith ( ”Y”))&&(! ch . s tartsWith ( ”N” ) ) ) ;21 i f ( ch . s tartsWith ( ”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 ( Create ) : 1 ” ) ;24 System . out . p r i n t l n ( ” S t e r g e r e ( De lete ) : 2 ” ) ;25 System . out . p r i n t l n ( ” Actua 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=scanner . next Int ( ) ;29 St r ing nume , emai 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=scanner . next ( ) . tr im ( ) ;36 System . out . p r i n t l n ( ”Adresa e−mail : ” ) ;37 emai l=scanner . next ( ) . tr im ( ) ;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 . setEmai l ( emai l ) ;41 try{42 dao . c reateAdrese ( e n t i t y ) ;43 System . out . p r i n t l n ( ” Operat ia a f o s t executata cu succe s ! ” ) ;44 }45 catch ( Exception e ){46 System . out . p r i n t l n ( ” Except ie : ”+e . getMessage ( ) ) ;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 ( ” Id : ” ) ;52 id=scanner . next Int ( ) ;53 try{54 dao . de l e t eAdrese ( id ) ;55 System . out . p r i n t l n ( ” Operat ia a f o s t executata cu succe s ! ” ) ;56 }57 catch ( Exception e ){58 System . out . p r i n t l n ( ” Except ie : ”+e . getMessage ( ) ) ;59 }

Page 293: DISTR1

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=scanner . next ( ) . tr im ( ) ;65 System . out . p r i n t l n ( ”Adresa e−mail : ” ) ;66 emai l=scanner . next ( ) . tr im ( ) ;67 System . out . p r i n t l n ( ”Cheia i n r e g i s t r a r i i ( Id ) : ” ) ;68 id=scanner . next Int ( ) ;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 . setEmai l ( emai l ) ;72 e n t i t y . s e t I d ( id ) ;73 try{74 dao . updateAdrese ( e n t i t y ) ;75 System . out . p r i n t l n ( ” Operat ia a f o s t executata cu succe s ! ” ) ;76 }77 catch ( Exception e ){78 System . out . p r i n t l n ( ” Except ie : ”+e . getMessage ( ) ) ;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 ( ” Id : ” ) ;84 id=scanner . next Int ( ) ;85 try{86 e n t i t y=dao . readAdrese ( id ) ;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 . getEmail ( ) ) ;89 }90 catch ( Exception e ){91 System . out . p r i n t l n ( ” Except ie : ”+e . getMessage ( ) ) ;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 cautare : ” ) ;96 System . out . p r i n t l n ( ”Dupa nume : 1” ) ;97 System . out . p r i n t l n ( ”Dupa emai l : 2” ) ;98 int c r i t e r i u=scanner . next Int ( ) ;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=scanner . next ( ) . tr im ( ) ;103 sc=new S e a r c h C r i t e r i a ( ) ;104 sc . setNume (nume ) ;105 try{106 l i s t=dao . searchAdrese ( sc ) ;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 . next ( ) ;110 System . out . p r i n t l n ( i n r eg . ge t Id ()+” : ”+111 i n r e g . getNume()+” : ”+in r e g . getEmail ( ) ) ;112 }113 }114 catch ( Exception e ){115 System . out . p r i n t l n ( ” Except ie : ”+e . getMessage ( ) ) ;116 }117 break ;118 case 2 :

Page 294: DISTR1

294 APPENDIX B. UTILIZAREA SGBD IN JAVA

119 System . out . p r i n t l n ( ”Adresa e−mail : ” ) ;120 emai l=scanner . next ( ) . tr im ( ) ;121 sc=new S e a r c h C r i t e r i a ( ) ;122 sc . setEmai l ( emai l ) ;123 try{124 l i s t=dao . searchAdrese ( sc ) ;125 i t e r a t o r=l i s t . i t e r a t o r ( ) ;126 while ( i t e r a t o r . hasNext ( ) ){127 Adrese i n r e g =(Adrese ) i t e r a t o r . next ( ) ;128 System . out . p r i n t l n ( i n r eg . ge t Id ()+” : ”+129 i n r e g . getNume()+” : ”+in r e g . getEmail ( ) ) ;130 }131 }132 catch ( Exception e ){133 System . out . p r i n t l n ( ” Except ie : ”+e . getMessage ( ) ) ;134 }135 break ;136 default :137 System . out . p r i n t l n ( ” C r i t e r i u de cautare eronat ” ) ;138 }139 break ;140 default : System . out . p r i n t l n ( ”Comanda eronata ” ) ;141 }142 }143 else144 System . e x i t ( 0 ) ;145 }146 }147 }

B.8 Java Persistence API - JPA

Interfata JPA este standardizarea accesului din Java la un SGBD relational. JPAeste un strat care se interpune ıntre programul Java si SGBD. JPA este dezvoltatpe modelul dat modelul pachetului javax.persistence initiat de Oracle-Sun Mi-croSystems, din Java Enterprise Edition (JEE), dar pentru care exista mai multeimplemaentari. De asemenea, exista mai multe implementari a interfetei JPA.

O alternativa la JPA ıl reprezinta produsul Hibernate.JPA contine:

• Persistence: Clasa javax.persistence.Persistence contine metode staticepentru obtinerea unei instante a clasei EntityManagerFactory, ıntr-o manieraindependenta de producatorul JPA.

• EntityManagerFactory : Clasa javax.persistence.EntityManagerFactory

este producatorul obiectelor EntityManager.

• EntityManager : javax.persistence.EntityManager este actorul JPA prin-cipal ıntr-o aplicatie. Un obiect EntityManager mijloceste ıntretinerea si in-terogarea unei baze de date. Fiecarui obiect de tip EntityManager i se asociazaun obiect de tip javax.persistence.EntityTransaction.

Page 295: DISTR1

B.8. JAVA PERSISTENCE API - JPA 295

• Entity : Obiectele Entity corespund ınregistrarilor ın tabelele bazei de date.

• EntityTransaction: asigura integritatea bazei de date. Operatiile care privescpersistenta datelor sunt grupate ın unitati de lucru care sunt executate cusucces sau deloc.

• Query : Interfata javax.persistence.Query este specifica implementarii. Prinobiecte de tip Query se asigura accesul la baza de date. Portivit standardu-lui JPA este suportat atat limbajul Structured Query Language (SQL) cat siJava Persistence Query Language (JPQL). Un obiect Query este instantiatprin obiecte EntityManager.

B.8.1 apache-openjpa

Asa cum sugereaza numele produsului, openjpa este implementarea oferita deapache.

Instalarea revine la dezarhivarea fisierului descarcat.Utilizarea. Compilarea si executia unei aplicatii o vom face prin intermediul

lui apache-ant. Construim structura de cataloage si fisiere:

|--> catalogul_aplicatiei

|--> META-INF

| | persistence.xml

| build.xml

Fisierul persistence.xml specifica unitatile de persistenta. Fiecare unitate depersistenta corespunde unui tabel al bazei de date si i se asociaza o clasa Entity,

de fapt o componenta Java. Clasa si tabelul au acelasi nume. Doar tabelele carorali s-a declarat o unitate de persistenta pot fi accesate prin apache-openjpa.

Principial fisierul persistence.xml este

1 <?xml version=” 1 .0 ” encoding=”UTF−8”?>2 <p e r s i s t e n c e xmlns=” ht tp : // java . sun . com/xml/ns/ p e r s i s t e n c e ”3 xmlns :x s i=” h t t p : //www. w3 . org /2001/XMLSchema−i n s t ance ”4 version=” 1 .0 ”>

6 < !−−7 We need to enumerate each p e r s i s t e n t c l a s s f i r s t in the p e r s i s t en c e .xml8 See: h t t p : // i s s u e s . apache . org/ j i r a /browse/OPENJPA−789 −−>

10 <p e r s i s t e n c e−uni t name=”none” t ransac t i on−type=”RESOURCE LOCAL”>11 <c l a s s>Ent i ty c la s s name</ c l a s s>12 </ p e r s i s t e n c e−uni t>

14 < !−−15 A per s i s t en c e un 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 we l l16 the con f i gu ra t i on o f an EntityManagerFactory . We con f i gure each17 example in a separa te pe r s i s t ence−uni t .18 −−>19 <p e r s i s t e n c e−uni t name=” Per s i s t ence un i t name ”

Page 296: DISTR1

296 APPENDIX B. UTILIZAREA SGBD IN JAVA

20 t ransac t i on−type=”RESOURCE LOCAL”>21 < !−−22 The default prov ider can be OpenJPA, or some other product .23 This element i s op t i ona l i f OpenJPA i s the only JPA prov ider24 in the current c l a s s l o a d i n g environment , but can be s p e c i f i e d25 in cases where there are mu l t i p l e JPA implementat ions a v a i l a b l e .26 −−>27 < !−−28 <prov ide r>29 org . apache . openjpa . p e r s i s t en c e . Pers i s t enceProv ider Imp l30 </ prov ide r>31 −−>

33 < !−− We must enumerate each en t i t y in the p e r s i s t en c e un i t −−>34 <c l a s s>appagenda . Te l e f</ c l a s s>

36 <p r o p e r t i e s>37 < !−−38 We can con f i gure the default OpenJPA prope r t i e s here . They39 happen to be commented out here s ince the prov ided examples40 a l l s p e c i f y the va lue s v ia System prop e r t i e s .41 −−>

43 < !−−44 <property name=” openjpa . ConnectionURL”45 value=” jdbc :derby :open jpa−database ; c r e a t e=true ”/>46 <property name=” openjpa . ConnectionDriverName”47 value=” org . apache . derby . jdbc . EmbeddedDriver”/>48 <property name=” openjpa . ConnectionUserName”49 value=” user ”/>50 <property name=” openjpa . ConnectionPassword ”51 value=” 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−uni t>55 </ p e r s i s t e n c e>

Atributele ce apar ın comentarii, pot fi specificate si prin proprietati System.

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

// introducerea unei inregistrari

em.persist(obiect_Entity)

// actualizarea sau stergerea unei inregistrari

query.executeUpdate();

Page 297: DISTR1

B.8. JAVA PERSISTENCE API - JPA 297

// interogare bazei de date

List result=query.getResultList();

em.getTransaction().commit();

em.close();

factory.close();

Daca fraza SQL este specifica unui SGBD atunci obiectul de tip Query se instantiazaprin

Query query=em.createNativeQuery(sql,clasa_Entity_utilizata.class);

Exemplul B.8.1 Aplicatie pentru ıntretinerea si interogarea bazei de date Agen-daEMail.

Tabelei adrese a bazei de date ıi corespunde clasa Adrese

1 package agendae . dao ;2 import java . i o . S e r i a l i z a b l e ;3 import javax . p e r s i s t e n c e . ∗ ;

5 @Entity6 public class Adrese implements S e r i a l i z a b l e {7 private int id ;8 private St r ing nume ;9 private St r ing emai l ;

11 public Adrese ( ){}

13 public Adrese ( int id , S t r ing nume , S t r ing emai l ) {14 this . id = id ;15 this . nume = nume ;16 this . emai l = emai l ;17 }

19 public int get Id ( ) {20 return id ;21 }22 public void s e t I d ( int id ) {23 this . id = id ;24 }

26 public St r ing getNume ( ) {27 return nume ;28 }29 public void setNume ( St r ing nume) {30 this . nume = nume ;31 }

33 public St r ing getEmail ( ) {34 return emai l ;35 }36 public void setEmai l ( S t r ing emai l ) {37 this . emai l = emai l ;

Page 298: DISTR1

298 APPENDIX B. UTILIZAREA SGBD IN JAVA

38 }39 }

Accessarea bazei de date se face prin clasa AdreseDAOImpl. Aceasta clasa im-plementeaza interfata AdreseDAO, data ın sectiunea anterioara.

1 package agendae . dao ;2 import java . u t i l . L i s t ;3 import javax . p e r s i s t e n c e . ∗ ;

5 @SuppressWarnings ( ”unchecked” )6 pub l i c c l a s s AdreseDAOImpl implements AdreseDAO{7 EntityManagerFactory f a c t o r y=n u l l ;8 EntityManager em;

10 pub l i c AdreseDAOImpl ( EntityManagerFactory 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 pub l i c void createAdrese ( Adrese i n r eg ){15 St r ing name=i n r e g . getNume ( ) ;16 St r ing emai l=in r e g . getEmail ( ) ;17 em=f a c t o r y . createEntityManager ( ) ;18 em. getTransact ion ( ) . begin ( ) ;19 St r ing s q l=”INSERT INTO adrese (nume , emai l ) VALUES(\ ’ ”+name+” \ ’ ,\ ’ ”+emai l+” \ ’ ) ” ;20 Query query=em. createNativeQuery ( s q l ) ;21 query . executeUpdate ( ) ;22 em. getTransact ion ( ) . commit ( ) ;23 em. c l o s e ( ) ;24 }

26 pub l i c void updateAdrese ( Adrese i n r e g ){27 St r ing nume=” \ ’ ”+in r e g . getNume()+” \ ’ ” ;28 St r ing emai l=” \ ’ ”+in r e g . getEmail ()+” \ ’ ” ;29 i n t i n r e g I d=i n r eg . ge t Id ( ) ;30 em=f a c t o r y . createEntityManager ( ) ;31 em. getTransact ion ( ) . begin ( ) ;32 St r ing 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 . emai l=”+emai l+” WHERE e n t i t y . id=”+i n r e g I d ;34 Query query=em. createQuery ( s q l ) ;35 query . executeUpdate ( ) ;36 em. getTransact ion ( ) . commit ( ) ;37 em. c l o s e ( ) ;38 }

40 pub l i c Adrese readAdrese ( i n t i n r e g I d ){41 em=f a c t o r y . createEntityManager ( ) ;42 em. getTransact ion ( ) . begin ( ) ;43 St r ing 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 . id=”+i n r e g I d ;44 Query query=em. createQuery ( 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. getTransact ion ( ) . commit ( ) ;47 em. c l o s e ( ) ;48 r e turn in r e g ;49 }

51 pub l i c void de l e t eAdrese ( i n t i n r e g I d ){52 em=f a c t o r y . createEntityManager ( ) ;53 em. getTransact ion ( ) . begin ( ) ;54 St r ing s q l=”DELETE FROM Adrese e n t i t y WHERE e n t i t y . id=”+i n r e g I d ;

Page 299: DISTR1

B.8. JAVA PERSISTENCE API - JPA 299

55 Query query=em. createQuery ( s q l ) ;56 query . executeUpdate ( ) ;57 em. getTransact ion ( ) . commit ( ) ;58 em. c l o s e ( ) ;59 }

61 pub l i c L i s t<Adrese> searchAdrese ( 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 St r ing nume=s e a r c h C r i t e r i a . getNume ( ) ;63 St r ing emai l=s e a r c h C r i t e r i a . getEmail ( ) ;64 St r ing searchSQL ;65 i f (nume==n u l l ){66 searchSQL=” e n t i t y . emai l =\ ’”+emai l+” \ ’ ” ;67 }68 e l s e {69 searchSQL=” e n t i t y . nume=\ ’”+nume+” \ ’ ” ;70 }71 em=f a c t o r y . createEntityManager ( ) ;72 em. getTransact ion ( ) . begin ( ) ;73 St r ing 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. createQuery ( 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. getTransact ion ( ) . commit ( ) ;78 em. c l o s e ( ) ;79 r e turn l i s t ;80 }81 }

Programul client este acelasi cu cel utilizat anterior (AgendaEClient). iar clientuleste AgendaTClient

Fisierul persistence.xml pentru exemplul de mai sus este

1 <?xml version=” 1 .0 ” encoding=”UTF−8”?>2 <p e r s i s t e n c e xmlns=” ht tp : // java . sun . com/xml/ns/ p e r s i s t e n c e ”3 xmlns :x s i=” h t t p : //www. w3 . org /2001/XMLSchema−i n s t ance ”4 version=” 1 .0 ”>

6 <p e r s i s t e n c e−uni t name=”none” t ransac t i on−type=”RESOURCE LOCAL”>7 <c l a s s>agendae . dao . Adrese</ c l a s s>8 </ p e r s i s t e n c e−uni t>

10 <p e r s i s t e n c e−uni t name=”agendae” t ransac t i on−type=”RESOURCE LOCAL”>11 <c l a s s>agendae . dao . Adrese</ c l a s s>12 </ p e r s i s t e n c e−uni t>13 </ p e r s i s t e n c e>

Structura desfasurata a aplicatiei este

agendae

|--> dao

| | *.class

| AgendaEClient.class

META-INF

| persistence.xml

Fisierul build.xml pentru procesarea prin ant are codul

1 <?xml version=” 1 .0 ” encoding=”UTF−8”?>2 <p r o j e c t default=”run”>

Page 300: DISTR1

300 APPENDIX B. UTILIZAREA SGBD IN JAVA

3 <property name=” package ” value=”agendae”/>4 <property name=”dbname” value=”AgendaEMail” />5 <property name=” classname ” value=”AgendaEClient” />6 <property name=” bu i ld . d i r ” va lue=” bu i ld ” />

8 < !−− database connect ion p rop e r t i e s −−>

10 <property name=” dbdr iver ”11 value=” org . apache . derby . jdbc . C l i en tDr ive r ”/>12 <property name=” dburl ”13 value=” 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 <property name=” dbdr iver ”17 value=”com . mysql . jdbc . Dr iver ”/>18 <property name=” dburl ”19 value=” jdbc :mysq l : // l o c a l h o s t : 3 3 0 6 /AgendaEMail? user=root ”/>20 −−>

22 <property name=” dbuser ” value=””/>23 <property name=” dbpass ” value=””/>

25 <path id=” c l a s s pa t h ” >26 <pathelement path=”${ bu i ld . d i r }”/>27 < f i l e s e t d i r=”${ openjpa }/ l i b ”>28 <i n c l ude name=” ∗ . j a r ”/>29 </ f i l e s e t>30 < f i l e s e t d i r=” l i b ”>31 <i n c l ude name=” ∗ . j a r ”/>32 </ f i l e s e t>33 </path>

35 <path id=” javaagent ”>36 < f i l e s e t d i r=”${ openjpa}”>37 <i n c l ude name=”openjpa −∗. j a r ”/>38 </ f i l e s e t>39 </path>40 <pathconvert property=” javaagent ” r e f i d=” javaagent ”/>

42 <t a r g e t name=” i n i t ”>43 <d e l e t e d i r=” bu i ld ”/>44 <mkdir d i r=”${ bu i ld . d i r }”/>45 </ t a r g e t>

47 <t a r g e t name=” compile ” depends=” i n i t ”>48 <javac s r c d i r=” s r c ” c l a s s p a t h r e f=” c l a s sp a t h ”49 d e s t d i r=”${ bu i ld . d i r }”50 inc ludeantrunt ime=” f a l s e ” debug=” yes ” />51 </ t a r g e t>

53 <t a r g e t name=”run” depends=” compile ”>54 <mkdir d i r=”${ bu i ld . d i r }/META−INF”/>55 <copy t o d i r=”${ bu i ld . d i r }/META−INF” f i l e=”META−INF/ p e r s i s t e n c e . xml”/>56 <java classname=”${package } . ${ classname }” c l a s s p a t h r e f=” c l a s s pa th ”57 f o rk=” yes ” f a i l o n e r r o r=” yes ”>58 < !−−59 Spec i f y ing the openjpa ja r as the javaagent argument i s60 necessary in order f o r automatic c l a s s−enhancement to work .61 −−>

Page 301: DISTR1

B.8. JAVA PERSISTENCE API - JPA 301

62 <jvmarg value=”−j avaagen t : ${ javaagent }”/>

64 < !−−65 Spec i f y the system prop e r t i e s to use when con f i gu r ing66 OpenJPA. Note t ha t t he se w i l l on ly be used becuase in the67 packages , the c a l l to ” P e r s i s t e n c e . createEntityManagerFactory ”68 i s passed ”System . g e t P r o p e r t i e s ( ) ” .69 −−>

71 < !−−72 By default , use the stand−alone Derby database ( prov ided ) .73 This can e a s i l y be changes to use your own database ’ s d r ive r ,74 provided you ensure i t i s a c c e s s i b l e in the c l a s sp a th .75 −−>76 <sysproper ty key=”openjpa . ConnectionDriverName”77 value =”${dbdr iver}”/>78 <sysproper ty key=”openjpa . ConnectionURL” value =”${dburl}”/>79 <!−−80 <sysproper ty key=”openjpa . ConnectionUserName” value =”${dbuser}”/>81 <sysproper ty key=”openjpa . ConnectionPassword ” value =”${dbpass}”/>82 −−>83 <!−−84 Te l l OpenJPA to automat i ca l l y c r e a t e t a b l e s in the database85 f o r e n t i t i e s . Note that t h i s should be d i s ab l ed when86 running aga in s t a product ion database , s i n c e you probably87 don ’ t want to be a l t e r i n g the schema at runtime .88 −−>89 <sysproper ty key=” openjpa . jdbc . SynchronizeMappings ”90 value=”buildSchema”/>

92 < !−−93 Output a l l the SQL for educa t i ona l purposes , but s e t the94 genera l l o g g i n g l e v e l to only show warnings .95 −−>96 <sysproper ty key=” openjpa . Log”97 value=” Defau l tLeve l=WARN,SQL=TRACE”/>98 </ java>99 </ t a r g e t>

100 </ p r o j e c t>

Page 302: DISTR1

302 APPENDIX B. UTILIZAREA SGBD IN JAVA

Page 303: DISTR1

Bibliografie

[1] ATHANASIU I., COSTINESCU B., DRAGOI O.A., POPOVICI F.I., 1998,Limbajul Java. O perspectiva pragmatica. Ed. Computer Libris Agora, Cluj-Napoca.

[2] BOIAN F.M., BOIAN R. F., 2004, Tehnologii fundamentale Java pentruaplicatii Web. Ed. Albastra, Cluj-Napoca.

[3] BURAGA S.C., 2001, Tehnologii Web. Ed. Matrix Rom,Bucuresti.

[4] BURAGA S. (ed), 2007, Programarea ın Web 2.0., Ed. Polirom, Iasi.

[5] JURCA I., 2000, Programarea retelelor de calculatoare. Ed. de Vest, Timisoara.

[6] HUNTER J., CRAWFORD W., 1998, Java Servlet Programming. O’Reilly.

[7] ALBOAIE L., BURAGA S., 2006, Servicii Web. Ed. Polirom, Iasi.

[8] SCHEIBER E., 2007, Programare concurenta si paralel distribuita ın Java. Ed.Albastra, Cluj-Napoca.

[9] TANASA S., OLARU C., 2005, Dezvoltarea aplicatiilor Web folosind Java. Ed.Polirom, Bucuresti.

[10] * * * , Java 2 SDK /docs/, Sun Microsystems.

[11] * * * , JavaWS Tutorial 1.*, Sun Microsystems.

[12] * * * , J2EE Tutorial, Sun Microsystems.

[13] * * * , Java 2 Tutorial, Sun Microsystems.

303