YAPoolMan User's Guide
YAPoolMan version 2.1

Document Last Updated: 2/19/03


1.0    Overview

SourceForge.net Logo


1.1    Summary
1.2    Object pooling and modern VM's
1.3    Features
1.4    Relevant technologies and API's
1.5    File and package structure


2.0    Installation


2.1    STEP ONE: YAPoolMan JAR file and your database driver
2.2    STEP TWO: Third-party JAR files
2.3    STEP THREE: Configure poolman.xml
2.4    Testing the installation
2.5    Upgrading from an earlier release



3.0    Usage


3.1    JDBC: JNDI and DataSource usage
3.2    JDBC: Driver usage
3.3    Pooling non-JDBC objects: The ObjectPool
3.4    Implement your own PooledObject
3.5    Implement your own ProxyHandler
3.6    Implement your own ObjectFactory
3.7    Programmatic usage: alternatives to poolman.xml
3.8    Starting YAPoolMan as a server


4.0    Administration


4.1    Enabling and Disabling JMX
4.2    JMX in YAPoolMan
4.3    The HTML JMX agent


5.0    Web App Integration

6.0    Resources


6.1    The poolman.xml configuration file in detail
6.2    The YAPoolMan WAR
6.3    Recommended tutorials and relevant specifications



1.0    Overview


1.1    Summary

YAPoolMan is an embeddable object pooling and caching library. It optimizes resource usage by managing reusable instances across multiple requests. It can be used to pool any Java Class type, and contains specialized features -- such as a JDBC DataSource and JDBC Driver implementations for JDBC resource pooling. It is designed to be embeddable, so it instantiates its underlying server lazily (that is, upon receipt of the first request) rather than requiring an explicit root configuration and startup semantics.

Programmers can get pooled object from pool by calling its specific API. The pool is retrieved using:

o       PoolManager

o       JNDI naming service.

However, you must explicitly start YAPoolMan if you want to use the second way.

XXXXXXXXXXX add multi server and handler XXXXXXX

The JDBC connection pooling is just same as normal object pooling, while it has some more specific programmatic views, i.e. API's, or behaves slightly different. The differing API's all provide exactly the same underlying functionality, the variety of views exist merely to satisfy different programming styles and designs. The JDBC-related views are:

·          JDBC Driver implementation

·          JDBC DataSource implementation through JNDI service, unlike normal object pooling which has JNDI service binding the pool itself, JDBC pooling will bind the DataSource instead

And in this implementation, dynamic proxy of physical connection is used to ensure that all open statement will be closed when connection is returned.

Multiple database connection and object pools,  their factories and JMX are configured via the poolman.xml descriptor file. This XML file may be given a different name, which is typically useful when embedding the YAPoolMan libary into other products. Regardless, YAPoolMan reads its metadata information for all its pools from an XML file, and that file contains a summary of configurable features for each pool.

From a high level, usage of YAPoolMan involves the following:

1.     Installing the YAPoolMan JAR into the appropriate CLASSPATH and verifying that all dependent JAR's (such as an XML parser and the required Java JAR's from Sun) are also available;

2.     Configuring the poolman.xml file for each pool you wish to create and ensuring that it is put into current working directory or its directory is included in all appropriate CLASSPATH entries;

3.     Accessing the pool in your code through one of the programmatic API views described above;

4.     Runtime operation, including JMX-based administration and monitoring of pool metrics

For web applications, you can either put the jar into common library, which will ensure that only one instance of YAPoolMan will started; you it can be put into each web application抯 lib directory, i.e. WEB-INF/lib directory. This way, each web context can have their own YAPoolMan instance and configuration file.





1.2    Object pooling and modern virtual machines

It is important to note that general Java instance pooling in advanced virtual machines is typically unnecessary. Modern virtual machines contain low-level resource optimization that app-level pooling may circumvent and interfere with. However, Java types that make use of underlying system resources -- such as file descriptors, and socket connections -- should still be pooled. In these cases, it is not simply the Java instance creation process in question, it is a larger resource management issue that spans beyond merely the VM. Thus socket pooling, thread pooling, and connection pooling remain a necessity even in systems deployed on advanced modern VM's.





