Aplicatiile Java se pot face de-acum înainte si din prefabricate, cu ajutorul noului BDK: un standard, o implementare si o multime de exemple.

JavaBeans

Eugen Rotariu

Va mai aduceti aminte de primele calculatoare? Erau niste cutii uriase, pline cu sertare uriase conectate printr-o multime de fire de diferite culori. Se strica ceva? Cel care putea repara un astfel de calculator era un fel de Guru care stia pur si simplu care fir din cele câteva mii trebuie conectat în care mufa. Priviti acum la calculatorul din fata dumneavoastra. Mic si nu prea complicat la vedere. Multi dintre dumneavoastra va puteti lauda ca l-ati construit singuri. Ati instalat placile în sloturile disponibile, ati legat cele câteva benzi de fire, ati alimentat. Greu de gresit ceva, piesele se potrivesc într-o singura pozitie.

Ce s-a schimbat în arhitec tu ra calculatoarelor în acest ras timp, în asa fel încât sa va per mita constructia propriului calculator? Nu se poate spune ca arhitectura calculatoarelor a devenit mai simpla. Dimpotriva, calculatoarele de azi sunt mult mai rapide si mai sofisticate decât cele vechi, iar daca nu întelegeati func tionarea calculatoarelor din trecut, cu atât mai putin o pu teti întelege pe cea a calculatoarelor de azi. Numai ca astazi nu mai este nevoie sa întelegeti prea mult pentru a construi un calculator. Este suficient sa cumparati câteva componente prefabricate si sa le asamblati împreuna, ca într-un joc Lego. Complexitatea este ascunsa în spatele metodelor simple de interconectare. Aceasta este esenta schimbarii: calculatoa re le vin ca niste componen te prefabricate, toate respectând aceleasi standarde de interconectare.

Si, odata cu aparitia componentelor prefabricate, s-a mai schimbat ceva: Nu mai este nevoie sa cumperi toate componentele calculatorului de la un singur producator. În zilele noastre, cumperi fiecare componenta în functie de câti bani ai si ce vrei sa faci cu calcu la torul respectiv. La sfârsit, componentele fabricate de diversi produ ca tori vor functiona foarte bine împreuna, pentru ca fiecare dintre ele respecta un standard international riguros definit. Sau cel putin asa ar trebui.

În industria software, aceasta uniformitate a venit mult mai târ ziu, desi unii cred ca nici azi nu a fost complet înteleasa si aplicata de toata lumea. Ideea generala este aceea de a crea componente binare pe care dezvoltatorii de aplicatii sa le poata combina între ele pentru a-si rezolva problemele. Desigur, pentru a crea astfel de componente este nevoie de standarde care sa descrie modul de comunicare dintre aceste componente si aplicatie sau alte componen te. Aceste standarde sunt la ora ac tuala doar partial definite si acceptate de comunitatea fir melor producatoare de software.

Cele mai cunoscute standarde în domeniu sunt ActiveX, CORBA/IIOP si Java Beans, ultimul dintre ele fiind si cel mai tânar. Fiecare dintre acestea încearca sa rezolve problema conectarii unei componente binare software într-o aplicatie care va beneficia de functionalitatea componentei, fara însa sa poa ta sa intervina în impleme n ta rea acesteia.

Ne vom ocupa în continu are doar de JavaBeans, care este o tehnologie specifica masinilor virtuale Java, din ce în ce mai mult acceptata de firmele de software care dezvolta si care utilizeaza componente. Desigur, si celelalte doua standarde pot fi folosite în cadrul aplicatiilor Java. CORBA/IIOP are o implementare excelenta în Visibroker for Java, care poate rula pe orice masina virtuala Java, în timp ce OLE poate fi implementat si utilizat de catre aplicatii Java cu conditia ca acestea sa ruleze în interiorul masinii virtuale Java produsa de Microsoft pe platforme Windows. Pentru celelalte platforme, lipsa unei implementari de COM/DCOM face deocamdata imposibila rularea obiectelor ActiveX (care se bazeaza pe COM). Microsoft a anuntat deja împreuna cu Software AG, o implementare COM pentru Solaris (beta) si a anuntat la conferinta JavaOne din acest an ca va implementa DCOM în totalitate în Java, ceea ce va duce la portabilitate si la o securitate superioara a tehnologiei ActiveX.

