JBoss mikrokonténer
A JBoss mikrokonténer a POJO-k (Plain Old Java Object - „Jó öreg Java-objektum”) konfigurálásához és kezeléséhez nyújt környezetet. Arra tervezték, hogy lemásolja a már létező JBoss mikrokernelt, de POJO környezetben, így azok használhatók önállóan a JBoss alkalmazásszerveren kívül is. A kezdeti kiadás a JBoss számára nyújt POJO környezetbe történő telepítéshez eszközöket, továbbá az alapvető szolgáltatásokat ad az önálló [EJB3] disztribúcióhoz. A POJO-k konfigurálása XML dokumentumok segítségével, összekapcsolásuk injektálással történik.
Bab gyűjtemények
[szerkesztés]A „babok” (JavaBeans) egyetlen csomagba való gyűjtése sokkal inkább egy konvenció, mint követelmény. Mindazonáltal ajánlott, hiszen így a "csomagok" mind önállóan, mind a JBoss alkalmazásszerveren belül használhatóak.
A mikrokonténer telepítés alapvető struktúrája egy .beans archívum, ami tartalmaz egy META-INF/jboss-beans.xml leíró dokumentumot, ami leírja a telepítendő szolgáltatásokat. Emellett a .beans archívum osztályokat és erőforrásokat tartalmaz, mint bármely más JAR állomány.
example.beans/
example.beans/META-INF/jboss-beans.xml
example.beans/com/acme/SomeClass.class
Ha el kívánunk helyezni egy .beans állományt egy EAR csomagban, szolgáltatás modulként hivatkozni kell rá a META-INF/jboss-app.xml
.ből.
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE jboss-app PUBLIC "-//JBoss//DTD J2EE Application 1.4//EN" "http://www.jboss.org/j2ee/dtd/jboss-app_4_0.dtd"> <jboss-app> <module> <service>example.beans</service> </module> </jboss-app>
Alapvető konfiguráció
[szerkesztés]A mikrokonténer fő célja, hogy levetővé tegye a POJO-k külső konfigurálását. Konfigurációs fájlt több szinten is megadhatunk, így csomag szinten, bab szinten, vagy akár egy tulajdonság altulajdonságának szintjén is. A konfiguráció fő eleme a bab, ami alapvetően egy POJO, tehát egy Java osztály egy példánya. Legfelső szinten a <deployement>
áll, mely egy telepítést jelöl, ennek elemei a <bean>
elemmel jelölt babok.
A bab egy osztály egy példánya, azaz az XML állomány határozza meg a memóriába betöltendő objektumokat. A <bean name="Name1" class="com.acme.Example"/>
hatására a new com.acme.Example();
Java kód hajtódik végre. Ez természetesen csak akkor működik, ha az osztálynak van alapértelmezett konstruktora. Ha nincs, akkor a <constructor>
elemet kell használni, melyek <parameter>
elemei adják meg a konstruktor paramétereit. Ez utóbbi opcionálisan tartalmazhat típusparamétert is, ha több azonos paraméterszámú konstruktor is van az osztályban. A rendszer típus-következtető képessége kiváló. Például:
public class Example{
public Example(String string, int integer) {}
public Example(String string, long long) {}
}
<bean name="Name1" class=com.acme.Example">
<constructor>
<parameter>example string</parameter>
<parameter class="long">4</parameter>
</constructor>
</bean>
new com.acme.Example(new String("example string"), (long) 4);
Némely osztálynak nem érhető el a konstruktora, például a Factory minta esetén. Ekkor is a <constructor>
elemet kell használni, a factoryClass
és factoryMethod
attribútumokkal, illetve a <factory>
alelemmel, melynek <bean>
attribútuma megadja azt az objektumot, mely az általunk kért objektumot "legyártja". A <parameter>
elem hasonlóan használható.
Fejlesztők között általában sok a vita arról, hogy mely tulajdonságokat kell a konstruktorba helyezni és melyeket kell set... utasításokkal elérni. A Java Bean-ek esetében általános konvenció, hogy az osztály konstruktora vagy az alapértelmezett, vagy minimális számú paramétert tartalmaz, és a tulajdonságok beállítására a setter metódusok szolgálnak. Ezt ebben az esetben a <bean>
elemen belüli <property>
elemmel lehet elérni, hogy a rendszer az objektum létrehozása után meghívja ezeket a metódusokat, ehhez a name
attribútumnak kell értékül adni a tulajdonság nevét. Például:
public class Example{
public String getTitle() {}
public void setTitle(String string) {}
}
<bean name="Name1" class=com.acme.Example">
<property name="title">example string</property>
</bean>
Example example = new com.acme.Example();
example.setTitle(new String("example string"));
Bár a mikrokonténer típusmeghatározása nagyon jó, bizonyos esetekben, különösen a primitív típusok és a null
érték esetén szükséges némi plusz információ. A null
értéket a <null/>
elem reprezentálja. Sok esetben pedig az objektum valamely tulajdonsága absztrakt osztály vagy interfész típusú, ekkor típuskényszerítésre lehet szükség, amit a <property>
elemen belüli <value>
elem class
attribútumának beállításával lehet elérni.
A babok összekapcsolása egy újabb problémakör, ugyanis az egyszerű literál értékeket a rendszer csak primitív típusokká (szöveg, szám, ...) képes feldolgozni, objektumokká nem. Ekkor szükséges az injektálás, ami a <property>
elemen belüli <inject>
elem bean
attribútumával adható meg.
Az összekapcsolás speciális esete a kollekciók injektálása. Ennek segítésére a mikrokonténer értelmezi az alapvető kollekcióknak megfelelő elemeket, mint <collection/>
, <list/>
, <set/>
és <array/>
. Az alapértelmezett megvalósítás ezekhez sorrendben java.util.ArrayList
, java.util.ArrayList
, java.util.HashSet
és java.lang.Object[]
, de saját is megadható a class
attribútummal, természetesen a típuskorláton belül. Meg kell adni az elemek típusát is, akár a felső szinten az elementClass
vagy minden elemen a class
attribútummal. Ezután a <value>
elemmel megadhatók az elemek. A <map>
elem megvalósítása ettől kis mértékben eltér, a kulcs-érték párok miatt. Fontos megjegyezni, hogy a mikrokonténer nem használja a generikus paramétereket.
Életciklus
[szerkesztés]A mikrokonténer életciklusa az alábbi elemekből áll:
- Nem telepített: a POJO-ról nincs leírás vagy törölték.
- Leírt: a POJO leírása beolvasásra került és a függőségeket sikerült meghatározni.
- Példányosított: minden, a konstruáláshoz szükséges függőség ki lett elégítve, tehát az osztály létezik, a konstruktor injektálandó paraméterei elérhetőek, minden szükséges factory objektum elérhető.
- Beállított: minden tulajdonsághoz szükséges injektálandó objektum elérhető, beleértve a kollekciók függőségeit.
- Létrehozott: minden függő objektum létre lett hozva, beleértve a
create
metódus injekcióit. - Indítás: minden függő objektum elindult, beleértve a
start
metódus injekcióit. - Telepített: a ciklus véget ért.
A függőségek explicit módon is megadhatók, a <depends>
elem segítségével, így a JMX-hez hasonló kétfázisú függőség-feloldásra van lehetőség. A create
, start
, stop
és destroy
metódusok felülírhatók, így akár paraméterek fogadására is alkalmassá tehetők.
Összefoglalás
[szerkesztés]A mikrokonténer erőteljes helyettesítés a JBoss JMX mikrokonténer helyére. Képes a JBoss lazán csatolt konfigurációs környezetét a POJO környezetbe átültetni, ezzel több irányítási lehetőséget és szolgáltatást adva a fejlesztőnek a JBoss alkalmazásszerveren mind kívül, mind belül. Ennek a megközelítésnek nagy a potenciálja új képességek terén, például aspektus orientáltság, on-demand szolgáltatások, verziókövetés, stb.