I am using JavaFX for my project and I have two classes - MainApp class and Database class.
Very simplified implementation would look like this:
public class MainApp extends Application {
@Override
public void start(Stage stage) throws Exception {
// Getting username & password doing some initialization, etc.
Database.setUserName(username);
Database.setPassword(password);
Database.testConnection();
}
// This method was pretty much generated by IDE
public static void main(String[] args)
{
launch(args);
}
}
Only relevant part of Database class implementation is as follows (note that I have declared and implemented variables that appear in mentioned methods, I just don't paste them here to keep the code short)
public class Database {
private static OracleDataSource dataSource;
static {
try {
dataSource = new OracleDataSource();
dataSource.setURL("myjdbcaddress");
dataSource.setUser(userName);
dataSource.setPassword(password);
System.out.print("Static block executed...");
}
catch (SQLException e)
{
System.out.print("Static block caught...");
throw new ExceptionInInitializerError("Initial Database Connection not established. Sorry.");
}
}
public static Connection getConnection()
{
Connection conn = null;
try
{
conn = dataSource.getConnection();
if (conn != null)
isConnected = true;
}
catch (SQLException e)
{
e.printStackTrace();
}
return conn;
}
}
I am getting null pointer exception because of this: static block in Database class is executed after overridden start() method. Therefore, when I access properties of Database class, they are not initialized yet.
Is there a way to force call static block before start method? Did I choose wrong approach? Should I start working with database somewhere else than start() method?
I am getting null pointer exception because of this: static block in Database class is executed after overridden start() method. Therefore, when I access properties of Database class, they are not initialized yet.
No this is not the issue. The static initializer is executed when the class is loaded, which should happen right before (It's always done before anything other than a static
constant in the class is used.)
Database.setUserName(username);
or earlier.
The problem probably is that the userName
and password
not being assigned yet (although it's hard to tell without more code).
I don't recommend using static
data to pass information but instead design the application in a way that allows access to a non-static object for communication with the database where it's needed.
However you could fix your problem by moving the code from the static initializer to a static
method:
public class Database {
private static OracleDataSource dataSource;
public static void login(String userName, String password) {
try {
dataSource = new OracleDataSource();
dataSource.setURL("myjdbcaddress");
dataSource.setUser(userName);
dataSource.setPassword(password);
System.out.print("Static block executed...");
} catch (SQLException e) {
throw new IllegalStateException("Initial Database Connection not established. Sorry.", e);
}
}
...
}
Database.login(username, password);
Database.testConnection();
But again: Try to avoid using such a Database
class that allows access from everywhere.
BTW: If you need to initialize something before the start
method of the Application
runs, it should be done in a overriden init()
method of the application class.