Documente online.
Zona de administrare documente. Fisierele tale
Am uitat parola x Creaza cont nou
 HomeExploreaza
upload
Upload




Entity Beans

java


Entity Beans

Entity beans sunt enterprise beans care stiu cum sa se salveze pe ele īnsele īntr-un mediu permanent de stocare. Entity beans stocheaza date cum ar fi numarul contului bancar, numerarul din cont, etc. Ele au asociate metode ca getBan() sau getAccountBalance(). Entity beans pot fi folosite si pentru integrarea aplicatiilor mai vechi (legacy systems).



Spre deosebire de session beans care modelaza procesele, actiunile pornite de utilizatori, entity beans contin datele legate de aplicatie, ca de exemplu conturi bancare, comenzi, informatii legate de utilizatori, etc. Un entity bean nu realizeaza sarcini complicate, cum e, de exemplu, realizarea platilor de la client.

Entity beans pot fi privite astfel:

o reprezentare īn memorie a datelor sub forma de obiect Java

obiecte capabile sa se citeasca din mediul de stocare si sa īsi populeze cāmpurile cu aceste date

un obiect care poate fi modificat īn memorie si care va schimba datele din mediul de stocare

2.5.1. Caracteristici ale entity beans

Entity beans au durata de viata egala cu cea a datelor pe care le reprezinta. De exemplu, un entity bean poate reprezenta contul unui client.

Entity beans supravietuiesc īn cazul unor caderi accidentale. Deoarece entity beans sunt parte dintr-un mediu persistent, o cadere a JVM (Java Virtual Machine) sau a bazei de date nu va afecta ciclul de viata al unui entity bean. De īndata ce lucrurile reintra īn normal, instantele entity beans pot fi recreate prin simpla citire a datelor din baza de date si crearea unor instante care sa le reprezinte īn memorie.

Legatura dintre entity beans si datele pe care le reprezinta

Entity beans au seminificatia unui zoom asupra datelor din baza de date pe care le reprezinta. Cu alte cuvinte, datele din baza de date si obiectul din memorie care le reprezinta (instanta bean - ului asociata lor) trebuie privite ca fiind unul si acelasi. Aceasta īnseamna ca, daca datele din memorie, adica din bean, sunt modificate, atunci, īn mod automat, sunt modificate si datele din baza de date. Desigur ca, īn realitate, obiectul din memorie, instanta entity bean - ului nu este unul si acelasi cu datele din baza de date. Din acest motiv, trebuie sa existe un mecanism prin care sa poata fi transferata informatia īntre obiectul din memorie si baza de date. Acest transfer este realizat prin intermediul a doua metode speciale pe care orice entity bean trebuie sa le implementeze: ejbLoad() si ejbStore(). Metoda ejbLoad() are rolul de a citi datele din mediul permanent de stocare si de a le plasa īn cāmpurile bean - ului. Metoda ejbStore() este complementara, realizānd salvarea datelor din bean īn baza de date.

Īntrebarea care se pune este cine decide momentele īn care sa fie transferate datele īntre obiectele din memorie si cele din baza de date. Cu alte cuvinte, cine apeleaza metodele ejbLoad() si ejbStore()? Dupa cum s-a vazut deja, este vorba de containerul EJB. El este cel care alege momentele īn care sa transfere datele din memorie īn mediul persistent si invers. Bean - ul trebuie sa fie pregatit sa accepte metodele ejbLoad() si ejbStore() aproape īn orice moment, dar nu īn decursul metodelor de business. Acesta este unul dintre avantajele EJB: programatorul nu trebuie sa se preocupe de sincronizarea īntre datele din bean - ul din memorie si datele din baza de date.

2.5.1.2. Mai multe entity beans pot reprezenta simultan aceleasi date din baza de date

Sa consideram cazul īn care mai multe fire de executie (threads) doresc sa acceseze simultan aceleasi date. De exemplu, se poate īntāmpla ca, simultan, mai multi clienti ai unui magazin virtual sa acceseze un catalog de produse.

Pentru a facilita accesul simultan al mai multor clienti la aceleasi date, trebuie sa existe un mecanism de acces la entity beans. O posibilitate ar fi sa se permita clientilor sa partajeze aceeasi instanta a unui entity bean. Aceasta este inadecvata din doua motive: codul din interiorul bean - ului ar trebui sa fie thread-safe si ar aparea o gātuitura la aceesul la date.

Codul thread-safe este un cod care permite executarea mai multor fire de executie folosind aceleasi date. Daca pentru entity beans ar fi mai multe fire de executie, tranzactiile ar fi aproape imposibile. Din acest motiv, īn specificarea EJB, se spune ca īn intreriorul unei instante a unui bean poate rula doar un thread. Acelasi lucru este adevarat si pentru session beans.

Gātuitura īn accesul la date ar aparea atunci cānd mai multi clienti acceseaza un bean, fiindca trebuie ca fiecare sa astepte dupa cei dinaintea lui. Pentru a evita aceasta, se permite containerului sa creeze mai multe instante ale aceluiasi entity bean (adica mai multe instante sa reprezinte exact aceleasi date). Aceasta va permite clientilor sa aiba acces concurent la date.

Totusi procedand asa apare o noua problema. Daca mai multe instante reprezinta aceleasi date, atunci unele dintre ele ar putea reprezenta, la un moment dat, datele vechi, nestiind ca, de fapt, ele s-au modificat īntre timp. Pentru a avea consistenta datelor, fiecare client are nevoie sa fie sincronizat cu mediul permanent de stocare. Containerul este cel care va realiza aceasta sincronizare īntre instanta bean - ului si mediul permanent de stocare, folosind metodele ejbStore() si ejbLoad(). Cānd o instanta de bean este modificata, containerul va apela metoda ejbStore() a acestuia si apoi va apela metoda ejbLoad() asupra fiecarei instante de bean care reprezinta aceleasi date.

Frecventa cu care sunt sincronizate bean - urile cu mediul de stocare este dictata de atributele privitoare la tranzactii. Tranzactiile permit fiecarui client sa fie complet izolat de toate celelalte cereri. Cu alte cuvinte, acestea fac posibila iluzia clientului ca el este singurul care opereaza asupra acelor date.

2.5.1.3. Entity beans suporta mecanismul de pooling

Cea mai simpla metoda de a satisface cererile clientilor īntr-un container, care suporta entity beans, ar fi ca, pe masura ce clientii se conecteaza sau se deconecteaza, sa se creeze si sa se distruga bean - uri penrtu acei clienti. Din pacate, desi simpla, aceasta metoda nu este tocmai eficienta, deoarece crearea si distrugerea de obiecte este īntotdeauna costisitoare ca resurse, mai ales daca cererile clientilor sunt foarte frecvente.

Un fapt foarte important, care trebuie avut īn vedere, este ca respectiva clasa, care defineste entity bean - ul, descrie cāmpurile ei si regulile pentru manipularea acelor cāmpuri, dar nu si datele specifice din acele cāmpuri. De exemplu, o clasa entity bean poate specifica un cont bancar care va contine numele posesorului, identificatorul contului, soldul contului. O instanta de bean poate reprezenta oricare dintre conturile din baza de date.

