programmera.net -> ejb -> normal     för utskrift      info@programmera.net

Livscykeln för en CMP entitetsböna

1. Livscykel
2. Initiering
3. Aktivering
4. Passivering
5. Skapa en entitet
6. Ta bort en entitet
7. setEntityContext()
8. unsetEntityContext()
9. ejbFindX()
10. ejbHomeX()
11. ejbSelectX()
12. ejbActivate()
13. ejbPassivate()
14. ejbCreateX(X x)
15. ejbPostCreateX()
16. ejbRemove()
17. ejbLoad()
18. ejbStore()

1. Livscykel

På denna sida går vi igenom en CMP entitetsbönans olika tillstånd och de "callback"-metoder som behållaren aropar på instansen då instansen går från ett tillstånd till ett annat.

  • CMP: Allt som står på denna sida gäller för entitetsbönor som utnyttjar CMP (Container Managed Persistence). BMP fungerar annorlunda, där används t.ex. "ejbLoad()" och "ejbStore()" för att implementera själva läsandet och skrivandet till databasen.
En entitetsböna har den mest komplicerade livscykeln av alla böntyper. Bilden nedan visar hur en entitetsböna fungerar:



De olika tillstånden beskrivs nedan:
  1. DOES NOT EXIST: Detta tillstånd betyder att instansen inte existerar. Avsnittet nedan märkt initiering beskriver hur en instans skapas.
  2. POOLED: Detta tillstånd innebär att instansen existerar men inte har någon enititet från databasen knuten till sig. När användaren gör ett anrop mot poolen kan vilken instans som helst utföra metoden. Behållaren kan anropa vissa metoder på instansen i detta tillstånd, nämligen "ejbHomeX()", "ejbFindX()" och "ejbSelectX()"-metoder. (Inget av dessa metodanrop får instansen att byta tillstånd). Det vanligaste sättet för en instans att hamna i METHOD READY är via aktivering. Instansen kan också hamna i METHOD READY genom att klienten skapar en entitet (orden i fetstil beskrivs i egna avsnitt nedan).
  3. METHOD READY: I detta tillstånd har instansens persistenta fält samma värden som entiteten i databasen. Instansen har också den primära nyckeln tillgänglig via "EntityContext"-objektet. I detta tillstånd kan instansen exekvera affärsmetoder. Behållaren kan anropa "ejbLoad()" och "ejbStore()" godtyckligt på instansen. Oftast går instasen tillbaka till poolen genom passivering. Instansen går också tillbaka till poolen om klienten tar bort entiteten (orden i fetstil beskrivs i egna avsnitt nedan).
  4. METHOD READY IN TRANSACTION: Detta tillstånd innebär att instansen befinner sig mitt i ett metodanrop. Märk att eftersom en entitetsböna alltid är av typen CMT så startar behållaren automatiskt en transaktion åt instansen då en affärsmetod anropas (om metoden kräver en transaktion). Behållaren kan inte passivera en instans som är i detta tillstånd. Om metoden kastar ett "System Exception" kommer instansen att gå direkt till DOES NOT EXIST och således hoppa över alla callbackmetoder som normalt skulle ha anropats på vägen till DOES NOT EXIST.

2. Initiering

Då servern startas skapar behållaren själv upp ett antal instanser av bönan och placerar dessa i en pool. Servern bestämmer själv hur många instanser som ska vara i poolen. När behållaren tycker att fler instanser behövs kommer fler att skapas upp. När en entitetsböna instansieras sker följande:

  1. newInstance() En ny instans skapas genom att newInstance() anropas på den meddelandedrivna bönan.
  2. setEntityContext() anropas på den nya instansen.
  3. Instansen placeras i poolen.

3. Aktivering

Aktivering innebär att instansen byter tillstånd från POOLED till METHOD READY. Tänk dig att en klient anropar en affärsmetod på "EJBObject" (som klienten har fått genom att anropa "findByPrimaryKey()"). Behållaren letar nu efter en instans av entitetsbönan som befinner sig i tillståndet METHOD READY och har samma primära nyckel som den anropande "EJBObject". Om ingen sådan instans hittas kommer behållaren att aktivera en instans i poolen. Aktivering innebär följande:

  1. Skapa en instans av "EJBObject", om det inte redan finns en.
  2. Skapa en primär nyckel och placera den i instansens "EntityContext"-objekt.
  3. Anropa "ejbActivate()".
  4. Fylla instansens persistenta fält med data från databasen.
  5. Anropa "ejbLoad()".
