EJB 2.x – Entity Beans (BMP – vytvorenie a použitie dátového zdroja)

27. října 2005

Bez ohľadu na to, či používate ORM (Object-Relational Mapping) alebo nie, mali by ste poznať aspoň základy technológie JDBC, ak chcete implementovať vaše entity beans použitím BMP (Bean-Managed Persistence). Preto tu budem predpokladať, že určité základy JDBC máte. V opačnom prípade vám odporúčam si ich naštudovať.

Obrovskou výhodou použitia EJB všeobecne je, že čo sa týka manažovania databázových pripojení (database connection pooling), väčšinu práce za vás vykonáva EJB kontajner (prostredníctvom vhodného správcu zdrojov). Okrem toho sa do hry zapája aj iný správca zdrojov (resource manager), zodpovedný za realizáciu transakcí a transakčnosť. O týchto dvoch pojmoch sa dozviete viac v ďalších článkoch.

Použitie JDBC vo vašich entitných triedach spoliehajúcich sa na BMP, sa líši len veľmi málo od iných bežných Java tried spolupracujúcich s DB systémami. Jediný poznateľný a dôležitý rozdiel je v tom, ako sa konfiguruje vhodný dátový zdroj a ako naň získame konekciu. Aby mohol databázový správca zdrojov pracovať pre vás, musíte požiadať o konekciu na DB server určitým konkrétnym predpísaným spôsobom. Tento spôsob spočíva v tom, že požiadate o konekciu takzvanú továrenskú triedu (resource manager connection factory). V našom prípade to musí byť objekt implementujúci rozhranie javax.sql.DataSource, alebo javax.sql.XADataSource. Možno to vyzerá na prvý pohľad komplikovane, ale čoskoro zistíte, že po nakonfigurovaní dátového zdroja sa pracuje a žiada o pripojenia oveľa jednoduchšie, ako pri použití triedy DriverManager.

Tu by som chcel poznamenať, že v tejto časti sa zameriavame výhradne na dátové zdroje, pretože o ne pri BMP ide. Ale aj ostatné typy zdrojov sú manažované EJB kontajnerom úplne rovnakým spôsobom, ako tu bude popísané. Napríklad sa jedná o JMS (Java Messaging System) a JavaMail zdroje, ktoré sú tiež manažované použitím príslušných továrenských objektov.

Definícia connection poolu

Z pohľadu programátora každý J2EE aplikačný server transparentne zabezpečuje vytváranie a správu databázových pripojení. Táto správa je na jednej strane veľmi náročná záležitosť a na strane druhej je veľmi dôležitá pre škálovateľnosť enterprise-class systémov. Skutočnosť, že sa to deje akoby za scénou, je podstatná výhoda použitia EJB.

Aby mohol aplikačný server správne manažovať jemu zverené dátové zdroje, musí mať o nich dostatok informácií. Keďže tieto zdroje bývajú obvykle využívané viac než jednou aplikáciou, musia byť uložené nezávisle, teda v externom súbore. Neexistuje štandard v tejto oblasti, preto každý dodávateľ aplikačného servera definuje vlastný spôsob a miesto, ako a kde zadefinovať potrebné informácie o dátových zdrojoch. Nasledovný príklad je určený pre server BEA WebLogic 8.1:

<Domain name=“mydomain“>
 …
 <!– Definícia dátového zdroja –>
 <JDBCDataSource
  JNDIName=“auctionSource“
  Name=“auctionSource“
  PoolName=“auctionPool“
  Targets=“myserver“ />
 <!– Definícia connection poolu –>
 <JDBCConnectionPool
  CapacityIncrement=“1″
  DriverName=“com.pointbase.jdbc.jdbcUniversalDriver“
  InitialCapacity=“2″
  MaxCapacity=“10″
  Name=“auctionPool“
  Password=“ejb20″
  Properties=“user=ejb20″
  RefreshMinutes=“0″
  ShrinkPeriodMinutes=“15″
  ShrinkingEnabled=“true“
  SupportsLocalTransaction=“true“
  Targets=“myserver“
  TestConnectionsOnRelease=“false“
  TestConnectionsOnReserve=“false“
  TestTableName=“SYSTABLES“
  URL=“jdbc:pointbase:server://localhost/ejb20″ />
 …
</Domain>