Din motivul expus mai sus, entity beans sunt privite de catre container ca obiecte reciclabile, asupra carora se poate aplica mecanismul de pooling. Īn acest fel, se vor salva resurse pretioase, care, alfel, ar fi fost irosite pe instantieri si distrugeri de obiecte. De exemplu, o instanta a unui entity bean, care reprezinta un cont bancar, poate fi reutilizata sa reprezinte datele altui client, dupa ce primul client a terminat de utilizat propriul cont bancar reprezentat de acea instanta a bean - ului. Containerul face aceasta prin asignarea dinamica a instantelor entity beans la diferite obiecte EJB, care sunt specifice cāte unui client. Mecanismul de pooling aplicat la entity beans este prezentat si īn Figura 2.21.

Din pacate, reasignarea instantelor entity beans la diferite obiecte EJB aduce dupa sine mai multe complicatii. Atunci cānd un entity bean este asignat unui obiect EJB particular, poate sa detina anumite resurse, cum ar fi conexiuni la baza de date sau conexiuni la alte aplicatii prin socket-uri. Cānd bean - ul nu mai este legat de vreun client (cānd se afla īn bazin), nu mai are nevoie de acele resurse. Pentru a permite bean - ului sa elibereze si recāstige resursele, se vor utiliza metodele ejbPassivate() si ejbActivate(). De fapt, aceste metode sunt foarte asemanatoare cu cele de la statefull session beans.

Metoda ejbPassivate() este invocata de container atunci cānd dezasociaza bean - ul de un obiect EJB specific. Pentru identificarea bean - ului se utilizeaza o cheie primara, care poate fi orice tip de obiect. Tot īn acest moment, se dezasociaza si cheia primara pe care acest bean a avut-o. La apelul acestei metode, bean - ul trebuie sa elibereze resursele pe care le detine.

Metoda ejbActivate() este invocata de container atunci cānd bean - ul este asociat unui anume obiect EJB. Tot acum se asociaza bean - ului si o cheie primara, care va fi utilizata ulterior. Bean - ul, acum atasat de un anume client, trebuie sa reobtina resursele pe care le-a eliberat la apelul metodei ejbPassivate().


Figura 2.21. Mecanismul de pooling la entity beans


Atunci cānd un entity bean este pasivizat, pe lānga faptul ca elibereaza resursele pe care le detine, īsi si salveaza starea īn mediul de stocare. Īn acest fel, mediul de stocare este īmprospatat cu ultima stare a instantei bean - ului. Pentru a salva cāmpurile bean - ului īn mediul de stocare, containerul invoca metoda ejbStore() īnainte de a apela ejbPassivate(). Īn mod similar, atunci cānd un bean este activat, el trebuie nu numai sa obtina resursele de care are nevoie, dar si sa īncarce ultimele date din baza de date. Pentru ca sa īncarce datele īn cāmpurile instantei entity bean - ului, containerul invoca metoda ejbLoad(). Aceasta metoda este invocata dupa ejbActivate(). Succesiunea metodelor la activare si pasivizare poate fi observata īn Figura 2.22.

Figura 2.22. Succesiunea metodelor la pasivizare si activare

Exista doua metode de a realiza persistenta pentru entity beans

Protocolul pentru transferul starii unei instante a unui entity bean spre mediul de stocare este denumit persistenta. Īn cadrul entity beans, persistenta poate fi implementata īn urmatoarele doua moduri:

Implementarea directa a persistentei īn clasa care defineste enterprise bean - ul sau īn una sau mai multe clase ajutatoare, care vor fi utilizate īn interiorul bean - ului. Acest mecanism de persistenta se numeste bean managed persistance (persistenta gestionata de entity bean).

Delegarea responsabilitatii persistentei la container. Acest mecanism de persistenta se numeste container managed persistance (persistenta gestionata de containerul īn care ruleaza entity bean - ul).

Īn cazul bean managed persistance, cade īn responsabilitatea programatorului de a scrie codul de acces la baza de date. Apelurile spre baza de date pot fi codate direct īn clasa entity bean - ului sau pot fi īncapsulate īntr-o componenta de Data Access ca parte a unui entity bean. Daca apelurile la baza de date sunt codate direct īn clasa entity bean - ului, va fi mult mai dificil sa se realizeze adaptarea entity bean - ului la o noua arhitectura a bazei de date. Īncapsularea apelurilor la baza de date īntr-un Data Access Object va duce la o mult mai mare adaptabilitate a aplicatiei la o noua arhitectura a bazei de date. De fapt, Data Access Object este un design pattern ce va fi reluat separat.

Īn cazul persistentei gestionate de catre container, programatorul identifica cāmpurile care vor fi stocate īn baza de date si va utiliza apoi, īn momentul deployment - ului, uneltele puse la dispozitie de container pentru a genera codul de acces la baza de date. Tipologia si structura bazei de date sunt transparente pentru programator. Uneltele puse la dispozitie de container pot folosi JDBC (Java Data Base Connectivity) sau SQL/J pentru a accesa starea entity bean - ului din tabelele bazei de date relationale sau din clase care implementeaza accesul la aplicatii enterprise deja existente. Starea bean - ului este definita independent de modul cum si locul unde va fi stocat, motiv pentru care este mai flexibil. Dezavantajul este ca sunt necesare unelte mai sofisticate la deployment pentru a putea mapa datele īn cāmpurile unei baze de date. Aceste unelte sunt īn general specifice fiecarei baze de date.

Atunci cānd un container suporta container managed persistance, el simplifica sarcina de scriere a codului entity beans, deoarece containerul īsi asuma complet responsabilitatea de a genera codul pentru accesul la baza de date. Programatorii ar trebui sa se foloseasca de acest avantaj pentru a delega sarcina salvarii starii entity bean - ului la container pe cāt posibil. Unele containere s-ar putea sa nu fie capabile sa gestioneze starea unor obiecte mai complexe (de exemplu obiectele care reprezinta rezultatul unui select cu mai multe join- uri imbricate). Īn asemenea cazuri, programatorii vor fi nevoiti sa utilizeze persistenta gestionata de bean.

2.5.1.5. Entity beans pot fi create, distruse si gasite

La session beans exista metoda de creare ejbCreate() si cea de distrugere ejbRemove(). Metoda ejbCreate() este chemata de container pentru a initializa bean - ul. Cānd un bean este pe cale de a fi distrus, containerul apeleaza metoda ejbRemove() care are rolul de a pregati bean - ul pentru distrugere.

La entity beans, initializarea si distrugerea sunt putin diferite. Entity beans sunt o reprezentare a datelor din baza de date, deci trebuie privite ca fiind una cu datele din baza de date. Din acest motiv, initializarea - crearea unui entity bean- trebuie sa īnsemne crearea datelor īn baza de date. Astfel, cānd datele sunt initializate īn memorie la ejbCreate(), este normal ca ele sa fie inserate si īn baza de date. Pe de alta parte, cānd este apelata metoda ejbRemove(), datele din baza de date sunt sterse. Daca se utilizeaza container managed persistance, este lasata pe seama containerului īntreaga sarcina de modificare īn baza de date. Din acest motiv, pentru container managed persistance nu este nevoie sa fie completat corpul metodelor ejbCreate() si ejbRemove().

