Executable Jar with Dependency on dll - java

I am attempting to deploy a swing application that uses a dll to facilitate a database connection (using sqljdbc4 jar that depends on sqljdbc_auth.dll). My deployment strategy is creating an executable jar file. The problem is that I cannot get the functions that rely on the sqljdbc_auth.dll to work in the executable jar I create.
I can get the project working fine in eclipse by using any of the following methods:
Reference the folder containing the dll in the build path configuration by specifying a Native library location on the Source folder
Put the dll in C:\Windows\System32 directory
Add the following VM argument referencing the relative path of the dll folder in my project "-Djava.library.path=path/to/dllfolder"
The 4th method I have tried is to load the dll directly in code via the following line. System.load("C:/Users/Me/Desktop/sqljdbc_auth.dll");
I have been unsuccessful with this approach and get the following error.
Mar 20, 2015 4:18:44 PM com.microsoft.sqlserver.jdbc.AuthenticationJNI <clinit>
WARNING: Failed to load the sqljdbc_auth.dll cause : no sqljdbc_auth in java.library.path
However, that error doesn't come directly from the line of code that loads the library, it seems to come afterwards when the sqljdbc library is trying to load the dll for use in making the connection.
Either way, I cannot get anything of the above methods working when I deploy the app as an executable jar file via the export functionality of eclipse. The only thing I can get is the previously mentioned error message.
The following sample application produces the same result.
public class TestApp {
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
JFrame mainFrame = new JFrame();
mainFrame.setSize(300,300);
mainFrame.setLocationRelativeTo(null);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setVisible(true);
try{
//System.load("C:/Users/Me/Desktop/sqljdbc_auth.dll");
String serverName = "local";
String databaseName = "test_database";
String connString = "jdbc:sqlserver://" + serverName + "; databaseName=" + databaseName + ";integratedSecurity=true";
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection conn = DriverManager.getConnection(connString);
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("select distinct name from test_table");
rs.next();
JOptionPane.showMessageDialog(null, "From db: " + rs.getString(1), "Test", JOptionPane.INFORMATION_MESSAGE);
} catch (SQLException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, e.getMessage(), "Test", JOptionPane.INFORMATION_MESSAGE);
} catch (ClassNotFoundException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, e.getMessage(), "Test", JOptionPane.INFORMATION_MESSAGE);
} catch (Exception e){
e.printStackTrace();
JOptionPane.showMessageDialog(null, e.getMessage(), "Test", JOptionPane.INFORMATION_MESSAGE);
}
}
});
}
}
I've read tons of posts on using dlls with executable jars and they all seem to reference using this System.load method. Ironically, that is the one thing I can't get working. I know I have the right dll; however, because I can get other methods to work in the IDE environment. I don't care if the dll is packaged with the executable jar or not, I just want it to work!

I would presume this has something to do with putting the dll's in your library
(In Eclipse, Properties->Java Build Path->Libraries).
When you export the jar, you also will have the option of exporting the library files into a folder.
If you decompile the Jar after that, you'll notice that there's a manifest file, and in it, paths to where your library files are (based on the export, which created a library folder for you, generally jarname_lib).
When you export, you have the option to save as ANT file, which you can then edit to change the export location of the library files to a folder name of your choice. You can then add this edited ANT file to your build so that it happens whenever you build the project:
(In Eclipse, Properties->Builders->New)

Related

ClassNotFound & No Suitable Driver, where did I go wrong?

