Odd behavior using Apache Commons Pool

I am trying to use an object pool. The idea is to reuse objects that require resources or time during their creation and that can easily be reset after each use. The classic example is a network connection pool, and the Apache Commons Database Connection Pool (DBCP) is the prime example and user of its sister project, Apache Commons Pool. DBCP is in very wide use and as such I felt is a good reason to rely on Commons Pool in my code. And like DBCP, I am using Commons Pool to manage connections, XMPP connections in my case.

Like a good object pool, Commons Pool relies on an Object Factory which is supposed to manage the lifecycle of the pooled objects. The factory, PoolableObjectFactory, has all the methods you would expect

  • instantiating pooled objects
  • activating objects when being ‘borrowed’ from the pool, taking back resources if necessary
  • validating objects – is the object ok for use? are all the resources successfully regained
  • passivating – releasing resources when the object is not in use, after it is ‘returned’
  • destruction – no need to keep too many objects around if no one is using them

My test case involves the use of an XMPP message source, sending messages every 50 milliseconds or less, and an XMPP message reader, which reads the message and replies to the source.

The reader runs on an infinite loop (e.g. for ( ; ; ) ) while the source sends the messages and then loops infinitely waiting for the responses. Since the sender sends the messages rapidly but in serial fashion, one XMPP connection was necessary, but the reader – which is supposed to do work on the messages, I wanted to use the pool. The sender sends 50 messages and as mentioned, waits, using built-in functionality in the XMPP client library I am using, Smack.

The final bit of information necessary to understand what I experienced is that to implement the pool I am using Commons Pool’s built-in GenericObjectPool with a setting telling it to block requests when all of the pool’s objects are in use. In order to avoid absolute lockups, I also set the pool up to time out after 10 seconds. More importantly, the pool is set up to have at least 2 objects, up to 5 objects if necessary, and to leave 4 idle if they are already created. These are all cool and pretty useful settings afforded to me by GenericObjectPool.

It appears that while the reader currently does nothing else but a one-line manipulation of the incoming message, I am reaching that timeout when no objects are available. The way my code initially worked was:

  • Poll the XMPP queue for messages. If none arrived, sleep for 150 milliseconds.
  • If a message arrived, borrow a connection from the pool
  • Process the message
  • Send response using connection
  • Return the connection to the pool

Apparently this caused this supposed deadlocking or timeout. While it is a single thread that sleeps, and I hope resumes when it wakes up, I kept getting exceptions pertaining to the timeout.

My current ‘solution’ reduces the borrow-object return-object time to the bear minimum, where the aforementioned workflow is now (changes underlined):

  • Poll the XMPP queue for messages. If none arrived, sleep for 150 milliseconds.
  • If a message arrived, process the message
  • Borrow a connection from the pool
  • Send response using connection
  • Return the connection to the pool

What is interesting to me is why the unused connection, which I *did* return to the pool, were not being reused and thus caused the timeout. My code is not even remotely great. The ‘solution’ mentioned above is but an empirical result with a mild shot of rationalization. Hope it keeps working.

Tags: , , , , ,

1 comment

  1. Doing an infinite loop like that seems like a really weird way to write an XMPP client – is there not an event based way to wait for messages, and a built in queue to send them?

    I’ve not done XMPP in Java, but I know it’s a whole lot simpler to do in PHP, and there are no infinite loops involved.

Leave a Reply

Your email address will not be published. Required fields are marked *