Īn orice baza de date, datele poarta un identificator unic. Deci este natural ca si entity beans, care sunt o reprezentare a lor, sa aiba un identificator unic. Īn cazul bazelor de date, se folosesc frazele de SELECT pentru a gasi anumite date. Īn cazul entity beans, sunt prevazute metodele de find (finder methods). Semnificatia lor este de cautare īn mediul persistent dupa datele reprezentate īn forma obiectuala. Rezultatul unei operatii de find este o colectie de referinte la obiecte EJB. Aceste obiecte vor fi asociate dinamic de catre container cu instante de bean - uri.

Finder methods apar expuse īn interfata Home a bean - ului. O īntrebare, poate nu chiar cea mai buna, este de ce īn interfata Home? Pentru ca s-ar putea ca sa nu se detina nici o referinta la vreun obiect EJB pentru vreun entity bean si ar fi, īn unele cazuri, imposibil sa se obtina una. Īn plus, scopul obiectului Home este de a furniza instante de obiecte EJB (acest lucru este adevarat si īn cazul session beans). Finder methods reprezinta diferenta cea mai mare īntre interfetele Home pentru entity beans si session beans.

Datele pe care le reprezinta entity beans pot fi modificate si altfel decāt prin intermediul entity beans. Daca, de exemplu, se folosesc baze de date relationale si mai sunt alte aplicatii care modifica datele, se poate considera ca s-au modificat si entity beans īn acelasi timp. Daca acele aplicatii sterg date, atunci se poate considera ca s-au sters si entity beans, ca si cānd s-ar fi apelat metoda ejbRemove() asupra interfetei Remote expusa de obiectul EJB. Īn mod asemanator, la introducerea de noi date, se poate considera ca s-a apelat metoda ejbCreate().

Cum se scrie un entity bean

Pentru ca o clasa sa poata fi un entity bean, trebuie sa implementeze interfata javax.ejb.EntityBean. Metodele din aceasta interfata sunt metode pe care le utilizeaza containerul pentru initializare, pasivizare, activare, distrugere, etc. Aceasta interfata are ca parinte interfata javax.ejb.EnterpriseBean, care, desi nu are metode, implementeaza interfata Serializable, deci orice enterprise bean; prin urmare si entity beans sunt serializabile.

Interfata javax.ejb.EntityBean este prezentata īn continuare:

Interfata javax.ejb.EntityBean

public interface javax.ejb.EntityBean

implements javax.ejb.EnterpriseBean

Pe lānga metodele din aceasta interfata, pentru un entity bean, se mai definesc metodele ejbCreate() si ejbFind(). Metodele de tipul ejbCreate() sunt utilizate pentru a crea entity beans, adica pentru a introduce date īn mediul persistent. Cele de tipul ejbFind() sunt utilizate pentru a gasi anumite date.

2.5.2.1. Crearea entity beans

O metoda ejbCreate() are rolul de a initializa un entity bean pentru un anume client si de a crea datele īn baza de date. Fiecare metoda ejbCreate() permite clientului o noua posibilitate de creare a unui entity bean.

Iata cāteva reguli pentru metodele ejbCreate() īn cazul entity beans:

Nu este obligatorie realizarea unor metode ejbCreate(). Spre deosebire de session beans, unde aceasta era singura modalitate de initializare a unui bean, īn cazul entity beans, datele pot fi inserate īn baza de date pe alte cai, deci se pot crea entity beans fara a avea nevoie de metodele ejbCreate(). Entity beans trebuie privite ca fiind una cu datele din baza de date, dupa cum s-a precizat mai sus.

Parametrii primiti de metodele ejCreate() pot varia. Aceasta permite existenta mai multor metode de initializare a bean - urilor, de fapt, de introducere a datelor īn baza de date.

Metodele ejbCreate() trebuie expuse si īn interfata Home pentru a putea fi utilizate. Ca si īn cazul session beans, orice entity bean este creat prin invocarea metodelor ejbCreate() asupra obiectului Home, care va crea un obiect EJB si va asocia un bean propriu - zis pentru acel obiect EJB.

De exemplu, se presupune ca exista un entity bean denumit AccountBean, care reprezinta un cont bancar. Acest bean va avea interfata Home AccountHome si cheia primara (acest concept se va clarifica imediat) va avea clasa AccountPK. Metoda ejbCreate() din interfata clasa bean - ului AccountBean

public AccountPK ejbCreate(String accountID, String owner)

trebuie sa poata fi utilizata, deci va apare si īn interfata Home, dar sub forma:

public Account create(String accountID, String owner).


Figura 2.23. Crearea unui entity bean pentru cazul bean managed persistance

Trebuie remarcat ca cele doua metode returneaza obiecte de tipuri diferite. Instanta bean - ului returneaza o cheie primara de clasa AccountPK, iar obiectul Home returneaza un obiect EJB de clasa Account. Bean - ul returneaza o cheie primara containerului (adica obiectului Home), care, astfel, poate identifica bean - ul. Dupa ce a obtinut cheia primara, containerul va genera obiectul EJB pe care-l va returna clientului. Īntregul proces poate fi observat īn Figura 2.23.

2.5.2.2. Gasirea entity beans

Finder methods sunt utilizate pentru a gasi bean - uri existente, deja create. Finder methods nu creeaza date īn baza de date, ci, doar īncarca date din baza de date. Pot exista mai multe metode de gasire, care toate realizeaza operatii diferite.

Cāteva reguli pentru finder methods sunt urmatoarele:

Trebuie sa existe cel putin o metoda find denumita ejbFindByPrimaryKey(), care este utilizata pentru a gasi o instanta a unui entity bean īn baza de date, folosind cheia primara asociata acestuia. Fiecare entity bean are asociata o cheie unica, care este īn legatura cu datele pe care le reprezinta din baza de date.

Pot exista mai multe finder methods care au denumiri diferite si primesc parametri diferiti. Aceasta permite cautarea prin folosirea mai multor semantici. De exemplu, pentru un obiect de business de tipul entity bean, care reprezinta un cont, pot exista, pe lānga ejbFindByPrimaryKey(), si alte metode de find ca: ejbFindBigAccounts(), ejbFindEmptyAccounts(), etc.

O metoda de tipul ejbFind trebuie sa returneze fie o cheie primara, fie o colectie de chei primare, daca gaseste mai mult de una.

Clientii nu invoca niciodata finder methods asupra instantei bean - ului. Aceste metode se invoca asupra obiectului Home implementat de containerul EJB, care le va delega bean - ului. Din acest motiv, pentru fiecare metoda ejbFind, care este declarata īn bean, trebuie sa existe un corespondent īn interfata Home. De exemplu, pentru metoda:

public AccountPK ejbFindBigAccounts( int minimum) throws ... implementata īn clasa entity bean - ului, trebuie sa existe urmatoarea metoda declarata īn interfata Home:

public Account findBigAccounts(int minimum ) throws ...

De remarcat ca metoda din interfata nu are prefixul ejb si ca returneaza un tip diferit de obiect. Instanta entity bean - ului returneaza o cheie primara sau o colectie de chei primare, iar obiectul Home returneaza clientului un obiect EJB sau o colectie de obiecte ejb.

2.5.2.3. Distrugerea entity beans

Pentru a distruge datele pe care le reprezinta un entity bean, clientul trebuie sa apeleze metoda remove() asupra obiectului EJB sau obiectului Home. Acesta va determina containerul sa realizeze un apel al metodei ejbRemove() a bean - ului.