Pâna atunci însa, tehnologia JavaBeans este deja pe piata de câteva luni si a iesit din beta odata cu aparitia JDK 1.1, varianta finala, în luna februarie.

O scurta prezentare

Deci, JavaBeans este un model de dezvoltare a componentelor software care permite com ponentelor scrise în Java si numite beans sa comunice între ele. Aceste beans pot fi uti li zate într-un editor vizual si pot fi înglobate în interiorul unor aplicatii. Un bean este în principiu o clasa Java care respecta anumite conventii de constructie. Pentru a construi beans este nevoie de Bean Development Kit (BDK), care vine împreuna cu Java Develop ment Kit 1.1 de la Sun, sau se poate obtine se parat. Kit-ul contine clasele suport pentru constructia de beans, o aplicatie container nu mita BeanBox, care permite inserarea de componente beans în vederea testarii lor, precum si o multime de exemple si de docu men tatii necesare celor care vor sa dezvolte beans.

Componentele construite pot fi folosite în interiorul unor utilitare de constructie vizuala de aplicatii, precum JavaWorkshop 2.0 (aflat în beta acum), Symantec Visual Cafe, Borland JBuilder (alpha), IBM VisualAge for Java (beta), Vibe, si asa mai departe. Este de prevazut ca multe alte aplicatii de acest tip vor apare în viitor pe piata. În plus, un bean Java poate fi folosit oriunde poate fi folosit un control ActiveX, gratie bridge-ului ActiveX-JavaBeans construit de JavaSoft (aflat si el în faza beta).

Dupa ce au fost folosite pentru constructia unei aplicatii, componentele vor rula în aplicatia finala fara probleme. Cele doua moduri de lucru sunt diferite dupa cum observati, ceea ce ne duce cu gândul la faptul ca un bean va avea doua moduri distincte de functionare: modul design si modul run-time. În cel de-al doilea mod nu mai sunt necesare utilitarele de configurare a bean-ului, asa ca probabil va fi utila îm par ti rea functionalitatii în clase distincte din care doar o parte vor fi livrate cu aplicatia fi nala. Pentru a putea utiliza un bean, o apli ca tie de dezvoltare vizuala trebuie sa aiba la îndemâna o cale de a analiza bean-ul si de a-l configura dupa dorinte.

Din punct de vedere constructiv, un bean are în interior o serie de valori numite proprietati, o serie de metode care actioneaza asupra lui si o serie de evenimente pe care le poate genera. Proprietatile descriu va lori prin care un bean este deosebit de altul de acelasi fel precum dimensiuni, culoare, etc. Metodele sunt functii care se pot apela asupra unui bean pentru a utiliza functiona li tatea încapsulata în interiorul acestuia. În fine, evenimentele sunt mesaje generate de catre un bean la anumite momente în timp, atunci când sunt îndeplinite conditii precum apasarea unui buton de mouse în interiorul bean-ului, schimbarea valorii unei proprie tati importante, etc.

Cum se creeaza un bean

Pentru început, se creeaza un fisier sursa Java în care se scrie clasa care va implementa bean-ul. Aceasta clasa va avea cu siguranta un constructor care va seta câteva dintre proprietatile bean-ului, precum culorile utilizate si o metoda getMinimumSize, care va returna dimensiunea minima a unui bean din clasa nou creata. Ceva de genul:

import java.awt.*;
public class PrimulExemplu extends Canvas { 
public PrimulExemplu() { 
setBackground( Color.blue );
} 
public Dimension getMinimumSize() { 
return new Dimension( 50, 50 );
} 
} 

