Főoldal

"Mérnököt a mérnöktől"

A Schönherz Bázis összeköti az állást kereső és állást kínáló mérnököket.

CV küldés

Küldj önéletrajzot! Gyorsan, egyszerűen.
Megjegyzésbe írd be a pozíció nevét.
CV küldés

Iratkozz fel hírlevelünkre!

Kövess minket!

Kövess minket!

Hírek

Részletes útmutató EJB-hez példakód-részletekkel
Részletes útmutató EJB-hez példakód-részletekkel


1996-ra a Java már népszerűvé vált a fejlesztők körében, köszönhetően az egyszerűen használható API-gyűjteményének és a Garbage Collectornak, így egyre szélesebb körben használták back-end rendszerek fejlesztésére. Azonban volt egy probléma: ezen rendszereknek bírnia kellett egy sor szabványos tulajdonsággal - mint például a tartósság, tranzakció-integritás, versenyhelyzet-kezelés - melyekkel akkoriban nem rendelkezett a JDK. Ez sok házi, zárt implementáció megszületéséhe vezetett.


Az IBM 1997-ben létrehozta az Enterprise Java Bean (EJB) specifikációt azzal a céllal, hogy a fejlesztők szabványos formában kódolhassanak úgy, hogy a rendszeres problémákat a rendszer kezeli. Így született meg az első vállalati Java keretrendszer; a specifikációt pedig 1999-ben EJB 1.0 néven adta ki a Sun.


Ugorjunk előre húsz évet, amikor az EJB 3.2 a JavaEE 9 specifikáció része.


Mi is az Enterprise Java Bean?


Egyszerűen szólva, egy Enterprise Java Bean egy Java osztály egy vagy több jelöléssel (annotation) az EJB specifikációból, amelyek különleges erőket adnak az osztálynak, amikor azt egy EJB konténerben futtatják. A következő részekben megmutatjuk, hogy mik ezek az erők és hogyan használhatod ki őket a programjaidban.

(A jelölések az EJB-ben viszonylag újak, az EJB 3.0 óta elérhetők. Az EJB előző verzió interfészeket használtak, melyeket az osztályoknak meg kellett valósítani. Erről a cikkben nem ejtünk több szót.)


JNDI nevek


A JNDI, vagyis Java Naming Directory Interface egy könyvtárszolgáltatás, amely lehetővé teszi az erőforrások felkutatását. Minden alkalmazásszerveren futó erőforrás, mint például egy EJB, adatforrás vagy JMS Queue kap egy JNDI nevet, amellyel elérhető lesz az elem.Minden szervernek van egy alap stratégiája a nevek kiosztására, de ez egyedi nevekkel felülírható. Az általános konvenció az {erőforrásTípus}/{erőforrásNév} formátum. Például egy adatforrás neve lehet a jdbc/TestDatabase vagy egy JMS Queue hallgathat a jms/TestQueue JNDI névre.


Az Enterprise Bean-ek típusai


Hatoljunk kicsit mélyebbre az Enterprise Bean-ek típusain belül:

  • Session (viszony) Beans
  • Message-Driven (üzenet-vezérelt) Beans


Session Beans


Egy session bean üzleti logikát foglal magába, melyet egy kliens hívhat meg. A meghívás történhet lokálisan egy másik osztály által ugyanazon JVM-en belül, vagy hálózaton keresztül egy másik JVM-ből. A bean végrehajtja a kliens számára a feladatot, egy webszolgáltatáshoz hasonlóan elfedve a részleteket.

Egy session bean példány életciklusát az EJB konténer szabályozza. A szabályzástól függően kétféle típusuk lehet:


A sokat sejtető nevű állapotmentes bean-ek állapotmentesek. Mint ilyenek, több kliens osztozik rajtuk. Lehetnek egy példányban létezők, de a legtöbb megvalósításban a konténerek létrehoznak egy példánykészletet az állapotmentes EJB-knek. MIvel nincs követendő állapot, gyorsak és a konténer könnyen szabályozza őket. A hátrányuk, hogy megosztott erőforrás lévén a fejlesztőknek maguknak kell gondoskodniuk a szálbiztonságról.


Az állapotos bean-ek a klienshez kötődve egyediek, a kliens állapotát reprezentálják. MIvel a kliens kölcsönösen hat egymára a beanjével (“beszélget vele”), ezt az állapotot gyakran nevezik párbeszéd állapotnak. Akárcsak az állapotmentes beanek esetén, az életciklust itt is a konténer szabályozza; a kliens leállításakor ezek is vele halnak.Egy Singleton session bean alkalmazásonként egy példányban létezik és az alkalmazéssal együtt záródik be. A SSB-karra valók, hogy az állapotot minden kliens közt meg lehessen osztani. Az állapotmentes beanekhez hasonlóan az SSB-k szálbiztonsgát is a fejlesztő feladata biztosítani. A versenyhelyzet-kezelés azonban különbözik a két típus között, ahogy arról még írunk.