De remarcat ca metoda ejbRemove() nu realizeaza stergerea din memorie a obiectului, ci va distruge datele din baza de date pe care le reprezinta acel bean. Bean - ul īnsusi poate fi reutilizat pentru a reprezenta alte date din baza de date.

Aceasta metoda trebuie sa fie definita de orice entity bean si e una singura: ejbRemove().

2.5.2.4. Contextul unui entity bean

Fiecare enterprise bean are un obiect context, care contine date despre mediul īn care traieste bean - ul. Aceste date sunt completate de container. Bean - ul poate accesa contextul pentru a obtine informatii privitoare la tranzactii, securitate sau alte feluri de informatii. Pentru session beans, contextul este un obiect care implementeaza interfata javax.ejb.SessionContext, iar pentru entity beans, obiectul context implementeaza interafata javax.ejb.EntityContext. Ambele interfete descind din interfata javax.ejb.EJBContext.

Interfata javax.ejb.EntityContext

public interface javax.ejb.EntityContext implements

javax.ejb.EJBContext

Metoda getEJBObject() este utilizata pentru a obtine obiectul EJB, care este asociat cu entity bean - ul. Clientii nu acceseaza niciodata bean - urile direct, ci fiecare client are asociat un obiectEJB. Obiectul EJB returnat de aceasta metoda poate fi utilizat pentru a avea o referinta la acelasi obiect. Cu alte cuvinte, poate fi utilizat pentru a simula rolul lui this din Java.

Metoda getPrimaryKey() este specifica pentru entity beans. Ea returneaza cheia primara, care este asociata la acel moment cu acea instanta a bean - ului. Cheia primara identifica īn mod unic acel entity bean, de fapt si datele īn baza de date sunt identificate unic prin cheile primare ale tabelelor. Aceasta metoda este utila pentru a afla care date din baza de date sunt asociate cu un entity bean īn momentul apelului. Instantele entity beans sunt asignate cānd la un obiect EJB, cānd la altul, conform politicii containerului pentru mecanismul de pooling. Din acest motiv este necesara aflarea cheii primare a datelor pe care le reprezinta bean - ul la un moment dat. Cheia primara obtinuta cu getPrimaryKey() poate fi utilizata la activare, pasivizare, ejbLoad() sau ejbStore().

Ciclul de viata al unui entity bean


Ciclul de viata al unui entity bean este prezentat prin automatul de stare din Figura 2.24.

Figura 2.24. Ciclul de viata al unui entity bean

Se porneste din starea īn care bean - ul nu a fost instantiat. Pentru a crea o noua instanta de bean, containerul apeleaza metoda newInstance() asupra clasei entity bean - ului. Aceasta va apela constructorul implicit al clasei. Apoi, prin intermediul metodei setEntityContext(), containerul asociaza bean - ului un EntityContext. Important de observat este faptul ca nu se creeaza o noua instanta de bean atunci cānd un client se leaga, deoarece instantele entity beans suporta mecanismul de pooling. O noua instanta de entity bean este creata atunci cānd containerul considera acest lucru necesar, pentru a īsi mari bazinul de bean - uri.

Acum bean - ul se afla īntr-un bazin cu alte entity beans. Īnca nu sunt nici un fel de date asociate cu acest bean si nici un fel de resurse nu au fost obtinute de acest entity bean. Īn aceasta faza, bean - ul poate fi distrus de catre container prin apelarea metodei unsetEntityContext(), iar apoi Garbage Collector - ul va curata zona de memorie respectiva.

Atunci cānd un client doreste sa insereze noi date īn baza de date, el va apela metoda create() asupra obiectului Home al bean - ului. Containerul va lua o instanta de bean din bazin si va apela metoda acestuia ejbCreate(), care va initializa entity bean - ul cu anumite date. Bean - ul īsi va popula variabilele membru cu aceste date si, daca se utilizeaza bean managed persistance, atunci va si insera datele īn baza de date. Acum bean - ul se afla īn starea de ready.

Īn aceasta stare, bean - ul este legat de anumite date din baza de date si de un anume obiect EJB. Daca exista mai multe bean - uri, care reprezinta aceleasi date din baza de date, containerul va trebui sa sincronizeze, ocazional, instanta bean - ului cu baza de date pentru a reprezenta ultimele date. Aceasta se face prin intermediul metodelor ejbLoad() si ejbStore().

Entity bean - ul poate fi trimis din nou īn bazin, īn cazul īn care clientul apeleza metoda remove() asupra obiectului Home sau īn cazul īn care datele sunt sterse pe alta cale din baza de date. De asemenea, bean -ul este trimis de container īn bazin daca acesta a decis ca timpul acordat clientului a expirat sau ca ramāne fara resurse sau ca are nevoie de acea instanta a bean - ului pentru a deservi un alt client. Īn aceste din urma situatii, containerul va apela metoda ejbStore() pentru a se asigura ca baza de date contine ultima versiune a datelor din memorie. Apoi el va apela metoda ejbPassivate() pentru ca resursele detinute de bean sa fie eliberate si sa poata fi reutilizate.

Atunci cānd containerul doreste sa asigneze un alt obiect EJB, instanta bean - ului trebuie activata prin apelul metodei ejbActivate(), astfel bean - ul va obtine toate resursele de care are nevoie. Pentru a īncarca date din baza de date īn bean, containerul va apela metoda ejbLoad().

2.5.2.6. Rezumatul tuturor metodelor din interfata EntityBean

Orice entity bean trebuie sa implementeze metodele din interfata javax.ejb.EntityBean. Tabelul 2.2. prezinta toate metodele care apar īn aceasta interfata, rolul lor, precum si utilizarea lor obisnuita. Pentru o īntelegere cāt mai buna se recomanda urmarirea ciclului de viata al unui entity bean din Figura 2.24. Metodele sunt prezentate īntr-o posibila ordine a apelarii lor de catre container.

Tabelul 2.2. Rezumatul metodelor din interfata EntityBean

Metoda

Semnificatie metodei

Utilizare obisnuita

setEntityContext()

Este apelata de container atunci cānd doreste sa creasca numarul de bean - uri din bazinul cu bean -uri. El va instantia un nou obiect de tipul clasei bean - ului.

Apoi imediat containerul va apela asupra noii instante metoda setEntityContext() care va asocia bean - ului un context īn care bean -ul poate gasi informatii despre mediu. Dupa apelul acestei metode, bean -ul poate sa apeleze metode pentru a afla mediul īn care ruleaza.

Se salveaza īntr-o variabila membru EntityContext -ul primit. Mai tārziu el poate fi utilizat pentru a obtine informatii legate de mediu de la container (ca de exemplu, cele despre securitate).

Se obtin acele resurse de care are nevoie un entity bean indiferent de ce date va reprezenta.

Acum bean -ul este īn bazin si nu este asociat cu nici un obiect, deci nu reprezinta nici un fel de date din baza de date

ejbFind<...>(<...>)

Cāt timp instanta bean - ului se afla īnca īn bazin ea poate fi utilizata pentru a deservi apelul unei metode de find. Metodele de find sunt utilizate pentru a gasi date īn mediul persistent. Este obligatorie implementarea cel putin a metodei ejbFindByPrimaryKey().

