Az Enterprise JavaBeanek (EJB) moduláris vállalati alkalmazásokban az üzleti logika megvalósításához használt szerveroldali komponensek. Működtetésükhöz egy EJB konténer szükséges, ami általában egy Java EE alkalmazásszerverben fut. Az EJB specifikációt eredetileg az IBM adta ki 1997-ben. Később, 1999-ben, a Sun Microsystems is elfogadta, alkalmazta (EJB 1.0 és 1.1), és tovább terjesztették a Java Community Process alatt mint JSR19, JSR152, JSR220 és JSR318.
Története Az EJB 1.0 specifikációt az IBM fejlesztette ki 1997-ben, majd a Sun Microsystems 1999-ben adoptálta.J2EE Design and Development, © 2002 Wrox Press Ltd., p. 5. A Java Community Process keretében fejlesztették tovább specifikációt és Java Specification Request dokumentumokként kerültek nyilvánosságra az újabb verziók: VerzióSpecifikációKiadás éveEJB 1.01998EJB 1.11999EJB 2.0JSR 192001EJB 2.1JSR 1532003EJB 3.0JSR 2202006EJB 3.1JSR 3182009EJB 3.2JSR 3452013
EJB Specifikáció Az EJB specifikációt arra tervezték, hogy egy alapvető módszer legyen a vállalati alkalmazásokban levő back-end üzleti kódok megvalósítására. Ezekben a kódokban gyakran ugyanazok a hibák jelentek meg, és ezeket a problémákat a programozók újra és újra ugyanúgy oldották meg. Az EJB-t arra hozták létre, hogy kezelje a perzisztenciát, a tranzakciók integritását és az adatvédelmet úgy, hogy a programozók szabadon koncentrálhassanak a megoldandó problémákra.
Az EJB specifikáció részletezi egy alkalmazás szolgáltatásait: Tranzakciókezelés Integráció a Java Persistence API által nyújtott perzisztenciaszolgáltatással Konkurenciakezelés Események kezelése a Java Message Service-zel, és a Java EE Connector Architecture használatával Aszinkron metódushívás Feladatütemezés Elnevezési- és könyvtár szolgáltatások (JNDI) Távoli eljáráshívás RMI-IIOP és webszolgáltatásokon keresztül Biztonság (Java Cryptography Extension (JCE) és JAAS) Szoftver komponensek telepítése alkalmazásszerverre
Mi több, az EJB specifikáció azokat a kötelességeket írja le, amit az EJB konténer és maga az EJB tartalmaz, mint ahogy azt is, hogyan kell telepíteni az EJB konténert. Megjegyzendő, hogy a jelenlegi EJB specifikáció nem részletezi többé, hogy egy alkalmazás hogyan gondoskodik a perzisztenciáról (egy olyan feladatról, ami a JPA specifikáció delegáltja), de ehelyett részletezi, hogy az üzleti logika könnyedén integrálható a perzisztencia szolgáltatásokkal, amiket a kiszolgáló alkalmazás nyújt.
A megjelenés utáni csalódás A problémák gyorsan előkerültek, ennek következtében az EJB hírneve kopni kezdett. Néhány API fejlesztő úgy gondolta, hogy az EJB API-ja sokkal összetettebb, mint amihez hozzá voltak szokva. A rengeteg ellenőrzött kivétel, igényelt interfész és a bean osztályok absztrakt osztályként való implementálása szokatlan és természetellenes volt a legtöbb programozó számára. Ismert, hogy az EJB szabvány nagyon összetett problémákat próbált kezelni. Ilyen pl. az objektum-relációs leképzés vagy a tranzakció épség. Ennek ellenére sok programozó az API-t is hasonló, vagy még nehezebbnek vélte, így alakult ki az a széles körű felfogás, miszerint az EJB által bemutatott összetettség nem nyújt igazi hasznot.
Mi több, a cégek úgy találták, hogy az EJB használata az üzleti logikában rontotta a teljesítményt. Ez azért történhetett, mert az eredeti specifikáció csak a CORBA-n, esetleg más hasonló protokollokon keresztül engedte a távoli eljárás hívást (és opcionálisan minden más eljárást is), annak ellenére, hogy a legtöbb üzleti alkalmazásnak nincs is szüksége az elosztott számítási funkcióra. Az EJB 2.0 specifikáció ennek az aggodalomnak a megszüntetésesre jött létre. Ezt úgy akarták kivitelezni, hogy hozzáadták a helyi interfész koncepcióját, amelyet egyenes úton lehetett hívni anélkül, hogy a többszörös szervereken eloszló alkalmazások által előhozott probléma megjelent volna.
Széles körben az EJB 1.0 által felmerült problémák megoldásaként mutatták be. Bonyolultsága azonban továbbra is hátráltatta az EJB elfogadását. Habár a kiváló fejlesztői környezetek az ismétlődő feladatok automatizálásával megkönnyítették az EJB létrehozását és használatát, ugyancsak ezek az eszközök nem segítették a technológia megtanulását. Ezen felül egy ellenálló mozgalom kezdett kibontakozni a programozók között. A fő eredménye ennek az ellenállásnak az EJB-hez képest könnyűsúlyúnak nevezhető Hibernate és a Spring keretrendszer lett. (A Hibernate a perzisztenciát és az object-relational mapping-et valósítja meg, a Spring framework pedig egy alternatív és kevésbé "bőbeszédű" módot nyújt az üzleti logika kódolásához). Annak ellenére, hogy a nagyobb cégek nem támogatták, ezek a technológiák ismertek lettek, és sok olyan cég kezdte használni őket, amelyek csalódtak az EJB-ben.
Az EJB-t a Java BluePrints, és a Sun Java Pet Store demója támogatta. Az EJB használata vitatható és befolyásoló volt. A Java EE programozók, mint például Rod Johnson, megkíséreltek egy olyan választ létrehozni a Java Pet Store-ra, ami támogatja az EJB használatát, és kiemelten hangsúlyozza annak fontosságát. A Sun létrehozott egy alternatívát, amit Plain Old Java Objects-nek neveztek (POJO). Az új EJB 3.0 használata könnyebb lett az EJB 2.0-nál, és több lehetőséget is nyújtott a fejlesztőknek.
Az EJB újraalkotása A cégek egymás között megegyeztek abban, hogy az EJB specifikáció elsődleges előnye, az elosztott alkalmazások tranzakciós épségének biztosítását a legtöbb üzleti alkalmazás kevéssé használja. Sokkal hasznosabbak voltak a könnyűsúlyú keretrendszerek által nyújtott funkciók. Példa erre a Spring, vagy a Hibernate.
Ennek megfelelően az EJB 3.0 (JSR 220) radikálisan különbözött az ősöktől, és ezt az új mintát követte. Nyilvánvaló a hasonlóság a Springgel abban, ahogy a POJO-kat használja. Továbbá a dependency injectiont is megvalósítja, ami egyszerűsíti a heterogén rendszer felépítését és összekapcsolását. Gavin King, a Hibernate megalapítója is részt vett az EJB 3.0 folyamatában, és a technológia köztudott szószólója. A Hibernate sok jellegzetessége megjelenik a Java Persistence API-ban, ami az Entity Beans-t helyettesíti az EJB 3.0-ban. Az EJB 3.0 erősen az annotációkon alapul, bár megtartotta a korábbi konfigurációs lehetőségeket is.
Az annotációk az 5.0-s verzióban kerültek a Java nyelvbe, egy tömörebb és biztonságosabb kódolási stílust lehetővé téve. Az EJB 3.0 így egy könnyebb súlyú API-t nyújt, és csak kevéssé hasonlít a megelőző EJB specifikációkra.
Példa
A következő példán látható egy EJB a gyakorlatban:
@Local public interface CustomerServiceLocal { void addCustomer(Customer customer); }
@Stateless public class CustomerService implements CustomerServiceLocal {
@PersistenceContext private EntityManager entityManager;
public void addCustomer(Customer customer) { entityManager.persist(customer);
A fenti kódban egy egyszerű lokális interfész és annak implementációja látható. Az implementáció egy O/R leképezés alapján perzisztálja a kapott Consumer objektumot, ami tranzakcionálisan és szálbiztosan történik. Az EJB csak a perzisztenciára és az üzleti logikára koncentrál, más egyedi részleteket, felépítést nem ismer.
Az EJB-t osztályokban is lehet használni, mint a következő példában is:
@Named @RequestScoped public class CustomerBacking {
@EJB CustomerServiceLocal customerService;
public String addCustomer() { customerService.addCustomer(customer); context.addMessage(...); // abbreviated for brevity return "customer_overview";
A fenti kódrészlet egy JSF backing bean-t mutat be, melybe a konténer (az @EJB annotáció hatására) egy EJB-t injektál. Az addCustomer() metódus a felhasználói felület egyes komponenseihez kapcsolódik, mint például egy gomb. Az EJB-vel ellentétben, a backing bean nem tartalmaz semmilyen üzleti logikát vagy perzisztencia kódot, de delegálja az efféle kéréseket az EJB-nek. A backing bean tud olyan egyedi implementációkról is, amiről az EJB-nek nincs tudomása.
EJB típusok Az EJB-k három csoportra oszthatók:
Session beanek
A session bean-ek lehetnek:
Állapotmentesek (stateless) Az állapotmentes session beanJSR 318, 4.7, http://jcp.org/en/jsr/detail?id=318 nem perzisztens bean. Nem tárol állapotot a sessionről, így az egyes hívásai függetlenek. Mivel az állapotmentes session bean példányai nem tárolnak a klienstől származó adatot, így a metódusainak végrehajtásához szükséges összes adat a metódusok paramétereiből származik.
Ezek a beanek nem használhatók párhuzamosan, viszont két hívás között ki tudnak szolgálni egy másik klienst is. Hogyha igény lenne a párhuzamos használatra, akkor a két szál külön példányt kap,JSR 318, 4.3.14, http://jcp.org/en/jsr/detail?id=318 így az állapotmentes session garantáltan szálbiztos. A metódusok hivatkozhatnak a bean belső állapotára, de nincs arra garancia, hogy két hívás között ne változzon meg az állapota.
Az adminisztrációs költségek csökkentése éredkében a konténer egy pool-t tart fent; egy bean egymás után több kliensnek is odaadható. Mivel nem tárolnak állapotot, kezelésük egyszerűbb és kevésbé időigényes, mint az stateful session beaneké.
Állapottartók (stateful)
Az állapottartó beanekJSR 318, 4.6, http://jcp.org/en/jsr/detail?id=318 üzleti objektumok, amelyek mezőikben tárolják a klienstől kapott információkat, és megőrzik őket az egész session folyamán. Kapcsolatuk szorosabb, mint a kliens és az állapotmentes beaneké; elvben egy munkamenet során egy bean egy klienshez tartozik,JSR 318, 4.10.3, http://jcp.org/en/jsr/detail?id=318 ám ha egyszerre sok klienst kell kiszolgálni, akkor a konténer dönthet úgy, hogy a beant állapotának elmentése (passziválás) után egy másik kliensnek ad oda (aktiválás). Ezért fontos, hogy a bean állapota elmenthető, szerializálható legyen.
A bean állapotát a munkamenet végéig őrzi meg. Ekkor a kliens bezárja a kapcsolatot, és a bean állapotának törlése után visszakerül a készletbe. Előfordul, hogy a kliens nem zárja be a munkafolyamatot; ekkor egy idő múlva a konténer elveszi a beant, hogy ne fogyjon el a készlet. Ez az idő a @AccessTimeout annotációval adható meg.JSR 318, 4.3.14, 21.4.2, http://jcp.org/en/jsr/detail?id=318 Az állapottartó session beanek támogatják a JPA kiterjesztett perzisztencia kontextust.
Példa: Klasszikus példa az online kosár, ami számon tartja a munkafolyamat alatt, hogy a vásárló milyen termékeket tett bele, esetleges lockokkal az adatbázisban. A végén a megrendelés zárja a munkamenetet. Szingletonok (singleton)
A szingletonokJSR 318, 4.8, http://jcp.org/en/jsr/detail?id=318 olyan üzleti objektumok, amelyek állapota megosztott egy JVM-en belül. A konkurens hozzáférést alapértelmezetten a konténer kezeli (Container-managed concurrency, CMC), de ez megváltoztatható. Ekkor a beannek magának kell biztosítania, hogy megőrizze állapotának konzisztens voltát (Bean-managed concurrency, BMC). A CMC-nek jelezhetjük a @Lock annotációval, hogy író vagy olvasó lockot igénylünk-e.
A szingleton beanek konkurensen használt beanek, amelyekből elvben egy példány létezik; gyakorlatilag azonban minden JVM-nek saját példánya van. Alapértelmezetten lustán jönnek létre, de ezt megváltoztathatjuk a @Startup annotációval.
Példa: Cachelés, vagy a napi árlista központi nyilvántartása.
Üzenetvezérelt bean
Az üzenetvezérelt beanek (MDB) olyan vállalati beanek, amelyek üzenetek aszinkron feldolgozását teszik lehetővé Java EE alkalmazások számára. Többek között a JMS (Java Message Service) kommunikáció magasabb szintű absztrakcióját nyújtja. Fel lehet iratkozni JMS üzenetsorokra vagy témákra, rendszerint a @MessageDriven activationConfig attribútumának hatására. Ezek az EJB-hez rendelődnek, hogy lehetővé tegyék az eseményvezérelt feldolgozást.