V tomto článku zakončíme tématiku BMP (Bean Managed Persistence), a to tým, že si ukážeme, ako nami vytvorené triedy a rozhrania nasadíme na aplikačný server. Vytvoríme si konfiguračný súbor označovaný ako deployment descriptor a ukážeme si, ako našu entitu otestovať.

V predchádzajúcich článkoch sme sa intenzívne zaoberali okrem iného aj definovaním jednotlivých domovských a komponent rozhraní EnglishAuctionHome (respektíve EnglishAuction) a tiež sme si vytvorili implementačnú triedu EnglishAuctionBean. Posledným krokom je obvykle definovanie informácií potrebných na ich úspešný deployment. Tieto informácie sa vkladajú do už spomínaného deployment deskriptora, ktorého názov je ejb-jar.xml. Nasledovný výpis obsahuje kompletný deskriptor pre entitu aukcie (EnglishAuction), položku aukcie (Item) a dražiteľa (Bidder).

XML Deployment Descriptor – ejb-jar.xml:

<?xml version=“1.0″?>
<!DOCTYPE ejb-jar PUBLIC
 ‚-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN‘
 ‚http://java.sun.com/dtd/ejb-jar_2_0.dtd‘>
 <ejb-jar>
  <enterprise-beans>
   <entity>
    <ejb-name>EnglishAuction</ejb-name>
    <local-home>interval.EnglishAuctionHome</local-home>
    <local>interval.EnglishAuction</local>
    <ejb-class>interval.EnglishAuctionBean</ejb-class>
    <persistence-type>Bean</persistence-type>
    <prim-key-class>java.lang.Integer</prim-key-class>
    <reentrant>False</reentrant>
    <ejb-local-ref>
     <description>EJB reference used to locate an item.
     </description>
     <ejb-ref-name>ejb/Item</ejb-ref-name>
     <ejb-ref-type>Entity</ejb-ref-type>
     <local-home>interval.ItemHome</local-home>
     <local>interval.Item</local>
    </ejb-local-ref>
    <resource-ref>
     <description>Reference to a connection factory.
     </description>
     <res-ref-name>jdbc/auctionSource</res-ref-name>
     <res-type>javax.sql.DataSource</res-type>
     <res-auth>Container</res-auth>
    </resource-ref>
   </entity>
   <entity>
    <ejb-name>Bidder</ejb-name>
    <local-home>interval.BidderHome</local-home>
    <local>interval.Bidder</local>
    <ejb-class>interval.BidderBean</ejb-class>
    <persistence-type>Bean</persistence-type>
    <prim-key-class>java.lang.Integer</prim-key-class>
    <reentrant>False</reentrant>
    <resource-ref>
     <description>Reference to connection factory.
     </description>
     <res-ref-name>jdbc/auctionSource</res-ref-name>
     <res-type>javax.sql.DataSource</res-type>
     <res-auth>Container</res-auth>
    </resource-ref>
   </entity>
   <entity>
    <ejb-name>Item</ejb-name>
    <local-home>interval.ItemHome</local-home>
    <local>interval.Item</local>
    <ejb-class>interval.ItemBean</ejb-class>
    <persistence-type>Bean</persistence-type>
    <prim-key-class>java.lang.Integer</prim-key-class>
    <reentrant>False</reentrant>
    <resource-ref>
     <description>Reference to connection factory.
     </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>
  <assembly-descriptor>
   <container-transaction>
    <method>
     <ejb-name>EnglishAuction</ejb-name>
     <method-name>*</method-name>
    </method>
    <trans-attribute>Required</trans-attribute>
   </container-transaction>
   <container-transaction>
    <method>
     <ejb-name>Bidder</ejb-name>
     <method-name>*</method-name>
    </method>
    <trans-attribute>Required</trans-attribute>
   </container-transaction>
   <container-transaction>
    <method>
     <ejb-name>Item</ejb-name>
     <method-name>*</method-name>
    </method>
    <trans-attribute>Required</trans-attribute>
   </container-transaction>
  </assembly-descriptor>
 </ejb-jar>

Deployment deskriptor samozrejme podporuje viac rôznych parametrov, pričom všetky sú uvedené v DTDčku http://java.sun.com/dtd/ejb-jar_2_0.dtd používaného v ejb-jar.xml. V podstate to môžeme zhrnúť tak, že uvedený deskriptor definuje aukčnú entitu EnglishAuction používajúcu Bean Managed Persistence, podporujúcu iba lokálnych klientov a majúcu primárny kľúč typu Integer. Vyžaduje lokálnu referenciu na Item entitu a používa dátový zdroj. Zároveň by všetky metódy mali byť implementované ako transakcie.

EnglishAuction – testovanie entity

Najjednoduchším spôsobom ako otestovať entitu je napísať jednoduchú Java triedu, ktorá otestuje biznis metódy entity beanu. Avšak za týmto účelom musíme najprv deklarovať testovacie remote a remote home rozhranie. Nasledujú výpisy týchto rozhraní, pričom je možné si všimnúť, že obsahujú podmnožinu metód deklarovaných v ich lokálnych náprotivkoch.

EnglishAuctionRemote.java:

package interval;
/**
* Title: EnglishAuctionRemote
* Description: Remote interface used to test the
* EnglishAuction entity bean
*/