I have created a program that works perfectly in the IDE on NetBeans, but anytime I build the .jar file, the database connection stops working. I've already added the CLASSPATH to the MySQL Connector, as well as defined Class.forName("com.mysql.jdbc.Driver"); Still nothing..
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/gearheads";
Connection conn = DriverManager.getConnection(url,"root","HellOnEarth202021");
Statement stmt = conn.createStatement();
ResultSet rs;
String pid = txt_staffID.getText();
rs = stmt.executeQuery("SELECT name,timeraccess FROM staff WHERE staffid = '"+pid+"'");
while ( rs.next() ) {
String timeraccess = rs.getString("timeraccess");
String staffName = rs.getString("name");
getLogin = staffName;
System.out.println(staffName);
System.out.println("Users Admin Level: " + timeraccess);
if ( timeraccess.equals("1")) {
this.dispose();
new menu().setVisible(true);
System.out.println("Access Granted");
}else
System.out.println("Access Restricted.");
}
conn.close();
} catch (Exception e) {
System.err.println("Got an exception! ");
txt_staffID.setText(e.toString());
System.err.println(e.getMessage());
}
This, as it stands, outputs:
java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
Where taking out the Class.forName outputs:
java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/gearheads
Please help me. This link is a screenshot of my libraries.
My Libraries:
If its runnning correctly inside Netbeans, then the MySQL driver is correct.
You have to search for Manifest file (MANIFEST.MF) and probably will have to unjar the contents of the driver inside your own JAR file.
I'll leave this answer by now, but will try to gather the details to bring it back here.
I also use NetBeans and when I generate the JAR file, its already copying the dependant libraries and generating the correct MANIFEST.MF.
I ended up with the following structure
MyProject\dist\lib\JdbcDriver.jar
and
MyProject\dist\MyProject.jar
Inside MyProject.jar, I have the following MANIFEST.MF:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.9.7
Created-By: 1.8.0_201-b09 (Oracle Corporation)
Class-Path: lib/JdbcDriver.jar
X-COMMENT: Main-Class will be added automatically by build
Main-Class: myproject.MyMainClass
Please, verify with you are copying the lib folder altogether with your JAR file.
Just to leave here the final solution (#Nick Media final comment): you have to check "Copy Dependent Libraries" in Build>Packaging Project Properties.
It is not clear exactly what you are doing wrong, but you are clearly doing something incorrectly:
It is often better to use DriverManager.getConnection rather than Class.forName and a specific driver class name. This is the approach recommended by the Oracle Java Tutorial; see https://docs.oracle.com/javase/tutorial/jdbc/basics/connecting.html
If you are loading the driver via its classname, use com.mysql.jdbc.Driver with MySQL Connector/J 5.x and com.mysql.cj.jdbc.Driver with MySQL Connector/J 8.x.
If this is a webapp, make sure that the relevant driver JAR file is actually in your WAR file, and/or that it is being deployed correctly.
If this is a command line app, make sure that you include the driver JAR on the runtime classpath. (Especially if you are trying to run it outside of your IDE.) Alternatively, consider creating a shaded JAR that included all of the apps dependencies. (It is a bit hard to advise since you haven't told us if you are using a build tool like Ant, Maven, Gradle, etc.)
The driver doesn't actually need to be a compile time dependency, though there is little harm in doing that. (The harm is that you might accidentally add imports to the MySQL implementation classes to your app ... and run into problems.)

IntelliJ, JInput and the java.library.path

I'm working on a java project that uses both Jogl and JInput, and I working in IntelliJ. I'm having some issues with the application not being able to find various DLLs. I know the recommended way is to extract the DLLs to a folder and then point the java.library.path at that folder. Is there a way to include those libraries in project configuration somehow? I'm pulling those files from jCenter, and I'd rather just point the jar files and let JNA do its work.
I use this method below to set the path dynamically just before the DLL is needed by some object. It is called as follows:
setDllLibraryPath("C:/yourPathToDLLs")
Method to set library path
public static void setDllLibraryPath(String resourceStr) {
try {
System.setProperty("java.library.path", resourceStr);
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);//next time path is accessed, the new path will be imported
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
}

Exported .jar when run on other computers give "No suitable driver found for jdbc"

I made a small and simple program using IntelliJ IDEA to update content on some new columns in a MSSQL database. I downloaded the external library sqljdbc4.jar and added this to Project Settings > Libraries, as well as making sure that the library .jar is added to the output layout. I have confirmed that the sqljdbc4.jar is included to the exported .jar-file by unpacking the file on the Mac I use.
The program runs just fine on my Mac, but when I copy the .jar over to a colleague's computer, or try to run in in Windows on Parallels, we only get a ClassNotFound Exception with a following note that "No suitable driver found for jdbc:sqlserver[server details]"
The code for the job is as following:
//[....]
private final static String SQL_DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
public SQLConnector(){
}
public boolean updateDatabase(String[] results, boolean inhouse){
Connection conn;
try{
Class.forName(SQL_DRIVER);
} catch (ClassNotFoundException e){
JOptionPane.showMessageDialog(null, "ERROR: " + e.getMessage(), "Exception type: ClassNotFoundException", JOptionPane.ERROR_MESSAGE);
return false;
}
//[...]
The ClassNotFound-exception is what is triggered. Any ideas? If some additional information is required, please do not hesitate to request it.
EDIT: I have the sqljdbc4.jar saved in /Library/Java/Extensions, and if I remove it from there then the program also fails with the same error on my Mac. Even if I have the .jar-file stored in a /bin/-folder in my project and make sure that this file is the file added as a library. With jdbc-jar removed from Extensions, the program will still run fine when executed from IntelliJ even so.
I figured it out. The problem was in the settings for artifacts. When specifying details to create JAR from modules, I had previously selected "extract to the target JAR", but the correct option seemed to be "copy to the output directory and link via manifest". Doing this gave an error that a manifest already existed, so I had to go manually in and delete the META-INF folder in both "src" and in "out > production > [project name]". Then allow IntelliJ to build the artifact anew. This resulted in the sqljdbc4.jar file being added alongside my own JAR, instead of copying the sqljdbc4.jar file into my own JAR.
I do not know what the major difference between these two options are however....

Unable to load .so file

I have an application which uses one native library "libSample.so" which is depend upon another .so file.I am trying to load that library using following code
File File1 = new File("libSample.so");
static
{
try {
System.load(File1.getAbsolutePath());
} catch (UnsatisfiedLinkError e) {
System.out.println("Link Error");
}
}
Before loading library I have tried setting up LD_LIBRARY_PATH where the library is located using command line.
export LD_LIBRARY_PATH=/home/usb:${LD_LIBRARY_PATH}
But still the library not get load.
What should I do now?
Please help.
static {
System.loadLibrary("libSample.so");
}
I assumed that you have your jars in /libs directory and .so file in /libs/armeabi directory so the system finds them. You do not have to add .so files in your eclipse build path.

I'm having trouble embedding HSQLDB into a simple Java (Eclipse) project

After reading up on some options (sqlite, derby etc...), I've decided to throw down with HSQLDB. I've downloaded it, read up on it and followed a 'hello world' type intro to it, and am now stuck.
I believe that you have to put the hsqldb.jar file in the src folder, so I did exactly that. Then I made a reference to the package with Eclipse by going into Run -> Run Configurations, then going into the Classpath tab, then clicking User Entries, then add External Jar, and selecting hsqldb.jar.
I get this :
java.lang.ClassNotFoundException: org.hsqldb.jdbcDriver
Here's my code :
package mysqlite;
import java.sql.*;
public class myclass {
public static void main(String[] args) {
try {
Class.forName("org.hsqldb.jdbcDriver");
String url = "jdbc:hsqldb:db";
String user = "aUser";
String password = "";
Connection conn = DriverManager.getConnection(url, user, password);
}
catch(Exception e) {
System.out.println(e.toString());
}
}
}
I understand it's unable to find a class, but I thought that was what the hsqldb.jar provided.
No, you do not have to put it into src folder. src is for source files (*.java). You have to add this jar into your classpath: click on project properties, choose "Java build path", select tab "Libraries" and add the jar here.
The jar can be stored anywhere in your file system. Sometimes people create lib directory under project home and put all 3rd party dependencies there.
Try putting the .jar here:
<YOUR_JAVA_HOME>\jre\lib\ext

Categories

Resources