Komponens alapú szoftverfejlesztés EJB használatával


Csúcs Gergely (wizard@avalon.aut.bme.hu)

Dr. Charaf Hassan (hassan@avalon.aut.bme.hu)

BME, Automatizálási és Alk. Informatikai Tanszék


Fejlõdése során a Java nyelv mindig igyekezett a kor kihívásainak maradéktalanul megfelelni. Idõrendben haladva ezek a követelmények a következõk voltak:

  1. Platformfüggetlenség

  2. Elosztott mûködés lehetõsége

  3. Komponensalapú szoftverfejlesztés lehetõsége

A szoftverek hordozhatóságának igénye nagyon régi. Tulajdonképpen tetszõleges magasszintû programozási nyelv teljesíti ezt az igényt, egy bizonyos szintig. Az adott nyelven készült program szinte hordozható (esetleg bizonyos típusos változók mérete ill. pontossága tartogathat meglepetéseket). Probléma akkor jelentkezik, amikor valamilyen API-hoz szeretne hozzáférni. Ugyanis az adott API vagy elérhetõ az adott nyelvi implementációból vagy nem. Mert az API-k implementációja már erõsen kötõdik a környezethez, így nem hordozható. Amíg valaki meg nem írja, addig nincs.

A Sun ehhez képest fogta magát, és a Java megalkotása mellett bevezette a bytecode-ot, ami egy pontosan specifikált virtuális környezetben fut. És mivel az összes Java API is így tesz, ezért az alkalmazások remekül hordozhatók (természetesen a JVM-et –Java Virtual Machine– ettõl még hardware/software környezettõl függõen kell implementálni, de ez úgy tûnik, sikerülni szokott).

Így a Java a hordozhatóság/platformfüggetlenség követelményének már a kezdetek óta eleget tesz; igazából vetélytárs nélkül.

Hálózatok márpedig vannak

Nagyon igaz. Három jelentõsen különbözõ mód áll rendelkezésre hálózatok eléréséhez:

Ez a legalacsonyabb szintû hálózatkezelési mód. Nem sok szolgáltatást nyújt; kapcsolatorientált (TCP) ill. datagram alapon (UDP) küldhetünk és fogadhatunk byte-sorozatokat. Támogatja az URL-ek használatát ill. a Java Web-barátságossága miatt a HTTP protokollt, de minden egyéb szolgáltatást magunknak kell megvalósítanunk. Cserébe bármivel együtt lehet mûködni, csak egyeztetni/ismerni kell a használt protokollt.

Ha egyszerû, de elosztott Java alkalmazást kívánunk készíteni, akkor a leghelyesebb, ha az RMI (Remote Method Invocation)-t használjuk. Ez ugyanis a Java saját ORPC (Object RPC) protokollja. Csak a legszükségesebb szolgáltatásokat nyújta: távoli metódushívásokat hajthatunk végre vele Remote-ból származó interfészt megvalósító objektumokon, valamint az ilyen objektumokra való referenciák megszerzése érdekében egy névszolgáltatást biztosít. A rendszer érdekessége az objektum típusú paraméterek kezelése: ha az adott objektum Remote interfészû, akkor távoli objektumreferencia közlekedik a hálózaton, ha az objektum szerializálható (a Serializable interfészt úgymond implementálja; igazából ez csak egy jelölõinterfész, a csomagolás automatikusan történik), akkor az objektumpéldány továbbítódik. Nem jelent problémát egyik esetben sem, ha a célállomáson nem áll rendelkezésre a távoli referencia kezeléséhez szükséges stub (“csonk”) ill. a szerializált osztály implementációja, mivel az RMI ilyenkor átküldi azt is. Ilyen lehetõséggel kevés más elosztott környezetben találkozhatunk, használatával hatékonyan kezelhetõk terheléselosztási, skálázási feladatok.

Hasonlóságok a Java “alap” és elosztott objektummodelje között:

Eltérések is vannak persze:

A CORBA (Common Object Request Broker Architecture) egy megoldás a komponens alapú elosztott rendszerek fejlesztése által felvetett problémákra. Az OMG (Object Management Group, a CORBA-n kívül pl. õk gondozzák az UML –Unified Modelling Language– specifikációját is, meglehetõsen sok – 800-nál is több – cég szövetsége) bábáskodása alatt született meg a CORBA 1.0 még a 90-es évek elején.

Az alap CORBA meglehetõsen haszontalanra sikerült: csak az OOP-t nem támogató C nyelvhez tartalmazott leképezést (pedig akkoriban a C++ nyelv már elég elterjedt volt, ezért rengeteg inkompatibilis házi-leképezés készült hozzá), ráadásul még nem sok szó esett a különféle ORB implementációk (és az alattuk fejlesztett komponensek) együttmûködésérõl, így ilyen nem is létezett.

