I am using JDBC connection pooling in Tomcat. To retrieve connections I have defined a connection factory as below:
public class ConnectionManager {
// reference to the ConnectionManager
private static ConnectionManager instance = null;
// Connection to MySQL database
private Connection connect = null;
private static DataSource ds = null;
// Logger
public static final Logger logger = Logger
.getLogger(ConnectionManager.class);
static {
try {
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
ds = (DataSource) envCtx.lookup("jdbc/ConnectionManager");
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Private Constructor .. since its a singleton
*
*/
private ConnectionManager() {
}
public static ConnectionManager getInstance() {
if (instance == null) {
instance = new ConnectionManager();
}
return instance;
}
public Connection getDbConnection() {
Connection conn = null;
try {
synchronized (DataSource.class) {
conn = ds.getConnection();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
public void closeDbConnection() throws SQLException {
conn.close();
}
}
Now I see that my code always gets stuck at conn = ds.getConnection(); line. Please let me know what I am doing wrong. From my DAO methods I am using the following to get connection: conn = ds.getConnection();
Clearly its a multi-threading issue. What should I do?
Most of your class seems geared around retrieving the JNDI datasource and using it to create connections. Not necessarily a bad idea but in this case you have introduced some bugs into your program with the additional complexity.
First off, your singleton is not a singleton. Your are not synchronizing the
getInstancemethod so its possible to multiple threads to invoke this method at the same time. The best method in Java (unfortunately) for implementing singletons is via an enum:Your second significant issue is that you are synchronizing on a class that you don’t explicitly control. There is nothing preventing third party JARs or even other classes in your own application from synchronizing on the DataSource class, making it a rife target for deadlocking issues. I would take out all the superfluous methods from the class and remove the synchronize block:
Now, most datasource implementations are thread safe in my experience, so the above code should work most of the time. But, we shouldn’t rely on implementations we cannot control, so lets add a safe synchronization to the code, like so:
You don’t have to add wrapper methods to close the connection, that is the responsibility of the calling code. Good luck.