import javax.ejb.EJBObject;
import java.rmi.RemoteException;
import java.sql.Timestamp;
public interface EnglishAuctionRemote extends EJBObject {
 public Integer getId() throws RemoteException;
 public void setName(String newName) throws RemoteException;
 public String getName() throws RemoteException;
 public void setDescription(String newDescription)
  throws RemoteException;
 public String getDescription() throws RemoteException;
 public void setStartingBid(Double newStartingBid)
  throws InvalidAuctionStatusException, RemoteException;
 public Double getStartingBid() throws RemoteException;
 public void setMinBidIncrement(Double newMinBidIncrement)
  throws InvalidAuctionStatusException, RemoteException;
 public Double getMinBidIncrement() throws RemoteException;
 public void setReserveAmount(Double newReserveAmount)
  throws InvalidAuctionStatusException, RemoteException;
 public Double getReserveAmount() throws RemoteException;
 public void setStartDateTime(Timestamp newStartDateTime)
  throws InvalidAuctionStatusException, RemoteException;
 public Timestamp getStartDateTime() throws RemoteException;
 public void setScheduledEndDateTime(Timestamp newScheduledEndDateTime)
  throws InvalidAuctionStatusException, RemoteException;
 public Timestamp getScheduledEndDateTime()
  throws RemoteException;
}

EnglishAuctionRemoteHome.java:

package interval;
/**
* Title: EnglishAuctionRemoteHome
* Description: Remote home interface for testing the
* EnglishAuction entity bean
*/

import java.rmi.RemoteException;
import java.util.Collection;
import javax.ejb.EJBHome;
import javax.ejb.CreateException;
import javax.ejb.FinderException;
public interface EnglishAuctionRemoteHome extends EJBHome {
 public EnglishAuctionRemote create()
  throws CreateException, RemoteException;
 public EnglishAuctionRemote createWithData(String name, String description)
  throws CreateException, RemoteException;
 public EnglishAuctionRemote findByPrimaryKey(Integer primaryKey)
  throws FinderException, RemoteException;
 public Collection getItemsBeingAuctioned()
  throws RemoteException;
}

Po vytvorení týchto dvoch rozhraní je vhodné prispôsobiť aj obsah deployment deskriptora ejb-jar.xml:

<entity>
 <ejb-name>EnglishAuction</ejb-name>
 <home>interval.EnglishAuctionRemoteHome</home>
 <remote>interval.EnglishAuctionRemote</remote>
 <local-home>interval.EnglishAuctionHome</local-home>
 <local>interval.EnglishAuction</local>
 <ejb-class>interval.EnglishAuctionBean</ejb-class>
 <persistence-type>Bean</persistence-type>
 <prim-key-class>java.lang.Integer</prim-key-class>
 <reentrant>False</reentrant>
</entity>

Deployment každej enterprise beany podľa špecifikácie EJB 2.0 vyžaduje vytvorenie JAR súboru ejb-jar, ktorého obsah bude zahŕňať implementáciu jednotlivých beanov vo forme class súborov a zároveň ich home a component rozhrania spolu s XML deployment deskriptormi, ktoré musia byť umiestnené v META-INF zložke.

Nasledujúci výpis obsahuje jednoduchého klienta, ktorý môže byť použitý na vytvorenie aukcie a modifikovanie jedného z jej atribútov.

EntityBeanClient.java:

package interval;
/**
* Title: EntityBeanClient
* Description: Simple java client to test EntityBean enterprise bean
*/

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
public class EntityBeanClient {
 public void createAuction() {
  try {
   // pull initial context factory and provider info from
   // jndi.properties

   Context ctx = new InitialContext();
   // obtain a reference to the auction remote home interface
   Object home = ctx.lookup(„EnglishAuctionRemote“);
   EnglishAuctionRemoteHome auctionHome = (
    EnglishAuctionRemoteHome) PortableRemoteObject.narrow(
    home, EnglishAuctionRemoteHome.class);
   // create a new auction
   EnglishAuctionRemote auction = auctionHome.createWithData(
    „My Auction“,“Test Auction“);
   // call a business method on the remote interface
   auction.setStartingBid(new Double(100.00));
   System.out.println(„Created auction: “ + auction.getName()
    + “ with starting bid “ + auction.getStartingBid());
   ctx.close();
  }
  catch (NamingException ne) {
   System.out.println(ne.getMessage());
  }
  catch (Exception e) {
   e.printStackTrace();
  }
 }
 public static void main(String[] args) {
  EntityBeanClient auctionClient = new EntityBeanClient();
  auctionClient.createAuction();
 }
}

V tejto časti sme ukončili tému Entity Beans Bean-Managed Persistence a v ďalšej sa začneme zaoberať druhým typom Entity Beans Container-Managed Persistence. Na záver vám ponúkam vytvorené triedy na stiahnutie. Niektoré z nich som mierne upravil.

V predchádzajúcich článkoch ste mali možnosť zistiť, že BMP znamená prevziať zodpovednosť za databázové volania potrebné na ukladanie stavu entitnej triedy. Za týmto účelom je možné použiť JDBC alebo niektorý z ORM frameworkov, ktoré vám pomôžu namapovať jednotlivé atribúty objektov na databázové tabuľky. Bez ohľadu na to, aké API si vyberiete, BMP bean musí implementovať načítanie a ukladanie jednotlivých entitných objektov a ich závislých objektov spôsobom, ktorý stanovuje kontajner. Je to totiž EJB kontajner, ktorý zabezpečuje spomínanú synchronizáciu jednotlivých inštancií BMP entity (volaním metód ejbLoad() a ejbStore(), okrem iných).

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět