Tuesday, January 13, 2009

Object pooling using Apache Commons

In this post I will give an introduction to Apache Commons Pools http://commons.apache.org/pool/

What is Pooling and why we need to care


Pooling is a mechanism used for either Object pooling in J2EE application servers or for database connection pooling.

Pooling is important since we know that object creation involves heavy processing. So each time when you request a connection towards database that will end up in creating a new object in the heap. This involves a bit of CPU work. And once your are done the object gets cleaned up from memory.
However, consider a web scenario where there might be thousands of requests towards database and creating and cleaning up connection objects can be time consuming.

Pooling enables the objects to be stored in memory(without any state) when the object is no more in use and retrieve it back to active status whenever the application requests for a new object. This saves the processing time needed for instantiation of an object with each single request. You can get more information on pooling in google.

Apache Commons Pool


In this post I will get started with basics of Commons Pool and which will serve as the basic for understanding Apache DBCP Pooling library which is what is the ultimate goal. Please note that by default most jdbc driver implementations do not implement pooling at the driver level, instead they delegate this task to the Application server or depend on the implementation of application server.

You can download the pools library from the following link http://commons.apache.org/pool/downloads.html and add them to your IDE.

Commons Pools have 2 important packages


org.apache.commons.pool.*;
org.apache.commons.pool.impl.*;



The first package introduces the interfaces required for pooling thereby giving a framework. The second package implements them.

The interface ObjectPool defines the common methods that each implementation of a pool should define. The Commons Pool library provides 2 implementations
of the pool (a) GenericObjectPool and (b) GenericKeyedObjectPool


    • GenericObjectPool: provides a wide variety of configuration options, including the ability to cap the number of idle or active instances, to evict instances as they sit idle in the pool, etc.

      GenericKeyedObjectPool: provides the same functionality but allows you to specify a key for each pool and associated the objects to it


  • The Commons Pool implementation separates the life cycle of the object and the way in which they are pooled. This is done by the means of Factory classes.
    Factory class helps to create, destroy, activate, passivate, and validate instances of the class. The PoolableObjectFactory interface defines life cycle methods
    to be used by an ObjectPool. ObjectPool is the interface that defines how the objects are to be pooled.








    Putting the pieces together


    In order to start with pooling you need to implement a PoolableObjectFactory and define the various life cycle methods viz activateObject,destroyObject,
    makeObject,passivateObject,validateObject for your Object.
    The framework provides you with an abstract class called BasePoolableObjectFactory and so that you dont have to implement all of them.

    Next you need to specify an implementation of ObjectPool in this case we will use a GenericObjectPool which derives from ObjectPool.



    We will begin with defining the object that we need to pool.

    public class LaptopComputer {

    private String operatingSystem;
    private String processor;
    private String memory;


    public String getOperatingSystem() {
    return operatingSystem;
    }
    public void setOperatingSystem(String operatingSystem) {
    this.operatingSystem = operatingSystem;
    }
    public String getProcessor() {
    return processor;
    }
    public void setProcessor(String processor) {
    this.processor = processor;
    }
    public String getMemory() {
    return memory;
    }
    public void setMemory(String memory) {
    this.memory = memory;
    }

    }



    Next we define the PoolableObjectFactory implementation for basic life cycle methods


    public class LaptopComputerObjFactory extends BasePoolableObjectFactory {

    static int i =1;

    @Override
    public Object makeObject() throws Exception {
    System.out.println("\t [LaptopComputerObjFactory] created object "+ i++);



    LaptopComputer tempCompObj = new LaptopComputer();
    //initialize the object
    tempCompObj.setMemory("4 gb");
    tempCompObj.setOperatingSystem("win");
    tempCompObj.setProcessor("X86");

    return tempCompObj;

    }

    @Override
    public void passivateObject(Object obj){

    if( obj != null ){
    System.out.println("\t [LaptopComputerObjFactory] passivating object ");
    //going out of state

    LaptopComputer compObj = (LaptopComputer)obj;
    //neutralize object - release state
    compObj.setMemory(null);
    compObj.setOperatingSystem(null);
    compObj.setProcessor(null);
    }
    }

    @Override
    public void destroyObject(Object obj) {

    if(obj != null) {

    System.out.println("\t [LaptopComputerObjFactory] destroying Object");
    LaptopComputer compObj = (LaptopComputer)obj;
    compObj = null;

    }
    }
    }


    Testing it out in main


    public static void main(String[] args) {


    try {
    GenericObjectPool genObjPool = new GenericObjectPool(new ComputerObjFactory());
    printStats(genObjPool,"Created Object Pool");

    LaptopComputer comp1 = (LaptopComputer)genObjPool.borrowObject();
    //borrow 10 objects from pool
    for(int i=0;i<5;i++)
    {
    genObjPool.borrowObject();
    }


    printStats(genObjPool,"Requested 2 objects");

    //return 1 object
    genObjPool.returnObject(comp1);
    printStats(genObjPool, "Returned 1 object");

    //close the pool
    genObjPool.close();
    printStats(genObjPool, "Pool closed");

    }
    catch(Exception ex) {
    ex.printStackTrace();
    }


    printStats method

    static void printStats(GenericObjectPool genObjPool,String strOperation){
    System.out.println("*******************"+strOperation+"*******************");
    System.out.println("# of Active Pools="+genObjPool.getNumActive());
    System.out.println("# of Idle Pools="+genObjPool.getNumIdle());

    }



    The commons pool implementation uses a doubly linked cursorable list to store the objects. I will delve in more detail about this in the next blog post..