Uvedený príklad definuje connection pool s názvom auctionPool asociovaný s PointBase serverom, bežiacim na tom istom stroji ako aplikačný server. Tento pool je asociovaný s dátovým zdrojom nazvaným auctionSource. To, čo bude zaujímať programátora, je práve definícia dátového zdroja. Tento zdroj budeme prostredníctvom JNDI žiadať o konekciu, pričom manažment konekcií bude realizovaný práve v asociovanom poole. Ostatné aplikačné servery majú veľmi podobný mechanizmus. Napríklad nasledujúca ukážka je určená pre SUN Application Server PE 8:

<domain …>
 <applications<…</applications>
 <resources>
  <!– Definícia dátového zdroja –>
  <jdbc-resource jndi-name=“jdbc/auctionSource“
   pool-name=“auctionPool“
   object-type=“user“ enabled=“true“ />
  <!– Definícia connection poolu –>
  <jdbc-connection-pool
   name=“auctionPool“
   connection-validation-method=“auto-commit“
   datasource-classname=“com.pointbase.xa.xaDataSource“
   fail-all-connections=“false“
   idle-timeout-in-seconds=“300″
   is-connection-validation-required=“false“
   is-isolation-level-guaranteed=“true“
   max-pool-size=“32″
   max-wait-time-in-millis=“60000″
   res-type=“javax.sql.XADataSource“
   pool-resize-quantity=“2″
   steady-pool-size=“8″ />
   <property
    name=“DatabaseName“
    value=“jdbc:pointbase:server://localhost:9092/ejb20″ />
   <property name=“Password“ value=“ejb20″ />
   <property name=“User“ value=“ejb20″ />
  </jdbc-connection-pool>
 </resources>
 <configs>…</configs>
 <servers>…</servers>
</domain>

Definícia referencie na connection factory

Entitná trieda, vyžadujúca prístup k spomínaným továrenským triedam, potrebuje vlastniť referenciu na tieto triedy definovanú v rámci existenčného prostredia entitnej triedy. Prvým krokom, potrebným na zabezpečenie uvedeného, je definovať element <resource-ref> v deployment deskriptore ejb-jar.xml. Jeho príkladom môže byť nasledovná ukážka:

<ejb-jar>
 <enterprise-beans>
  <entity>
   <ejb-name>EnglishAuction</ejb-name>
   …
    <reentrant>False</reentrant>
    <!– Definícia elementu <resource-ref> –>
    <resource-ref>
     <description>Definuje referenciu na továrenskú
     triedu manažéra zdrojov pre databázu aukčného systému
     </description>
     <res-ref-name>jdbc/auctionSource</res-ref-name>
     <res-type>javax.sql.DataSource</res-type>
     <res-auth>Container</res-auth>
    </resource-ref>
  …
  </entity>
  …
 </enterprise-beans>
 …
</ejb-jar>

Element <resource-ref> definovaný v deployment deskriptore svojím spôsobom definuje závislosť na konkrétnom dátovom zdroji. Subelement <res-ref-name> potom označuje dátový zdroj názvom, pod ktorým bude zaznamenaný v existenčnom prostredí EJB. Ďalší subelement <res-type> určuje typ továrenskej triedy, ktorá predstavuje manažéra databázových pripojení. Posledný subelement <res-auth> môže nadobúdať iba dve hodnoty – Application, alebo Container. V prípade, že použijete prvú z nich, budete musieť programovo zabezpečiť prihlásenie sa k manažérovi zdrojov. V druhom prípade to za vás vykoná EJB kontajner, použijúc pritom informácie poskytnuté pri definovaní connection poolu.

Ak pozorne sledujete všetky uvedené fakty, tak možno vás už v tejto chvíli napadlo, ako vlastne bude možné pristupovať k definovanému dátovému zdroju. Ako ho budeme môcť kontaktovať. Ak si všimnete ešte raz vyššie uvedené príklady, tak dátový zdroj (auctionSource) so všetkými svojimi parametrami je definovaný na úrovni aplikačného servera (BEA WebLogic 8.1, SUN Application Server PE 8). Na druhej strane na úrovni entitnej triedy v konfiguračnom súbore ejb-jar.xml sme zadefinovali len akýsi viacúrovňový názov pre dátový zdroj (jdbc/auctionSource). Je teda očividné, že niekde treba ešte zadefinovať prepojenie medzi týmito dvoma elementami.

