CDI Java EE 7 Context & Dependency Injection elméletben és gyakorlatban Hajba Gábor László This book is for sale at http://leanpub.com/cdijavaee7 This version was published on 2015-02-23
This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools and many iterations to get reader feedback, pivot until you have the right book and build traction once you do. ©2014 - 2015 Hajba Gábor László
Also By Hajba Gábor László XML processing and website scraping in Java
Tartalomjegyzék Előszó helyett . . . . . . . . Miért írom ezt a könyvet? LeanPub . . . . . . . . . . Mintaalkalmazások . . . . Konvenciók . . . . . . . . Formázás . . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
1 1 1 2 2 3
CDI – Contexts and Dependency Injection for the Java EE Platform . . . . . . . . . . Névkonvenció . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4 4
Mintaalkalmazások . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Az alkalmazásról . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Java SE alkalmazás CDI-vel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5 5 5
Előszó helyett A célom ezzel a könyvvel az, hogy bemutassam, hogyan lehet a Java EE 7 programozás CDI lehetőségét kihasználni – elméletben és gyakorlatban. Az elméleti részben leírom az egyes technikákat és elemeket, amik felépítik a függőség injektálást (dependency injection). A gyakorlati rész átnyúlik az egész könyvön, mivel minden egyes elméleti blokkot egy vagy több programkód-töredékkel szemléltetek. A könyben a Java EE 7-tel megjelent CDI 1.1-et ismertetem majd. Ahogy a neve is sugallja, vannak eltérések a 1.0-s verzióhoz képest, ami a Java EE 6-tal jelent meg. Az új elemeket külön ki fogom emelni, a többinél pedig megemlítem, ha valamennyire másként működik az előző verzióban.
Miért írom ezt a könyvet? Leginkább azért, mert kevés a magyar nyelvű szakirodalom a témában. Igaz, hogy angolul minden gyorsabban és könnyebben elérhető, azonban olykor sokkal egyszerűbb valaminek utána járni és megérteni az anyanyelvünkön. Illetve a szakkönyvek többsége, amit lefordítanak, egy az egyben közli az eredeti szöveget. Én igyekszem saját tapasztalataim alapján leírni az egyes programozási elemeket és ezzel is valamennyire érthetőbbé tenni a dolgokat. Mindezek mellett ez a könyv egy kisebb sorozat első eleme. A sorozatban szeretném bemutatni a Java EE 7 fejlesztésének különböző egységeit, hogy a végén egy egységes képet kapjon az olvasó. Azért nem konkrét könyvet készítek, mert így hamarabb elkészülnek az egyes részek, függetlenek egymástól, és ha valakit csak épp egy konkrét témakör érdekel, akkor nem kell annyi pénzt áldoznia az ismeretek megszerzésére. Cserébe majd a sorozat együtt olcsóbban kerül a polcokra, mint a könyvek egyesével.
LeanPub Azért a LeanPub-on jelenik meg a könyv mert • gyorsan meg tudok jelentetni újabb részeket • digitális verziók kaphatóak: kevesebb fát kell feláldozni a tudomány oltárán • olcsóbb, mert kevesebb infrastruktúra szükségeltetik hozzá (magam is inkább az olcsóbb könyveket veszem meg) • minden megvásárolt könyv megkapja a frissítéseket és javításokat (nem kell hibajegyzékeket böngészni) Tehát ha valaki félne feláldozni pár száz forintot (pár dollárt) ezért a könyvért, mert nem lesznek frissítések, hibás nyelvtannal és online hibajegyzékkel kell bíbelődnie, annak megnyugtatásul 1
2
Előszó helyett
csak azt tudom mondani, hogy ne aggódjon: itt megkap minden frissítést, ami jön a könyvhöz – és ezek már benne lesznek az árban. Az is előfordulhat, hogy a későbbiekben magamtól kibővítem a könyvet egy-egy fejezettel, vagy készítek egy új mintaalkalmazást, és akkor itt elérhető lesz az új verziója a könyvnek. Mindezt azért, mert a technológia folyamatosan változik, és rövid idő után már nem nagyon hasznos egy régi tudással teletömött könyv.
Mintaalkalmazások A könyv utolsó fejezetében összefoglalom az elmondottakat két teljes mintaalkalmazás keretében. Természetesen nem lehet egy vagy két egyszerű alkalmazásban lefedni a kontextusok és függőségek injektálását, de egy nagy részét igen - és én erre fogok törekedni. Az egyik alkalmazás web konténer nélkül, tehát egy alkalmazás-szerveren kívül futtatható, míg a másikhoz szükség van egy JBoss WildFly szerverre. A mintákat Maven projektként készítettem el, hogy a lehető legtöbb fejlesztői környezetben használható, kipróbálható, módosítható legyen. A mintaprojektek leírással, telepítési útmutatóval elérhetőek a BitBucket-en.
Miért pont WildFly? Azért, mert jelenleg ez az egyetlen ingyenesen elérhető alkalmazás-szerver, amelyikben lehet használni a CDI 1.1-es verzióját. Amennyiben idő közben kijön egy másik open source szerver, amely támogatja az 1.1-es verziót, úgy frissítem a könyvet. Természetesen az alkalmazás egyszerűen áttelepíthető lesz arra a szerverre is.
Konvenciók Annyira sok formázási elemet nem fogok használni a könyben, hogy egy külön fejezetet szenteljek ennek, ellenben amit mindenképp érdemesnek tartok megemlíteni, azok a forráskódok. A fejezetekben elhelyezett forráskód-részleteket megpróbáltam magyar nyelven írni, sajnos a LeanPub kicsit kiakadt ezen és tönkretette a formázást. Így arra gondoltam, hogy maradok a magyar megnevezéseknél, csak ékezet nélkül – ez azonban számomra is fájdalmas eredménnyel járt (optikailag), még akkor is, ha a szövegkiemelés most szépre sikeredett. Mindezek következtében arra az elhatározásra jutottam, hogy angol nyelven fogok programozni. A megjegyzéseket természetesen magyar nyelven írom – ott nincs semmilyen extra (félre)formázás. A forráskódokban olykor feltűnik három pont (…). Ez nem feltétlenül a változó számú paramétereket (var-args) jelöli, hanem inkább elhagyott kód-részleteket, amelyeket nem tartottam érdemesnek megjeleníteni abban a környezetben, ahol felbukkannak.
Dobozok Ezen kívül még különböző dobozolt tartalmakat is fogok a könyvhöz fűzni, ha szeretnék valamit kiemelni (érdekesség, figyelemfelhívás, gyakorlat, ilyesmi). Azok egy ehhez hasonló dobozban fognak megjelenni.
Előszó helyett
3
Formázás A könyv első teljes megjelenéséig csak apróbb formázásokkal fogok törődni. Addig a minta alapján örömmel várom a megjegyzéseket hogyan tehetném még olvashatóbbá mind a szöveget, mind pedig a forráskódokat. Első ötletem az volt, hogy zsebkönyv méretben jelentetem meg ezt a kiadványt, azonban a forráskód-példák túl sok sorra tördelődnének, így jelenleg megpróbálkozom az A5-ös formátummal. Amennyiben itt is nagyobb problémákba ütközök, úgy áttérek majd más oldalelosztásra. Ha valaki forráskód-sorok végén egy backslash-t (visszaperjel “\”) talál, az nagy valószínűséggel nem a programrészlethez tartozik, hanem a LeanPub így jelöli a sortörést. Ez a sor a következővel szorosan összetartozik. A formázási nyűgjeim leginkább PDF-re vonatkoznak, de többségében még a PDF a legelterjedtebb a digitális médiában.
CDI – Contexts and Dependency Injection for the Java EE Platform A CDI egy standard a Java EE 7 specifikációjának web profiljában. A feladata, hogy szolgáltatásokat és komponenseket kössön össze egy egységes szerveroldali alkalmazássá. Mindezek ellenére a CDI nem csak enterprise alkalmazásokban használható: alkalmazás szerver nélkül is lehet használni. Utóbbira is mutatok példát ebben a könyben egy kisebb mintaalkalmazás keretén belül. A CDI 1.0-t a JSR-299¹-ben definiálták, akkor még Web-Beans néven, és az volt a cél vele, hogy népszerű open source koncepciókat valósítsanak meg, melyeket a Spring és Weld keretrendszerek már alkalmaztak a gyakorlatban. Az első végleges verzió egy “könnyed” olvasmány a maga közel 100 oldalával. A CDI 1.1-et a JSR-346²-ban írták le. Ez már valamivel hosszabb, 126 oldal, mivel (fontos) kiegészítéseket tartalmaz az 1.0-s verzióhoz. Ezt a verziót 2013 május 24-én véglegesítették, majd közel egy évvel később kiadtak egy kisebb kiegészítést, az 1.2-es verziót (ami már 180 oldalra dagadt). A JBoss volt az a cég, amelyik elkészítette a referencia implementációját a CDI specifikációnak: a JBoss Weld³-et. Emellett az Apache OpenWebBeans néven, a Caucho pedig Candi néven készített egy-egy implementációt. Az említettek közül azonban a Weld az egyetlen, amelyiknek van CDI 1.1-es és 1.2-es verziója is. A többiek leragadtak 1.0-nál. Így érthető, hogy a mintaalkalmazásokban a Weld keretrendszert fogom használni, illetve egy olyan alkalmazás-szervert, amelyik integrálja ezt a konténert.
Névkonvenció A specifikáció a CDI konténer által kezelt bean-eket Managed Beans-nek nevezi. Ez a megnevezés kissé félrevezető, mert a Java EE más területein is használatos ez a kifejezés – és ott nem a CDI-vel kezelt beanekre vonatkozik. Emiatt én a CDI bean megnevezést fogom használni, ahol csak lehet. ¹https://jcp.org/en/jsr/detail?id=299 ²https://jcp.org/en/jsr/detail?id=346 ³http://weld.cdi-spec.org/download/
4
Mintaalkalmazások Ebben a fejezetben bemutatom, hogyan lehet hasznosítani a könyvben leírtakat kettő mintaalkalmazás segítségével. Az első egy egyszerű Java SE projekt lesz, amelyben egy JAR fájlt készítek. A fájl futtatásakor a Weld CDI konténer is élesítve lesz, így különböző szervízeket injektálással lehet közreműködésre bírni. A második egy webalkalmazás lesz, amelyet a JBoss WildFly alkalmazás-szerverben fogok futtatni. Mivel a projekt eredménye egy WAR fájl, így bármilyen alkalmazás-szerveren futtatható lesz, amelyik támogatja a CDI 1.1-es verzióját (a könyv írásakor jelenleg ezek azok a szerverek, amelyek a Weld legalább 2-es verzióját használják).
Az alkalmazásról Mivel a CDI-vel önmagában nem lehet teljes alkalmazást készíteni (pontosabban a mai világban nem nagyon elképzelhető, hogy egy nagyobb alkalmazás nem tartalmaz felhasználói felületet és nincs a hátterében egy adatbázis), ezért csak egy alkalmazás csontvázát tudom bemutatni és elkészíteni. Ezt a csontvázat pedig a későbbiekben át lehet alakítani és ki lehet egészíteni a még hiányzó funkcionalitással. Az alkalmazás egy képzeletbeli pizzéria szoftverét valósítja meg, ahol – értelem szerűen – pizzákat lehet rendelni. Mivel nincs a háttérben adatbázis, így a pizzák receptjét és a kínálatot az induláskor be kell tölteni, majd rendelés érkezésekor ki kell keresni az adott receptet és elkészíteni az alapján a pizzát. Az alapanyagok beszerzésével nem foglalkozom ebben az alkalmazásban. Mivel nincs felhasználói felület, ezért az alkalmazás az indítás után lefut egy képzeletbeli rendeléssel és kiírja a részleteket a konzolra, majd befejezi a futást.
Java SE alkalmazás CDI-vel Ahogy már a CDI ismertetésénél írtam, bizonyos CDI implementációkat⁴ nem csak alkalmazásszervereken lehet hasznosítani. Ezek közül most bemutatom, hogy lehet a JBoss Weld-et egyszerű Java alkalmazásokba integrálni. A projekt nagyon egyszerű lesz, nem törekszem egy komplett rendszer bemutatására. A koncepciók ugyanazok, mint a szerveroldali megoldásnál – és könnyen átültethetők a gyakorlatba.
Vannak azért megszorítások Sajnos a Weld-del sem fenékig tejfel a programozóélet a Java SE világában. Vannak megszorítások, amelyeket figyelembe kell venni: nem minden CDI funkció működik szerver nélkül, például EJB-k nem használhatóak (EJB-Lite sem). ⁴Ilyenek a bemutatott JBoss Weld és az Apache OpenWebBeans. A Caucho Candi-je sajnos nem képes a Resin server nélkül működni.
5
Mintaalkalmazások
6
Amit használható szerver nélkül is: • Menedzselt beanek @PostConstruct és @PreDestroy életciklust meghatározó annotációkkal • Függőség injektálás kvalifikátorokkal és alternatívákkal • @Application, @Dependent és @Singleton kontextusok • Interceptorok és dekorátorok • Sztereotípiák • Események • Kiterjesztések Mivel Maven alapú projekteket készítettem, így a Weld-et is egy Maven függőség (nem összekeverendő a tárgyalt témával) keretében emeltem be a projektbe⁵. A JBoss készített a Weld-ből egy kisebb változatot Java SE alkalmazásokhoz. Nem nagyon meglepő, hogy a neve Weld-SE. A következőképp lehet a Weld-et egy Maven 3 projektbe integrálni: <dependency>
org.jboss.weld.se <artifactId>weld-se
2.2.6.Final
Ezek után már nincs is nagyon más dolgunk, mint hátradőlni. Na jó, ez azért kicsit túlzás, a hátradőlés előtt még kell írnunk némi kódot. Ahhoz, hogy egy alkalmazásban kihasználjuk a Weld lehetőségeit, kettő opciónk is van: 1. A Weld StartMain osztályában rejlő main függvény felhívásával. 2. Egy saját main függvénnyel indítani. A lehetőségeket a könnyebb kipróbálás végett kettő külön Maven profilba osztottam el: az alapértelmezett profil egy JAR fájlt készít, amelyik a Weld indítási lehetőségeit használja ki. A másik profil (ownstart néven) pedig egy saját main függvénnyel rendelkező osztályon keresztül indítja el az alkalmazást.
Általánosságban a példákról A példák, mint már a fejezet elején is írtam, nagyon egyszerűek lesznek. Aki már fejlesztett Java SE alkalmazásokat, az tudja, hogy itt az indítás után a Java virtuális gépe (JVM) végrehajtja a bájtkódba átfordított utasítások sorozatát, majd véget ér. Ezt szálak és egy végtelen ciklus használatával ki lehet küszöbölni (figyelem: a grafikus felhasználói felületek szálakban futnak legalább egy végtelen ciklussal). Ebben a példában nincs szándékomban szálakat vagy éppen grafikus felületet alkalmazni, így az alkalmazás az elindulás után rögtön le is fog állni. Aki szeretné, bátran kibővtheti a programot saját ízlésére – ezért is áll verziókezelőben a kód. ⁵A könyv írásakor az aktuális Weld a 2.2.6.Final volt, amely már tartalmazza a CDI 1.2 módosításait is.
Mintaalkalmazások
7
A programok futtatása több módon is lehetséges. Mivel Maven projektekként vannak felépítve az alkalmazások, ezért lehet a parancssorból is futtatni őket, vagy be lehet importálni egy fejlesztőkörnyezetbe. Ebben a részben a parancssoros indítást ismertetem, mert így látható, hogy milyen paramétereket adok át az alkalmazásnak. Fejlesztőkörnyezetekben ezeket az indítási beállításoknál kell megadni, és futtatáskor nem látni rögtön, mivel is indítottunk. Ez olykor komolyabb fejtörésre ad okot. A futtatáshoz szüskéges, hogy előtte legyártsuk az alkalmazást. Ehhez a következő Maven parancsot kell kiadni a projekt könyvtárában (ahol a pom.xml fájl is található): mvn clean package
Ekkor a target mappában létrejött többek között egy cdi-standalone-1.0-SNAPSHOT.jar nevű fájl. Ebben található a mintaprogram, amelyben be van konfigurálva a Weld, és meg van adva, melyik az indító osztály (hol található a main függvény). Ezt a fájlt a következő módon futtathatjuk a projekt könyvtárából: java -jar target/cdi-standalone-1.0-SNAPSHOT.jar
Szerzői jogok Az alkalmazásokat MIT licenc alá helyeztem. Ez egy egyszerű megoldás: bárki használhatja a forrásokat, módosíthatja, tovább adhatja – csak annyit kell figyelembe venni, hogy a szerző nem felelős a felhasználásból és módosításból származó károkért. Természetesen ez egy nagyon tömör ismertető, a bővebb leíráshoz olvassa el a LICENSE nevű fájlt a példaprogram mellett.
A Weld start Ebben a részben lépésről lépésre építem fel a mintaalkalmazást, ha valakinek kedve tartja, kövesse a példát. Aki csak a végeredményt szeretné látni, ő megtekinheti a kész forrásfájlokat.
A Weld és a CDI típusbiztos esemény-modellje segítségével nincs szüksége az alkalmazásunknak saját main függvényre, elég az org.jboss.weld.environment.se.StartMain által dobott ContainerInitialized eseményre figyelni, és ezzel kapunk egy pontot a programkódunkban, ahonnan kezdhetjük az alkalmazás kiépítését. A bemutatott példa a Greeting.java fájlban található.
A kód, amiből kiindulunk egy egyszerű üdvözlő függvény, amelyik kiírja a konzolra, hogy “Hello World!”, mivel ez a legalapabb programkód, amivel a legtöbb könyv kezdődik.
Mintaalkalmazások
8
public class Greeter { public void printHello() { System.out.println("Hello World!"); } }
Ez a kódrészlet önmagában még nem fog működni, mert nincs benne egy main függvény, amit a JVM meghívhatna. Ellenben amint már mondtam, ebben a példában a Weld eseményét fogjuk felhasználni a függvény meghívására. Mindehhez arra van szükség, hogy a Shade pluginnek megadjuk a megfelelő osztályt, amely tartalmazza a main függvényt. Alternatívaként egy fejlesztő környezetből (én a JBoss Developer Studio-t használtam a példáknál) indítsuk el az alkalmazást – megnevezve a StartMain osztályt annak, amelyik tartalmazza a main függvényt. Aki futtatta a kódot az látta, hogy ennyi még nem elég, mert az indítás a következő hibaüzenetbe torkollik: Exception in thread "main" java.lang.IllegalStateException: WELD-ENV-000016: Missing beans.xml file in META-INF at org.jboss.weld.environment.se.Weld.initialize(Weld.java:128) at org.jboss.weld.environment.se.StartMain.go(StartMain.java:45) at org.jboss.weld.environment.se.StartMain.main(StartMain.java:55)
Szerencsére ez könnyen orvosolható: hozzuk létre a scr/main/resources mappában a META-INF mappát, majd ebben a mappában hozzunk létre egy beans.xml fájlt – ahogy a Weld is írta. Tartalomnak nem kell lennie benne: ez is a CDI 1.1 újításai közé tartozik. Ha most futtatjuk az alkalmazást, nem kapunk hibát – de annyira eredményt sem. Csak a Weld írja ki, hogy éppen mit csinál. Ez pedig nem sok, lássuk be. Ahogy írtam, szükségünk lesz a printHello függvényben arra, hogy észrevegyük, amikor a Weld elkészült, és elküldi a ContainerInitialized eseményt. Ezt könnyen megtehetjük a függvény paramétereinek kibővítésével: public void printHello(@Observes ContainerInitialized initialized) { System.out.println("Hello World!"); }
Ha most ismételten futtatjuk az alkalmazást, akkor a Weld indítási szövege után máris megkapjuk a konzolon a “Hello Wold!” feliratot. Az én környezetemben ez valahogy így néz ki: nov. 10, 2014 6:49:24 DE org.jboss.weld.bootstrap.WeldStartup INFO: WELD-000900: 2.2.6 (Final) nov. 10, 2014 6:49:24 DE org.jboss.weld.bootstrap.WeldStartup startContainer INFO: WELD-000101: Transactional services not available. Injection of @Inject UserTransaction ... Hello World!
Mintaalkalmazások
9
Hogy valamivel izgalmasabb legyen az alkalmazás, használjuk fel a programhívás paramétereit is: amennyiben vannak paraméterek, cseréljük le a World szót az üdvözlő üzenetünkben az első paraméterre. Ehhez csak annyit kell tennünk, hogy az előző metódusban az esemény mellé felvesszük a paraméterek listáját. A paramétereket két formában kaphatjuk meg: • tömb formátumban (ahogy azt a main függvény is megkapja), vagy • lista formátuban (könnyebb hozzáférést biztosítva ezzel)
Figyelem A paraméterek csak azután elérhetőek, hogy a ContainerInitialized esemény elküldésre került. Ha az inicializáláshoz szükség volna a paraméterekre, úgy azok tömbjét a StartMain osztály statikus getParameters() függvényének segítségével lehet lekérni.
Ebben a mintában a listás verziót használom fel, és a metódus a következőképp fog kinézni: public void printHello(@Observes ContainerInitialized initialized, @Parameters final List<String> parameters) { String greet = "World"; if (parameters != null && !parameters.isEmpty()) { greet = parameters.get(0); } System.out.println(String.format("Hello %s!", greet)); System.out.println("Hello World!"); }
Ha most az alkalmazást például a java -jar target/cdi-standalone-1.0-SNAPSHOT.jar CDI könyv
paranccsal futtatjuk, akkor a következő üdvözlő üzenet fogad minket:
Kis fejtörő Mielőtt tovább olvasná, kedves Olvasó, gondolkodjon el, mi lehet az alkalmazás futásának eredménye?
Mintaalkalmazások
10
nov. 11, 2014 5:13:59 DU org.jboss.weld.bootstrap.WeldStartup INFO: WELD-000900: SNAPSHOT nov. 11, 2014 5:13:59 DU org.jboss.weld.bootstrap.WeldStartup startContainer INFO: WELD-000101: Transactional services not available. ... nov. 11, 2014 5:13:59 DU org.jboss.weld.interceptor.util.InterceptionTypeRegistry WARN: WELD-001700: Interceptor annotation class javax.ejb.PostActivate not found, interception... nov. 11, 2014 5:13:59 DU org.jboss.weld.interceptor.util.InterceptionTypeRegistry WARN: WELD-001700: Interceptor annotation class javax.ejb.PrePassivate not found, interception... nov. 11, 2014 5:13:59 DU org.jboss.weld.bootstrap.MissingDependenciesRegistry ... INFO: WELD-000119: Not generating any bean definitions from org.jboss.logging.JBossLog... nov. 11, 2014 5:13:59 DU org.jboss.weld.bootstrap.MissingDependenciesRegistry ... INFO: WELD-000119: Not generating any bean definitions from org.jboss.logging.JBossLog ... nov. 11, 2014 5:13:59 DU org.jboss.weld.bootstrap.MissingDependenciesRegistry ... INFO: WELD-000119: Not generating any bean definitions from org.jboss.logging.Slf4jLogger ... nov. 11, 2014 5:14:00 DU org.jboss.weld.bootstrap.MissingDependenciesRegistry ... INFO: WELD-000119: Not generating any bean definitions from org.jboss.logging.Log4jLogger... nov. 11, 2014 5:14:00 DU org.jboss.weld.bootstrap.MissingDependenciesRegistry ... INFO: WELD-000119: Not generating any bean definitions from org.jboss.logging.Slf4jLoca... Hello CDI!
Igen, Hello CDI!, mert a “könyv” a paraméter listában külön paraméternek számít. Ha együtt szeretnénk megjeleníteni őket, akkor idézőjelek között kell átadni az alkalmazásnak.
Vége Pontosabban csak a minta könyvnek van ezzel vége. Aki kíváncsi a folytatásra, ő megveheti az elkészült könyvet, amely tartalmazza az eddig olvasott fejezeteket és még többet is. Szerintem megéri azt a 3 amerikai dollárt a könyv, olcsóbbat sehol sem találni.
Ami a könyv hátralevő részében lesz benne: • • • • • • • • • • • • • •
Beanek elérése és injektálása Minősítők Alternatívák CDI bean-ek gyártása Kontextusok Interceptorok Dekorátorok Sztereotípiák Kiterjesztések Események Tervezett újítások a CDI 2.0-ban A leírás, hogyan használhatjuk a Weld-et saját indító osztályból Egy összetettebb CDI SE példa, amelyben nem csak egy metódust hívunk meg Egy Java EE 7 webalkalmazás