User: mulder
Date: 00/08/31 12:08:49
Modified: src/main/org/jboss/minerva minerva.html
Log:
Updates to Minerva documentation.
Revision Changes Path
1.2 +552 -236 jboss/src/main/org/jboss/minerva/minerva.html
Index: minerva.html
===================================================================
RCS file: /products/cvs/ejboss/jboss/src/main/org/jboss/minerva/minerva.html,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- minerva.html 2000/06/02 13:48:40 1.1
+++ minerva.html 2000/08/31 19:08:49 1.2
@@ -1,241 +1,557 @@
<HTML>
-<HEAD>
-<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
-<TITLE>JBuilder Project minerva.jpr</TITLE>
-</HEAD>
-<BODY>
-<H1>Minerva Object/Database Pools</H1>
-<HR>
-<P><FONT SIZE=+1>
-<STRONG>Project: </STRONG>Minerva Object Pools<BR>
-<STRONG>Author: </STRONG><A HREF="mailto:[EMAIL PROTECTED]">Aaron
- Mulder</A><BR>
-<STRONG>Description: </STRONG> Generic object pools, and specifically, JDBC
- connection pools.<BR>
-<STRONG>Release: </STRONG> 0.95
-<BR><STRONG>Download Minerva JAR:</STRONG>
- <A HREF="minerva.jar">minerva.jar</A> - not necessary for jBoss
-<BR><STRONG>Download Test Bean:</STRONG>
- <A HREF="SQLTest.jar">SQLTest.jar</A> - includes jBoss 2.0 XML files
-<BR><STRONG>Download Test Client JAR:</STRONG>
- <A HREF="SQLClient.jar">SQLClient.jar</A> - put in jboss/dist/client
- and run with <CODE>java -jar SQLClient.jar</CODE>
-</FONT></P>
-<OL>
- <LI><A HREF="#drivers">JDBC 1.0 drivers vs. JDBC 2.0 drivers</A></LI>
- <LI><A HREF="#using">Using the JDBC Connection Pools in jBoss 2.0</A></LI>
- <LI><A HREF="#client">Using the JDBC Connection Pool test EJB and client in jBoss
2.0</A></LI>
- <LI><A HREF="#bugs">Outstanding Features/Bugs</A></LI>
-</OL>
-<HR>
-
-<H3><A NAME="drivers">JDBC 1.0 drivers vs. JDBC 2.0 drivers</A></H3>
-<P>The database drivers for JDBC 1.0 cannot participate in two-phase commits,
- which is generally assumed to be used in a J2EE server. It is possible for
- the server to use a one-phase commit protocol, but only if it can establish
- that it's safe. JDBC 2.0 drivers may provide the appropriate support - which
- is part of the optional JDBC 2.0 Standard Extension.</P>
-<P>This package can be used to pool either kind of connection - normal JDBC
- 1.0 or 2.0 one-phase commit connections, or JDBC 2.0 two-phase commit
- connections. For normal operation of a J2EE server, you must use the latter.
- There is a set of wrappers for JDBC 1 drivers to operate in the two-phase
- commit environment, under certain restrictions. For example, if you request
- several connection from the pool within the scope of one Transaction, you
- will get the same connection every time. Also, a connection is not returned
- to the pool until you commit or rollback the transaction. Finally, these
- wrappers are not truly two-phase aware, and you will experience heuristic
- commits or rollbacks (only a problem if one data source attemps to commit
- while another attempts to rollback, etc.).</P>
-<P>If your driver supports one-phase commit, you would use it in the traditional
- JDBC way - use the DriverManager to get a Connection. You supply those
- parameters to the pool configuration. For two=phase commit, you must specify
- the name of a vendor class (or the Minerva wrapper class) that implements
- javax.sql.XADataSource, so there's no DriverManager interaction, though you
- still provide certain connection parameters (which may or may not be the same
- - see your vendor's documentation). For the Minerva wrapper class, specify
- the parameters as if you were using DriverManager (which is what the wrapper
- classes do!).</P>
-
-<HR>
-
-<H3><A NAME="using">Using the JDBC Connection Pools in jBoss 2.0</A></H3>
-<P>There are four things you need to do:</P>
-<OL>
- <LI>If you are building jBoss from source, the minerva packages are included.
- If you are using a binary, they are not yet included, so you should include
- the minerva.jar archive in your jBoss libraries</LI>
- <LI>Include an MLET entry in your jboss.conf for each pool</LI>
- <LI>Specify a Resource Manager in your jBoss configuration for each
- EJB JAR</LI>
- <LI>Specify a Resource Reference in your EJB configuration for each
- EJB (two places)</LI>
-</OL>
-
-<H4>Including the JAR</H4>
-<P>If you're using a binary distribution, copy minerva.jar to
- jboss/lib/ext/minerva.jar.</P>
-
-<H4>Add MLET entries for the MBeans</H4>
-<P>In the future, the MBeans will be included in the jBoss distribution, but
- for now they live in the Minerva JAR. Edit your jboss.conf to include a
- section like the example below. For a JDBC 2.0 pool (which participates in
- Transactions), use the parameters in the table below. The URL, username,
password,
- and Properties are used to connect to your underlying database. So if you
- had an Oracle database with JDBC 1.0 drivers that you wanted to pool, you'd
- specify the Minerva 1.0 wrapper data source, and the Oracle URL and username
- and password and properties (any you don't need should be included but left
- blank).</P>
-<TABLE BORDER="1">
- <TR><TH>Position</TH><TH>Type</TH><TH>Value</TH></TR>
- <TR><TD>1</TD><TD>java.lang.String</TD><TD>Pool Name</TD></TR>
- <TR><TD>2</TD><TD>java.lang.String</TD><TD>XADataSource class name (use
org.jboss.minerva.xa.XADataSource for the JDBC 1.0 wrapper)</TD></TR>
- <TR><TD>3</TD><TD>java.lang.String</TD><TD>JDBC Connection URL</TD></TR>
- <TR><TD>4</TD><TD>java.lang.String</TD><TD>JDBC Connection user name</TD></TR>
- <TR><TD>5</TD><TD>java.lang.String</TD><TD>JDBC Connection password</TD></TR>
- <TR><TD>6</TD><TD>java.lang.String</TD><TD>JDBC Connection properties (in the
format name=value;name=value;name=value)</TD></TR>
- <TR><TD>7</TD><TD>java.lang.Integer</TD><TD>Pool minimum size (pool starts at 0,
but never shrinks below this)</TD></TR>
- <TR><TD>8</TD><TD>java.lang.Integer</TD><TD>Pool maximum size (exceptions once
it's full)</TD></TR>
- <TR><TD>9</TD><TD>java.lang.String</TD><TD><I>Optional!</I> Advanced Pool
parameters (in the format name=value;name=value;name=value)</TD></TR>
-</TABLE>
-<P>Here are the valid properties for the pool parameters (case sensitive). You
- may include any or all of these in whatever order you prefer:</P>
-<TABLE BORDER="1">
- <TR><TH>Name</TH><TH>Type</TH><TH>Description</TH><TH>Default</TH></TR>
- <TR><TD>Blocking</TD><TD>boolean</TD><TD>Whether the pool should block if there's
no connection available, or return null</TD><TD>false</TD></TR>
- <TR><TD>GCEnabled</TD><TD>boolean</TD><TD>Whether the pool should attempt to
return connections to the pool after a period of inactivity</TD><TD>false</TD></TR>
- <TR><TD>GCInterval</TD><TD>long</TD><TD>How often (in ms) garbage collection
and/or shrinking should run</TD><TD>120000</TD></TR>
- <TR><TD>GCMinIdleTime</TD><TD>long</TD><TD>How long a connection must be unused
(in ms) before being returned to the pool</TD><TD>1200000</TD></TR>
- <TR><TD>ShrinkingEnabled</TD><TD>boolean</TD><TD>Whether the pool should shrink
if some connections haven't been used recently</TD><TD>false</TD></TR>
- <TR><TD>ShrinkMinIdleTime</TD><TD>long</TD><TD>How long a connection must be
unused (in ms) in the pool before its eligible for shrinking</TD><TD>600000</TD></TR>
- <TR><TD>ShrinkPercent</TD><TD>float (0-1)</TD><TD>How many of the eligible
connections will be released</TD><TD>0.33</TD></TR>
- <TR><TD>TimestampUsed</TD><TD>boolean</TD><TD>Whether to track last used times on
SQL events (queries, cursor movements, etc.) (true) or just pool checkin and checkout
(false)</TD><TD>false</TD></TR>
-</TABLE>
-
-<P>Here's an example with a JDBC 1.0 Oracle driver using the wrapper classes,
- and custom configuring the pool paramters:</P>
-<PRE>
-<MLET CODE = "org.jboss.jdbc.XADataSourceLoader" ARCHIVE="jboss.jar,minerva.jar"
CODEBASE="../lib/ext/">
- <ARG TYPE="java.lang.String" VALUE="TestOraclePool">
- <ARG TYPE="java.lang.String" VALUE="org.jboss.minerva.xa.XADataSourceImpl">
- <ARG TYPE="java.lang.String"
VALUE="jdbc:oracle:thin:@host.domain.com:1521:instance">
- <ARG TYPE="java.lang.String" VALUE="user">
- <ARG TYPE="java.lang.String" VALUE="password">
- <ARG TYPE="java.lang.String" VALUE="">
- <ARG TYPE="java.lang.Integer" VALUE="2">
- <ARG TYPE="java.lang.Integer" VALUE="5">
- <ARG TYPE="java.lang.String"
VALUE="GCEnabled=true;ShrinkingEnabled=true;GCMinIdleTime=30000;GCInterval=10000;ShrinkMinIdleTime=30000">
+ <HEAD>
+ <TITLE>Minerva Database Pools 0.98</TITLE>
+ </HEAD>
+ <BODY>
+ <H1>Minerva Database Pools 0.98</H1>
+ <P>This is the documentation for the Minerva pools. It is aimed
+ at both developers and users, so be selective. I suggest everyone read
+ the section on
+ <A HREF="#jdbc">JDBC vs the JDBC Standard Extension</A>, since a lot of
+ the rest may be pretty muddled without it. You don't need a very
+ thorough understanding to use the JDBC Standard Extension pools - all the
+ tricky stuff is done under the covers. Just be aware of the advantages
+ and limitations.</P>
+ <UL>
+ <LI><A HREF="#intro">Introduction to Minerva</A></LI>
+ <LI><A HREF="#jdbc">JDBC 1/2 vs the JDBC Standard Extension</A>
+ <UL>
+ <LI>Concepts</LI>
+ <LI>Reality</LI>
+ </UL></LI>
+ <LI><A HREF="#j1pools">Using Minerva JDBC 1/2 Pools</A></LI>
+ <LI><A HREF="#j2epools">Using Minerva JDBC 2 Standard Extension Pools</A></LI>
+ <LI><A HREF="#jboss">Using Minerva JDBC Pools with jBoss 2.0</A></LI>
+ <LI><A HREF="#j2ee">Using Minerva JDBC Pools with Other J2EE
Containers</A></LI>
+ <LI><A HREF="#obpools">Using Minerva Object pools</A></LI>
+ <LI><A HREF="#arch">Minerva Architecture</A></LI>
+ <LI><A HREF="#examples">Minerva Examples</A>
+ <UL>
+ <LI><A HREF="#ex1">Creating a JDBC Pool</A></LI>
+ <LI><A HREF="#ex2">Getting a JDBC Pool connection directly</A></LI>
+ <LI><A HREF="#ex3">Getting a JDBC Pool connection from JNDI</A></LI>
+ <LI><A HREF="#ex4">Getting a JDBC Pool connection from the
DriverManager</A></LI>
+ <LI><A HREF="#ex5">Creating a JDBC Standard Extension (<B>S.E.</B>)
Pool</A></LI>
+ <LI><A HREF="#ex6">Getting a JDBC S.E. Pool connection directly</A></LI>
+ <LI><A HREF="#ex7">Getting a JDBC S.E. Pool connection from JNDI</A></LI>
+ <LI><A HREF="#ex8">Getting a JDBC S.E. Pool connection from the
DriverManager</A></LI>
+ <LI><A HREF="#ex9">Configuring a JDBC S.E. Pool with jBoss and a JDBC
S.E. Driver</A></LI>
+ <LI><A HREF="#ex10">Configuring a JDBC S.E. Pool with jBoss and a JDBC
1/2 Driver</A></LI>
+ <LI><A HREF="#ex11">Configuring an Enterprise Java Bean with a
DataSource</A></LI>
+ <LI><A HREF="#ex12">Linking the EJB DataSource to a Minerva Pool with
jBoss</A></LI>
+ <LI><A HREF="#ex13">Getting a connection in an EJB implementation</A></LI>
+ <LI><A HREF="#ex14">Creating a pool for a generic Object type</A></LI>
+ <LI><A HREF="#ex15">Getting and returning Objects</A></LI>
+ <LI><A HREF="#ex16">Getting and returning PooledObjects</A></LI>
+ </UL></LI>
+ <LI><A HREF="#nyi">Outstanding Features</A></LI>
+ </UL>
+
+ <HR><BR>
+ <H2><A NAME="intro">Introduction to Minerva</A></H2>
+ <P>The Minerva library is a multi-layered set of classes that can manage
+ pools of Java objects. At the lowest level, this can be any type of Java
+ object. At a higher level, it provides implementations for database
+ connections. It is part of the jBoss project (an open-source J2EE server),
+ but does not depend on jBoss - it can be used independently in any Java 2
+ environment. You will need the JDBC 2 Standard Extension, JNDI, and JTA
+ to take full advantage of the J2EE JDBC features, but you can ignore all
+ that if you just want a simple object or database pool (you may still need
+ the jdbc 2 standard extension and JNDI jars at runtime, but you won't have
+ to use them directly).</P>
+ <P>The rest of this document is devoted to the different uses of the
+ Minerva pools - J2EE connections, plain JDBC connections, objects, etc.
+ There's a section on integrating the Minerva pools with jBoss, which you
+ should read if you're using jBoss, and skip if you're not.</P>
+
+ <HR><BR>
+ <H2><A NAME="jdbc">JDBC 1/2 vs the JDBC Standard Extension</A></H2>
+ <H3>Concepts</H3>
+ <P>JDBC 1 was part of Java 1, and JDBC 2 is part of Java 2. So most of you
+ probably have a pretty clear understanding of JDBC. However, the JDBC 2
+ Standard Extension brings a whole new set of concepts to the table.</P>
+ <P>In "normal" JDBC, there's a very tight coupling between transactions
+ and connections. Every transaction is attached to exactly one connection
+ (even if auto-commit is on - whereupon they're just very <I>short</I>
+ transactions). Though there may be many transactions over the life of
+ one connection, the reverse is not true - there cannot be more than one
+ connection associated with a single transaction. As soon as you create a
+ new connection, you've created a new transaction too. Additionally, you
+ cannot start a new transaction on a connection until the last one is
+ complete. There is no concept of more than one set of "pending work" for
+ a connection. Once you start doing things, the only way to get a new
+ transaction on the same connection is to commit or rollback, and at that
+ time a new transaction is automatically started.</P>
+ <P>To quote a little green guy, "you must un-learn what you have learned" in
+ order to work with the JDBC 2 Standard Extension. Here, connections and
+ transactions are completely independent. You may use many connections in
+ the scope of a single transaction, and you may do work on many uncommitted
+ transactions with a single connection. A connection is just a way for
+ you to communicate with the database - it's up to you and the database to
+ decide what you're talking about (which transaction, etc).</P>
+ <P>The primary advantage of this is that you can do work across many
+ databases, or indeed many data <I>sources</I>, and commit it all together
+ or roll it back all together. One way to do this is known as "two-phase
+ commit." In the first phase, you ask all your data sources whether they
+ can commit, and then in the second phase, based on the responses, you tell
+ everything to either commit or rollback. And it may be that some of these
+ data sources are legacy systems, message queues, or something else
+ altogether. Another advantage is that it makes it easy and efficient to
+ pool database connections - the connection can be returned to the pool
+ immediately, even if it will be a while before the work is committed.</P>
+ <P>So a J2EE server needs to support the JDBC standard extension, diverse
+ data sources, and transaction management. If you see me refer to a
+ "transactional" or "XA" connection, I'm talking about a JDBC 2 Standard
+ Extension connection, which can participate in JTA transactions. JDBC 1
+ or JDBC 2 connections can't, since they don't support two-phase commit,
+ and they can't separate a connection from a transaction.</P>
+ <H3>Reality</H3>
+ <P>Unfortunately, most database vendors do not yet support the JDBC Standard
+ Extension. And those that do generally don't have very robust support yet.
+ This presents a problem, since most J2EE users want to use databases.</P>
+ <P>The solution to this is a set of wrapper classes for plain JDBC 1 or JDBC
+ 2 connections. This allows them to participate in JTA transactions, though
+ in a somewhat limited fashion. First, you can only use one connection per
+ data source per transaction. Second, if the connection cannot commit,
+ it won't tell you during the first inquiry phase when it's supposed to -
+ it will fail during the commit phase, which may mean some data sources
+ get committed and others rolled back. That's clearly undesirable, which
+ is why we want all vendors to provide good JDBC 2 Standard Extension
+ implementation. Take this moment you bother your vendor's support line.
+ Third, a connection cannot be closed or returned to a connection pool
+ untle the pending work is either committed or rolled back - you wouldn't
+ want someone else adding work to the transaction <I>before</I> you
+ commit it!</P>
+
+ <HR><BR>
+ <H2><A NAME="j1pools">Using Minerva JDBC 1/2 Pools</A></H2>
+ <P>In order to create normal JDBC pools, you should interact with the class
+ org.jboss.minerva.datasource.JDBCPoolDataSource. It's pretty
+ straightforward - create it, set all the JDBC properties (URL, user,
+ password, etc.) and pool properties (name, min size, max size, whether it
+ blocks, shrinks, etc.) that you need, and then initialize() it. It
+ implements the DataSource interface from the JDBC 2 Standard Extension,
+ so you can just call getConnection() to get a connection. When you're
+ done with the connection, close() it, and it will get returned to the
+ pool. When you're done with the pool, call close() on the data source
+ and it will close all the connections in the pool and shut everything
+ down.
+ <P>If you want to make your pools more accessible, you can do that in two
+ ways. The first is to call setJNDIName to register the pool in JNDI.
+ The second is to use the JDBC driver org.jboss.minerva.datasource.PoolDriver
+ and a URL of the form "jdbc:minerva:<I>PoolName</I>". In this way, you
+ get pooled database connections in the same way you'd normally get
+ connections - DriverManager.getConnection(url). There's no need to supply
+ a user, password, or any properties - all that is set by the pool itself.
+ </P>
+
+<P>Finally, if you want to interact with the pool directly rather than using the
+ DataSource or DriverManager interfaces, you can use the Object pools with the
+ object factory org.jboss.minerva.factories.JDBCConnectionFactory. Take a look
+ at the source code for JDBCPoolDataSource if it's not clear.</P>
+
+ <HR><BR>
+ <H2><A NAME="j2epools">Using Minerva JDBC 2 Standard Extension Pools</A></H2>
+ <P>In order to create JDBC 2 Standard Extension pools, you should interact
+ with the class org.jboss.minerva.datasource.XAPoolDataSource. This also
+ implements the DataSource interface. All the transactional-ness is
+ handled under the covers. You'll need to set some additional properties,
+ but you will still get a normal java.sql.Connection, and close it when
+ you're done to return it to the pool. You don't have to know anything
+ about the inner mechanics of transactions or
+ It's pretty
+ straightforward - create it, set all the JDBC properties (URL, user,
+ password, etc.) and pool properties (name, min size, max size, whether it
+ blocks, shrinks, etc.) that you need, and then initialize() it. It
+ implements the DataSource interface from the JDBC 2 Standard Extension,
+ so you can just call getConnection() to get a connection. When you're
+ done with the connection, close() it, and it will get returned to the
+ pool. When you're done with the pool, call close() on the data source
+ and it will close all the connections in the pool and shut everything
+ down.
+ <P>If you want to make your pools more accessible, you can do that in two
+ ways. The first is to call setJNDIName to register the pool in JNDI.
+ The second is to use the JDBC driver org.jboss.minerva.datasource.PoolDriver
+ and a URL of the form "jdbc:minervaxa:<I>PoolName</I>". In this way, you
+ get pooled database connections in the same way you'd normally get
+ connections - DriverManager.getConnection(url). There's no need to supply
+ a user, password, or any properties - all that is set by the pool itself.
+ </P>
+
+<P>Finally, if you want to interact with the pool directly rather than using the
+ DataSource or DriverManager interfaces, you can use the Object pools with the
+ object factory org.jboss.minerva.factories.XAConnectionFactory. Take a look
+ at the source code for XAPoolDataSource if it's not clear.</P>
+
+ <HR><BR>
+ <H2><A NAME="jboss">Using Minerva JDBC Pools with jBoss 2.0</A></H2>
+ <P>There are several steps required to use Minerva pools with jBoss 2.0:</P>
+ <OL>
+ <LI>Add your database driver to jboss.properties
+ <BLOCKQUOTE>Add or update a line with the driver class names
(comma-separated) like:<BR>
+ <CODE>jdbc.drivers=oracle.jdbc.driver.OracleDriver</CODE>
+ </BLOCKQUOTE>
+ </LI>
+ <LI>Add a Minerva pool entry to jboss.conf
+ <BLOCKQUOTE>See the example below for
+ <A HREF="#ex9">Standard Extension drivers</A> or
+ <A HREF="#ex10">JDBC 1/2 drivers</A>.</BLOCKQUOTE>
+ </LI>
+ <LI>Add the pool's specific configuration to jboss.jcml
+ <BLOCKQUOTE>See the example below for
+ <A HREF="#ex9">Standard Extension drivers</A> or
+ <A HREF="#ex10">JDBC 1/2 drivers</A>.</BLOCKQUOTE>
+ </LI>
+ <LI>Add a resource reference to your EJB's ejb-jar.xml (not jBoss specific)
+ <BLOCKQUOTE>See the <A HREF="#ex11">example below</A>.</BLOCKQUOTE>
+ </LI>
+ <LI>Add a resource manager to your EJB's jboss.xml
+ <BLOCKQUOTE>See the <A HREF="#ex12">example below</A>.</BLOCKQUOTE>
+ </LI>
+ </OL>
+ <P>You can use more than one Minerva pool at the same time, and even from
+ the same bean. You'd have to repeat all the steps for each one, unless
+ they use the same drivers (only add it once to jboss.properties). Once
+ you have a pool set up, you can refer to it from additional beans by
+ repeating the last 2 steps for each bean.
+
+ <HR><BR>
+ <H2><A NAME="j2ee">Using Minerva JDBC Pools with Other J2EE Containers</A></H2>
+ <P>The only real requirement here is that the TransactionManager for the
+ container must be in JNDI, so the pools can find it and register
+ connections as they are used. You'll need to find out how to start a
+ service for the container, and probably provide a skeletal class that
+ lets the user set all the configuration parameters. You can use the
+ JMX classes to load Minerva pools in jBoss as a reference (see
+ org.jboss.jdbc.*). There would be a different way to link an EJB
+ DataSource reference to the actual DataSource implementation, but the
+ container vendor probably has a GUI tool for deployment like EJX.
+
+ <HR><BR>
+ <H2><A NAME="obpools">Using Minerva Object pools</A></H2>
+ <P>If you want to pool something other than JDBC connections, you can do
+ that with the classes org.jboss.minerva.pools.ObjectPool and
+ org.jboss.minerva.pool.PoolObjectFactory. ObjectPool has all the logic,
+ so you just need to implement a custom subclass of PoolObjectFactory.
+ The only method you need to implement is createObject(), though you can
+ customize the object handling more than that. You can manipulate each
+ object as it is created, destroyed, given out by the pool, returned to
+ the pool, etc. You can even make the pool give out objects other than
+ the actual instances in the pool, as long as there's a one-to-one mapping
+ (some kind of wrapper, etc.).</P>
+ <P>You can use any kind of Object for a custom pool. However, you may
+ choose to use objects that implement org.minerva.jboss.pools.PooledObject.
+ If you do this, the pool will handle close and error events generated by
+ your objects, so you would not need to explicitly return objects to the
+ pool. It will also handle last-used events to automatically track the
+ usage of pooled object for garbage-collection purposes.</P>
+ <P>There are several example below of Object Pool usage, but I encourage you
+ to visit the JavaDoc for ObjectPool, PoolObjectFactory, and PooledObject.
+ </P>
+
+ <HR><BR>
+ <H2><A NAME="arch">Minerva Architecture</A></H2>
+ <P>All the Minerva classes have JavaDoc comments, and you can see the
+ JavaDoc output online on the
+ <A HREF="http://www.jboss.org/Jaws.htm">jBoss JAWS page</A>.</P>
+
+ <H3>Overview</H3>
+ <P>There are five packages under minerva:</P>
+ <TABLE BORDER="1">
+ <TR><TD>pools</TD><TD>Pool implementation</TD></TR>
+ <TR><TD>jdbc</TD><TD>Support classes for JDBC pools</TD></TR>
+ <TR><TD>factories</TD><TD>Default object factories for JDBC 1/2 and XA
+ connections</TD></TR>
+ <TR><TD>datasource</TD><TD>Client interface for JDBC 1/2 and XA
pools</TD></TR>
+ <TR><TD>xa</TD><TD>Wrapper classes for JDBC 1/2 drivers in an XA
environment</TD></TR>
+ </TABLE>
+ <P>So, you'll want to look in a different place depending on what you want
+ to do. If you want to change the way to pools work, look in pools
+ (specifically, ObjectPool). If you want to create an implementation to
+ pool something other than database connections, add a PoolObjectFactory
+ to factories. If you want to change the timestamping or other
+ characteristics of the connections that are given out from the pool, look
+ in jdbc. The logic around XA connections is split between xa (for the
+ JDBC 1/2 wrappers) and the XA factory in factories (which registers with
+ the current transaction, etc.).</P>
+
+ <H3>Object Pools</H3>
+ <P>At heart, Minerva is a pooling scheme for any type of objects. The
+ problem was, JDBC 1/2 pools need to pool java.sql.Connections, while
+ XA pools need to pool javax.sql.XAConnections. Even though in the end,
+ you get a Connection either way. (See the JDBC 2 Standard Extension
+ document section 7.3.1)</P>
+ <P>The easiest way to implement this is as a generic Object pool. So
+ there's a class that can pool anything, and an abstract base class for an
+ Object Factory that creates (and destroys) the object for the pool. The
+ factory turns out to be fairly complex if you override all the methods --
+ you don't have to actually return the exact object in the pool, you can
+ process things going in and out, etc. But for a basic implementation, all
+ you have to do is override createObject and return whatever kind of
+ objects you want to pool.</P>
+ <P>There's also an interface (PooledObject) that an object in the pool can
+ implement to activate some additional functionality. For example, when
+ a PooledObject sends a close or error event, the pool will automatically
+ take the correct action. Otherwise, you have to return things to the
+ pool by hand, manually update last-used times, etc. You can do the same
+ things either way, it's just a matter of what works best for the specific
+ objects you're pooling.</P>
+ <P>So to create a pool, you need the class of the instances you're going to
+ pool, and a factory to create those instances. Plug the factory in to the
+ ObjectPool, set some parameters (size, etc.), and voila! You have a pool.</P>
+
+ <H3>Pool Parameters</H3>
+
+<P>I was about to rewrite descriptions of all the pool parameters, but it's already
+ in the JavaDoc for ObjectPool. Just look at all the setters.</P>
+
+ <H3>JDBC Helpers</H3>
+ <P>The JDBC class has wrapper classes that manage things like: returning a
+ connection to the pool when it's closed, updating the last-used timestamp
+ when a connection or child object is used, sending notifications when a
+ SQLException crops up, etc. It has been suggested that these could be
+ proxies instead of full-blown classes, but there are a fair number of
+ methods overridden...</P>
+
+ <H3>JDBC 1/2 Wrappers for XAConnections</H3>
+ <P>The xa package holds the things that make a JDBC 1/2 connection look like
+ an XAConnection. There are implementations of all the XA classes, hooks
+ into the JDBC wrappers mentioned above, and so on. However, note that
+ some of the logic dealing directly with pools lives in the pooled object
+ factory for XAConnections.</P>
+ <P>Basically, each java.sql.Connection gets wrapped by an XAConnection and
+ XAResource, which stay with it for as long as it's in the pool. They make
+ one-off java.sql.Connection instances each time the client requests one,
+ which die when they are closed by the client (so the client can't hook
+ into a connection after closing it by just stashing the reference
+ somewhere). The factory registers the XAResource with the
+ TransactionManager when it's given out from the pool, and deregisters it
+ when it's returned. The XAResource explodes if you try to use it for a
+ new transaction before the old one has been committed or rolled back
+ (since the underlying connections don't support that).</P>
+
+ <HR><BR>
+ <H2><A NAME="examples">Minerva Examples</A></H2>
+
+ <H4><A NAME="ex1">Creating a JDBC Pool</A></H4>
+ <PRE>
+JDBCPoolDataSource source = new JDBCPoolDataSource();
+source.setPoolName(poolName);
+source.setJDBCURL(url);
+source.setJDBCUser(username);
+source.setJDBCPassword(password);
+source.setMinSize(minSize);
+source.setMaxSize(maxSize);
+source.initialize();
+ </PRE>
+
+ <H4><A NAME="ex2">Getting a JDBC Pool connection directly</A></H4>
+ <PRE>
+JDBCPoolDataSource source = ...
+Connection con = source.getConnection();
+ </PRE>
+
+ <H4><A NAME="ex3">Getting a JDBC Pool connection from JNDI</A></H4>
+ <PRE>
+JDBCPoolDataSource source = ...
+source.setJNDIName("jdbc/pool-"+source.getPoolName());
+source.initialize();
+...
+DataSource ds = (DataSource)context.lookup("jdbc/pool-PoolName");
+Connection con = ds.getConnection();
+ </PRE>
+
+ <H4><A NAME="ex4">Getting a JDBC Pool connection from the DriverManager</A></H4>
+ <PRE>
+JDBCPoolDataSource source = ...
+Connection con = DriverManager.getConnection("jdbc:minerva:PoolName");
+ </PRE>
+
+ <H4><A NAME="ex5">Creating a JDBC Standard Extension (<B>S.E.</B>) Pool</A></H4>
+ <PRE>
+XADataSource vendorSource = ... // Could use org.jboss.minerva.xa.XADataSourceImpl
+XAPoolDataSource = new XAPoolDataSource();
+source.setPoolName(poolName);
+source.setDataSource(vendorSource);
+source.setJDBCUser(username);
+source.setJDBCPassword(password);
+source.setMinSize(minSize.intValue());
+source.setMaxSize(maxSize.intValue());
+source.setTransactionManagerJNDIName("TransactionManager");
+source.initialize(); // ^^^ Name depends on your container
+ </PRE>
+
+ <H4><A NAME="ex6">Getting a JDBC S.E. Pool connection directly</A></H4>
+ <PRE>
+XAPoolDataSource = ...
+Connection con = source.getConnection();
+ </PRE>
+
+ <H4><A NAME="ex7">Getting a JDBC S.E. Pool connection from JNDI</A></H4>
+ <PRE>
+XAPoolDataSource = ...
+source.setJNDIName("jdbc/xapool-"+source.getPoolName());
+source.initialize();
+...
+DataSource ds = (DataSource)context.lookup("jdbc/xapool-PoolName");
+Connection con = ds.getConnection();
+ </PRE>
+
+ <H4><A NAME="ex8">Getting a JDBC S.E. Pool connection from the
DriverManager</A></H4>
+ <PRE>
+XAPoolDataSource = ...
+Connection con = DriverManager.getConnection("jdbc:minervaxa:PoolName");
+ </PRE>
+
+ <H4><A NAME="ex9">Configuring a JDBC S.E. Pool with jBoss and a JDBC S.E.
Driver</A></H4>
+ <P>This will result in the pool's DataSource living in JNDI under the name
+ <B>xa.PoolName</B>.</P>
+ <P>In <B>jboss.conf</B>:</P>
+ <PRE>
+<MLET CODE="org.jboss.jdbc.XADataSourceLoader" ARCHIVE="jboss.jar,vendor.jar"
CODEBASE="../lib/ext/">
+ <ARG TYPE="java.lang.String" VALUE="PoolName">
+ <ARG TYPE="java.lang.String" VALUE="VendorXADataSourceClassName">
</MLET>
-</PRE>
-<P>And here's the same thing (without pool parameters) using the native Oracle
- XADataSource driver. Note this is not recommended with the 8.1.6.0.1 release,
- as the driver does not generate connection error events, so the connections
- are never returned to the pool if there's a SQLException. You still need to
- provide connection parameters for the vendor pool implementation.</P>
-<PRE>
-<MLET CODE = "org.jboss.jdbc.XADataSourceLoader" ARCHIVE="jboss.jar,minerva.jar"
CODEBASE="../lib/ext/">
- <ARG TYPE="java.lang.String" VALUE="TestOraclePool">
- <ARG TYPE="java.lang.String"
VALUE="oracle.jdbc.xa.client.OracleXADataSource">
- <ARG TYPE="java.lang.String"
VALUE="jdbc:oracle:thin:@host.domain.com:1521:instance">
- <ARG TYPE="java.lang.String" VALUE="user">
- <ARG TYPE="java.lang.String" VALUE="password">
- <ARG TYPE="java.lang.String" VALUE="">
- <ARG TYPE="java.lang.Integer" VALUE="2">
- <ARG TYPE="java.lang.Integer" VALUE="5">
+ </PRE>
+ <P>In <B>jboss.jcml</B>:</P>
+ <PRE>
+<mbean name="DefaultDomain:service=XADataSource,name=PoolName">
+ <attribute name="URL">jdbc:VendorURL</attribute>
+ <attribute name="JDBCUser">user</attribute>
+ <attribute name="Password">password</attribute>
+</mbean>
+ </PRE>
+ <P>You'll notice that after you run jBoss with a jboss.jcml like the one
+ above, it will update your jboss.jcml to list all the available
+ properties for the XADataSource, with their default values. If the
+ vendor uses properties other than URL, username, and password to configure
+ their XADataSource, you'll have to use the "properties" attribute to
+ list them (in the form "name=value;name=value" etc.).</P>
+
+ <H4><A NAME="ex10">Configuring a JDBC S.E. Pool with jBoss and a JDBC 1/2
Driver</A></H4>
+ <P>This will result in the pool's DataSource living in JNDI under the name
+ <B>xa.PoolName</B>.</P>
+ <P>In <B>jboss.conf</B>:</P>
+ <PRE>
+<MLET CODE="org.jboss.jdbc.XADataSourceLoader" ARCHIVE="jboss.jar,vendor.jar"
CODEBASE="../lib/ext/">
+ <ARG TYPE="java.lang.String" VALUE="PoolName">
+ <ARG TYPE="java.lang.String"
VALUE="org.jboss.minerva.xa.XADataSourceImpl">
</MLET>
-</PRE>
+ </PRE>
+ <P>In <B>jboss.jcml</B>:</P>
+ <PRE>
+<mbean name="DefaultDomain:service=XADataSource,name=PoolName">
+ <attribute name="URL">jdbc:JDBC1/2URL</attribute>
+ <attribute name="JDBCUser">user</attribute>
+ <attribute name="Password">password</attribute>
+</mbean>
+ </PRE>
+ <P>You'll notice that after you run jBoss with a jboss.jcml like the one
+ above, it will update your jboss.jcml to list all the available
+ properties for the XADataSource, with their default values. If the
+ JDBC 1/2 driver uses properties other than URL, username, and password to
+ connect, you'll have to use the "properties" attribute to list them (in
+ the form "name=value;name=value" etc.).</P>
+
+ <H4><A NAME="ex11">Configuring an Enterprise Java Bean with a
DataSource</A></H4>
+ <P>You need to add a resource reference to your ejb-jar.xml file. The
+ requirement and XML syntax is standard across all containers - but each
+ container has a different GUI for configuring this if you don't do it
+ manually. The key parts here are that you specify a resource reference
+ of type <B>javax.sql.DataSource</B>, and you give it the name you expect
+ to see in JNDI. So, in the example below, if you call it <B>TestDB</B>,
+ it will be in JNDI under <B>java:comp/env/TestDB</B>. However, you'll
+ need to do something container-specific to match this up with a specific
+ database pool.</P>
+ <PRE>
+<resource-ref>
+ <description>Test Database</description>
+ <res-ref-name>TestDB</res-ref-name>
+ <res-type>javax.sql.DataSource</res-type>
+ <res-auth>Container</res-auth>
+</resource-ref>
+ </PRE>
+
+ <H4><A NAME="ex12">Linking the EJB DataSource to a Minerva Pool with
jBoss</A></H4>
+ <P>The easiest way to do this is to use EJX. You need to add a resource
+ manager that links the EJB ref-name (<A HREF="#ex11">see example above</A>)
+ to the database pool JNDI name (<A HREF="#ex9">see example above</A>).
+ Since the database pool JNDI name is <I>xa.PoolName</I> that should be
+ your resource jndi name, and the name in ejb-jar.xml should be the
+ resource name.</P>
+ <P>If you don't use EJX, you will need to add the reference manually in two
+ places - first at the top level of jboss.xml, and then again at the bean
+ level for each bean that uses the resource. Technically you can give the
+ resource manager a different name that the bean expects, and use the
+ bean-specific name with the resource manager name in the bean-level entry.
+ This is only recommended if you have multiple beans in the JAR that have
+ different resource names but can all be served by the same database pool.
+ </P>
+ <PRE>
+<resource-managers>
+ <resource-manager res-class="org.jboss.ejb.deployment.JDBCResource">
+ <res-name>TestDB</res-name>
+ <res-jndi-name>xa.TestPool</res-jndi-name>
+ </resource-manager>
+</resource-managers>
+
+<enterprise-beans>
+ <session>
+ <resource-ref>
+ <res-ref-name>TestDB</res-ref-name>
+ <resource-name>TestDB</resource-name>
+ </resource-ref>
+ ...
+ <session>
+ <resource-ref>
+ <res-ref-name>OtherDB</res-ref-name>
+ <resource-name>TestDB</resource-name>
+ </resource-ref>
+ ...
+ </PRE>
+
+ <H4><A NAME="ex13">Getting a connection in an EJB implementation</A></H4>
+ <PRE>
+Context naming = new InitialContext();
+DataSource ds = (DataSource)naming.lookup("java:comp/env/"+poolName);
+Connection con = ds.getConnection();
+ </PRE>
+
+ <H4><A NAME="ex14">Creating a pool for a generic Object type</A></H4>
+ <PRE>
+PoolObjectFactory myFactory = new MyPoolObjectFactory();
+... // Configure Factory
+ObjectPool pool = new ObjectPool(myFactory, "MyPoolName");
+... // Configure Pool
+pool.initialize();
+ </PRE>
+
+ <H4><A NAME="ex15">Getting and returning Objects</A></H4>
+ <PRE>
+ObjectPool pool = ...
+MyObject o = (MyObject)pool.getObject();
+...
+pool.releaseObject(o);
+ </PRE>
+
+ <H4><A NAME="ex16">Getting and returning PooledObjects</A></H4>
+ <PRE>
+ObjectPool pool = ...
+MyObject o = (MyObject)pool.getObject();
+...
+o.close(); // Assumes that a PoolEvent(o, PoolEvent.OBJECT_CLOSED) is sent
+ </PRE>
+
+ <HR><BR>
+ <H2><A NAME="nyi">Outstanding Features</A></H2>
+ <UL>
+ <LI>The JDBC 1/2 XA wrapper expects that a connection will be closed
+ before the transaction is rolled back or committed. Though this works
+ well for a container-demarcated transaction environment, it does not
+ allow full client-demarcated transaction functionality.</LI>
+ <LI>Last-used updates aren't passed through by JDBC 1/2 XA wrapper</LI>
+ <LI>Last-used updates aren't implemented for CallableStatements</LI>
+ </UL>
-<H4>Specify Resource Managers</H4>
-<P>The pools you configured are bound in JNDI to "jdbc.<I>PoolName</I>" for
-JDBC 1.0 pools (not described), or "xa.<I>PoolName</I>" for transactional pools
-(described above). <I>These names will probably change in the future!</I></P>
-<P>You can add perform all of the following configuration in EJX, but I give
-XML samples for completeness.</p>
-<P>To create a ResourceManager, add an entry to <B>jboss.xml</B> that looks like
-the following (just include the resource-manager if you already have the
-resource-managers section!):</P>
-<PRE>
- <resource-managers>
- <resource-manager res-class="org.jboss.ejb.deployment.JDBCResource">
- <res-name>MyPooledDB</res-name>
- <res-jndi-name>xa.<I>PoolName</I></res-jndi-name>
- </resource-manager>
- </resource-managers>
-</PRE>
-
-<H4>Specify Resource for each Bean</H4>
-<P>Also in <B>jboss.xml</B>, within the beans you would like to access this
-pool, add a resource-ref entry. The res-ref-name should match the res-name
-specified above, and the resource-name is the name your bean will use to access
-this resource. Here's the sample (relevant addition in italics):</P>
-<PRE>
- <enterprise-beans>
- <session>
- <ejb-name>SomeBean</ejb-name>
- <jndi-name>SomeBean</jndi-name>
- <configuration-name>Default Stateless
SessionBean</configuration-name>
- <I><resource-ref>
- <res-ref-name>ResourceResName</res-ref-name>
- <resource-name>BeansDBName</resource-name>
- </resource-ref></I>
- </session>
- <secure>true</secure>
- </enterprise-beans>
-</PRE>
-<P>Finally, within your <B>ejb-jar.xml</B> you need to add a resource reference
- for each bean that will use the pool:</P>
-<PRE>
- <resource-ref>
- <description>Database</description>
- <res-ref-name>ResourceResName</res-ref-name>
- <res-type>javax.sql.DataSource</res-type>
- <res-auth>Container</res-auth>
- </resource-ref>
-</PRE>
-<P>Currently, the name used in ejb-jar.xml res-ref-name must match the name
- used in jboss.xml res-ref-name, and the name used in jboss.xml resource-name
- must match the name used in jboss.xml res-name. The client sees the latter
- as the java:comp/env/ JNDI name, so it's easiest to make all 4 names
- match. <I>This big was fixed recently, but may not be in the binary build
- yet - please make all 4 names match for now!</I></P>
-
-<HR>
-
-<H3><A NAME="client">Using the JDBC Connection Pool test EJB and client in jBoss
2.0</A></H3>
-<P>There is a SQLTest.jar and a SQLClient.jar included with this
-package. To run the tests, add an MLET tag for the test pool to your jboss.conf
-and then put SQLTest.jar in your jBoss deployment directory. If it deploys
-correctly, add SQLClient.jar, jboss-client.jar, jnp-client.jar, ejb.jar, and
-jndi.properties to your client classpath, and run com.mearaworks.sql.SQLClient.
-Or take the easy route and put SQLClient.jar in you jboss/dist/client directory
-and run it with "java -jar SQLClient.jar". It will give you a SQL> propmt,
-from which you may execute multi-line SQL queries against the connections in the
-pool. It is fairly simple-minded - anything that starts with "select" is
-executed as a query, otherwise as an update, and any SQL errors will cause it to
-exit. But if you can successfully run simple queries, your pool is working!</P>
-<P><I>A note on names:</I> You must either name your pool "TestPool" or update
-the jboss.xml distributed in SQLTest.jar to make the Resource "TestDB" map to
-your pool name for the SQLTest bean.</P>
-
-<HR>
-
-<H3><A NAME="bugs">Outstanding Features/Bugs</A></H3>
-<UL>
-<LI>Last-used updates aren't implemented for prepared statements and callable
- statements.</LI>
-<LI>Last-used updates aren't passed through by XAClientConnection even if
- they're activated for the pool.</LI>
-<LI>JDBC 1.0 wrappers for XAConnections don't provide error notification on
- ResultSet, PreparedStatement, or CallableStatement operations.</LI>
-<LI>JDBC 1.0 wrappers for XAConnections don't return the same connection for
- every getXAConnection request for a particular transaction (Xid).</LI>
-<LI>MBeans for jBoss have an awfully unintuitive interface</LI>
-<LI>Document JDBC 1 interface and generic Object Pool interface</LI>
-<LI>Exception-handling does not yet follow the spec - on a recognized
- SQLException, the connection is automatically returned to the pool. This will
- likely cause errors with SQLExceptions in the midst of a rollback or commit
- (since then the connection will be returned twice!)</LI>
-<LI>Connections are not removed from the pool in the case of a failure during
- commit or rollback (JDBC 1 and JDBC 2 wrappers).</LI>
-</UL>
-</BODY>
+ </BODY>
</HTML>