Se cauta īn baza de date, utilizānd, de exemplu, JDBC. De obicei, se va realiza o interogare de tipul "SELECT ... FROM ...".

Se returneaza containerului cheile primare gasite.    Containerul va crea apoi niste obiecte EJB pe care le va putea invoca clientul. Probabil va asocia cātorva obiecte EJB instante de bean-uri. Instantele asociate nu se mai afla īn bazin si au anumite date specifice din baza de date cu care sunt asociate.

ejbCreate(<...>)

Atunci cānd un client apeleaza create() asupra obiectului Home containerul va apela metoda ejbCreate() a bean - ului. Metoda este responsabila de crearea noilor date īn baza de date si de initializarea bean - ului cu acele date.

Se verifica validitatea parametrilor de initializare si apoi folosind JDBC se vor stoca datele īn baza de date.

Bean - ul nu mai este īn bazin , are asociate anumite date pe care le reprezinta. Containerul va asocia bean - ul cu un anume obiect EJB.

ejbPostCreate(<...>)

Pentru fiecare metoda ejbCreate() trebuie sa existe o metoda ejbPostCreate() care accepta exact aceeasi parametri. Metoda este apelata imediat dupa ce a fost apelata perechea ei ejbCreate().

Este apelata de container imediat dupa ce i s-a asociat bean - ului un obiect EJB. Acum poate fi terminata initializarea. Se poate face orice operatiune care necesita un obiect EJB ca de exemplu pasarea unei referinte spre obiectul EJB la alte bean - uri.

ejbActivate()

Atunci cānd un client apeleaza o metoda de business asupra unui obiect EJB si nu este nici un bean asociat cu el, containerul va lua un bean din bazin pe care-l va trece īn starea Ready. Īn cadrul acestui proces denumit activare containerul apeleaza metoda ejbActivate().

Metoda nu este apelata niciodata īn decursul unei tranzactii.

Se obtin orice resurse specifice de care are bean - ul nevoie pentru a deservi un anume client, ca de exemplu socket - uri. Nu este nevoie ca īn cadrul acestei metode sa se citeasca datele din baza de date. Aceasta se realizeaza īn cadrul metodei ejbLoad() care este apelata imediat dupa ejbActivate().

ejbLoad()

Containerul apeleaza aceasta metoda pentru a īncarca īn bean datele din baza de date pe baza starii tranzactionale curente.

Īn primul rānd se afla cheia primara a bean - ului prin apelul metodei getPrimaryKey() a EntityContext - ului. Din aceasta cheie primara a bean -ului se va determina care date trebuie īncarcate din baza de date folosind de cele mai multe ori JDBC.

ejbStore()

Containerul va apela aceasta metoda pentru a actualiza datele din baza de date cu cele din bean. Astfel se sincronizeaza datele din baza de date cu cele din bean. Starea tranzactionala curenta este utilizata de container pentru a decide cānd sa apeleze aceasta metoda. Metoda este apelata si īn timpul procesului de pasivizare exact īnainte de apelul ejbPassivate().

Se actualizeaza datele din baza de date de obicei prin JDBC. Se executa de obicei un statement de tipul "UPDATE ..." īn care se salveaza anumite atribute ale bean - ului īn tablele bazei de date.

ejbPassivate()

Containerul īnainte sa trimita bean - ul īnapoi īn bazin el va apelea aceasta metoda.

Metoda nu este apelata niciodata īn decursul unei tranzactii.

Se elibereaza orice resurse care au fost obtinute la ejbActivate() sau care depind de clientul pe care l-a deservit pāna īn prezent.

Nu trebuie salvata starea bean - ului īn baza de date deoarece containerul a apelat deja ejbStore() deci starea este deja salvata.

ejbRemove()

Distruge datele din baza de date. Nu trebuie distrusa si instanta bean - ului deoarece containerul o poate refolosi pentru alt client.

Īn primul rānd se afla cheia primara a bean - ului prin apelul metodei getPrimaryKey() a EntityContext - ului. Din aceasta cheie primara a bean -ului se va determina care date trebuiesc sterse din baza de folosind de cele mai multe ori JDBC. De obicei se vor executa statementuri de tipul "DELETE ... FROM"

unsetEntityContext()

Aceasta metoda dezasociaza un bean de mediul cu care a fost asociat la instantiere. Containerul invoca aceasta metoda exact īnainte de distrugerea bean - ului.

Se elibereaza orice resurse care au fost obtinute īn cadrul metodei setEntityContext() si se pregateste bean -ul pentru distrugerea sa de catre Java Garbage Collector.

Tabelul 2.2. Rezumatul metodelor din interfata EntityBean

2.5.3. Un exemplu de entity bean cu bean managed persistance

Acest exemplu de entity bean cu bean managed persistance prezinta un cont bancar. Acest cont bancar este stocat īntr-o baza de date īntr-un tabel account. Accesul la baza de date se face folosind JDBC. Tabelul din baza de date poate fi generat cu urmatorul script SQL. Se pastraza numele si prenumele deponentului, soldul contului si un identificator al contului. Īn cazul de fata, s-a considerat drept identificator unic pentru un client seria si numarul de buletin concatenate īntr-un sir de caractere.

Scriptul SQL pentru tabelul account

CREATE TABLE tbl_account

(id VARCHAR(30)

firstname VARCHAR(24),

lastname VARCHAR(24),

balance DECIMAL(10,2)

);

ALTER tbl_account ADD CONSTRAINT pk_account PRIMARY KEY

2.5.3.1. Clasa entity bean

Clasa entity bean - ului implementeaza metodele din interfata javax.ejb.EntityBean. Pentru accesul la baza de date se folosesc metode. Codul acestei clase este prezentat īn continuare:

Clasa AccountEJB

package exemple.entityBeanBMP;

import java.sql.*;

import javax.sql.*;

import java.util.*;

import javax.ejb.*;

import javax.naming.*;

public class AccountEJB implements EntityBean

public void debit(double amount)

throws InsufficientBalanceException

balance -= amount;

}

public String getFirstName()

public String getLastName()

public double getBalance()

//__________EntityBean interface methods ____________

public void setEntityContext(EntityContext context) catch (Exception ex)

}

public void ejbActivate()

public String ejbCreate(String id, String firstName,

String lastName, double balance)

throws CreateException

try catch (Exception ex)

this.id = id;

this.firstName = firstName;

this.lastName = lastName;

this.balance = balance;

return id;

}

public void ejbPostCreate(String id, String firstName,

String lastName, double balance)

public void ejbStore() catch (Exception ex)

}

public void ejbLoad() catch (Exception ex)

}

public void ejbRemove() catch (Exception ex)

}

public void ejbPassivate()

public void unsetEntityContext() catch (SQLException ex)

}

public String ejbFindByPrimaryKey(String primaryKey)

throws FinderException catch (Exception ex)

if (result)

else

}

public Collection ejbFindInRange(double low, double high)

throws FinderException catch (Exception ex)

if (result.isEmpty())

else

}

// ________________data base methods _______________

private void makeConnection() throws NamingException, SQLException

private void insertRow (String id, String firstName, String lastName,

double balance) throws SQLException

private void deleteRow(String id) throws SQLException