Nu har instansen nått tillståndet METHOD READY.

4. Passivering

Passivering är motsatsen till aktivering, d.v.s. instansen går från METHOD READY till POOLED. Passivering sker när behållaren vill spara resurser och anser att instansen inte behöver hålla entitetens data längre (det är upp till tillverkaren av behållaren att avgöra när passivering ska ske). Passivering innebär följande:

  1. Anropa "ejbStore()".
  2. Skriv instansens data till databasen.
  3. Anropa "ejbPassivate()".
Nu har instansen tillståndet POOLED.

5. Skapa en entitet

Att skapa en entitet innebär att entiteten läggs till i databasen. Detta sker då klienten anropar "createX()" på sin referens av "EJBHome". Följande sker:

  1. Behållaren väljer (slumpvis) ut en instans ur poolen.
  2. Anropa "ejbCreateX(X x)" på den valda instansen (med samma parametrar som klienten skickade). Detta anrop resulterar i att en primär nyckel skapas.
  3. Lagra instansens data till i databasen.
  4. Skapa en instans av "EJBObject".
  5. Tilldela "EJBObject" entitetens primära nyckel.
  6. Tilldela "EntityContext" entitetens primära nyckel.
  7. Anropa "ejbPostCreateX()".
  8. En stubbe av "EJBObject" skickas till klienten.
Nu har instansen tillståndet METHOD READY.

6. Ta bort en entitet

Att ta bort en entitet innebär att entiteten tas bort ur databasen. En entitet tas bort då klienten anropar "remove()" på motsvarande "EJBObject". Följande sker:

  1. Synkronisering mot databasen. Anledningen till denna synkronisering är att man kanske måste utföra "cascade delete" (och då måste instansen ha färska data).
  2. Kanske (!) anropa "ejbStore()" (detta verkar vara upp till severtillverkaren, se Manning).
  3. Anropa "ejbRemove()".
  4. Placera instansen i poolen.
  5. Radera datat i databasen.
Nu har instansen tillståndet POOLED.

7. setEntityContext()

Anropas av behållaren i samband med att bönan initieras. I denna metod ska du se till att instansen lagrar EntityContext någonstans, vanligtvis i en medlemsvariabel:
public void setEntityContext(EntityContext ctx){
	// Save the context	
	this.context = ctx;
}	
Nu kan du komma åt alla metoder som exponeras i EntityContext via medlemmen "context".

8. unsetEntityContext()

Anropas av behållaren i samband med att bönan tas ur poolen och raderas ur minnet. Denna metod har samma funktion som "ejbRemove()" för en stateless session bean. I denna metod ska du frigöra eventuella resurser som bönan knutit upp.

9. ejbFindX()

Metoden Motsvaras av en "findX()"-metod i "Home"-gränssnittet som alltså anropas av klienten. En "ejbFindX()"-metod kör alltid en SELECT-sats mot databasen. Metoden returnerar en eller flera referenser till instanser av "EJBObject". Det existerar inga motsvarande instanser av entitetsbönor för de returnerade "EJBObject"-referenserna. Det är först när någon anropar en metod på referensen som en entitet läses upp ur databasen. Följande exempel förklarar hur det går till:

  1. Klienten anropar "findByPrimaryKey("7")" på "EJBHome".
  2. Behållaren väljer (slumpvis) ut någon instans ur poolen och anropar "ejbFindByPrimaryKey("7")" på den.
  3. Instansen gör en SELECT mot databasen för att hitta raden med PK=7. Om den ej hittas kastas "ObjectNotFoundException".
  4. Om raden hittas skapar behållaren en instans av "EJBObject" och tilldelar den PK=7.
  5. En stubbe av "EJBObject"-instansen returneras till klienten.
  6. Klienten anropar en affärsmetod på "EJBObject" referensen.
  7. Behållaren väljer (slumpvis) ut en instans ur poolen och aktiverar den enligt beskrivningen av aktivering ovan.
  8. Behållaren anropar affärsmetoden på instansen.