Evezzünk gyakorlatiasabb vizekre, írjunk egy kis kódot. Itt egy Maven projektet hozunk létre ejb típusú csomagolással, javaee-api függőséggel:


<project ...>

   <modelVersion>4.0.0</modelVersion>

   <groupId>com.stackify</groupId>

   <artifactId>ejb-demo</artifactId>

   <version>1.0-SNAPSHOT</version>

   <packaging>ejb</packaging>

   <dependencies>

       <dependency>

           <groupId>javax</groupId>

           <artifactId>javaee-api</artifactId>

           <version>8.0</version>

       </dependency>

   </dependencies>

</project>


Alternatívaként a célszerver futásidejű  függőségeit is megadhatnánk a JavaEE API-k helyett, de ez rontaná a hordozhatóságot. A modern EJB-t könnyű konfigurálni, így egy EJB osztály írásához csak hozzá kell adnunk a jelöléseket, mint a , (vessző) vagy a . (pont). Ezek a javax.ejb csomagból származnak:


@Stateless

public class TestStatelessEjb {

   public String sayHello(String name) {

       return "Hello, " + name + "!";

   }

}


Vagy:


@Stateful

public class TestStatefulEjb {

}


Végül:


@Singleton

public class TestSingletonEjb {

}


Létezik a javax.inject.Singleton jelölés is, de az a CDI specifikáció része, szóval figyelnünk kell erre is, ha használni akarjuk.


Üzenetvezérelt beanek


Az üzenetvezérelt bean (Message Driven Bean, MDB) egy enterprise bean, melynek segítségével üzeneteket aszinkron módon dolgozhatunk fel. Ez a bean-típus alapvetően JMS üzenetfigyelőként funkcionál, ami egy eseményfigyelőhöz hasonlít, de JMS üzeneteket fogad események helyett.


Sok aspektusuk hasonlít az állapotmentes session beanekre, de nem egy kliens hívja meg őket, hanem eseményvezéreltek:


@MessageDriven(mappedName = "jms/TestQueue")

public class TestMessageDrivenBean implements MessageListener {

   @Resource

   MessageDrivenContext messageDrivenContext;

   public void onMessage(Message message) {

       try {

           if (message instanceof TextMessage) {

               TextMessage msg = (TextMessage) message;

               msg.getText();

           }

       } catch (JMSException e) {

           messageDrivenContext.setRollbackOnly();

       }

   }

}


Itt a párosított név annak a JMS queue-nak a neve, amelyre az MDB figyel. Amikor egy üzenet érkezik, a konténer meghívja a bean onMessage metódusát, hogy feldolgozza azt. Az onMessage metódus alapvetően besorolja az üzenetet az öt JMS üzenettípus valamelyikébe és az alkalmazás üzleti logikája szerint kezeli. Az onMessage metódus kisegítő függvényeket is hívhat, vagy akár session bean-eket is, hogy feldolgozza az üzenetben tárolt információt. Egy üzenetvezérelt bean egy tranzakción belül tud fogadni egy üzenetet, szóval az onMessage összes művelete egy tranzakción belül játszódik le. Ha az üzenetfeldolgozást visszavonják, az üzenet újraküldődik.


Az Enterprise Beanek elérése


Ahogy azt már említettük, az MDB-k eseményvezéreltek. Ebben a szakaszban a session beanek metódusainak elérését tárgyaljuk. Ahhoz, hogy egy EJB metódusait lokálisan elérjük, a beant beszúrhatjuk a konténer bármely managelt osztályába - például egy Servletbe.


public class TestServlet extends HttpServlet {

   @EJB

   TestStatelessEjb testStatelessEjb;

   public void doGet(HttpServletRequest request,

     HttpServletResponse response) {

       testStatelessEjb.sayHello("Stackify Reader");

   }

}


Egy távoli JVM metódusának meghívása már bonyolultabb és egy kicsit több kód szükséges hozzá. Előkövetelmény, hogy az EJB-nek rendelkeznie kell egy távoli elérésű interfésszel. Szükség lesz egy EJB kliensre is, amelyik a hálózaton kutatja fel az erőforrást.


Az interfészt jelöljük:


@Remote

public interface TestStatelessEjbRemote {

   String sayHello(String name);

}


Gondoskodjunk róla, hogy a TestStatlessEjb megvalósítja ezt az interfészt.


Most írjuk meg a klienst, amely jelen esetben egy egyszerű Java SE alkalmazás a main függvénnyel.


public class TestEjbClient {

   public static void main(String[] args) throws NamingException {

       Properties properties = new Properties();

       properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,

         "org.apache.openejb.client.LocalInitialContextFactory");

       properties.setProperty(Context.PROVIDER_URL, "ejbd://host:4201");

