Wrappers

There is a common coding mechanism called a “wrapper”, which attempts to make an existing solution take on some extra characteristics. Just like your overcoat is a wrapper that converts an ordinary human into a human with pockets. And maybe a hood.

Today I battled with a database connection wrapper and eventually observed it being secretly and unexpectedly de-cloaked. To be precise, I was dealing with a javax.sql.Connection wrapper known as a ProxyConnection. In an earlier version of my solution I had a raw (uncloaked) Connection and I used this to create some additional items (ResultSet and Statement) that I needed when interacting with my database. Then I processed the data, and finally I destroyed the Connection. (One should never leave connections lying around idle, because they can be in short supply.)

In my earlier implementation I introduced what I thought was a simple optimization: as soon as I am finished with the ResultSet/Statement, close the connection. Don’t wait until the processing is completed. This worked fine. I even retained the “finally” part as a second chance to close the connection just in case something had gone wrong during the earlier phases.

But then, knowing that I would have to deal with a higher volume of operations, I decided to introduce a wrapper. This ProxyConnection wrapper went arround a normal Connection and introduced some pockets. Well, in fact it introduced “pooling” which meant that instead of actually closing the Connection it would instead go back into a pool of open Connections where it could be immediately reused if needed. You see, opening and closing connections takes time. Moving them into, and out of, a pool is a hundred times faster.

Unfortunately, the pooled connections broke. Very strange. I started to see error messages saying “No operations allowed after connection closed“. Closed? Surely not. The wrapped connections don’t really close, they just go back into the pool to be reused.

It took quite a while to track this one down, but the answer was simple. The optimization I had introduced in the days before pools was not going to work when pools are being used. Why? Because when you ask a ResultSet to give you its Statement, and then you ask the Statement to point you to the Connection, what the Statement actually gives you is the original unwrapped Connection.

To be precise, rs.getStatement().getConnection().close() will actually close the real connection, not the wrapper.

Once the problem was found, the solution was simple: move the “finally” part into where that optimization was located. Now, instead of using the ResultSet/Statement as a means of closure, I merely guarantee that I close the wrapped connection instead.

Note: I had a load of source code to illustrate all this, but I thought I’d have a go at writing it in prose instead. Just for fun.

Categorised as: Coding, Technology

Comment Free Zone

Comments are closed.