1.3    Features

YAPoolMan contains the following high level features (see the poolman.xml resource for detailed info):

·         JDBC: JDBC Driver and DataSource is supported, and since dynamic proxy is used, changing of JDBC standard will not force YAPoolMan to change the code accordingly, which is true for original YAPoolMan implementation. Pools automatically attempt to bind their DataSources to JNDI.

·         Custom XML-based pool types: Pool any Class type, not just JDBC connections, using XML -- without writing a line of code. The config file is read from xml file into java objects using Jakarta Commons-Digester.

·         Seperation of Pool and Factory: Pool no longer creates objects, factory takes the responsibility. Factories are configured for each pool.

·         JMX: Administer live pools through a web browser, via the JMX Reference Implementation HTML agent, or be registered to any running JMX MBean Server.

·         Lazy Initialization: To better suit embeddability use cases, pools aren't created until they are first requested. This feature can be disabled programmatically. Not true when using JNDI to access the pool.

·         Multiple servers: Factory can create object among several server settings. For example, there is a database server having two connecting nodes in the cluster, you can have the factory creating connections connecting to either node. 揥eight  of the server can be used to balance the load. Servers can also be grouped into different priority, marked as busy standby or fail standby.

·         Multitude of configurable parameters: All pool parameters and definitions are exposed via standard XML.

·         Automatic resource collection: Pooled objects automatically return to their pools after a configurable user timeout value.

·         Emergency objects: Factories can temporarily be allowed to exceed their maximum limit under duress, and will automatically shrink back to their bounds as load decreases.

·        Aspect like proxy handler: proxy handler is set, dynamic proxy of the native object will be used instead, the proxy handler can be used to change the behavior before the proxy invocation, after the invocation and when exception occurs.

·        Native JNDI support: simplified JNDI implementation is used when no default InitailContext available.

  • Jakarta Commons-Logger: can use the underlying JDK 1.4 logging or Log4j.






1.4    Related API's

YAPoolMan implements the JDBC API as virtual driver and data source. It supports use of the Java Management Extension (JMX) for service management, and ships with the JMX Reference Implementation. It also makes use of Jakarta Commons-Digester to parse its XML.





1.5    File and package structure

The distribution contains the following directories:

Directory: root level
CHANGELOG: A code-level description of recent changes
LICENSE: The LGPL text covering legal usage of this library
README: A brief set of instructions for quick installation and setup
build.xml: Ant build script to build the project and create distribution.

Directory: docs
This document, the XML quick reference for all poolman.xml parameters and the difference between YAPoolMan and YAPoolMan.

Directory: dist
Distribution of YAPoolMan.

Directory: dist/samples
A directory containing sample code.

Directory: dist/docs
The copy of all files with docs directory in project root.

Directory: dist/docs/javadocs
The javadoc pages generated from the source code.

Directory: dist/lib
The JAR files and configuration files necessary to support the build, runtime, and test suite in the YAPoolMan distribution including the generated yapoolman.jar.

Directory: lib
The JAR files and configuration files necessary to support the build, runtime, and test suite in the YAPoolMan distribution.

Directory: src/java
The top level of the core source code for the YAPoolMan library.

Directory: src/testsuite
The top level of the source of JUnit-based YAPoolMan test suite.

Directory: src/samples
The top level of the source and runtime of samples.




2.0    Installation

Installation involves adding the appropriate JARs to the CLASSPATH, configuring poolman.xml, copying it to current working directory or adding the directory containing poolman.xml to the CLASSPATH, and testing the install.


2.1    STEP ONE: Add YAPoolMan JAR and your Database Driver to the CLASSPATH

You have three options for installing the YAPoolMan JAR file and your database driver:

(1) System-wide option: Explicitly add the yapoolman.jar file and your driver JAR file to all relevant CLASSPATH variables. The JAR is located in the "lib" subdirectory of this distribution, but can be moved anywhere you like. Adding the JAR is OS-specific; consult your system help files if you have trouble. In the simplest case, you will merely need to append yapoolman.jar to your existing CLASSPATH environmental variable value. If you are using an application server, you must add yapoolman.jar to the app server's CLASSPATH or include it in a packaged application, such as a WAR file, where the app server's ClassLoaders can locate it.

