Umesto da kuću gradite tako što čak i najmanje delove pravite sami, možete zidati koristeći gotove komponente sklapajući od njih celinu. Ovakav proces, tako uobičajen u životu, dugo nije bio moguć u programerskom svetu; prvo popularno razvojno okruženje koje je uspešno primenilo ovakav proces bio je Microsoft Visual Basic, a sledili su ga i mnogi drugi. Osnovni cilj je brzina: tempo kreiranja današnjih softverskih paketa je paklen, a od projektanata se po pravilu očekuje da softver bude završen „juče“. Ako se uračunaju i troškovi testiranja i ispravljanja grešaka, dobici su mnogo veći.
Mr. Bean
Pošto je uspeh Jave iznenadio i same kreatore jezika, ovo okruženje je dugo postojalo bez standarda za „pakovanje“ u softverske komponente. Tek je verzija Jave 1.1 (razlike između verzija 1.0 i 1.1 su ogromne) donela specifikaciju o kojoj je ovde reč. Specifikacijom se precizno definiše način pisanja klasa koje postaju „zrna“ (Beans – moglo bi se prevesti i kao „pasulj“). Razlika između klase i „zrna“ je mala, pa dolazimo do glavne prednosti JavaBeans-a: jednostavnosti.
Ako pravite nevidljivo „zrno“, dovoljno je da to bude obična klasa, koja implementira interfejs Serializable. Ovaj interfejs omogućava perzistenciju, zamrzavanje trenutnog stanja objekta i njegovo čuvanje do ponovnog oživljavanja u identičnom stanju. Ako pravite „zrno“ koje treba da bude vidljivo, potrebno je da nasledite klasu java.awt.Canvas. Osnovni elementi jednog „zrna“ su osobine (properties), metodi (methods) i događaji (events). Osobine definišu izgled i ponašanje, pozivanjem metoda „zrno“ radi posao kome je namenjeno i pri tome generiše događaje.
Pre nego što se upustimo u detaljno opisivanje glavnih elemenata, moramo se zapitati kako saznajemo osobine jednog „zrna“, kada ga dobijemo? Koristićemo klasu java.beans.Introspector, koja kao rezultat vraća objekat klase BeanInfo, koji „zna“ sve o dotičnom „zrnu“. Osobinama „zrna“ se ne pristupa direktno, već preko get i set metoda. Ako definišete metode:
public void setXXX(XXXType vrednost);
public XXXType getXXX();
klasa Introspector će „znati“ da „zrno“ poseduje osobinu naziva XXX i tipa XXXType, koja se može čitati i pisati. Izostavljanjem jednog od metoda dobija se read-only, odnostno write-only osobina. Ako pretpostavimo da naše „zrno“ poseduje objekat klase String, metodi za rad sa tim objektom bi izgledali ovako (ako imamo logičku promenljivu, možemo koristiti i oblik isXXX().:
public void setStatus(String status);
public String getStatus();
Metodi i događaji
Događaji su jedini vid komunikacije „zrna“ sa spoljnim svetom. Događaj je predstavljen objektom klase java.util.EventObject (ili iz nje izvedene klase). Dužnost „zrna“ je da vredno radi i kreira definisane događaje kadgod je to potrebno i da obezbedi metode kojima će se drugi zainteresovani objekti prijavljivati za primanje određenih događaja. Za svaki događaj je potreban po par metoda.
Uzmimo za primer imaginarno „zrno“ LazyBean, koje obavlja neki posao koji dugo traje. Lepo bi nam došao događaj StatusChangeEvent, ekstenzija standardnog događaja koja sve „zainteresovane stranke“ obaveštava o trenutnom stanju zadatka koji se izvršava (slika 1). Uz svaki događaj ide bar jedan interfejs koji predstavlja „uputstvo“ ostalim objektima. Poslednja karika u ovom lancu je par metoda potrebnih za prijavljivanje i odjavljivanje primanja određenih događaja. U našem slučaju, oni bi izgledali kao na slici 2a (listener je objekat klase java.util.Vector), a obaveštavanje zainteresovanih klijenata dato je na slici 2b.
Metodi za dodavanje adresa objektu listener su sinhronizovani, jer se pretpostavlja da se jednom „zrnu“ može pristupiti iz više aktivnih niti. Preporučuje se sinhronizacija objekta samo prilikom pribavljanja spiska adresa na koje treba poslati događaj. „Zrno“ može imati događaj koji će poslati samo jednom primaocu. U tom slučaju bi se metod za prijavljivanje definisao ovako:
public synchronized addStatusChangeListener
(StatusChangeListener scl)
throws java.util.TooManyListenersException;
pri čemu „zrno“ baca izuzetak java.util.TooManyListenersException, ako je mesto primaoca već popunjeno. Ovakvi događaji nazivaju se unicast, za razliku od uobičajenih, multicast događaja.
Usko vezani za događaje su specijalne klase-adapteri, koje ćemo ovde samo kratko pomenuti. Oni mogu poslužiti u razne svrhe uz najčešću upotrebu za povezivanje dva nesrodna „zrna“ i demultipleksiranje događaja. Recimo da imate „zrno“ koje može kao događaj primiti pritisak tastera. Kako vi želite da na to „zrno“ zakačite dva tastera, recimo ok i cancel, morate da napravite malu akrobaciju, kreirajući dve nove klase koje će primati pritisak jednog tastera i prosleđivati ga na odgovarajući metod „zrna“.
Korišćenje JavaBeans-a
„Zrno“ koristite kao i svaku drugu klasu: novi objekat kreiraćemo new pozivom, ako smo zainteresovani prijavićemo se za primanje događaja koje „zrno“ šalje i to je sve. Ako želimo da kreiramo „zrno“ čije ime ne znamo u toku pisanja programa, poslužićemo se klasom java.beans.Bean, koja poseduje metod instantiate(), kojim se kreira „zrno“ samo na osnovu zadatog naziva.
Kod ozbiljnijeg rada zatrebaće vam i dodatne opcije, kao što je klasa BeanInfo. Klasa Introspector je dovoljno „pametna“ da, koristeći Reflection API, na osnovu naziva polja, otkrije osobine „zrna“. Ovo znatno olakšava posao piscima softverskih komponenti koji ne moraju „ručno“ da kreiraju opis. Zgodno je to što Introspector vraća objekat klase BeanInfo, koji sadrži sve otkrivene informacije.
Ako želimo nešto da dodamo opisu, možemo kreirati sopstveni objekat ove klase, a Introspector će ga proslediti, umesto da sam vrši analizu. Ovim postupkom se ne može efikasno sprečiti korišćenje javnih metoda „zrna“, jer će svako ko direktno koristi Reflection API moći da dođe do kompletnih podataka. Moguće je pružiti detaljne informacije o „zrnu“, počevši od naziva i podataka o proizvođaču preko naziva metoda pa sve do ikona koje će se koristiti za predstavljanje „zrna“ u razvojnim alatima.
Interesantno je da BeanInfo podržava internacionalizaciju – isti metodi mogu imati različite nazive, zavisno od područja na kome se koriste. Niz zanimljivih mogućnosti postoji kada su u pitanju osobine „zrna“. Najinteresantnije su mogućnosti postojanja vezanih (bound) i uslovljenih (constrained) osobina. Vezane osobine su kombinacija običnih osobina i događaja. Svaki put kada se neka od vezanih osobina „zrna“ promeni, nastaje događaj, koji obaveštava ostale objekte o promeni.
Uslovljene osobine su vrlo slične, ali se događaj emituje pre promene vrednosti, a od primalaca se očekuje da promenu odobre (ne reagujući) ili odbace, emitujući izuzetak PropertyVetoException. Metod za postavljanje nove vrednosti uslovljene promenljive bi glasio public void setStatus(String status) throws PropertyVetoException, uz normalne metode za prijavljivanje i odjavljivanje. JavaBeans specifikacija uključuje i specijalne klase za promenu i podešavanje (customization) osobina „zrna“. Ako napravite iole komplikovanije „zrno“, možete uz njega isporučiti i Wizard za lakše korišćenje, što će korisnici verovatno s radošću prihvatiti.
Šta će biti sutra?
Pretpostavljajući da će JavaBeans tehnologija uspeti, u JavaSoft-u ubrzano rade na ispravljanju nedostataka postojeće specifikacije. Sledeća verzija nosi ime Glasgow i trebalo bi da donese bar tri nove osobine: Drag & Drop funkcionalnost (što je zapravo deo JFC-a ali blisko povezano sa JavaBeans-om), specifikaciju za interakciju „zrna“ sa okolinom (slično AppletContext-u, ali komplikovanije) i JavaBeans Activation Framework, tehnologiju koja omogućava pridruživanje tipa grupi podataka i čuvanje informacija o tom tipu kao i o „zrnima“ potrebnim da njime barataju.
Nezavisno od sistema koji koristite, softverske komponente predstavljaju veliki korak napred. One efektivno dele programerski svet na dve grupe, jednu čiji je posao pisanje komponenti i rad na niskom nivou, sa puno programskog koda, i drugu u koju spadaju programeri koji rade sa razvojnim alatima visokog nivoa, spajajući gotove komponente u aplikacije. JavaBeans je dobro balansirana tehnologija, koja se prirodno nadovezuje na Javu i dozvoljava da brzo krenete sa radom, držeći sve konce u svojim rukama. Uspeh JavaBeans tehnologije u potpunosti zavisi od uspeha samog Java okruženja.
Slika 1
public class StatusChangeEvent
extends java.util.EventObject {
protected String status;
public StatusChangeEvent(LazyBean source,
String status) {
super(source);
this.status = status; }
public String getStatus() {
return new String(status); }
}
interface StatusChangeListener
extends java.util.EventListener {
void statusChanged(StatusChangeEvent sce);
}
Slika 2
public synchronized void addStatusChangeListener
(StatusChangeListener scl) {
listeners.addElement(scl); }
public synchronized void
removeStatusChangeListener
(StatusChangeListener scl) {
listeners.removeElement(scl); }
protected void fireEvent(String status) {
Vector v;
StatusChangeEvent sce =
new StatusChangeEvent(this, status);
synchronized(this) {
v = (Vector)listeners.clone(); }
for(int i=0; i v.size; i++)
((StatusChangeListener)v.elementAt(i)).
statusChanged(sce); }
Beanbox
JavaSoft-ov Bean Development Kit, sa desetak gotovih primera, pretvara čitavu ovu priču u praksu. Koristeći BeanBox možete da ubacujete „zrna“ u peščanik, međusobno ih povezujete i izazivate događaje. Zahvaljujući dobro izabranim primerima, proces istraživanja JavaBeans tehnologije je vrlo zabavan. Prva stvar koju sam probao (baš kao i pola miliona drugih ljudi, pretpostavljam) je da na radnu površinu postavim Jugglera i dva tastera. Pritiskom na prvi taster žongler počinje sa žongliranjem, a pritiskom na drugi prestaje. Jednostavnost kreiranja je zadivljujuća.
Na možete videti ovaj primer, kao ni radnu površinu posle pola sata igranja ovom aplikacijom. Da biste se i sami poigrali, potrebni su vam sledeći sastojci: Java Development Kit 1.1.4 ili viši, Bean Development Kit (Februar 98) i nešto slobodnog prostora na disku. Kao i uvek, sve relevantne informacije o Javi preuzećete sa www.javasoft.com.
|