Configuring a Data Source

   

A benefit of EJB is that the container manages database connection pooling for you. It also enlists the resource manager to manage transactions automatically. You'll learn more about resource managers and transaction enlistment in Chapter 12, "Transactions," so don't worry about what that part means yet if it's unfamiliar to you. In short, a resource manager provides access to a data store of some type. In this chapter, a relational database management system is the resource manager of the most interest.

Most of the JDBC coding you do in a bean class that uses BMP is no different than what you'd do in a non-EJB application. The only significant difference is in how you configure a data source and obtain a connection to it. For a container to do its work for you, you must obtain a connection to a database a certain way so that the container can manage it. The way you do this is to obtain your connections through a resource manager connection factory. In the case of databases, this factory is an object that implements the javax.sql.DataSource interface. This might sound more difficult than what you're accustomed to with JDBC, but once you have a data source configured, it's easier than working with the methods of DriverManager to obtain connections.

Note

This section focuses only on database resources because that's what matters to BMP, but other types of resources are managed by the container in the same way described here. In particular, JMS and JavaMail resources are managed using resource manager connection factories.


Defining a Connection Pool

A J2EE application server makes the pooling of database connections transparent to you as an application developer. Managing this type of resource is difficult to do yourself but it's critical to scalability in an enterprise system. Having it done for you behind the scenes is a significant benefit of EJB.

For an application server to manage connections for you, it needs to know about the data stores you're using. More than one application can use the same database, so you provide this information separate from any details about your applications. There's no standard way to do this, so it's up to each vendor to provide the necessary tools to define data sources and connection pools. The following configuration information illustrates the data you supply to WebLogic 6.1 to do this:

 <Domain    Name="mydomain"  >    ...    <JDBCDataSource      JNDIName="auctionSource"      Name="auctionSource"      PoolName="auctionPool"      Targets="myserver"    />    <JDBCConnectionPool      CapacityIncrement="1"      DriverName="weblogic.jdbc.mssqlserver4.Driver"      InitialCapacity="1"      MaxCapacity="3"      Name="auctionPool"      Properties="user=ejb20;password=ejb20;server=localhost;port=4073"      Targets="myserver"      URL="jdbc:weblogic:mssqlserver4:ejb20"    />    ...  </Domain> 

This particular example defines a connection pool named auctionPool associated with a SQL Server database running on the same machine as the application server at the specified port. This pool is associated with a data source named auctionSource . It's actually the data source and not the pool that's referenced by the deployer of an EJB application to associate the application with a particular database. Other application servers have a similar mechanism for defining data sources.

Defining a Resource Manager Connection Factory Reference

For a bean class to access a connection factory, it must have a reference to it defined within its environment. The first step in doing this is to define a resource-ref entry in the ejb- jar.xml deployment descriptor for the bean, as shown in the following:

 <ejb-jar>    <enterprise-beans>      <entity>        <ejb-name>EnglishAuction</ejb-name>        ...        <reentrant>False</reentrant>        <resource-ref>          <description>Define a reference to a resource manager connection            factory for the auction database          </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> 

The complete deployment descriptor for the auction entity bean is provided at the end of this chapter, but you'll see it built up along the way. A resource-ref element in the deployment descriptor lets the deployer know of an EJB's dependence on a particular data source. The res-ref-name defines the name used for the entry in the bean's environment. As shown in this example, you should use the jdbc subcontext for all JDBC resources that you define. The res-type of javax.sql.DataSource designates this reference as being one to a Connection object factory. The res-auth element can be assigned a value of either Application or Container . If you specify Application , your bean code must programmatically log in to the resource manager. If you specify Container , as was done here, the container logs in for you using the information supplied by the deployer to define the connection pool. This is the recommended approach.

The resource-ref entry in ejb-jar.xml defines an entry in the bean's environment for a connection factory but it doesn't map that entry to an actual data source. You must do that using whatever method your application server vendor provides. In the case of WebLogic, that means including an entry in the weblogic-ejb-jar.xml deployment descriptor as shown in the following:

 <weblogic-ejb-jar>    <weblogic-enterprise-bean>      <ejb-name>EnglishAuction</ejb-name>      ...      <reference-descriptor>        <resource-description>          <res-ref-name>jdbc/auctionSource</res-ref-name>          <jndi-name>auctionSource</jndi-name>        </resource-description>        ...      </reference-descriptor>      ...    </weblogic-enterprise-bean>    ...  </weblogic-ejb-jar> 

This deployment descriptor associates the res-ref-name for the auction data source given in the ejb-jar.xml file with a data source known by the application server. The jndi-name given here for the data source has to match a data source name recognized by the server.

Getting a Connection from Within an EJB

After you've configured a data source and defined a reference to a connection factory for it, getting a connection to a database is easy. Listing 6.1 shows an example method you can use for doing this. You could implement this within an entity bean class, but it's shown here as a static helper method that can be used by multiple bean classes. The name you use in the lookup must match the res-ref-name in the deployment descriptor. For the auction data source, you would call this method and pass the string " auctionSource" as the argument.