Pâna acum nimic diferit de o componenta AWT oarecare. Dupa ce avem fisierul sursa, putem trece la constructia bean-ului propriu-zis. Pentru aceasta constructie este nevoie de mai mult decât simpla compilare a fisierului sursa, este nevoie si sa organizam totul sub forma unui fisier JAR. Pentru aceasta, trebuie mai întâi compilat fisierul cu o comanda de genul:

javac PrimulExemplu.java

dupa care trebuie creat fisierul JAR. Acesta are nevoie de un fisier in care se vor specifica doua linii continând numele bean-ului si un indicator, ca în exemplul urmator:

Name: PrimulExemplu.class
Java-Bean: True

În fine, urmeaza sa cream arhiva cu o comanda de genul:

jar cfm PrimulExemplu.jar PrimulExemplu.class ...

În loc de punctele de la sfârsitul comenzii, trebuie introduse fisierele de date necesare bean-ului pentru a fi executat (în cazul nostru nu exista) si eventuale alte clase auxi liare necesare bean-ului.

Si acum gata, se poate testa bean-ul nou creat cu ajutorul utilitarului BeanBox care spuneam ca vine împreuna cu BDK. Acest utilitar ne lasa sa încarcam o arhiva JAR (care poate contine mai multe beans si nu doar unul singur) si ne lasa sa cream instante ale bean-urilor înregistrate si sa vedem proprie tatile acestora într-o fereastra separata. Bean-ul creat de noi are o forma dreptunghiulara si culoarea albastra.

Proprietati

O proprietate este un atribut public al unui bean. Proprietatile pot fi citite si scrise, doar citite sau doar scrise. Dintr-un alt punct de vedere exista proprietati simple, indexate, legate si constrânse.

O proprietate simpla este o valoare simpla pentru care sunt definite doua functii, get si set. Numele proprietatii este derivat din numele metodelor atasate. De exemplu, existenta a doua metode numite setCuloare si getCuloare specifica existenta unei proprietati numite Culoare. Daca exista si o metoda numita isCuloare, putem trage concluzia ca proprietatea este booleana.

De exemplu, putem crea o proprietate numita Nume prin adaugarea la sursa de mai sus a urmatoarelor linii de cod:

String nume = "Fara Nume";

 

public void setNume( String nume ) { 
this.nume = nume;
} 

 

public String getNume() { 
return nume;
} 

Aceasta proprietate va putea fi vazuta imediat în fereastra în care aplicatia BeanBox afiseaza proprietatile.

În cazul proprietatilor indexate, proprie tatile ale caror nume începe cu get si set trebuie sa aiba un parametru întreg. În acelasi timp, proprietatea ar putea suporta si setarea sau citirea tabloului într-un singur pas. Iata codul ce trebuie adaugat pentru a crea o astfel de proprietate:

int[] note = { 4, 5, 6, 5, 7, 10 } ;

 

public void setNote( int[] note ) { 
this.note = note;
} 

 

public void setNote( int index, int 
 nota ) { 
note[index] = nota;
} 

 

public int[] getNote() { 
return note;
} 

 

public int getNote( int index ) { 
return note[index];
} 

Prima si a treia metoda sunt destinate acce su lui direct la tablou, într-un singur pas, iar ce lelalte pentru accesul indexat. Sa mai no tam ca BeanBox nu suporta proprietatile indexate.

Proprietatile legate notifica alte obiecte atunci când valoarea lor se schimba. De fiecare data când valoarea se schimba, este generat un eveniment de tip PropertyChange care contine în interior informatii despre numele proprietatii, vechea valoare precum si cea noua. Pentru implementarea acestui tip de proprietati, exista o clasa numita PropertyChangeSupport. Aceasta clasa trebuie instantiata în interiorul bean-ului prin:

