Java 7’s Little Engine That Could

Today is just a bit on a funny effect of Java 7’s way of doing try-with-resource scoping. Consider the following partial class for a poolable autoclosong resource:

public class PoolResource<T> extends AutoClosable {
  T resource;
  Pool<T> pool;
  public PoolResource(Pool<T> pool) {
    this.pool = pool;
    resource = pool.borrow();
  }

  public void invalidate() {
    synchronized(this) {
      pool.invalidate(resource);
      resource = null;
    }
  }

  @Override
  public void close() {
    synchronized (this) {
      if (resource != null) {
        pool.returnObject(resource);
        resource = null;
      }
  }
}

Now, for the weird part. Java 7 closes the resource before a catch, which causes a weird issue in order to be able to catch and invalidate the pool resource.

  try (PoolResource myOb = ...) {
    try {
      // do work with myOb
    } catch (…) {
      myOb.invalidate();
      // some other exception routine stuff
    }
  }

Note that you wind up with a try that contains the full body of the outer try. So, try-try again. It’s just funny.

It would be nice if you could do the following:

  try (PoolResource myOb = ...) {
    // do work with myOb
  } catch (…) {
    myOb.invalidate();
    // some other exception routine stuff
  }

Alas, there are reasons. It would be nice though.

Here are a few ideas if you are facing this issue (and a short commentary):

Validate-On-Borrow

One option is to validate the object from your pool is good on borrow. This ensures that your object is good right away and unlikely to be bad. This may be a bad solution if you cannot validate the object easily or if there is a potential that the object will become invalid part way through the routine.

Validate-On-Return

This is a play on the previous option. This is unique in that if the object was truly invalidated, and validation would detect it, all that would have changed would have been where the code executes.

The try-try solution executes in the following order:

  1. Error Occurs
  2. Enter Catch Block of Inside Try
  3. Invalidate object
  4. Additional Catch block code
  5. AutoClose the object & find it’s already invalidated
  try (PoolResource myOb = ...) {
    // do work here
  }

A Validate on Return (with no inner try) would look similar to:

  1. Error Occurs
  2. AutoClose the object, detect that its invalid and invalidate the object
  3. Error goes on to its ultimate destination

Tighten up your catch block

This is another option. It’s not a terrible idea to tighten up the try inside to only pertain to places where your resource is actually in use. It makes the code appear less weird, but in the end, not a lot actually changed structurally.

Conclusion

This basically turns into a preference and appropriateness of the solution for your problem. If you can’t validate, the little engine that could solution – try, try again – is maybe your best bet. If you can validate, you can chose when to validate your objects based on what’s best. If you want to keep stale objects out of your pool, do it last. If your objects can become stale while in the pool, maybe validate before starting your method.

Happy Coding!