1994-re jutottak a cégek közös nevezõre, és elkészült a CORBA 2.0 specifikáció, amely már számos nyelvhez tartalmazott egységes leképezést, valamint az IIOP (Internet Inter-ORB Protocol) protokollt az együttmûködés érdekében. Ez jelentette a fordulópontot a CORBA elterjedése szempontjából, “használható”-vá vált.

Mivel a Java már a nyelv szintjén el tudja különíteni interfészt és implementációt, ezért különösen jól illeszkedik a CORBA szemléletbe. Tulajdonképpen ugyanazt nyújtja, mint az RMI, több szolgáltatással (CORBA service-k igénybevehetõk), viszont az implementáció küldözgetésének meglehetõsen speciális lehetõségérõl le kell mondanunk.

Ami mégis elõnyössé teszi egy Java programozó számára az az, hogy a CORBA egy nyelv- és – az IIOP bevezetése óta – implementációfüggetlen komponensrendszer; a tulajdonképpeni munka pedig ugyanannyi: nem Java, hanem IDL nyelven kell megírni a Remote interfészt, a fejlesztés hátralevõ része pedig megegyezõ (szisztematikusan végrehajtható eltérésekkel csupán). Érdekesség, hogy maga az RMI alrendszer is rávehetõ, hogy IIOP segítségével kommunikáljon.

JavaBeans

A Java nyelv komponensalapú programfejlesztést támogató API-ja. Egy komponens alkalmazások összeállításához használható. Különválik ugyanis a programozó (“hagyományos” értelemben vett fejlesztõ, “developer”, aki a komponenseket készíti), és az összeállító (“assembler”, ez egy felhasználó-közelibb tevékenység, kész komponensek segítségével szereli össze a nagy egészt) szerepköre. JavaBean ugyanis szinte bármi lehet, egy apró GUI-elemtõl kezdve (például egy gomb vagy egy gördítõsáv) egy akár önállóan is mûködõképes alkalmazásig (közkedvelt példa: egy táblázatkezelõ). Amivel egy Bean több: egyszerûbb esetben egy összetett dokumentum, tágabb értelemben egy összetett alkalmazás része lehet. Például az említett GUI elemek tipikusan egy alkalmazás kezelõfelületének létrehozásakor kerülnek felhasználásra, egy táblázat pedig megjelenhet egy dokumentumban (“szöveg”-file vagy prezentáció).

Egy JavaBean nem más, mint egy vizuálisan kezelhetõ újrafelhasználható szoftverkomponens.

A következõ tulajdonságokkal kell rendelkeznie:

Érezhetõ, hogy nem érdemes válogatás nélkül mindent JavaBean-né alakítani, hiszen ezeknek a tulajdonságoknak csak az osztályhierarchia felsõ, már vizuális (“egérrel böködök”) szerkesztésre alkalmas részében vehetjük hasznát. A JavaBeans architektúra még csak komponensorientált; lokális komponensekben gondolkodik, így elosztott környezetben futó üzleti logika megalkotására önmagában kevéssé használható (természetesen a példaként felhozott GUI komponensek esetében semmi értelme az elosztott mûködésnek, de már az összetett dokumentumok esetében nem ilyen egyértelmû a helyzet).

Jini

A Jini egy nagyon érdekes kezdeményezés: saját megfogalmazása szerint felhasználói csoportok és a rendelkezésükre álló erõforrások szövetségén alapuló elosztott rendszer. Célja, hogy a hálózaton keresztül megosztott erõforrásokat egy könnyen adminisztrálható, dinamikus entitássá fogja össze, amely rugalmasan képes az õt használó munkacsoport igényeihez alkalmazkodni.

Az említett erõforrások szolgáltatások formájában kerülnek megosztásra, és igazából nem számít, hogy egy szolgáltatás mi implementál (nem fontos a nyelv, sõt: “majdnem puszta” hardware eszközök is integrálhatók a rendszerbe).

Egy Jini rendszer középpontjában a Lookup szolgáltatás (esetleg szolgáltatások, mert szükség esetén hierarchiába szervezhetõek) áll: természetesen ez egy névszolgáltatás.

Architekturális bõvítés még az elosztott biztonsági rendszer megjelenése (a lokális hozzáférésvezérlés hálózatos kiterjsztése).

A Jini programozási modellje üzenetalapú (ennyiben emlékeztet a JavaBeans-re, csak persze itt bonyolítja a dolgot, hogy elosztott környezetben való mûködésrõl van szó), a szolgáltatásokhoz való hozzáférés azok kibérlésével (lease) történik: a bérlet bizonyos idõtartamra szól (megbízhatatlannak tekintendõ hálózatos környezetben ez a legbiztonságosabb), lehet kizárólagos vagy osztott, esetleg meghosszabbítható illetve meghosszabbíthatatlan.