(2) VM-wide option: To automatically include the JAR whenever Java is used, copy the yapoolman.jar file and your driver JAR file to the JDK_HOME/jre/lib/ext directory of your JDK installation, where JDK_HOME is the root directory where you installed Java on the machine. This makes the yapoolman.jar available to every invocation of that VM. If you use multiple virtual machines, then you will need to copy yapoolman.jar to each of them.

(3) Application option: To include the JARs in a specific application, such as a web application, follow the packaging rules of the app. For instance, if you're using it in a web application, include the JARs in WEB-INF/lib (see the notes on Using YAPoolMan in web apps).





2.2    STEP TWO: Install third-party JAR files

The following additional JAR's or valid subsititues for them must be available to your CLASSPATH according to one of the three options outlined abovein step one. All of these JAR's can be found in the "lib" directory of the distribution. 

·         Jakarta Commons-Logging: This is the Apache/Jakarta logging library that provides common interface among Log4J, Logging of JDK 1.4, or any other implementation. YAPoolMan makes use of it for all logging tasks. Location: lib/commons-logging.jar

·        Jakarta Commons-Digester: This is the Apache/Jakarta xml file digester library used to load xml configuration file. Location: lib/commons-digester.jar

·         Jakarta Commons-Collections: This Apache/Jakarta enhanced Collection is picked up for the implementation of BinaryHeap, a Priority Queue helps factory and pool which object choose. Location: lib/commons-collections.jar

·        Jakarta Commons-BeanUtils: This Apache/Jakarta util provides bean related functionality and is used by other Jakarta Commons library. Location: lib/commons-beanutils.jar


·         JMX Reference Implementation from SUN: Required only when JMX is enabled. Location: lib/jmxri.jar, lib/jmxtools.jar

·         Jakarta Ant: If you wish to build YAPoolMan from source. It is not provided by the project, you can download from Jakarta.apache.org/ant.

·         JUnit Testing Framework: If you wish to run the YAPoolMan test suite, you must have JUnit available. Location: lib/junit.jar





2.3    STEP THREE: Configure and install poolman.xml

Configure: The "poolman.xml" file contains the XML-defined details of the pools you wish to create. A template for this file is located in the "lib" directory of the distribution: src/samples/poolman.xml.template. An extremely basic example file is located in the same directory: src/samples/poolman.xml.example. See the Resources section for definitions of all the possible configuration elements.

Install: Be sure that poolman.xml is put into current working directory, or the directory containing it is in all relevant CLASSPATH entries. For example, if you save your poolman.xml file as /poolman/lib/poolman.xml be sure that your CLASSPATH contains the /poolman/lib directory. Do not put the file itself in the CLASSPATH, put the directory containing it in your CLASSPATH.

Web App Install: If you are embedding YAPoolMan within a web application, put poolman.xml in the WEB-INF/classes directory (see the notes for web app usage).





2.4    Testing the installation

Once the appropriate CLASSPATH updates have been made and the poolman.xml file configured, enter the "samples" directory and execute the following command from a prompt:

./runSample.bat [sql statement] [database name]

./runSample.sh [sql statement] [database name]

For example, if you have named a database "testdb" in your poolman.xml file, and "select * from users" is a valid statement for that database, and if you are on Windows, execute the following:

./runSample.bat "select * from users" "testdb"

If YAPoolMan has been configured correctly, results should appear for each of the sample methods. If not, the reported error should provide a hint about the problem.

You can also reference web.xml in samples directory to see how to deploy poolman.xml in JSP/servlet engine. (see The YAPoolMan web application).





2.5    Upgrading from PoolMan 2.x release

Modify poolman.xml file

This file has been completely changed, you have to modify it manually. Please reference the document and sample xml file before you make the change. A DTD file is provided to assist if you have xml editors such as XMLSpy.

Modify your code

The SQLManager, SQLUtil has been removed, any code using this class should be re-written or you can provide your own SQLUtil implementation.

The good news is that after setting up poolman.xml and put yapoolman.jar into class path, any code that uses previous versions of YAPoolMan should continue to function. Other means of accessing the DataSource, the Driver and the pool should continue to function even better than before.