       Context context = new InitialContext(properties);

       TestStatelessEjbRemote testStatelessEjbRemote

         = (TestStatelessEjbRemote) context.lookup("ejb/TestStatelessEjbRemote");

       testStatelessEjbRemote.sayHello("Stackify");

   }

}


Először létrehoztunk egy, a távoli JVM-re hivatkozó Context-et. A kezdeti context factory name és a provider URL az OpenEJB alapértelmezett értékeit veszik fel. Ez szerverenként változó érték. Ezután a bean JNDI nevének felhasználásával felkutattuk az EJB-t és a megfelelő távoli típusra konvertáltuk. Amint megkapjuk a távoli EJB példányt, meghívhatjuk a metódust.


Figyelj rá, hogy két JAR fájlra lesz szükséged a kliensed osztályelérési fájában:

  • Egy tartalmazza az eredeti context beépített osztályt. Ez szerverenként változó.
  • Egy másik az EJB távoli interfészét tartalmazza.


Éppenséggel a Maven EJB plugin generál egy kliens JAR fájlt, amely pontosan a távoli interfészeket tartalmazza. A felhasználónak csak konfigurálnia kell a plugint:


<plugin>

   <groupId>org.apache.maven.plugins</groupId>

   <artifactId>maven-ejb-plugin</artifactId>

   <version>3.0.0</version>

   <configuration>

     <!-- this is false by default -->

     <generateClient>true</generateClient>

   </configuration>

</plugin>


Ha a kliens felkutatja az erőforrásokat, az állapotos beanek közül minden alkalommal új példányt kap vissza. Állapotmentes beaneknél a készletből bármelyik visszatérhet.


Versenyhelyzet a Singleton Beanekben


Az állapotos és állapotmentes beanekkel egyaránt több kliens vagy egy kliens több szála hívhatja meg ugyanazokat a metódusokat. Ezzel ellentétben a Singleton enterprise beanek alapvető módja a LockType.WRITE. Ez azt jelenti, hogy egyszerre csak egy szál hívhatja meg a metódust.

Ez megváltoztatható a metódushoz való hozzáfűzéssel és a LockType.READ beállításával:


@Singleton

public class TestSingletonEjb {

   @Lock(LockType.READ)

   public String sayHello(String name) {

       return "Hello, " + name + "!";

   }

}


Ez a finoman szabályozható, metódusszintű versenyhelyzet-kezelés lehetővé teszi, hogy a fejlesztők robosztus többszálú alkalmazásokat készítsenek anélkül, hogy a szálak kezelésében kéne elveszni.


Tegyük fel, hogy van egy Map példányváltozónk egy Singleton EJB-ben. A legtöbb kliens csak olvas a Map-ből, de csak kevés ír is bele. Ha megjelöljük a get metódust lock type readként, a put metódust pedig lock type write-ként, ez tökéletes megvalósítás lenne.:


@Singleton

public class TestSingletonEjb {

   private Map<String, String> elements;

   public TestSingletonEjb() {

       this.elements = new HashMap<>();

   }

   @Lock(LockType.READ)

   public String getElement(String key) {

       return elements.get(key);

   }

   @Lock(LockType.WRITE)

   public void addElement(String key, String value) {

       elements.put(key, value);

   }

}


A write-lock zárolja az egész osztályt, szóval amikor a Map-et az addElement metódus frissíti, mindegyik, a getElement-et elérni próbáló szál is blokkolva lesz.


EJB időzítők


Az időzített feladatok végrehajtása a végletekig le van egyszerűsítve az EJB-ben: add hozzá a jelölést a metódushoz, amelyiket meg kell hívni. A jelölés paraméterei az időzítő végrehajtásakor állítódnak be:


@Singleton

public class TestScheduleBean {

   @Schedule(hour = "23", minute = "55")

   void scheduleMe() {

   }

}


Jegyezd meg, hogy az EJB egy Singleton. Ez azért fontos, mert csak a singleton beanek garantálják, hogy egy példány létezhet belőlük és nem akarjuk, hogy az időzítőnket több példány is indítsa.


Összefoglaló

Bár a Spring feltörekvő szereplő a enterprise fejlesztés világában, az EJB még mindig elég releváns és erőteljes. A készen kapott, távelérést biztosító képességek és versenyhelyzet-kezelés még mindig az Enterprise Beans sajátja; a JMS és a JPA a JavaEE specifikáció része, ezért elsőrangú lakosok az EJB-ben. AZ EJB túltett a saját gyengeségein, megújította magát és egy modern, erőteljes eszközzé vált a gazdag Java ökoszisztémában.


(Forrás


Ha Te is kreatív, kihívásokkal teli mérnök állást keresel minõségi munkáltatónál, jó helyen jársz, mert a Schönherz Bázis épp azért jött létre, hogy Neked segítsen.
Gyere, nézz szét aktuális állásaink között!