Reputation: 25999
I'm a bit confused on how to return an object(successfully) back to a pool. I am testing creating a pool of channels for rabbitmq(this doesn't have anything to do specifically with rabbitmq though). The process in rabbitmq is to create a connection to a server, then create a channel and I'm trying to have it create channels and use part of a pool but it just keeps creating new ones and does not seem to reuse older channels. I believe this is so because when I check the web UI for rabbit it says I have as many channels as I have items in my queue but my upload speed is about 10k messages a second so I would expect to only have channels around that range.
I am pretty sure this is happening because I have no process(or idea) how to successfully return to the pool. I am using returnObject but do I need to do anything to make it ready to use by another process?
Here's the code(its alot of code but I think the problem is in the MyPooledObject class
and in the pool.returnObject(obj)
part:
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 com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.MessageProperties;
public class PoolExample {
public static class MyPooledObject {
Connection connection;
public MyPooledObject() throws IOException {
System.out.println("hello world");
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
connection = factory.newConnection();
}
public Channel sing() throws IOException {
//System.out.println("mary had a little lamb");
return connection.createChannel();
}
public void destroy() {
System.out.println("goodbye cruel world");
}
}
public static class MyPoolableObjectFactory extends BasePoolableObjectFactory<MyPooledObject> {
@Override
public MyPooledObject makeObject() throws Exception {
return new MyPooledObject();
}
@Override
public void destroyObject(MyPooledObject obj) throws Exception {
obj.destroy();
}
// PoolableObjectFactory has other methods you can override
// to valdiate, activate, and passivate objects.
}
public static void main(String[] args) throws Exception {
PoolableObjectFactory<MyPooledObject> factory = new MyPoolableObjectFactory();
ObjectPool<MyPooledObject> pool = new GenericObjectPool<MyPooledObject>(factory);
// Other ObjectPool implementations with special behaviors are available;
// see the JavaDoc for details
try {
for (int i = 0; i < 500000000; i++) {
MyPooledObject obj;
try {
obj = pool.borrowObject();
} catch (Exception e) {
// failed to borrow object; you get to decide how to handle this
throw e;
}
try {
// use the pooled object
Channel channel = obj.sing();
String message = "Mary Had a little lamb";
channel.basicPublish( "", "task_queue",
MessageProperties.PERSISTENT_TEXT_PLAIN,
message.getBytes());
} catch (Exception e) {
// this object has failed us -- never use it again!
pool.invalidateObject(obj);
obj = null; // don't return it to the pool
// now handle the exception however you want
} finally {
if (obj != null) {
pool.returnObject(obj);
}
}
}
} finally {
pool.close();
}
}
}
Upvotes: 0
Views: 942
Reputation: 3634
The behavior is as expected. Put a break point on makeObject, you'll find that you only ever use it once, because you only use one object in the pool at a time.
If you were to use multiple objects in the pool at the same time, the pool would fill up and be using different objects.
Upvotes: 1