A Jini tartalmaz elosztott tranzakciókezelést biztosító szolgáltatást, de ennek használatához persze “tranzakció-képesnek” kell lennie a résztvevõ szolgáltatásoknak is.

És hogy mitõl olyan érdekes a Jini? Attól, hogy elegánsan használja az RMI ismertetésénél említett lehetõséget: a Lookup szolgáltatás ugyanis az igénylõ kliens számára egyszerûen átküld egy Server Object néven emlegetett apró proxy objektumot (szükség esetén implementációval együtt ugye), és a késõbbiekben ez kommunikál a szolgáltatóval. Természetesen akármilyen implementációjú szolgáltatóval, akármilyen protokollt használva.

EJB

Az Enterprise JavaBeans a JavaBeans technológia kiterjesztése elosztott rendszerek számára. Az Enterprise Bean-ek kiszolgálóoldali software-komponensek, egy többrétegû alkalmazás üzleti logikáját lehet belõlük összeállítani.

Bár az EJB rokona a JavaBeans-nek, más követelményeket (is) támaszt, és másra is való:

Az Enterprise Bean-ek háromfélék lehetnek:

      1. Session Bean

Egy Session Bean arról kapta a nevét, hogy olyan, mint egy párbeszédes elérés: nem megosztható (egy Session Bean egyetlen egy klienshez tartozhat csak), nem perzisztens (állapota ugyan lehet, de miután a kliens bontja a kapcsolatot, az állapot többet nem értelmezhetõ). A Session Bean-ek tekinthetõk egy alkalmazás tulajdonképpeni kliens-részének, hiszen a felhasználónál csak egy terminál-szerû mûködést produkáló programrészlet található, ami igazából a Session Bean-eket mûködteti.

Amikor használható:

      1. Entity Bean

Egy többrétegû alkalmazásnak két vége van; a klienseket a Session Bean-ek képviselik. Az Entity Bean-ek az alkalmazás másik végén található objektumokat képviselik, amelyek valamilyen perzisztens tárolóból származnak (tipikus példa: egy relációs adatbázisból). Egy Entity Bean többnyire megfeleltethetõ egy táblának az adatbázisban, és minden egyes példánya a tábla egy sorát reprezentálja.

Az Entity Bean-ek jelentõsen eltérnek a Session Bean-ektõl:

Amikor Entity Bean-t érdemes használni:

      1. Üzenetvezérelt (Message-Driven Bean)

Egy eseményvezérelt Enterprise Bean (egyelõre csak) JMS üzenetekre reagál. Ezek az üzenetek viszont bárhonnan származhatnak (a JMS nem követeli meg a J2EE technológia használatát).

Tulajdonságaiban egy állapot nélküli Session Bean-re emlékeztet:

Üzenetvezérelt Bean-ek használata akkor indokolt, amikor üzenetek aszinkron fogadására van szükség (ekkor a Bean Container egyszerûen meghívja a Bean onMessage metódusát, Session és Entity Bean viszont csak explicit várakozással képes üzenetet fogadni). Egy üzenetvezérelt Bean ugyanis másra nem is alkalmas (a BeanContainer-rel való kapcsolattartáshoz szükséges Bean interfészen kívül más interfésszel nem rendelkezik).

Enterprise Bean felülete

Egy Enterprise Bean (a meglehetõsen speciális üzenetvezérelt esetet leszámítva) az elérési módjától (távoli és/vagy lokális) függõen számos interfésszel rendelkezik:

A szóhasználat elosztott rendszert sejtet, de ugyanezt az interfész-párost lokális eléréshez is biztosíthatjuk: Local és LocalHome interfész néven. Tipikusan egymással a Bean Container által kezelt relációban álló entity bean-ek használatakor szokás implementálni.

Az EJB használata

Az EJB egy JAR csomagban szállítható, ami a következõket tartalmazza:


Látható, hogy egy Enterprise Bean létrehozása nem sokban tér el bármilyen Java osztály elõállításától, igazából csak egy szabványos formátumú leírást kell csupán nyújtani róla, és máris elõáll egy elosztott környezetben (is) használható, számos szolgáltatást akár automatikusan használó (pl. ha a Container-re bízzuk a tranzakciók és a perzisztencia kezelését) szoftverkomponens.

Irodalomjegyzék:

JavaTM 2 SDK, Standard Edition Documentation

Enterprise JavaBeans Specification, Version 2.0 (ejb-2_0-fr2-spec.pdf)

JavaTM 2 Enterprise Edition Developer's Guide (devguide1_2_1.pdf)

The J2EE Tutorial (j2ee-1_3-doc-tutorial-draft3.pdf)