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: 1491
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. 2025 )