Saturday, 5 March 2011

Run tasks in parallel and set your own time out

Many times blocking method calls might cause problems in your applications.
If the code is waiting for some resource availablity and you cannot specify a timeout option...well you're stuck!

You might have seen this with javax.jms.Connection, you try to open a connection when the network is down and your application freezes. No exceptions or anything telling you what's wrong.

Using the the java.util.concurrent api you can run the problematic code in a separate thread and wait for the completion or timeout of this execution.

Here is some code calling a jms connection factory in a separate thread.

private Connection getConnection() throws NamingException, JMSException {
 FutureTask<Connection> createConnectionTask = null;
 try {
  createConnectionTask = new FutureTask<Connection>(new Callable<Connection>() {
   @Override
   public Connection call() throws Exception {
    logger.debug("Calling connection on the connection factory");
    Connection connection = (Connection) connectionFactory.createConnection();
    return connection;
   }
  });
  // start task in a new thread
  new Thread(createConnectionTask).start();

  logger.debug(String.format("Wait for the execution of createConnection to finish, timeout after %d ms", CONNECTION_TIME_OUT));
  connection = createConnectionTask.get(CONNECTION_TIME_OUT, TimeUnit.MILLISECONDS);
 } catch (TimeoutException e) {
  JMSException jmsException = new JMSException(e.getMessage());
  jmsException.setLinkedException(e);
  throw jmsException;
 } 
 return connection;
}


The main thread will create a java.util.concurrent.FutureTask that returns the connection you need.
It'll wait a maximum of CONNECTION_TIME_OUT milliseconds before throwing a TimeoutException. This way you can have complete control of your code execution!

2 comments:

Markus said...

You should check this page out. It addresses this issue, and pokes holes in your implementation. On the surface yours is fine, but it doesn't deal with a lot of corner cases like the connection succeeding after you're done waiting: http://weblogs.java.net/blog/2007/05/23/making-jmx-connection-timeout

mericano1 said...

very good point. Thanks