Listing 6.1 getConnection “A Method for Obtaining a JDBC Database Connection Using JNDI
 package com.que.ejb20.common.ejb;  ...  public class BMPHelper {   ...    public static Connection getConnection(String dataSourceJNDIName) {     InitialContext initCtx = null;      try {       initCtx = new InitialContext();        // look up the reference in the jdbc subcontext        DataSource source =         (DataSource)initCtx.lookup("java:comp/env/jdbc/" + dataSourceJNDIName);        // get a connection from the pool        return source.getConnection();      }      // wrap any JNDI or SQL exception with a system exception      catch (NamingException ne) {       throw new EJBException(ne);      }      catch (SQLException se) {       throw new EJBException(se);      }      finally {       // close the InitialContext        try {         if (initCtx != null) {           initCtx.close();          }        }        catch (Exception ex) {         throw new EJBException(ex);        }      }    }    ...  } 

Note

Listing 6.1 and the other examples in this chapter use the approach described in Chapter 4, "Java Naming and Directory Interface," of calling the no-argument constructor of InitialContext . This assumes that a jndi.properties file containing the necessary environment entries exists in the classpath.


The Auction Schema

The intent of this chapter isn't to build up all the code needed to implement the auction site, but it does use parts of the EnglishAuctionBean implementation to illustrate BMP method implementations . These methods make more sense if you understand the underlying database schema, so the SQL needed to create a database for the auction code appears in Listing 6.2.

Listing 6.2 DDL for Creating the Auction Schema
 CREATE TABLE address (   id int NOT NULL ,    AddressLine1 varchar (50) NOT NULL ,    AddressLine2 varchar (50) NULL ,    City varchar (25) NOT NULL ,    State varchar (2) NOT NULL ,    ZipCode varchar (10) NOT NULL  );  CREATE TABLE auction (   id int NOT NULL ,    Name varchar (30) NOT NULL ,    Description varchar (100) NULL ,    Status varchar (15) NULL ,    StartingBid numeric (19,4) NULL ,    MinBidIncrement numeric (19,4) NULL ,    ReserveAmount numeric (19,4) NULL ,    StartDate datetime NULL ,    ScheduledEndDate datetime NULL ,    ActualEndDate datetime NULL ,    ItemId int NULL ,    Quantity int NULL ,    LeadingBidId int NULL ,    WinningBidId int NULL  );  CREATE TABLE bid (   id int NOT NULL ,    TransactionId varchar (15) NOT NULL ,    BidDateTime datetime NOT NULL ,    Amount numeric (19,4) NOT NULL ,    AuctionId int NOT NULL ,    BidderId int NOT NULL  );  CREATE TABLE bidder (   id int NOT NULL ,    FirstName varchar (20) NOT NULL ,    LastName varchar (40) NOT NULL ,    EmailAddress varchar (50) NULL ,    UserName varchar (15) NOT NULL ,    Password varchar (15) NOT NULL ,    BillingAddressId int NULL ,    ShippingAddressId int NULL  );  CREATE TABLE item (   id int NOT NULL ,    Name varchar (50) NOT NULL ,    Description varchar (100) NULL ,    ImageURL varchar (100) NULL  );  ALTER TABLE address ADD CONSTRAINT PK_address PRIMARY KEY (id);  ALTER TABLE auction ADD CONSTRAINT PK_auction PRIMARY KEY (id);  ALTER TABLE bid ADD CONSTRAINT PK_bid PRIMARY KEY (id);  ALTER TABLE bidder ADD CONSTRAINT PK_bidder PRIMARY KEY (id);  ALTER TABLE item ADD CONSTRAINT PK_item PRIMARY KEY (id);  ALTER TABLE auction ADD CONSTRAINT FK_auction_item FOREIGN KEY (ItemId)    REFERENCES item (id);  ALTER TABLE auction ADD CONSTRAINT FK_auction_leadbid FOREIGN KEY    (LeadingBidId)    REFERENCES bid (id);  ALTER TABLE auction ADD CONSTRAINT FK_auction_winbid FOREIGN KEY (WinningBidId)    REFERENCES bid (id);  ALTER TABLE bid ADD CONSTRAINT FK_bid_auction FOREIGN KEY (AuctionId)    REFERENCES auction (id);  ALTER TABLE bid ADD CONSTRAINT FK_bid_bidder FOREIGN KEY (BidderId)    REFERENCES bidder (id);  ALTER TABLE bidder ADD CONSTRAINT FK_bidder_billaddress    FOREIGN KEY (BillingAddressId) REFERENCES address (id);  ALTER TABLE bidder ADD CONSTRAINT FK_bidder_shipaddress    FOREIGN KEY (ShippingAddressId) REFERENCES address (id); 

Note

The DDL in Listing 6.2 was developed for Microsoft SQL Server 2000. If you're using a different database, you'll need to adapt this to the syntax and types supported by your vendor.


This database schema is for the most part a direct mapping of the object model given back in Chapter 2, Setting the Stage ”An Example Auction Site. The most notable difference is that the AuctionOffering class has been collapsed down and implemented as two attributes of EnglishAuctionBean stored in the ItemId and Quantity fields in the auction table.



Special Edition Using Enterprise JavaBeans 2.0
Special Edition Using Enterprise JavaBeans 2.0
ISBN: 0789725673
EAN: 2147483647
Year: 2000
Pages: 223

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net