private boolean selectByPrimaryKey(String primaryKey)

throws SQLException

private Collection selectInRange(double low, double high)

throws SQLException

prepStmt.close();

return a;

}

private void loadRow() throws SQLException

else

}

private void storeRow() throws SQLException

}

} // end of AccountEJB

Pentru a crea o noua instanta de bean, containerul apeleaza costructorul bean - ului, apoi imediat el va apela setEntityContext(). Īn cadrul metodei, se stocheza contextul īn care se afla bean - ul si se obtin resursele necesare bean - ului. De remarcat ca desi īnca bean - ul nu este asociat cu un obiect EJB, totusi obtine o legatura la baza de date. Aceasta din motivul ca indiferent de obiectul EJB cu care va fi asociat bean - ul, acesta are nevoie de aceasta conexiune la baza de date, cu alte cuvinte, indiferent de contul pe care īl va reprezenta bean - ul, el va avea nevoie de conexiune. Bean - ul sta, īn acest moment, īn bazinul cu bean - uri.

Metoda ejbActivate() este apelata de catre container pentru a asocia un bean cu un obiect EJB. Bean - ul este scos din bazinul cu bean - uri si i se asociaza o cheie primara, care va fi folosita pentru a identifica datele pe care le reprezinta. Īn cazul de fata, īn corpul metodei, singura operatie realizata este setarea atributului cheie primara din bean cu cheia primara asociata de container bean - ului. Daca bean - ul n-ar fi fost proiectat sa obtina o conexiune la baza de date īn setEntityContext, aici ar fi fost locul unde s-ar fi putut realiza aceasta.

Metoda ejbCreate() din clasa bean - ului insereaza īn baza de date o noua īnregistrare cu datele primite la apelul metodei. Īnainte de a realiza inserarea īn tabelul account din baza de date, se verifica daca suma de bani ce va intra īn viitorul cont este pozitiva. Daca suma este negativa, atunci se arunca o exceptie de tipul javax.ejb.CreateException. Exceptia de tipul CreateException este de regula aruncata daca unul dintre parametrii de intrare nu este valid. Daca cheia primara exista deja, se arunca o exceptie de tipul DuplicateKeyException, care, de fapt, descinde din CreateException. Inserarea se va realiza folosind metoda insertRow(), care nu este prezentata si care realizeaza inserarea īn baza de date folosind JDBC. Dupa ce inserarea īn baza de date a reusit, fara a fi aruncate exceptii, se vor initializa variabilele membru ale clasei cu datele ce au fost inserate īn baza de date, deoarece acestea sunt datele pe care le reprezinta acest bean. La ultimul pas al metodei, se va returna cheia primara a acestei īnregistrari. Trebuie mentionat ca datele pot fi inserate īn baza de date si altfel, de exemplu prin intermediul unui script. Desi datele nu au fost introduse īn baza de date prin apelul ejbCreate(), se pot utiliza entity beans pentru a le reprezenta.

Metoda ejbPostCreate() este apelata de catre container imediat dupa ce a fost apelata metoda ejbCreate(), īnsa, spre deosebire de aceasta, ea poate invoca metoda getPrimaryKey() si getEJBObject() din interfata EntityContext. Aceasta are sens, deoarece containerul afla cheia primara doar dupa ce aceasta a fost returnata de metoda ejbCreate(). Īn cadrul metodei ejbCreate(), nu are sens apelul celor doua metode. De cele mai multe ori, metoda ejbPostCreate() va fi fara continut. Metoda respecta regulile pe care fiecare metoda ejbPostCreate() trebuie sa le respecte:

primeste exact aceiasi parametri ca si metoda ejbCreate() cu care este pereche

nu returneaza nici un parametru

este publica

Trebuie spus ca modificatorii static si final nu pot fi utilizati.

Metodele ejbLoad() si metodele ejbStore() sunt utilizate de catre container pentru a sincroniza datele din bean cu cele din baza de date. Metoda ejbLoad() reīmprospateaza atributele bean-ului cu datele din baza de date, pe cānd metoda ejbStore() salveaza datele din atributele bean - ului īn baza de date. Daca o metoda de business este asociata cu o tranzactie, atunci containerul invoca metoda ejbLoad() īnainte ca metoda sa fie executata. Dupa executia metodei de business, containerul va apela metoda ejbStore(). Deoarece apelul acestor metode este automatizat de catre container, nu este nevoie ca īn corpul metodelor de business sa se realizeze sincronizarea datelor din bean cu cele din baza de date. Cu alte cuvinte, este o greseala de īntelegere sa se apeleze īn metodele de business ejbLoad() sau ejbStore().

Daca cele doua metode nu reusesc sa gasesca datele īn baza de date, se va arunca exceptia javax.ejb.NoSuchEntityException. Aceasta este o subclasa a EJBException, care, la rāndul ei, descinde din RuntimeException, deci nu trebuie declarata īn clauza throws. Atunci cānd NoSuchEntityException este aruncata, containerul EJB o īnfasoara īntr-o exceptie de tipul RemoteException si o va trimite la client. Salvarea datelor īn baza de date se realizeaza prin apelul metodei storeRow(), iar īncarcarea lor din baza de date prin metoda loadRow().

Metoda ejbPassivate() este apelata de container pentru a dezasocia instanta bean - ului de un anume obiect EJB. Dupa apelul ei, instanta este trimisa īn bazinul cu bean - uri si nu va reprezenta practic nici un fel de date. De aceea, īn corpul metodei, s-a setat cheia primara a datelor pe care le reprezinta bean - ul cu null. Daca, pe parcursul ejbActivate(), s-ar fi obtinut anumite resurse, aici era locul unde ele trebuiau eliberate.

Metoda ejbRemove() este utilizata pentru a realiza stergerea entity beanI -ului, deci si a datelor din baza de date pe care le reprezinta. Aceasta se realizeaza prin apelul metodei deleteRow(), care prin JDBC realizeaza operatiunea de stergere a īnregistrarii din baza de date. Metoda aceasta nu este prezentata. Daca apare vreo eroare, aceasta este prinsa si se arunca o exceptie de tipul RemoveException. Trebuie mentionat ca datele pot fi sterse si altfel din baza de date, ca de exemplu folosind un script SQL.

Metoda unsetEntityContext() este apelata de container chiar īnainte ca instanta bean - ului sa fie stearsa. Din acest motiv, īn cadrul ei, se va dezasocia bean - ul de contextul sau. De regula, aici este locul unde se vor elibera resursele pe care bean - ul le-a obtinut īn metoda setEntityContext(). Īn cazul de fata, aici se va elibera conexiunea la baza de date.

Metodele utilizate pentru gasirea bean- urilor au prefixul find. Metoda ejbFindByPrimaryKey() poate fi utilizata pentru a gasi un entity bean dupa cheia primara furnizata de client. Metoda findByPrimaryKey() este obligatorie pentru orice entity bean. Aceasta metoda pare a fi ciudata, deoarece primeste si returneaza un obiect cheie primara. Trebuie remarcat ca cele doua obiecte cheie primara sunt diferite. Obiectul cheie primara primit ca parametru este cheia primara din punctul de vedere al clientului, iar cel returnat este cheia primara din punctul de vedere al containerului. Este posibil ca cele doua obiecte sa nu fie de acelasi tip. Īn mod obisnuit ele sunt identice ca īn cazul de fata. Daca nu exista un entity bean, atunci se va arunca exceptia ObjectNotFoundException. Acesta exceptie descinde din FinderException. Ea este utilizata atunci cānd o finder method returneaza o singura cheie primara.

Metoda ejbFindInRange() este utilizata pentru a gasi toate acele entity beans a caror sold din cont este īntr-un anume interval. Metoda returneaza un obiect de tipul java.util.Collection īn care sunt stocate cheile primare ale tuturor bean - urilor care satisfac cerintele impuse. Trebuie mentionat ca, folosind fiecare cheie din colectie, containerul va crea un obiect EJB. Clientul poate apela doar metoda findInRange() din interfata Remote care va returna tot o colectie, dar de obiecte EJB. Īn cadrul metodei ejbFindInRange(), se foloseste metoda de acces la baza de date findInRange(). Aceasta metoda obtine toate cheile primare ale conturilor, care au soldul īn intervalul specificat si le adauga īntr-un obiect de tipul ArrayList. Obiectul de tipul ArrayList implementeaza interfata Collection, motiv pentru care poate fi returnat cu succes de catre metoda.

Metodele de business contin logica de business a bean - ului. De obicei, metodele de business nu acceseaza baza de date. Astfel se realizeaza separea logicii de business de codul de acces la baza de date. Aceasta separare este foarte utila, deoarece permite componentelor sa fie utilizate īmpreuna cu alta baza de date fara a fi nevoie sa fie facuta vreo modificare īn metodele de business. Metodele de business realizeaza exact ceea ce le spune si numele: cu metoda credit() se depun bani īn cont, iar cu metoda debit() se extrag bani din cont.

Metodele de acces la baza de date pot fi accesate doar īn interiorul clasei. Ele utilizeaza JDBC 2.0. pentru a realiza accesul la baza de date, inserarea, gasirea, stergerea datelor etc. Pentru obtinerea conexiunii la baza de date se utilizeaza serviciul JNDI, cu care se obtine un obiect de tipul DataSource, care este un factory de conexiuni la baza de date.

Īn cadrul clasei bean - ului, este utilizata exceptia InsufficientBalanceException care este prezentata īn continuare.

Clasa InsufficientBalanceException

public class InsufficientBalanceException extends Exception

public InsufficientBalanceException(String msg)

2.5.3.2. Interfata Home

Interfata Home defineste metodele pe care le foloseste clientul pentru crearea si gasirea entity bean - urilor.

Interfata Home pentru beanul Account

package exemple.entityBeanBMP;

import java.util.Collection;

import java.rmi.RemoteException;

import javax.ejb.*;

public interface AccountHome extends EJBHome

Metodele create... din interfata Home trebuie sa aiba aceiasi parametri ca perechea lor ejbCreate... din clasa bean - ului. Ele vor returna un obiect de tipul interfetei Remote a bean - ului. Exceptiile aruncate de o metoda de create sunt identice cu cele pe care le poate arunca metodele ejbCreate... si ejbPostCreate... cu care este pereche. Obligatoriu trebuie aruncate exceptiile javax.ejb.CreateException si java.rmi.RemoteException. Īn cazul de fata, pentru unica metoda de create pe care o avem toate aceste conditii sunt satisfacute.

La fel, metodele find... vor primi aceiasi parametri ca perechile lor ejbFind... din clasa bean - ului. O metoda find... poate īntoarce un obiect de tipul interfetei a bean - ului, cum este cazul metodei findByPrimaryKey() sau poate returna o colectie cu astfel de obiecte, cum este cazul metodei findInRange(). Exceptiile aruncate sunt cele pe care le arunca metoda pereche din clasa bean - ului. Obligatoriu trebuiesc aruncate exceptiile javax.ejb.FinderException si java.rmi.RemoteException.

2.5.3.3. Interfata Remote

Interfata Remote defineste toate metodele de business pe care un client le poate invoca. Ea extinde interfata javax.ejb.EJBObject. Fiecare metoda din interfata Remote trebuie sa aiba antetul identic cu cel al metodei din clasa bean - ului si obligatoriu sa arunce exceptia java.rmi.RemoteException. Tipurile de date returnate de metodele de business trebuie sa fie valide RMI, cu alte cuvinte sa fie serializabile. Tipurile primitive de date sunt valide RMI, deoarece pot fi serializate.

Interfata Remote pentru beanul Account

package exemple.entityBeanBMP;

import javax.ejb.EJBObject;

import java.rmi.RemoteException;

public interface Account extends EJBObject

2.5.3.4. Un client pentru componenta Account

Clientul pentu entity bean - ul Account foloseste serviciul JNDI pentru a gasi interfata Home a bean - ului, apoi creeaza doua conturi. Cheia primara pentru aceste conturi este seria buletinului fiecarui posesor al contului. Se creeaza doua conturi īn care se depun si se extrag niste sume.

Client pentru beanul Account

package exemple.entityBeanBMP;

import javax.ejb.*;

import javax.naming.*;

import java.rmi.*;

import java.util.*;

public class Client extends Object

// .. retragere din contul lui Mihai 150 (mai mult decat soldul) ..

// .. se va arunca exceptia InsufficientBalanceException ..

trycatch(InsuffiecientBalanceException ibex)

} catch(Exception ex)

}// end of main

}// end of Client class

Pentru ca exemplul sa poata fi rulat, este necesar ca, la deployment - ul componentei īn serverul J2EE, sa se specifice numele JNDI AccountHome. Daca nu se specifica exact acest nume nu se va ridica o exceptie īn codul clientului la gasirea componentei folosind JNDI. Deployment - ul unei aplicatii nu este ceva complicat, īnsa, pentru fiecare server J2EE se face altfel. Pentru implementarea de referinta de la Sun, exista cāteva exemple īn care se arata cum se instaleaza serverul J2EE si cum se face deployment - ul unei aplicatii.

Serverul J2EE de referinta este gratis pentru utilizari necomerciale si poate fi obtinut de la adresa: https://java.sun.com/j2ee/j2sdkee/ . El poate fi instalat pe Windows NT 4, Windows 2000, Linux, Solaris. Kitul pentru Windows are aproximativ 12MB.

Instructiunile de instalare pot fi gasite la adresa: https://java.sun.com/j2ee/j2sdkee/install.html.

Exemple de aplicatii si deployment - ul lor pot fi gasite la adresa:

https://java.sun.com/j2ee/j2sdkee/techdocs/guides/ejb/html/DevGuideTOC.html

sau pentru download īn format PDF la adresa: https://java.sun.com/j2ee/j2sdkee/devguide1_2_1.pdf

2.5.4. Un exemplu de entity bean cu container managed persistance

Exemplul īsi propune stocarea unor produse care au un indentificator unic, o descriere si un pret. Toate aceste date vor fi stocate de catre container īntr-o baza de date proprie. Baza aceasta de date ar putea fi una obiectuala, oricum acest aspect nu este important pentru aplicatiile care folosesc container managed persistance. Programatorul scapa de scrierea codului legat de accesul la baza de date. Acest cod va fi generat de catre container, īnsa programatorul va trebui sa specifice care atribute ale bean - ului trebuie sa fie stocate. Atributele bean - ului, care vor fi stocate īn baza de date de catre container, se numesc container managed fields.

