illegalstateexception pool not open with ObjectPool
<p>I'm trying to learn how to use to pool connections so I can get better throughput by not having to open/close channels to a server but I can't seem to get it to work.  I had a slightly modified version of my code that worked when I forked a thread and made each thread run a loop to dump data, but now I'm trying to use <code>ThreadPoolExecutor</code> to send jobs vai a single thread and then spawn 2 threads to deal handle the work.  My experiment should hopefully show around 2 channels open at any given time(or as many threads as I have) but instead when i change my code I get <code>illegalstateexception: pool not open</code>  </p>

<p>I'm really confused if my design of the pool is wrong or my understanding of ThreadPoolExecutor is flawed.  My understanding of ThreadPoolExecutor was that it kept the threads alive if there was work to be done and didn't keep killing/respawning them upon each iteration.</p>

<p>Here's the code(you can ignore all the rabbitmq stuff, the gist of it is you need to open a connection to a server, then open a channel. I am trying to open one connection to the server and then a pool of channels that are shared). My idea was to create an instance of the objectpool class and then pass it to a runnable which <code>borrows</code> channels as needed.</p>

<p><strong>Code:</strong></p>

<pre><code>import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;

import java.io.IOException;
import java.util.NoSuchElementException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.MessageProperties;

public class PoolExample {

    private static ExecutorService executor_worker;
    static {
        final int numberOfThreads_ThreadPoolExecutor = 2;
        executor_worker =
            new ThreadPoolExecutor(numberOfThreads_ThreadPoolExecutor, numberOfThreads_ThreadPoolExecutor, 1000, TimeUnit.SECONDS,
                                   new LinkedBlockingDeque&lt;Runnable&gt;());   
    }

    public static void main(String[] args) throws Exception {
        System.out.println("starting..");       
        PoolableObjectFactory&lt;MyPooledObject&gt; factory = new MyPoolableObjectFactory();
        ObjectPool&lt;MyPooledObject&gt; pool = new GenericObjectPool&lt;MyPooledObject&gt;(factory);
        for (int x = 0; x&lt;500000000; x++) {
            executor_worker.submit(new Thread(new MyRunnable(x, pool)));
        }
    }
}

class MyPooledObject {
    //Connection connection;
    Channel channel;
    public MyPooledObject() throws IOException {
        System.out.println("hello world");
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        channel = connection.createChannel(); 
    }

    public Channel sing() throws IOException {
        //System.out.println("mary had a little lamb");
        return channel;
    }

    public void destroy() {
        System.out.println("goodbye cruel world");      
    }
}

class MyPoolableObjectFactory extends BasePoolableObjectFactory&lt;MyPooledObject&gt; {
    @Override
    public MyPooledObject makeObject() throws Exception {
        return new MyPooledObject();
    }
    @Override
    public void destroyObject(MyPooledObject obj) throws Exception {
        obj.destroy();
    }
}

class MyRunnable implements Runnable{  
    protected int x = 0;
    protected ObjectPool&lt;MyPooledObject&gt; pool = null;

    public MyRunnable(int x, ObjectPool&lt;MyPooledObject&gt; pool) {
        // TODO Auto-generated constructor stub
        this.x = x;
        this.pool = pool;
    }

    public void run(){
        try {
                MyPooledObject obj;
                obj = pool.borrowObject();
                Channel channel = obj.sing();
                String message = Integer.toString(x);
                channel.basicPublish( "", "task_queue", 
                        MessageProperties.PERSISTENT_TEXT_PLAIN,
                        message.getBytes());
                pool.returnObject(obj);
        } catch (NoSuchElementException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                pool.close();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
</code></pre>

<p>Any idea what's wrong with my design? or is my entire approach to pool objects flawed?</p>

<p>UPDATE1: as per request here is the stack trace (I get many many of these continuously):</p>

<p><strong>stacktrace:</strong></p>

<pre><code>java.lang.IllegalStateException: Pool not open
    at org.apache.commons.pool.BaseObjectPool.assertOpen(BaseObjectPool.java:140)
    at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1079)
    at MyRunnable.run(PoolExample.java:85)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:680)
</code></pre>

<p>If it helps, line 85 in my code(where this error is triggered is): <code>obj = pool.borrowObject();</code></p>

<p>UPDATE2: very odd. I get the error but it does write 2 items to the queue.  I don't want to send anyone on a wild goose chase but I'm thinking that means it can successfully borrow objects when its creating them but not when they are being returned to the pool?</p>

<p>UPDATE3: I designed the code so it doesn't go through the middle step I had above. I no longer get the error but it basically does nothing..I launch 10 threads and expect 10 channels but I only get 1 channel for a few seconds then it turns off as well.
code:</p>

<pre><code>import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;

import java.io.IOException;
import java.util.NoSuchElementException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.MessageProperties;

public class PoolExample {

    private static ExecutorService executor_worker;
    static {
        final int numberOfThreads_ThreadPoolExecutor = 20;
        executor_worker =
            new ThreadPoolExecutor(numberOfThreads_ThreadPoolExecutor, numberOfThreads_ThreadPoolExecutor, 1000, TimeUnit.SECONDS,
                                   new LinkedBlockingDeque&lt;Runnable&gt;());   
    }

    public static void main(String[] args) throws Exception {
        System.out.println("starting..");           
        ObjectPool&lt;Channel&gt; pool =
                new GenericObjectPool&lt;Channel&gt;(
                new ConnectionPoolableObjectFactory(), 5);

        for (int x = 0; x&lt;500000000; x++) {
            executor_worker.submit(new MyRunnable(x, pool));
        }
        executor_worker.shutdown();
        pool.close();
    }
}

 class ConnectionPoolableObjectFactory extends BasePoolableObjectFactory&lt;Channel&gt; {
     Channel channel;

    public ConnectionPoolableObjectFactory() throws IOException {
        System.out.println("hello world");
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        channel = connection.createChannel(); 
    }

    @Override
    public Channel makeObject() throws Exception {                
        return channel;
    }

    @Override
    public boolean validateObject(Channel channel) {
        return channel.isOpen();
    }

    @Override
    public void destroyObject(Channel channel) throws Exception {
        channel.close();
    }

    @Override
    public void passivateObject(Channel channel) throws Exception {
        //System.out.println("sent back to queue");
    }
}

class MyRunnable implements Runnable{  
    protected int x = 0;
    protected ObjectPool&lt;Channel&gt; pool;

    public MyRunnable(int x, ObjectPool&lt;Channel&gt; pool) {
        // TODO Auto-generated constructor stub
        this.x = x;
        this.pool = pool;
    }

    public void run(){
        try {
                Channel channel = pool.borrowObject();
                String message = Integer.toString(x);
                channel.basicPublish( "", "task_queue", 
                        MessageProperties.PERSISTENT_TEXT_PLAIN,
                        message.getBytes());
                pool.returnObject(channel);
        } catch (NoSuchElementException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }
}
</code></pre>
