I'm just starting to build Java apps (I do have .NET experience) and I was trying to build a small test app whose whole code is this :
package com.company;
import com.microsoft.sqlserver.jdbc.SQLServerDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) throws SQLException {
System.out.println("Buna lume!");
SQLServerDataSource ds = new SQLServerDataSource();
ds.setIntegratedSecurity(true);
ds.setServerName("localhost");
ds.setPortNumber(1433);
ds.setDatabaseName("Test");
Connection con = ds.getConnection();
String SQL = "SELECT * FROM Test WHERE ID = ?";
PreparedStatement stmt = con.prepareStatement(SQL);
stmt.setInt(1, 2);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
System.out.println(rs.getInt(1) + ", " + rs.getString(2));
}
rs.close();
stmt.close();
con.close();
}
}
If I run the app in the IDE (IntelliJ IDEA 12.1.6 Community Edition), having the SQL Server available, the app runs fine doing exactly what it should.
The SQL Server Driver is downloaded from Microsoft and added as an External Library. I have created an artifact as JAR file :
Now, if I include the sqljdbc4.jar in the cliTest.jar (my JAR) the resulted JAR is fat (550kB and includes the classes in that JAR too). Or I can exclude it. Either way, running
java -jar cliTest.jar
Results in
Buna lume!
Exception in thread "main" java.lang.NoClassDefFoundError: com/microsoft/sqlserv
er/jdbc/SQLServerDataSource
at com.company.Main.main(Main.java:15)
Caused by: java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLSer
verDataSource
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more
I bet I'm missing something quite basic but I just can't figure out what exactly is causing this.
LE1 : I tried adding sqljdbc4.jar (although it didn't seem necessary) and sqljdbc_auth.dll in the directory containing the JAR but still no change.
Later edit 2 : Based on Nikolay's answer I've done the following :
.. and resulted this :
Build -> Build artifacts -> cliTest.jar -> Rebuild
CMD Prompt at the folder containing :
[cliTest.jar 566 KB was generated]
java -jar cliTest.jar
Now I get :
Exception in thread "main" java.lang.SecurityException: Invalid signature file d
igest for Manifest main attributes
at sun.security.util.SignatureFileVerifier.processImpl(Unknown Source)
at sun.security.util.SignatureFileVerifier.process(Unknown Source)
at java.util.jar.JarVerifier.processEntry(Unknown Source)
at java.util.jar.JarVerifier.update(Unknown Source)
at java.util.jar.JarFile.initializeVerifier(Unknown Source)
at java.util.jar.JarFile.getInputStream(Unknown Source)
at sun.misc.URLClassPath$JarLoader$2.getInputStream(Unknown Source)
at sun.misc.Resource.cachedInputStream(Unknown Source)
at sun.misc.Resource.getByteBuffer(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$100(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
Use java -cp
instead of java -jar
and put all of you dependencies jars to classpath.
Another way is pack all of dependencies to single jar, that allowing you to run application using java -jar
.
EDIT:
In Java *.jar file contains a bulk of classes. When you build your own app, typically, result jar file contains only your classes, but still have to load classes from external libraries you use (so-called dependencies).
It can be done two different ways:
You create a folder for your application, for example, called lib
and place your application jar and all dependencies into. Then you run application using java -cp lib:/\* com.company.Main
or (thanks @NilsH, I miss this variant) you make MANIFEST.MF
file and specify Main-Class
and Classpath
attributes inside as described here
You use special tool (like maven-dependency-plugin if you use maven for build) to pack all classes, either your own, either external to single jar. You got one huge file and can run it using java -jar cliTest.jar
.
Generally, first approach is preferred and using a MANIFEST.MF
file is a good form.