private PropertyChangeSupport schimbare = new PropertyChangeSupport( this );

si apoi apelata prin metoda firePropertyChange ori de câte ori valoarea proprietatii se modifica, înainte de schimbarea propriu-zisa a valorii:

schimbare.firePropertyChange( "Nume", Nume, nouaValoare );

În BeanBox exista suport pentru legarea si monitorizarea acestor evenimente.

În fine, trebuie specificati ascultatorii, adica obiectele care vor primi evenimentul în clipa în care acesta se produce. Pentru asta exista în ChangePropertySupport doua metode numite addPropertyChangeListener si removePropertyChangeLis tener. În mod normal, un bean redefineste aceste doua proprietati în propriul corp ca doua metode care redirecteaza cererea catre obiectul schimbare de mai sus.

Proprietatile constrânse sunt proprietati a caror modificare de valoare poate fi blocata de un ascultator. Ascultatorul poate anula modificarea valorii aruncând o exceptie numita PropertyVetoException. Pentru folosirea acestui tip de proprietati, exista o alta clasa suport numita VetableChangeSupport.

Metode

În mod implicit, toate metodele publice defi nite în clasa care implementeaza bean-ul sunt considerate a fi metode disponibile în medii de scripting. Aceasta comportare poate fi alterata folosind API-ul de introspectie prezentat mai jos.

Evenimente

Evenimentele sunt folosite la comunicatia între beans. Ele apar atunci când anumite conditii sunt îndeplinite. Evenimentele se petrec între un obiect sursa si unul sau mai multe obiecte tinta, numite si ascultatori. Evenimentele pot fi de orice tip în Java Beans, dar în mod normal ele se refera la evenimente legate de lucrul cu mouse-ul, tastatura sau redesenarea ferestrelor specifice unui kit de interfata grafica utilizator.

Iata câteva dintre trasaturile modelului de evenimente implementat în JavaBeans:

În mod normat, un bean care vrea sa genereze evenimente trebuie mai întâi sa creeze un nou tip de obiect, derivat din java.util.EventObject. Dupa crearea noului tip, trebuie creata o interfata derivata din java.util.EventListener care sa defineasca metodele de prelucrare a evenimentului respectiv. De exemplu,

class PlouaEvent extends java.util.EventObject { 
....
} 
interface PlouaListener extends java.util.EventListener { 
void incepePloaia( PlouaEvent e );
} 

De obicei interfata contine la sfârsitul numelui cuvântul „Listener" iar metodele au o forma bine precizata, precum

void <numeMetoda>( <clasaDeEveniment> e );

Clasa de eveniment trebuie sa fie derivata din EventObject. Aceasta forma comuna ajuta la detectarea automata a evenimentelor care pot fi prelucrate de o anumita clasa. În fine, pentru a crea o clasa care prelucreaza evenimentele dintr-o anumita interfata, clasa trebuie sa declare ca implementeaza interfata respectiva:

class CareiaIiPasaCaPloaua implements PlouaListener { 
public void incepePloaia( PlouaEvent ) { 
...
} 
} 

Desi exista si o cale prin care se pot crea clase care prelucreaza evenimente cu un numar arbitrar de argumente, utilizarea acestei cai este descurajata pentru ca îngreu neaza detectarea automata.

Înainte de a primi evenimente, un obiect trebuie sa se înregistreze ca ascultator pentru o anumita sursa de evenimente. Înregis tra rea se face cu metode care urmeaza urmatoarea forma:

add<TipDeAscultator>( <TipDeAscultator> a );
remove<TipDeAscultator>( <TipDeAscultator> );

Daca o clasa de obiecte implementeaza acest tip de functii se poate deduce ca ea genereaza evenimentele definite în interfata <TipDeAscultator>. În plus, se poate pre su pune ca aceasta clasa poate transmite un e veniment la mai multi ascultatori deodata. E xista si cazuri în care o sursa de evenimente nu suporta decât un singur ascultator, caz care trebuie semnalizat prin faptul ca metoda add<TipDeAscultator> arunca exceptia java.util.TooManyListenersException.

