Bez ohľadu na to, akú perzistentnú metódu si vyberiete pre danú entitu, vždy musíte implementovať rozhranie EntityBean. Z toho okrem iného vyplýva, že vždy musíte implementovať tie isté CCM metódy. Rozdiel je iba v tom, za čo ste zopovední pri implementácii ich obsahu. Jedinou výnimkou je implementácia vyhľadávacích metód, ktoré nie sú povinné pri CMP perzistencii.

Základným obmedzením pri implementácii CCM (Container Callback Methods) metód je, že ich nemôžete označiť ako static alebo final. Asi už tušíte, že je to dané tým, že EJB kontajner musí mať možnosť tieto metódy preťažiť pri implementácii vašej abstraktnej entitnej triedy. Ako ešte uvidíte, vačšina CCM metód sa implementuje ako „nerob-nič“ metóda. Preto je celkom dobrým nápadom vytvoriť si vlastnú abstraktnú triedu, ktorá by poskytovala prázdnu implementáciu CCM metód. Od tejto triedy by ste potom dedili všetky vaše CMP entitné triedy. Napríklad trieda AbstractEntity, ktorú sme si predstavili už skôr pri BMP entitách, je toho veľmi dobrým príkladom.

Priradenie objektu EntityContext

Kontajner priraďuje objekt EntityContext ku konkrétnej entite počas jej prvotného vytvárania. Rovnako ako pri BMP ste zodpovední za implementáciu nasledovných dvoch metód:

public void setEntityContext(EntityContext ctx)
 throws EJBException, RemoteException;
public void unsetEntityContext()
 throws EJBException, RemoteException;

Z pohľadu životného cyklu inštancie každého beanu je možné tieto metódy použiť na alokovanie a dealokovanie zdrojov, ktoré sú zdieľané všetkými inštanciami entitnej triedy. Avšak nemôžete tu alokovať zdroje špecifické pre jednu konkrétnu entitu, pretože jej inštancia môže byť znovu použitá bez toho, aby kontajner zavolal metódu setEntityContext. Väčšinou aj tak nebude treba robiť nič špeciálne v rámci týchto metód a obvykle stačí jednoduchá implementácia, ako je uvedené v nasledujúcej ukážke:

public abstract class EnglishAuctionCMPBean
 implements EntityBean {
 //…
 EntityContext ctx;
 //…
 public void setEntityContext(EntityContext ctx) {
  this.ctx = ctx;
 }
 public void unsetEntityContext() {
  ctx = null;
 }
 //…
}

Vytváranie a odstraňovanie entít (ejbCreate, ejbRemove)

V rámci každej deklarovanej entity musíte pre každú create metódu deklarovanú v home rozhraní, implementovať aj metódu ejbCreate. Pri použití BMP musí táto ejbCreate metóda vykonať potrebné inicializačné úlohy vrátane zápisu do databázy. Pri CMP vám starosť o prístup do DB odpadá, avšak kontajner preto volá túto metódu, aby vám dal šancu nastaviť určité inicializačné parametre.

Nasledovný kód zobrazuje príklad CMP implementácie metódy ejbCreate:

public Integer ejbCreateWithData(String name,
  String description)
  throws CreateException {
 // vyhodenie výnimky ak meno nie je validné
 if ((name == null) | (name.trim().length() == 0)) {
  throw new CreateException(„Cannot create an auction without a name“);
 }
 // inicializuje objekt entity pred jeho vložením do DB
 setNameField(name);
 setDescriptionField(description);
 // v tejto metóde treba vždy vrátiť null (pri CMP)
 return null;
}

Všimnite si, že metóda ejbCreateWithData vracia null. V prípade BMP by musela vrátiť primárny kľúč, ktorý bol priradený novo vzniknutému objektu entitnej triedy. Avšak pri CMP musí vždy vrátiť null a nechať priradenie primárneho kľúča na EJB kontajner. Potom, čo kontajner zavolá vašu ejbCreate metódu a uloží objekt (respektíve jeho primárny kľúč), zavolá vašu metódu ejbPostCreate. Podobne ako pri BMP do tela tejto metódy sa obvykle vkladá inicializácia, ktorej priebeh závisí od hodnoty primárneho kľúča entitného objektu, ktorému bol priradený. Toto je zároveň jediný bod celého procesu vytvárania entity, kedy môžete asociovať objekty priradené k CMR poliam.

V prípade objektu AuctionBidBean je potrebné pri vytváraní definovať CMR vzťah s aukciou a dražiteľom. Napríklad nasledovne:

