I'm trying to connect to a PostgreSQL database using Java and the postgresql-42.7.5.jar JDBC driver.
I have the following files in the project directory:
Main.java, Main.class, postgresql-42.7.5.jar
Main.java:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Main {
private static final String URL = "jdbc:postgresql://localhost:5432/testdb";
private static final String USER = "testuser";
private static final String PASSWORD = "password";
public static void main(String[] args) {
try {
Class.forName(".postgresql.Driver");
Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);
System.out.println("Connected to PostgreSQL successfully!");
connection.close();
} catch (ClassNotFoundException e) {
System.err.println("PostgreSQL Driver not found!");
e.printStackTrace();
} catch (SQLException e) {
System.err.println("Connection failed: " + e.getMessage());
e.printStackTrace();
}
}
}
I successfully compile the code using:
javac -cp .:postgresql-42.7.5.jar Main.java
However, when I try to run it, I get the following error:
java -cp .:postgresql-42.7.5.jar Main
Error: Could not find or load main class Main
Caused by: java.lang.ClassNotFoundException: Main
I'm trying to connect to a PostgreSQL database using Java and the postgresql-42.7.5.jar JDBC driver.
I have the following files in the project directory:
Main.java, Main.class, postgresql-42.7.5.jar
Main.java:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Main {
private static final String URL = "jdbc:postgresql://localhost:5432/testdb";
private static final String USER = "testuser";
private static final String PASSWORD = "password";
public static void main(String[] args) {
try {
Class.forName(".postgresql.Driver");
Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);
System.out.println("Connected to PostgreSQL successfully!");
connection.close();
} catch (ClassNotFoundException e) {
System.err.println("PostgreSQL Driver not found!");
e.printStackTrace();
} catch (SQLException e) {
System.err.println("Connection failed: " + e.getMessage());
e.printStackTrace();
}
}
}
I successfully compile the code using:
javac -cp .:postgresql-42.7.5.jar Main.java
However, when I try to run it, I get the following error:
java -cp .:postgresql-42.7.5.jar Main
Error: Could not find or load main class Main
Caused by: java.lang.ClassNotFoundException: Main
Share
Improve this question
edited Mar 21 at 23:10
Drax
asked Mar 21 at 22:04
DraxDrax
1691 silver badge9 bronze badges
4
|
1 Answer
Reset to default 1The path separator on windows is the ;
, not the :
.
Most developers are on a posix-like system, either because their OS is posix compatible (mac, linux), or they develop on windows but in a posixy environment (a bash shell, for example).
This popularity means tutorials and documentation is generally not written primarily with powershell or a windows terminal (cmd.exe
) in mind. This can go so far that they just assume the reader is on a posixy system.
Not much you can do about it, except keep an eye out. Java development generally doesn't care much about your underlying OS (not just 'java', the entire ecosystem, e.g. all IDEs run on all major OSes and look about the same on all of them). Point is, here, it 'caught' you, because that's one difference that matters.
The reason is that on windows specifically :
means something in paths (drive letter separator); on posix file systems it does not. Java started on posixy systems and used :
because it was "available", then on windows that was a problem so specifically on windows ;
is used.
It 'works' with your javac
command because you aren't using the postgres driver in your compilation at all (you do not refer to it anywhere. Yes, you pass the name of it to Class.forName
but that's just a string, the compiler just compiles 'make this string, write the bytecode that invokes Class.forName
, whatever that might be, and that's all you have to d') - in other words, you can write javac -cp whateverInvalidCrudYouPlease Main.java
and it'll work just fine because that command doesn't need a classpath for anything it's going to do.
At runtime however both .
and the psql driver has to be there or it won't work. Hence, -cp
actually matters, and thus, your incorrect cp param causes that error to occur.
The fix is to use ;
:
java -cp .;postgresql-42.7.5.jar Main
NB: The Class.forName
line does nothing; some tutorials include it but that means they are either written by newbies/clueless folks, or it's 20 years old, not a good start. Just remove the line. Or if you want an actual compilation failure if the classpath isn't set up right, make that .postgresql.Driver.class.getName();
to ensure it'll fail if your classpath isn't in order. I don't really recommend doing that; it's not idiomatic java.
java ... Main
" -- usually we usejavac
and the file name with extension (Main.java
) to compile;java
is used to execute (btw, which OS?) – user85421 Commented Mar 21 at 22:09java.exe
executable - and Windows require;
as path separator in the class path (since:
is used to specify the drive - e.g.D:\...
) -- but;
is also interpreted by bash, so it needs to be escaped:java -cp .\;some.jar Main
– user85421 Commented Mar 22 at 8:05