3.0    Usage


3.1    JDBC: JNDI and DataSource usage

The preferred method of accessing JDBC Connections is through a DataSource object. DataSource usage should replace the original Driver usage in all J2EE code. Standard Java Naming and Directory Interface (JNDI) server practice is to bootstrap the naming provider through a jndi.properties file that specifies basic settings such as which ContextFactory to use. Your JNDI provider will include such a properties file; you need only add its directory to your CLASSPATH. Most J2EE containers set it automatically. If YAPoolMan finds that no default context factory is available, it will start to use the provided simple memory implementation.

When a connection pool is created, that pool will attempt to bind itself to the naming provider. When a pool is stopped, it unbinds itself.

The name under which the pool is bound is specified in the poolman.xml file, through the <jndiName> element. If no <jndiName> element is specified, then the pool will not bind its DataSource to JNDI, and thus not available for users.

Code Samples

EXAMPLE 1: Below is a code snip illustrating client DataSource usage:

Context   ctx = new InitialContext(params);

DataSource ds = (DataSource) ctx.lookup("java:db/testdb");

Connection con = ds.getConnection();

// your code to make use of the connection here






3.2    JDBC: Driver usage

The original standard means of accessing JDBC connections is through the local DriverManager, which locates JDBC Drivers appropriate for a particular connection request. YAPoolMan does contain a virtual JDBC Driver that wraps underlying drivers, so it can be accessed in this way.