public void ejbPostCreate(EnglishAuction newAuction,
  Bidder newBidder, Timestamp newDateTimeSubmitted,
  Double newAmount, String newTransactionId) {
 // iba v tejto metóde môžu byť CMR polia nastavované
 setAuction(newAuction);
 setBidder(newBidder);
}

Životný cyklus každej entity zahŕňa nielen metódy na jej vytvorenie, ale aj na odstránenie. Keď klient zavolá remove metódu na odstránenie entity, kontajner vykoná metódu ejbRemove ešte predtým, ako vymaže konkrétne dáta z databázy. Vy môžete vyhodiť výnimku RemoveException a zabrániť tak vymazaniu, ale nie ste zodpovední za vytvorenie samotného príkazu na vymazanie z podkladovej databázy. Účelom volania metódy ejbRemove je možnosť najprv uvolniť zdroje držané inštanciou. Po ukončení tejto metódy EJB kontajner danú entitu odstráni z podkladovej databázy, ako aj zo všetkých referencií na ňu naviazaných.

Načítanie a ukladanie stavu entity (ejbLoad, ejbStore)

Kedykoľvek, keď kontajner načítava stav objektu entity z databázy, tento process zahŕňa aj volanie metódy ejbLoad nad jeho inštanciou. Toto miesto je obvykle vhodné na aktualizáciu stavu premenných inštancie deklarovaných v entitnej triede, ktorých hodnota je závislá od hodnoty perzistentných polí entitného objektu. Presne opačne je to s metódu ejbStore, ktorú kontajner zavolá ešte predtým, ako zapíše stav entity do databázy. Aj použitie tejto metódy je v podstate opačné a obvykle sa môže využiť na aktualizáciu stavu perzistentných polí, ktorých hodnota je vo vzťahu s premennými inštancie.

Avšak príliš často sa opísané použitie v praxi neuplatňuje. Vo väčšine prípadov sa stretnete s prázdnou implementáciou týchto metód.

Aktivácia a pasivácia entity (ejbActivate, ejbPassivate)

V čase, keď sa EJB kontajner pripravuje preniesť entitu do stavu pripravenosti, zavolá jej metódu ejbActivate. A to ešte predtým ako sa zavolá metóda ejbLoad. Účelom metódy ejbActivate je umožniť načítanie akýchkoľvek zdrojov vyžadovaných inštanciou entity. A podobne, kedykoľvek sa kontajner rozhodne pasivovať inštanciu entity, zavolá metódu ejbStore a následne aj ejbPassivate. V tejto metóde by ste mali uvolniť všetky zdroje, ktoré boli v aktivačnej metóde načítané.

Implementácia home metód

V rámci implementácie home metód existujú určité obmedzenia, ktoré vám neumožňujú pristupovať k premenným alebo metódam inštancie. Je to dané tým, že tieto metódy nie sú asociované s konkrétnym entitným objektom v čase vykonávania. V prípade CMP beanu to znamená, že nemôžete volať CMP alebo CMR get/set metódy v rámci vašich home metód.

Rozhranie EnglishAuctionHome, vytvorené v predchádzajúcich článkoch, obsahuje aj nasledovnú home metódu:

public Collection getItemsBeingAuctioned();

Túto metódu potom možete implementovať napríklad nasledovne:

public Collection ejbHomeGetItemsBeingAuctioned() {
 try {
  return ejbSelectAuctionedItems();
 }
 catch (FinderException e) {
  return null;
 }
}

V tomto príklade vráti home metóda kolekciu referencií na lokálne rozhranie Item, ktoré korešpondujú so všetkými položkami aktuálne priradenými k aukciám. Všimnite si, že implementačné detaily sú delegované na metódu ejbSelectAuctionedItems. Táto výberová metóda je unikátnym prvkom CMP beanov. V prípade BMP sa s nimi nestretnete.

Výberové metódy (select methods) vám umožňujú dopytovať databázu a žiadať informácie o stave entity, respektíve objektov, s ktorými je v CMR vzťahu pomocou frameworku poskytovaného EJB kontajnerom. Výberové metódy sú niečo ako lookup metódy pri BMP, ale s tým rozdielom, že sú implementované priamo kontajnerom a nie tvorcom beanov. Tiež pre ne platí, že ich nemôžete poskytnúť v home rozhraní entitnej triedy, sú určené iba na vnútorné potreby CMP beanov. Jediný kód, ktorý musíte vytvoriť, je abstraktná deklarácia v tele triedy a názov výberovej metódy musí začínať na ejbSelect.

Výberová metóda použitá v implementácii home metódy ejbHomeGetItemsBeingAuctioned bude teda deklarovaná nasledovne:

public abstract Collection ejbSelectAuctionedItems() throws FinderException;

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět