I am trying to implement a ConnectionFactory using Enum Singleton and hitting a strange problem with loading the DB driver (Class.forName). Now, I know, Singleton is a controversial pattern and not everybody likes it, and yeah, I am not a big fan too. But this is for illustration purpose only.
Here is my main code:
public class HelloWorld {
public static void main(String[] args) {
ConnectionFactory.getConnection();
}
}
And the ConnectionFactory:
public enum ConnectionFactory {
INSTANCE;
// Database details
private static final String JDBC_DRIVER_PARAM="org.h2.Driver";
private static final String DB_URL_PARAM="jdbc:h2:file:./h2database/homedb";
private static final String DB_USER_PARAM="admin";
private static final String DB_PASS_PARAM="pass";
private ConnectionFactory() {
try {
Class.forName(JDBC_DRIVER_PARAM);
System.out.println("Driver Loaded!");
} catch (ClassNotFoundException e) {
System.out.println(e);
}
}
private Connection createConnection() {
Connection conn = null;
try{
conn = DriverManager.getConnection(DB_URL_PARAM, DB_USER_PARAM, DB_PASS_PARAM);
}catch (Exception e) {
System.out.println(e);
}
return conn;
}
//public method to obtain connection
public static Connection getConnection() {
return INSTANCE.createConnection();
}
}
And here is the output:
java.lang.ClassNotFoundException: org.h2.Driver
Though, below works fine - so it is definitely not a classpath issue. I am running both approaches from Eclipse and it is the same maven project, so no issue with dependencies.
public class HelloWorld {
public static void main(String[] a) throws Exception {
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:file:./h2database/homedb", "admin", "pass");
System.out.println("Connected");
conn.close();
}
}
And here is the output:
Connected
The only real difference I can see between the 2 approaches is the use of Enum Singleton. So my question: Is there something specific going on when I use Class.forName()
from Enum Constructor? I thought, the constructor is called when enum is loaded by class loader, and that should be able to use other classes on the classpath. Am I missing something here?