Problém je v tom, že element <resource-ref> síce definuje záznam pre použitú továrenskú triedu, ale nemapuje tento záznam na konkrétny dátový zdroj. Toto je však nutné vykonať, a to pomocou nástrojov, ktoré definuje dodávateľ aplikačného servera. V prípade servera WebLogic 8.1 je treba pridať záznam do súboru weblogic-ejb-jar.xml:

<weblogic-ejb-jar>
 <weblogic-enterprise-bean>
  <ejb-name>EnglishAuction</ejb-name>
  …
  <reference-descriptor>
   <resource-description>
    <!– Mapovanie záznamu na skutočný dátový zdroj –>
    <res-ref-name>jdbc/auctionSource</res-ref-name>
    <jndi-name>auctionSource</jndi-name>
   </resource-description>
   …
  </reference-descriptor>
  …
 </weblogic-enterprise-bean>
 …
</weblogic-ejb-jar>

Uvedený deployment deskriptor weblogic-ejb-jar.xml prepojí hodnotu elementu <res-ref-name>, definovanú pre aukčný dátový zdroj v súbore ejb-jar.xml, s dátovým zdrojom, ktorý pozná aplikačný server. Z toho dôvodu musí položka <jndi-name> presne odpovedať názvu dátového zdroja, rozpoznateľného serverom.

Získanie databázového pripojenia na dátový zdroj

Po tom, čo nakonfigurujeme dátový zdroj a definujeme referenciu na connection factory, získanie databázového pripojenia je hračka. Nasledujúci výpis kódu predstavuje príklad, ktorý je možné použiť ako ukážku. Kód môže byť implementovaný v rámci konkrétnej entitnej triedy, ale tu je vo forme pomocnej triedy, ktorá tým pádom môže byť použitá ľubovoľným počtom iných tried. Reťazec, ktorý poskytnete ako parameter metódy getConnection(), respektíve metódy lookup(), musí presne odpovedať hodnote subelementu <res-ref-name> umiestnenom v deployment deskriptore ejb-jar.xml. V prípade aukčného systému to bude reťazec "auctionSource".

DSConnectionHelper.java:

import java.sql.Connection;
import java.sql.SQLException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class DSConnectionHelper {
 public static Connection getConnection(
                               String dataSourceJNDIName) {
  InitialContext initCtx = null;
  try {
   initCtx = new InitialContext();
   /** vyhľadáme danú referenciu v jdbc subkontexte
   * @param dataSourceJNDIName JNDI referencia na dátový zdroj
   **/

   DataSource source =
   (DataSource)initCtx.lookup(„java:comp/env/jdbc/“ +
   dataSourceJNDIName);
   /**
   * požiadame o konekciu z connection poolu
   **/

   return source.getConnection();
  }
  /**
  * zaobalíme JNDI alebo SQL výnimku do systémovej výnimky
  **/

  catch (NamingException ne) {
   throw new EJBException(ne);
  }
  catch (SQLException se) {
   throw new EJBException(se);
  }
  finally {
   /**
   * uzatvoríme InitialContext
   **/

   try {
    if (initCtx != null) {
     initCtx.close();
    }
   }
   catch (Exception ex) {
    throw new EJBException(ex);
   }
  }
 }
}

Uvedený príklad využíva princípy, ktoré sú popísané v JNDI – Java Naming and Directory, takže ak by vám nebolo celkom jasné, čo vykonáva metóda lookup(), respektíve k čomu je objekt InitialContext, skúste nazrieť do niektorého článku. Toto okrem iného predpokladá, že niekde v classpath máte umiestnený konfiguračný súbor jndi.properties, obsahujúci nutné premenné prostredia.

Vytvorenie databázovej schémy aukčného systému.

Cieľom tohto článku nie je vybudovať a implementovať všetok kód potrebný pre aukčný systém, ale zároveň využívame určité časti implementácie triedy EnglishAuctionBean. A to preto, aby sme ilustrovali použitie BMP metód. Tieto metódy určite dostanú väčší zmysel vtedy, ak pochopíte podkladovú databázovú schému. Aby som tu však nevypisoval všetky potrebné SQL príkazy, umiestnil som ich do súboru, ktorý si môžete stiahnuť. Ešte podotýkam, že uvedená schéma je vytvorená pre MS SQL 2000 server. Takže ak budete používať odlišnú databázu, budete musieť zrejme adaptovať uvedenú syntax a prípadne dátové typy k „obrazu svojmu“.

Předchozí článek CSS3 - zpět do budoucnosti
Další článek whitwa.net
Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *