I feel as though I haven't got my design right here and that I'm stuck between two techniques. I'm attempting to write a class which hands out connections to a database. The code is below:
public final class DBUtil {
private static String databaseDriver = null;
private static String databaseConnectionString = null;
private static String databaseUser = null;
private static String databasePassword = null;
private static String serverName = null;
private static ComboPooledDataSource dataSource = null;
private DBUtil() {
throw new AssertionError();
}
private static void getParameters() {
final Properties configFile = new Properties();
try {
configFile.load(DBUtil.class.getClassLoader().getResourceAsStream("my.properties"));
if (configFile.containsKey("databaseConnectionString") && configFile.containsKey("databaseUser") && configFile.containsKey("databasePassword") && configFile.containsKey("databaseDriver")) {
DBUtil.databaseConnectionString = configFile.getProperty("databaseConnectionString");
DBUtil.databaseDriver = configFile.getProperty("databaseDriver");
DBUtil.databaseUser = configFile.getProperty("databaseUser");
DBUtil.databasePassword = configFile.getProperty("databasePassword");
}
else {
// Properties file not configured correctly for database connection
}
}
catch (IOException e) {}
}
public static Connection getDatabaseConnection() {
if (Strings.isNullOrEmpty(databaseConnectionString) || Strings.isNullOrEmpty(databaseUser) || Strings.isNullOrEmpty(databasePassword) || Strings.isNullOrEmpty(databaseDriver)) {
DBUtil.getParameters();
}
dataSource = getDataSource();
int retryCount = 0;
Connection connection = null;
while (connection == null) {
try {
connection = dataSource.getConnection();
}
catch (SQLException sqle) {}
}
return connection;
}
private static ComboPooledDataSource getDataSource() {
if (dataSource == null) {
dataSource = new ComboPooledDataSource();
try {
dataSource.setDriverClass(databaseDriver);
dataSource.setJdbcUrl(databaseConnectionString);
dataSource.setUser(databaseUser);
dataSource.setPassword(databasePassword);
}
catch (PropertyVetoException pve) {}
}
return dataSource;
}
public static void cleanUpDataSource() {
try {
DataSources.destroy(dataSource);
}
catch (SQLException sqle) {}
}
}
FindBugs is returing Incorrect lazy initialization and update of static field when I do:
if (dataSource == null) {
dataSource = new ComboPooledDataSource();
...
Any advice greatly appreciated. I feel as though I'm stuck here somewhere between the Singleton pattern and a class which consists of simply a set of static methods.
More generally, is this a good way to hand out database connections to DAOs?
Many thanks.
That method should be synchronized in order to avoid two parallel executions (two threads calling it at the same time).
Added
Not synchronized exception could lead to two threads executing this:
T1 if (datasource == null) YES
T2 if (datasource == null) YES
T1 datasource = new Datasource...
T2 datasource = new Datasource(...); AGAIN!
and T1 and T2 calling methods on one of two datasources (depending when T2 overrides the T1 object creation).
Volatile
As #Jean-Marc proposes you should declare datasource field as volatile. That keyword ensures that thread don't use a thread-local copy of the variable (that would potentially cause problems if a thread reads an outdated cached value).
I'm not sure if this case happens between different method invocations, or if syncrhonized deals with it but it's better to be sure :)
Findbugs is complaining because your getDataSource method is not synchronized. With your current code it is possible for two concurrent threads to call getDataSource and retrieve to separate DataSource objects.
The problem with that code is that in the presence of multitheading you could end up creating multiple instances of ComboPooledDataSource, and having dataSource point to different instances at different times.
This could happen if the method were to be called by several threads at about the same time.
Let's say dataSource is null, and the execution of two threads is interleaved as follows:
Thread 1: if (dataSource == null) { // condition is true
Thread 2: if (dataSource == null) { // condition is true
Thread 1: dataSource = new ComboPooledDataSource();
Thread 2: dataSource = new ComboPooledDataSource();
An easy way to fix the concurrency issue is by adding synchronization.
This is why FindBugs is complaining:
http://findbugs.sourceforge.net/bugDescriptions.html#LI_LAZY_INIT_UPDATE_STATIC
As mentioned, if you don't have multiple threads you shouldn't have a problem.
Related
How to get same connection from a DataSource in multiple classes? Is it possible?
Suppose I have a DataSource which I pass to 2 classes. The DataSource is using a Connection Pooling.
Then I call a method in 1st Class which get a Connection from the DataSource, uses that Connection and then closes that Connection.
Then I call a method in 2nd Class which get a Connection from the DataSource, uses that Connection and then closes that Connection.
Is it possible to be sure that the method in 2nd Class will get the same Connection which was used by method in 1st Class?
This is the example code:
This is the 1st class whose method will be called by the unit of work:
public class Class1 {
private DataSource dataSource = null;
public Class1(DataSource dataSource) {
this.dataSource = dataSource;
}
public void class1Method1() throws Exception {
Connection conn = null;
try {
conn = dataSource.getConnection();
... // do your work
} finally {
try {
if (conn != null)
conn.close();
} catch (Exception e) {
} finally {
conn = null;
}
}
}
}
This is the 2nd class whose method will be called by the unit of work:
public class Class2 {
private DataSource dataSource = null;
public Class2(DataSource dataSource) {
this.dataSource = dataSource;
}
public void class2Method1() throws Exception {
Connection conn = null;
try {
conn = dataSource.getConnection();
... // do your work
} finally {
try {
if (conn != null)
conn.close();
} catch (Exception e) {
} finally {
conn = null;
}
}
}
}
And this is my unit of work:
InitialContext initialContext = null;
DataSource dataSource = null;
Class1 class1 = null;
Class2 class2 = null;
initialContext = new InitialContext();
dataSource = (DataSource) initialContext.lookup("java:comp/env/jdbc/MyDB");
class1 = new Class1(dataSource);
class2 = new Class2(dataSource);
class1.class1Method1();
class2.class2Method1();
Closing a connection releases the connection resources, see here and connections should always be closed. Depending on the DataSource implementation (e.g. connection pool) it could then for instance give that same connection back on the next getConnection call. But it does not have to do so, it can also terminate the first connection and return a new one each time.
For more info, see here and here.
As #EJP said in a comment, You would need to pass the Connection around into the other class before you close it. You'd also need to make sure the second class doesn't close it if you plan to use it later in the outer class. This is a low level solution and quite a headache.
You can use Spring or Java EE to solve this problem at a higher level. It lets you mark all your relevant methods to say, "these should be transactional". If you call one for the first time, a new transaction is started. When you leave that outer method, the transaction automatically ends. But, if that method calls another transactional method, it knows the transaction is still open so it reuses it. It removes a lot of headache.
I believe these two technologies use Aspect Oriented Programming under the hood.
Read more for JEE: http://docs.oracle.com/javaee/6/tutorial/doc/bncih.html
Read more for Spring: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html
I have many threads accessing MYSQL database, at first I didn't use connection pool so I had this error "You can't operate on a closed ResultSet"
I searched on Google and found out that I should used connection pool so I tried c3p0 API for implementation, but I still have the same problem and nothing changed.
so should I Synchronize getAllcountries method or there's another better solution.
public class DataSource {
private static DataSource datasource;
private ComboPooledDataSource cpds ;
private DataSource() throws IOException, SQLException, PropertyVetoException {
cpds = new ComboPooledDataSource();
cpds.setDriverClass("com.mysql.jdbc.Driver"); //loads the jdbc driver
cpds.setJdbcUrl("jdbc:mysql://localhost/question_game");
cpds.setUser("root");
cpds.setPassword("");
cpds.setMaxPoolSize(500);
}
public static DataSource getInstance() throws IOException, SQLException, PropertyVetoException {
if (datasource == null) {
datasource = new DataSource();
return datasource;
} else {
return datasource;
}
}
public Connection getConnection() throws SQLException {
return this.cpds.getConnection();
}
public List<Country> getAllCountries() {
String query = "SELECT * FROM country order by name ";
List<Country> list = new ArrayList<Country>();
Country country = null;
ResultSet rs = null;
try {
try {
connection = DataSource.getInstance().getConnection();
} catch (IOException e) {
e.printStackTrace();
} catch (PropertyVetoException e) {
e.printStackTrace();
}
statement = connection.createStatement();
rs = statement.executeQuery(query);
while (rs.next()) {
//getting countries
}
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
//DbUtil used to check if null
DbUtil.close(rs);
DbUtil.close(statement);
DbUtil.close(connection);
}
return list;
}
In addition to #stephen-c 's observation,
you basically have two options: either synchronize getAllCountries method, or make the database connection local to that method instead of having it as a class member.
As you have it now, 'connection' is a class member (available to all invocations of getAllCountries(), on all threads), so the connection is probably being overwritten by a second thread. Move it to a variable in the method, and then each invocation of the method will have its own connection.
I see a method called getConnection, I don't see where you are calling it. Instead, I see your getAllCountries method using a static DataSource object that is created like this:
new DataSource();
I searched on Google and found out that I should used connection pool so I tried c3p0 API for implementation, but I still have the same problem and nothing change
Yea ...
It looks like you just cut-and-pasted the code you found into your application without really thinking about it. Obviously ... you need to understand what the code is doing AND figure out how to use it in your application.
I created a GUI (Eclipse Wizard) where a user can log in into a database. I swapped the db-access into an external thread. The method startDBCheck() is called from the listeners when user inputs some text. Here's the code:
public class DBPage
extends MyWizardPage
{
public final class ConnectionCheckingThread
extends Thread
{
boolean interrupted;
#Override
public void run()
{
updateStatus("Checking connection..."); // Method in MyWizardPage using Display.getDefault().asyncExec() to make changes to the GUI
String dbError = Database.getInstance().checkDBAccess(); //checkDBAccess() is synchronized
if (interrupted)
return;
if (dbError != null)
{
updateStatus("Error connecting database: " + dbError);
return;
}
updateStatus(null);
}
public void disable()
{
interrupted = true;
}
}
private ConnectionCheckingThread connectionCheckingThread;
private void startDBCheck()
{
if (connectionCheckingThread != null)
connectionCheckingThread.disable();
connectionCheckingThread = new ConnectionCheckingThread();
connectionCheckingThread.start();
}
}
I am watching the memory usage and notice that the eclipse instance is taking more memory with every change on the graphical interface. If I play with the GUI for some time I get a OutOfMemoryError. This makes me think the dead threads aren't being deleted by garbage collector for some reason. I don't see any problem in my code though. If i set the reference on connectionCheckingThread to a new thread, there are no other references pointing the old one, so it should be removed. Am I right and the memory leak is somewhere else, or is there really a problem with this part of code?
upd: I get a PermGen space error which makes me consider if this code look suspicious.
private synchronized Connection getConnection()
throws Exception
{
// load JDBC drivers from jar file
File driverFile = new File(pathToJar);
URL[] urls = {driverFile.toURI().toURL()};
URLClassLoader child = new URLClassLoader(urls, this.getClass().getClassLoader());
Class< ? > clazz = Class.forName(className, true, child);
if (clazz != null)
{
Driver driver = (Driver)clazz.newInstance();
delegatingDriver.setDriver(driver);
DriverManager.registerDriver(delegatingDriver);
}
// Open a connection. If no exception is thrown, the settings work
return DriverManager.getConnection(dbURL, dbUser, dbPassword);
}
upd2: classloading is definitely the cause. Now I need to find out how to fix it.
I decided not to use DelegatingDriver as well as DriverManager anymore. Plus I created a subclass of a URLClassLoader to make it possible to add URLs dynamically. Here's my solution:
public class Database
{
private static final class InstanceHolder
{
static final Database INSTANCE = new Database();
}
private static final class DynamicURLClassLoader
extends URLClassLoader
{
public DynamicURLClassLoader(URL[] urls, ClassLoader parent)
{
super(urls, parent);
}
#Override
protected void addURL(URL url)
{
super.addURL(url);
}
}
// skipped
private DynamicURLClassLoader childClassloader;
private Database()
{
childClassloader = new DynamicURLClassLoader(new URL[]{}, this.getClass().getClassLoader());
}
public static Database getInstance()
{
return InstanceHolder.INSTANCE;
}
private synchronized Connection getConnection()
throws Exception
{
// load JDBC drivers from jar file
File driverFile = new File(pathToJar);
childClassloader.addURL(driverFile.toURI().toURL());
java.util.Properties info = new java.util.Properties();
if (dbUser != null)
{
info.put("user", dbUser);
}
if (dbPassword != null)
{
info.put("password", dbPassword);
}
if (dbURL == null)
{
throw new SQLException("The url cannot be null", "08001");
}
Class< ? > clazz = Class.forName(className, true, childClassloader);
if (clazz != null)
{
Driver driver = (Driver)clazz.newInstance();
// Open a connection. If no exception is thrown, the settings work
Connection con = driver.connect(dbURL, info);
if (con != null)
// Success!
return (con);
}
throw new SQLException("The chosen driver is not suitable for " + dbURL, "08001");
}
}
I am trying to create a pool of channels/connections to a queue server and was trying to use ObjectPool but am having trouble using it from the example on their site.
So far I have threads that do work but I want each of them to grab a channel from the pool and then return it. I understand how to use it(borrowObject/returnObjects) but not sure how to create the intial pool.
Here's how channels are made in rabbitmq:
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
and my code just uses channel to do stuff. I'm confused because the only example I could find (on their site) starts it like this:
private ObjectPool<StringBuffer> pool;
public ReaderUtil(ObjectPool<StringBuffer> pool) {
this.pool = pool;
}
Which does not make sense to me. I realized this is common to establishing database connections so I tried to find tutorials using databases and ObjectPool but they seem to use DBCP which is specific to databases(and I can't seem to use the logic for my queue server).
Any suggestions on how to use it? Or is there a another approach used for pools in java?
They create a class that creates objects & knows what to do when they are returned. That might be something like this for you:
public class PoolConnectionFactory extends BasePoolableObjectFactory<Connection> {
private final ConnectionFactory factory;
public PoolConnectionFactory() {
factory = new ConnectionFactory();
factory.setHost("localhost");
}
// for makeObject we'll simply return a new Connection
public Connection makeObject() {
return factory.newConnection();
}
// when an object is returned to the pool,
// we'll clear it out
public void passivateObject(Connection con) {
con.I_don't_know_what_to_do();
}
// for all other methods, the no-op
// implementation in BasePoolableObjectFactory
// will suffice
}
now you create a ObjectPool<Connection> somewhere:
ObjectPool<Connection> pool = new StackObjectPool<Connection>(new PoolConnectionFactory());
then you can use pool inside your threads like
Connection c = pool.borrowObject();
c.doSomethingWithMe();
pool.returnObject(c);
The lines that don't make sense to you are a way to pass the pool object to a different class. See last line, they create the pool while creating the reader.
new ReaderUtil(new StackObjectPool<StringBuffer>(new StringBufferFactory()))
You'll need a custom implementation of PoolableObjectFactory to create, validate, and destroy the objects you want to pool. Then pass an instance of your factory to an ObjectPool's contructor and you're ready to start borrowing objects.
Here's some sample code. You can also look at the source code for commons-dbcp, which uses commons-pool.
import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;
public class PoolExample {
public static class MyPooledObject {
public MyPooledObject() {
System.out.println("hello world");
}
public void sing() {
System.out.println("mary had a little lamb");
}
public void destroy() {
System.out.println("goodbye cruel world");
}
}
public static class MyPoolableObjectFactory extends BasePoolableObjectFactory<MyPooledObject> {
#Override
public MyPooledObject makeObject() throws Exception {
return new MyPooledObject();
}
#Override
public void destroyObject(MyPooledObject obj) throws Exception {
obj.destroy();
}
// PoolableObjectFactory has other methods you can override
// to valdiate, activate, and passivate objects.
}
public static void main(String[] args) throws Exception {
PoolableObjectFactory<MyPooledObject> factory = new MyPoolableObjectFactory();
ObjectPool<MyPooledObject> pool = new GenericObjectPool<MyPooledObject>(factory);
// Other ObjectPool implementations with special behaviors are available;
// see the JavaDoc for details
try {
for (int i = 0; i < 2; i++) {
MyPooledObject obj;
try {
obj = pool.borrowObject();
} catch (Exception e) {
// failed to borrow object; you get to decide how to handle this
throw e;
}
try {
// use the pooled object
obj.sing();
} catch (Exception e) {
// this object has failed us -- never use it again!
pool.invalidateObject(obj);
obj = null; // don't return it to the pool
// now handle the exception however you want
} finally {
if (obj != null) {
pool.returnObject(obj);
}
}
}
} finally {
pool.close();
}
}
}
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 getInstance method 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:
public enum ConnectionManager {
INSTANCE;
}
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:
public enum ConnectionManager {
INSTANCE;
private DataSource ds = null;
ConnectionManager() {
try {
final Context initCtx = new InitialContext();
final Context envCtx = (Context) initCtx.lookup("java:comp/env");
ds = (DataSource) envCtx.lookup("jdbc/ConnectionManager");
} catch (NamingException e) {
e.printStackTrace();
}
}
public Connection getConnection() throws SQLException {
if(ds == null) return null;
return ds.getConnection();
}
}
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:
public enum ConnectionManager {
INSTANCE;
private DataSource ds = null;
private Lock connectionLock = new ReentrantLock();
ConnectionManager() {
try {
final Context initCtx = new InitialContext();
final Context envCtx = (Context) initCtx.lookup("java:comp/env");
ds = (DataSource) envCtx.lookup("jdbc/ConnectionManager");
} catch (NamingException e) {
e.printStackTrace();
}
}
public Connection getConnection() throws SQLException {
if(ds == null) return null;
Connection conn = null;
connectionLock.lock();
try {
conn = ds.getConnection();
} finally {
connectionLock.unlock();
}
return conn;
}
}
You don't have to add wrapper methods to close the connection, that is the responsibility of the calling code. Good luck.
#arya, seems like you are having the problem of connection leak, and because of that the pool is getting exhausted and the code just waits till it gets a new connection, To analyze the problem , use any of the database monitoring tools, or manually try to trace the leak (The point in code where you have consumed a connnection but forgot to return it to the pool after use).
Well I would say first try out your dataSource is working or not with a test source.
I suggest look at Apache Tomcat JNDI Data Resource How To, for Apache Tomcat 6.0 and for Apache Tomcat 7.0.
Look at the instructions carefully and analyse what's going wrong in your code, then update your question with specific problem.
That code is virtually guaranteed to cause connection leaks in a multithreaded system. closeDbConnection() closes only the last connection borrowed from pool - so if 10 threads have called getDbConnection(), and after that closeDbConnection(), only 1 connection is closed and 9 still alive. Repeat that several times and pool is exhausted (unless connection is cleaned up in finalize(), but that's probably not the case). I would get rid of the whole class, or reworked it to act only as a datasource locator.