2.5.4.1. Clasa entity bean - ului

Cāmpurile bean - ului care vor fi gestionate de catre container sunt productId, description si price. Aceste cāmpuri vor fi specificate folosind deployment tool. Containerul poate gestiona doar cāmpuri care sunt de un tip primitiv Java, clasa serializabila, referinta la o interfata Home sau o referinta la o interfata Remote. Un cāmp gestionat de container trebuie sa aiba specificatorul de acces public si sa nu fie definit cu specificatorul transient, fiindca nu va putea fi serializat. Clasa entity bean - ului este urmatoarea:

Clasa entity bean-ului product

package exemple.entityBeanCMP;

import java.util.*;

import javax.ejb.*;

public class ProductEJB implements EntityBean

public double getPrice()

public String getDescription()

public String ejbCreate(String productId, String description,

double price) throws CreateException

this.productId = productId;

this.description = description;

this.price = price;

return null;

}

public void setEntityContext(EntityContext context)

public void ejbActivate()

public void ejbPassivate()

public void ejbRemove()

public void ejbLoad()

public void ejbStore()

public void unsetEntityContext()

public void ejbPostCreate(String productId, String description,

double balance)

} // ProductEJB

Metodele setEntityContext() si unsetEntityContext() au exact aceeasi utilizare ca si īn cazul bean managed persistance. Īn cazul de fata metodele nu contin nici un fel de cod, deoarece bean - ul nu are nevoie de resurse. Īn exemplul Account, deoarece se utiliza bean managed persistance, se obtinea o conexiune la baza de date.

Metoda ejbCreate() initializeaza cāmpurile gestionate de container cu valoarea parametrilor de intrare. Metoda returneaza null, deoarece containerul ignora valoarea de return atunci cānd se utilizeaza container managed persistance. Dupa executia metodei ejbCreate(), containerul insereaza datele īn baza de date.

Metoda ejbPostCreate() este apelata imediat dupa ejbCreate() de catre container si are aceeasi semnificatie ca la bean managed persistance. Īn cazul de fata, ea nu contine cod.

Metoda ejbActivate() are rolul neschimbat si realizeaza activarea bean - ului, ocazie īn care se obtine de la EntityContext cheia primara asociata īn momentul īn care bean - ul a fost asociat cu obiectul EJB. Aceasta cheie primara este pastrata īntr-un atribut al bean - ului.

Metoda ejbStore() realizeaza sincronizarea datelor din baza de date cu cele din bean, nu si stocarea datelor īn baza de date, deoarece aceasta va fi realizata de catre container imediat dupa apelul acestei metode. Īn corpul metodei, ar trebui pregatite datele pentru stocare īn baza de date, de exemplu pentru un text s-ar putea realiza comprimarea sa.

Metoda ejbLoad() care realizeaza sincronizarea datelor din bean cu cele din baza de date va trebui sa pregateasca datele citite din baza de date de catre container pentru prelucrare. De exemplu, ar putea decomprima un text care a fost salvat īn baza de date sub forma comprimata.

Metoda ejbPassivate() are acelasi rol, iar, īn cadrul ei, se marcheaza dezasocierea bean - ului de obiectul EJB cu care era asociat mai īnainte. Dezasocierea se realizeaza prin setarea cheii primare cu null. Tot aici se realizeaza si curatarea cāmpurilor de datele pe care le-au reprezentat mai īnainte. Pretul este lasat, deoarece nu poate fi setat la null, deci, oricum, nu poate fi curatat.

Metoda ejbRemove() este aplelata de catre container pentru a permite programatorului sa faca toate operatiunile premergatoare stergerii datelor din baza de date. Datele vor fi sterse de catre container imediat dupa ce s-a executat metoda ejbRemove(). Daca containerul va īntāmpina dificultati īn stergerea datelor, se va arunca o exceptie de runtime, care nu trebuie declarata īn clauza throws.

2.5.4.2. Interfata Home

Interfata Home respecta aceleasi reguli ca si īn cazul persistentei gestionate de bean. Se observa ca īn interfata apar metode de find care nu au nici un corespondent ejbFind... īn clasa bean - ului. Codul pentru aceste metode este generat de catre container, folosind deployment tool.

Interfata Home a    bean-ului product

package exemple.entityBeanCMP;

import java.util.Collection;

import java.rmi.RemoteException;

import javax.ejb.*;

public interface ProductHome extends EJBHome

Metoda findByPrimaryKey() este implementata īn totalitate de catre deployment tool, inclusiv fraza de select care aduce un rānd din baza de date. Celelalte doua metode utilizate pentru gasirea datelor sunt: findByDescription() si findInRange(). Ambele metode sunt implementate de catre container, īnsa clauza where din fraza de select este specificata de catre programator. Dupa cum se poate observa, aceste metode nici macar nu apar īn clasa bean - ului, codul lor fiind gestionat de catre container.

2.5.4.3. Interfata Remote

Interfata Remote expune toate metodele de business ale bean - ului.

Interfata Remote a    bean-ului product

package exemple.entityBeanCMP;

import javax.ejb.EJBObject;

import java.rmi.RemoteException;

public interface Product extends EJBObject

2.5.4.4. Client pentru bean - ul Product

Pentru ca exemplul sa poata fi verificat, se poate folosi codul client prezentat īn continuare.

Codul client pentru bean - ul    ProductEJB

package exemple.entityBeanCMP;

import java.util.*;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.rmi.PortableRemoteObject;

public class Client

// .. afisarea tuturor obiectelor cu pretul intre 5 si 10

c = home.findInRange(5.00, 10.00);

i = c.iterator();

while (i.hasNext())

} catch (Exception ex)

}

Pentru ca exemplul sa poata fi rulat, este necesar ca la deployment - ul componentei īn serverul J2EE sa se specifice numele JNDI: "ProductHome". Daca nu se specifica exact acest nume, nu se va putea gasi componenta.

Serverul J2EE de referinta este gratis pentru utilizari necomerciale si poate fi obtinut de la adresa: https://java.sun.com/j2ee/j2sdkee/ . El poate fi instalat pe Windows NT 4, Windows 2000, Linux, Solaris. Kitul pentru Windows are aproximativ 12MB.

Instructiunile de instalare pot fi gasite la adresa: https://java.sun.com/j2ee/j2sdkee/install.html.

Exemple de aplicatii si deployment - ul lor pot fi gasite la adresa:

https://java.sun.com/j2ee/j2sdkee/techdocs/guides/ejb/html/DevGuideTOC.html

sau pentru download īn format PDF la adresa: https://java.sun.com/j2ee/j2sdkee/devguide1_2_1.pdf


Document Info


Accesari: 1402
Apreciat: hand-up

Comenteaza documentul:

Nu esti inregistrat
Trebuie sa fii utilizator inregistrat pentru a putea comenta


Creaza cont nou

A fost util?

Daca documentul a fost util si crezi ca merita
sa adaugi un link catre el la tine in site


in pagina web a site-ului tau.




eCoduri.com - coduri postale, contabile, CAEN sau bancare

Politica de confidentialitate | Termenii si conditii de utilizare




Copyright © Contact (SCRIGROUP Int. 2024 )