Commons

Home

Information

Project Files

About Us

Jakarta Community

A Simple Pool Client

Suppose you're writing a set of java.io.Reader utilities, and would like to provide a method for dumping the contents of a Reader to a String. Here's the code for the ReaderUtil, implemented without an ObjectPool:

import java.io.Reader; 
import java.io.IOException; 
 
public class ReaderUtil { 
    public ReaderUtil() { 
    } 
 
    /** 
     * Dumps the contents of the {@link Reader} to a 
     * String, closing the {@link Reader} when done. 
     */ 
    public String readToString(Reader in) throws IOException { 
        StringBuffer buf = new StringBuffer(); 
        try { 
            for(int c = in.read(); c != -1; c = in.read()) { 
                buf.append((char)c); 
            } 
            return buf.toString(); 
        } catch(IOException e) { 
            throw e; 
        } finally { 
            try { 
                in.close(); 
            } catch(Exception e) { 
                // ignored 
            } 
        } 
    } 
}

For the sake of this example, let's assume we want to to pool the StringBuffers used to buffer the Reader's contents. (A pool of StringBuffers may or may not be useful in practice. We're just using it as a simple example here.)

Let's further assume that a complete pool implementation will be provided via a constructor. (We'll show you how to create such an implementation in just a moment.) Then to use the pool we simply call borrowObject to obtain the buffer, and then call returnObject when we're done with it. Then a ReaderUtil implementation using a pool of StringBuffers might look like this (changed code is in bold face):

import org.apache.commons.pool.ObjectPool;
import java.io.Reader; 
import java.io.IOException; 
 
public class ReaderUtil { 
    private ObjectPool pool;
 
    public ReaderUtil(ObjectPool pool) { 
        this.pool = pool;
    } 
 
    /** 
     * Dumps the contents of the {@link Reader} to a 
     * String, closing the {@link Reader} when done. 
     */ 
    public String readToString(Reader in) throws IOException { 
        StringBuffer buf = null;
        try { 
            buf = (StringBuffer)(pool.borrowObject());
            for(int c = in.read(); c != -1; c = in.read()) { 
                buf.append((char)c); 
            } 
            return buf.toString(); 
        } catch(IOException e) { 
            throw e; 
        } catch(Exception e) {
            throw new RuntimeException("Unable to borrow buffer from pool" + 
                    e.toString());
        } finally { 
            try { 
                in.close(); 
            } catch(Exception e) { 
                // ignored 
            } 
            try {
                if(null != buf) {
                    pool.returnObject(buf);
                }
            } catch(Exception e) {
                // ignored
            }
        } 
    } 
}

Since we've constrained ourselves to the ObjectPool interface, an arbitrary pool implementation (returning, in our case, StringBuffers) can be used. When a different or "better" pool implemenatation comes along, we can simply drop it into our ReaderUtil without changing a line of code.


A PoolableObjectFactory

Recall that Pool provides a simple toolkit for creating object pools. The PoolableObjectFactory interface is an important part of this toolkit. PoolableObjectFactory defines lifecycle methods for pooled objects. We can use it to separate the kinds of objects that are pooled and how they are created, persisted, or destroyed, from the pooling algorithm itself.

Suppose we have an ObjectPool implementation that accepts a PoolableObjectFactory (for example, any of the implementations in the org.apache.commons.pool.impl package). Then we need only provide the factory implemenation in order to pool a new kind of object.

Here's a PoolableObjectFactory implementation that creates StringBuffers as used above.

import org.apache.commons.pool.BasePoolableObjectFactory; 
 
public class StringBufferFactory extends BasePoolableObjectFactory { 
    // for makeObject we'll simply return a new buffer 
    public Object makeObject() { 
        return new StringBuffer(); 
    } 
     
    // when an object is returned to the pool,  
    // we'll clear it out 
    public void passivateObject(Object obj) { 
        StringBuffer buf = (StringBuffer)obj; 
        buf.setLength(0); 
    } 
     
    // for all other methods, the no-op  
    // implementation in BasePoolableObjectFactory 
    // will suffice 
}

We can, for example, use this factory with the StackObjectPool to instantiate our ReaderUtil as follows:

new ReaderUtil(new StackObjectPool(new StringBufferFactory()))



Copyright © 1999-2003, Apache Software Foundation