Introspectie

Specificatia de JavaBeans este construita în asa fel încât folosind API-ul de reflexie sa se poata determina proprietatile, metodele si evenimentele generate ale unui bean. Totusi, dupa cum am observat în cazul evenimentelor cu argumente multiple, exista si situatii în care nu se pot deduce în totalitate elementele unui bean. Pentru aceasta situatie, JavaSoft a proiectat un API cu care dezvoltatorul de beans poate specifica exact continutul produselor sale. Acest API se numeste API de introspectie.

Pentru a defini explicit continutul unui bean, dezvoltatorii pot defini o clasa cu acelasi nume ca si clasa care implementeaza bean-ul, dar la care se adauga extensia BeanInfo. De exemplu, pentru clasa PrimulE xemplu definita mai sus, noua clasa ar fi PrimulExempluBeanInfo. Noua clasa trebuie sa implementeze interfata java.beans.BeanInfo. Aceasta interfata defineste metode precum getEventSetDescriptors, si getPropertyDescriptors precum si metode care returneaza proprietatea sau evenimentul implicit ale bean-ului. Tot aici exista si metode pentru a defini un icon pentru bean sau alte informatii precum numele producatorului.

În fine, utilitarele care lucreaza cu beans trebuie sa foloseasca interfata numita java. bean.Introspector pentru a anali za un bean. Metodele din aceasta interfata combi na facilitatile oferite de BeanInfo cu anali za directa (folosind API-ul de reflexie) a clasei.

Configurare

În JavaBeans exista si suport pentru configu rarea beans în timpul proiectarii de aplicatii (design time). Cu alte cuvinte, se poate defini un dialog cu ajutorul caruia sa se editeze pro prietatile unui bean. Utilitarele de pro iec tare vizuala nu sunt însa obligate sa foloseasca acest suport si pot alege sa editeze proprietatile folosindu-se de un editor intern. Dupa configurarea unui bean, utilitarul vizual trebuie sa memoreze starea rezultata în asa fel încât ea sa poata fi restau ra ta la crearea componentei în timpul rularii aplicatiei rezultate.

JavaBeans permite crearea unor editoare diferite pentru diferite tipuri de proprietati. O clasa speciala, numita java.beans.Pro per tyEditorManager poa te fi utilizata pentru regasirea editorului potrivit într-un anumit context pentru o anumita proprietate. Daca dezvoltatorul nu creeaza implementari potrivite pentru editoarele proprietatilor, exista si un set de editoare predefinite în pachetul java.beans.editors.

În fine, utilitarele de configurare trebuie sa derive din java.awt.Component si sa im plementeze interfata java.beans.Custo mi zer.

Concluzii

Odata cu aparitia specificatiei JavaBeans, crearea de componente software a luat un nou avânt datorita faptului ca, pentru prima data, crearea unei astfel de componente a devenit o sarcina foarte simpla. Spre deosebire de alte modele, modelul Java Beans merge pe idea ca dezvoltatorii trebuie sa stie si sa implementeze doar atât cât au nevoie. Restul este rezolvat automat de catre sistem.

În plus, JavaBeans ruleaza deja pe toate platformele care au JDK 1.1 implementat si sunt folosite deja, asa cum aminteam la început, de multe dintre mediile moderne de programare. Chiar si Microsoft, în noua sa masina virtuala JVM 2.0 are suport pentru JavaBeans si suport pentru comunicare usoara între JavaBeans si componente le ActiveX, de asemenea disponibile în masina virtuala Microsoft.

Dl. Eugen Rotariu este lector universitar la Universitatea „Petru Maior" din Tg. Mures. Poate fi contactat prin e-mail la erotariu@uttgm.ro

(C) Copyright Computer Press Agora