Here is a relevant code snip detailing this approach. It should be familiar, as it is simply an example of YAPoolMan plugged into the standard pre-DataSource JDBC API. The important element is the Driver name ("com.codestudio.sql.YAPoolMan") and the URL passed to the DriverManager ("jdbc:poolman://" + database name as specified in the <dbName> element of poolman.xml).

    try {
        // load the YAPoolMan JDBC Driver
    } catch (Exception ex) {
            System.out.println("Could Not Find the YAPoolMan Driver. \n" +
            "Is yapoolman.jar in your CLASSPATH?");

    Connection con = null;
    try {

        // establish a Connection to the database with
        // <dbname>testdb</dbname>
        //in the poolman.xml file
        con = DriverManager.getConnection("jdbc:poolman://testdb");

        // Use the Connection to create Statements and do JDBC work
        Statement stm = con.createStatement();
        // ... etc. ...

    } catch (SQLException sqle) { sqle.printStackTrace(); }
    finally {
        try { con.close(); } catch (SQLException csqle) {}

NOTE: "closing" the Connection merely returns it to its pool, its real close() is called only when pool decided to discard it.

If a user forgets to close a Connection, YAPoolMan will eventually take it back automatically if it has been sent back for time longer than poolman.xml <userTimeout> element. A forgotten opened statement will get closed when the connection is returned.





3.3  Pooling non-JDBC objects: The Object

Objects of any Java Class type with a default no-args constructor may be pooled through the object pool. These pools can be created and configured through poolman.xml, eliminating the need to write any new code to create a custom object pool.

Here is a usage example:

    // Assumes there is an ObjectPool in poolman.xml with
    // a name "mypool" of type "java.lang.StringBuffer":

    PoolManager manager = PoolManager.getInstance();

    StringBuffer sb = (StringBuffer) manager.requestObject("mypool");

    // use the object however you wish...

    // return it to its manager

Again, generic pooled objects must have a default no-args constructor.






3.4    Implement your own PooledObject

As 3.3 demonstrated, an object pool can be used serve normal objects. However, since only the default constructor can be used to instantiate the object, it is hardly useful to handle complex objects requires various information to initiate, e.g. JDBC connection. Thus, you should wrap the object interested in a PooledObject. JdbcConnectionWrapper is a good example to demonstrate how to use PooledObject to deal with such kind of objects.

First, you must decide how many parameters it needs to initiate itself. As a JDBC connection, you must define url, username and password. For a corba connection, you may need iorFile and interfaceName. So you can define the factory setting in poolman.xm file:















And then you can extend BasePooledObject and implements the following method:

·       open(): to open the connection using the serverInfo provided. serverInfo is an Hashtable containing all name/value pairs defined in poolman.xml for that server. In this corba case, they are iorFile, interfaceName and their values /corba/ior/server1.ior, my.package.IBusiness respectively.

·       closeAllResources(): to close the physical connection. In this case, by calling _release() of org.omg.CORBA.Object

·       clean(): to clean all temporary information and get ready for the connection to serve another user

·       validate(): to check the status of the connection. In this case, you can call _non_existent() of org.omg.CORBA.Object to determine whether the server object for this object reference has been destroyed.





3.5    Implement your own ProxyHandler

Sometime you need more control when your pooled object is used. For a JDBC connection implemented in this project, tracking the opened statement is important. So whenever a Statement is created by the Connection object, whether through createStatement, preparedStatement or prepareCall, it will be monitored and closed when the connection is returned to pool, if user forgets to do so. In corba, I may want to get statistics for the method call to know which ones are more likely to be called, which ones are throwing out exceptions unwanted. That抯 the concept of aspect programming, we can achieve this simply by implement a ProxyHandler for the PooledObject. A proxy handler used during dynamic proxy invocation, called before, after the invocation, and when exception caught as well.  Following methods should be implemented:

public void beforeExecute(PooledObject pooledObject, Method method, Object[] args) throws ProxyHandlerException

Called  before the invocation. If an ProxyHandlerException is thrown and isResultReplaced() is true, the invocation will be ignored, and the object get from getReplaceResult() will be returned as result,  or the exception message will be put into InvocationTargetException and thrown out. Normally, just return.




public Object afterExecute(PooledObject pooledObject, Method method, Object[] args, Object result) throws ProxyHandlerException

Called after the invocation. If exception is thrown, the invocation result will be discarded and the IllegalStateException will be put into InvocationTargetException and thrown out. Normally, the result received should also be returned.


public InvocationTargetException processException(PooledObject pooledObject, Method method, Object[] args, invocationTargetException exception) throws ProxyHandlerException

Called when the invocation caught an exception. You can return the same InvocationTargetException in argument or assemble your new InvocationTargetException, it will then thrown by the proxy. If you want the invocation to return an object rather than throw an exception, you can throw a ProxyHandlerException with replaceResult set. Normally, return the exception received.


The following implementation counts for every method call.


 static public Hashtable methods = new Hashtable();

 public Object afterExecute(PooledObject pooledObject, Method method, Object[] args,

  Object result) throws ProxyHandlerException {

     return result;



  public void beforeExecute(PooledObject pooledObject, Method method, Object[] args) throws ProxyHandlerException {

  Integer count = (Integer) methods.get(method);

  if (count == null)

     methods.put(method, new Integer(1));


     methods.put(method, new Integer(count.intValue()+1);



  public InvocationTargetException processException(PooledObject pooledObject, Method method, Object[] args, InvocationTargetException exception)throws ProxyHandlerException {


     return exception;








3.6    Implement your own ObjectFactory

If you are not satisfied with the service of provided SimpleFactory and MultipleFactory, you can write your own one. The following methods should be implemented:

Object create():Choose a server from all server settings, create a new object by calling newObject(ServerInfo) and store it, the count will get increased


void destroy(Object, boolean): return the object to the factory, and physically close the object. The count will get decreased. If the object is marked bad, the server who is responsible for the object should get checked to see if it is really have problem to serve anymore.


reset(): reset the status, count, history count and destroy all created objects. It is used when you need a fresh restart of the factory.


ServerInfo getServerInfo(Object obj): get the server infomation who serves the object specified


closeAllResources(): close all the factory, not like reset, calling this method means that the factory is no longer required.








3.7    Programmatic usage: alternatives to poolman.xml

It is possible to programmatically create JDBC and Object pools instead of configuring them through poolman.xml metadata.

All pools are described by a JavaBean-like metadata object that is created before the actual pool, so the process involves instantiating a new instance of this metadata object and configuring it, then passing that metadata object to a pool constructor.

Here's an illustrative code snip:

       JdbcPoolInfo poolInfo = new JdbcPoolInfo();








     pool = new JdbcPool(poolInfo);


Or, calling PoolManager.createPool(PoolInfo) directly.






3.8    Starting YAPoolMan as a server

Typically, YAPoolMan does not create its pools and make them available to calling clients until it receives its first request. It is possible to avoid using this lazy initialization, however. To create the pools explicitly before a user request, essentially starting YAPoolMan's underlying embedded server as a first-class server instance, invoke the following line of code:






3.9    Other Poolable Connections

In this package, there are some pre-created connections can be pooled in Object Pool.  They are CICS, MQSeries, JMS and Corba. Refer the javadoc of package net.sf.yapoolman.util to get more information.





4.0    Administration


4.1    Enabling and Disabling JMX

To enable JMX, set the <enabled> param in poolman.xml to "true". Default is not enabled.





4.2    JMX in YAPoolMan

The Java Management Extension (JMX) is a J2EE-optional package aimed at providing a standard management API for all manageable components. It uses the concept of MBeans, or managed beans, to define any manageable resource in a JavaBeans-like manner. In the simplest scenario, every JMX MBean provides get/set methods for exposed attributes.

A layer removed from JMX, YAPoolMan makes use of a JavaBean metadata architecture; every pool is defined by a metadata object. It is this metadata object that JMX manages for YAPoolMan -- one MBean per YAPoolMan metadata object. Thus JMX doesn't directly administer pools, it administers the metadata for the pools. This allows other non-JMX management systems to be plugged into the YAPoolMan library.

When YAPoolMan loads its pools, it calls upon a bootstrap service to parse the poolman.xml file and create a set of MBeans for the entries -- one MBean per pool. The MBeans have methods that mirror the YAPoolMan metadata objects. During the parsing of the XML, the attributes are automatically set on the MBean and therefore on the underlying metadata object. After setting all the initial values, a pool is constructed; the pool constructor requires the metadata object that JMX has configured.

Subsequent changes in any MBean attribute result in a change in the pool's metadata, and will take effect immediately.





4.3    The HTML JMX agent

The JMX Reference Implementation includes an HTML agent that can be used to administer MBeans. In YAPoolMan, this agent is configured like the pools -- through poolman.xml.

Once YAPoolMan has loaded its pools -- either after the first caller request or after invoking the PoolManBootStrap.start() method -- the HTML agent will be available. The port on which it runs is a configurable attribute in poolman.xml, if not specified, the agent will not get started. You can administer YAPoolMan after its pools have loaded by browsing to the following URL:


The agent will NOT be available until YAPoolMan has been started (you will receive a 404 error if it has not yet started). For more information on JMX and this HTML agent, please see Resources.

Important Notes:

1.     You should comment-out the HTML agent entries in poolman.xml before deploying YAPoolMan to a production environment! Database passwords are exposed through the HTML agent, and represent an obvious gaping security risk.

2.     Note that changes made through the HTML agent will not propogate to the poolman.xml file! This functionality may be available in a forthcoming release, but for the time being you must manually edit poolman.xml file to make persistent, long-lived changes.





5.0    Integration: Embeddable YAPoolMan

In general, YAPoolMan is automatically embeddable due to its lazy-initialization architecture. It will be started in the same process as its first invoking caller. Assuming the parent product includes the necessary YAPoolMan entries and dependencies in its CLASSPATH settings (detailed in Installation), YAPoolMan will be accessible as an embedded component regardless of which view -- DataSource, Driver, PoolManager, ObjectPool, JdbcPool -- is used.



6.0    Resources



6.1    The poolman.xml file in detail

See PoolManXML.html for detail.






6.2    The YAPoolMan web application

·        The YAPoolMan web application, packaged in the poolman.war file located in the samples directory, contains the configuration required in a web container.





6.3    Recommended tutorials and relevant specifications

Specifications: JDBC 1.2, JDBC 2.1 Update, JDBC 3.0 (Proposed Spec)
Tutorials: http://www.javasoft.com/products/jdbc/learning.html

Specification: API Spec (for users of JNDI), SPI Spec (for creators of JNDI providers)
Tutorials: Sun's Online Tutorial

Specification: JMX Zip Collection
Site: JMX Web Site





TriLoad Load Balance Server