1

I would like JdbcPersistenceManager to always have just one jdbcConnection and for it to be instantiated through: JdbcConnectionManager.getJdbcConnection()

Here's a simple pattern taken from (2004-11-01 | Head First Design Patterns | O'Reilly Media | 688p | by Elisabeth Freeman | ISBN-0596007124), possibly misused, misunderstood and out of place.

Should synchronized() lock on "this" or a specific, new (static?) field just dedicated to tracking locks? How would I do that?

public class JdbcPersistenceManager implements PersistenceManager {
  private volatile Connection jdbcConnection;
  /* ... */
  private Connection getJdbcConnection() throws JdbcConnectionFailureException {
    if (jdbcConnection == null) {
      synchronized (this) {
        if (jdbcConnection == null) {
          jdbcConnection =
              JdbcConnectionManager.getJdbcConnection(jdbcConnectionParameters);
        }
      }
    }
    // label:here
    return jdbcConnection;
  }
}

Assuming instantiation of jdbcConnection, even at the point marked as "label:here" if we want, just for argument's sake, how best to check that the connection is still valid and re-create it if it isn't?

ConnectionPooling is not what I'd like to do here. Just one connection... regenerating/reopening it if it's "null" or "invalid".

EDIT:

What I would like getJdbcConnection to do is:

1) dish out jdbcConnections, ensuring only one of them exists at any given time (no clients should be allowed to keep references to 2 different connections)

and

2) regenerate (i.e. re-invoke JdbcConnectionManager.getJdbcConnection()) the "private volatile Connection jdbcConnection" field if for some reason it got closed

(e.g. Client 1 comes along, gets a connection but closes it, client 2 comes along, the connection is not null but can't be used so she gets a regenerated one).

Note: I realise there's nothing stopping Client 1 from getting a connection whilst Client 2 gets the same one, as by design, and using it just one millisecond after Client 1 closes it through his reference... I don't know if that's solvable at all?

Robottinosino
  • 10,384
  • 17
  • 59
  • 97
  • You can create a wrapper/proxy `Connection` instance for each client that all wrap the same real `Connection` and don't propagate the `close()` method, but if it's closed set the internal real `Connection` to `null`/invalid and throws exceptions when attempting further use. – Torious Jun 09 '12 at 19:54
  • It seems like a good idea to have a wrapper class... "every problem is solvable by adding another level of indirection", how was the actual quote? Your suggestion to throw on problems defeats the regeneration capabilities I desire though... doesn't it? – Robottinosino Jun 09 '12 at 20:07
  • I intended that per-client, so if a client calls `close()`, any subsequent operations throw exceptions, like with a real connection, but that's just a detail. – Torious Jun 09 '12 at 20:09

4 Answers4

0

Yes the synchronized() lock is just for tracking locks so that no two threads instantiates the jdbcConnection one after other when they see that jdbcConnection=NULL.

if you want to check for the integrity of the connection at the // label:here position. You can call the getJdbcConnection() method recursively.

return jdbcConnection!=NULL?jdbcConnection:jdbcConnection();
Akhi
  • 2,242
  • 18
  • 24
  • What I would like getJdbcConnection to do is: 1) dish out jdbcConnections, ensuring only one of them exists at any given time (no clients should be allowed to keep references to 2 different connections) and 2) regenerate (i.e. re-invoke JdbcConnectionManager.getJdbcConnection()) the "private volatile Connection jdbcConnection" field if for some reason it got closed (e.g. Client 1 comes along, gets a connection but *closes* it, client 2 comes along, the connection is *not null* but can't be used so she gets a regenerated one). Adding this to the requirements above... – Robottinosino Jun 09 '12 at 19:39
  • If you want one one connection at a given time you should make the jdbcConnection as static (why volatile ?).But connection sharing between multiple threads is not advisable. If its static the regeneration of the connection is also handled. – Akhi Jun 09 '12 at 19:55
0

The double-checked locking should be done on the class not on this:

if (jdbcConnection == null) {
  synchronized (JdbcPersistenceManager.class) {
    if (jdbcConnection == null) {
      jdbcConnection =
          JdbcConnectionManager.getJdbcConnection(jdbcConnectionParameters);
    }
  }
}

As per the connection checking you could do it after creation as you suggest. I wouldn't call the method recursively, just null the Connection instance and try calling getJdbcConnection() again.

Eduardo Sanchez-Ros
  • 1,777
  • 2
  • 18
  • 30
  • Why on the ".class" and not on "this"? The field is non-static so each persistence manager will have its separate data layer... (they are instantiated with information about where to connect to). Am I wrong? It could be! :) – Robottinosino Jun 09 '12 at 20:06
  • I think I am confused with your question. If you want a single connection across all objects you should lock on the class. If you want to have a connection per instance of JdbcPersistenceManager and make sure that the connection is initialized once then you want to lock on this. – Eduardo Sanchez-Ros Jun 09 '12 at 20:14
  • When you say no clients should be allowed to keep references to two different connections, how are you planning on doing that? As soon as you instantiate two objects, having your Connection object non-static, you will have two different connections there. – Eduardo Sanchez-Ros Jun 09 '12 at 20:18
0

If you want to implement a Singleton pattern then you want to make sure that there will be a single instance of a given class, and this is why the Singleton pattern is typically implemented using a static instance.

The best way to avoid any synchronization issues would be to initialize the singleton inline or within a static initilizer, because the initialization occurs when the class is first accessed and it is guaranteed that this initialization is not compromised by concurrency, that is, the class cannot be used until it is fully initialized:

public class Singleton {
    private static final Singlenton instance = new Singleton();

    //private constructor here

    public static Singleton getIntance() { return instance; } 
}

Now, if you want to lazily initialize your singleton, then you would be forced to consider the possibility that more than one thread may try to obtain an instance of it simultaneously, in whose case, you would synchronize access to your class:

public class Singleton {
    private static Singlenton instance;

    //private constructor here

    public static synchronized Singleton getIntance() { 
       if(instance == null) {
            intance = new Singleton();
       }
       return instance; 
    } 
}

Some would recommend to reduce the scope of the synchronized code, by this, also reducing the amount of time the lock is held by a given thread. In such case, you could do something like:

public class Singleton {
    private static Singlenton instance;

    //private constructor here

    public static Singleton getIntance() { 
       synchronized(Singleton.class) {
          if(instance == null) {
               instance = new Singleton();
          }
       }
       return instance; 
    } 
}

In this last example, once the singleton instance is safely assigned, you can concurrently return it.

Another pattern to lazily initialize a Singleton consists in using an static inner class:

public class Singleton {

  //private constructor

   private static class SingletonHolder { 
       public static final Singleton instance = new Singleton();
  }

   public static Singleton getInstance() {
       return SingletonHolder.instance;
   }
}

This would imply that the singleton is not created until the inner class is first accessed, which will not happen until you invoke the getIntance method. Once again, since the class initialization happens in a thread-safe way, you can be sure that creation of the singleton is not compromised.

Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205
  • Nice list of all the options ... but you've missed out the `enum` [technique](http://stackoverflow.com/a/8027815/823393). Cover that and you've got my vote. – OldCurmudgeon Jun 09 '12 at 21:30
  • @OldCurmudgeon I don't do it for the upvotes, I do it for the fun of it. You can always extend my answer in your own answer. Do it so, and you've got my upvote :-) – Edwin Dalorzo Jun 09 '12 at 21:33
0

In addition to @edalorzo's comprehensive list there is one more technique, using the singleton mechanisms provided by enum. There's a good example here and it might look a bit like this.

public enum SingletonConnection {
  INSTANCE;
  // Not sure if this needs to be volatile.
  private volatile Connection jdbcConnection;

  private SingletonConnection() {
    jdbcConnection = JdbcConnectionManager.getJdbcConnection(jdbcConnectionParameters);
  }

  public Connection getConnection() {
    return jdbcConnection;
  }
}

// use it as ...
SingletonConnection.INSTANCE.getConnection ();

However, you may be interested in the idea of using ThreadLocal connections.

Community
  • 1
  • 1
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213