Märk att:
  • OBS: Entitetsbönor med CMP vare sig implementerar eller deklarerar "ejbFindX()"-metoden i bönan, utan allt görs av behållaren. De implementeras istället i "ejb-jar.xml" med hjälp av EJB-QL.

10. ejbHomeX()

Denna typ av metod kallas för "home business"-metod. Den motsvaras av en "X()"-metod (där X står för någon textsträng) i "Home"-gränssnittet. Denna metod ska innehålla funktionalitet som inte är knutet till någon speciell böna, och påminner mycket om "ejbFindX()"-metoden. "home business"-metoder finns till för att användaren ska kunna utföra operationer på databasen som till skillnad från "ejbFindX()"-metoder inte skapar och returnerar några "EJBObject". En "ejbHomeX()"-metod utnyttjar i typfallet en "ejbSelectX()"-metod för att göra en eller flera SELECT, men manipulerar sedan svaret innan det returneras till klienten.

  • Till exempel: Tänk dig att du vill beräkna hur många kunder i databasen som har köpt mer än 5 produkter. Om du använder en "ejbFindX()" metod för att göra denna beräkning kommer den att returnera en Collection med referenser till "EJBObject", en för varje relevant kund. Om du istället använder en "ejbHomeX()"-metod kan du få svaret som en siffra (som beskriver antalet kunder som har köpt mer än 5 produkter).

11. ejbSelectX()

Motsvaras inte av någon metod i "Home"- eller komponentgränssnittet eftersom denna hjälpmetod bara kan anropas inifrån bönan. Precis som "ejbFindX()"-metoden används "ejbSelectX()" för att utföra en SELECT mot databasen. Följande metoder kan anropa "ejbSelectX()":

  1. Affärsmetoder.
  2. "ejbHomeX()".
  3. "ejbLoad()".
  4. "ejbStore()".
Märk att:
  • Precis som för "ejbFindX()" implementeras metoden "ejbSelectX()" av dig i "ejb-jar.xml" med hjälp av EJB-QL. Däremot ska metoden (till skillnad från "ejbFindX()") också finnas deklarerad som "abstract" i bönan.

12. ejbActivate()

Anropas av behållaren innan instansen har aktiverats (se beskrivningen ovan). Här får programmeraren en möjlighet att initiera resurser som kan användas då instansen ligger i tillståndet METHOD READY.

13. ejbPassivate()

Anropas efter att behållaren passiverat instansen tillbaka till poolen. Här får programmeraren ett tillfälle att frigöra alla resurser som instansen har knutit upp i "ejbActivate()".

14. ejbCreateX(X x)

Denna metod anropas av behållaren innan entiteten skapas. Denna metod ansvarar för att alla parametrar (X) som klienten skickar med i sitt anrop "createX(X x)" faktiskt lagras i instansen. När du implementerar denna metod ska du vara medveten om att:

  • Du MÅSTE lagra alla parametrar som bygger upp den primära nyckeln.
  • Det är rekommenderat att du returnerar "null" istället för den primära nyckeln, detta trots att metoden är deklarerad att returnera den primära nyckeln. Om alla persistenta fält (som motsvarar den primära nyckeln) är satta kommer behållaren själv skapa den primära nyckeln.

15. ejbPostCreateX()

Denna metod anropas av behållaren efter att entiteten har skapats.

16. ejbRemove()

Denna metod anropas av behållaren innan raden i databasen raderas. Här kan programmeraren göra vissa kontroller för att undersöka om det finns någon anledning att inte ta bort entiteten.

17. ejbLoad()

Anropas direkt efter att behållaren har laddat instansen med färskt data från databasen. Detta kan ske vid godtycklig tidpunkt av behållaren. Vi är garanterade att "ejbLoad()" anropas av behållaren efter att instansen aktiverats. Instansens persistenta fält har nu laddats med data och programmeraren har i denna metod möjlighet att göra eventuella kontroller av dessa fält.

18. ejbStore()

Anropas precis innan behållaren skriver instansen till databasen. Detta kan ske vid godtycklig tidpunkt av behållaren. Vi är garanterade att "ejbStore()" anropas innan behållaren passiverar instansen tillbaka till poolen. Här får programmeraren ett tillfälle att uppdatera bönans persistenta fält innan de skrivs till databasen.