Creating an uberjar for a project that uses MySQL and SQLServer - java

I'm trying to build a project in clojure that takes data from a
Microsoft SQL Server database, and pushes it to a MySQL database.
The project runs fine using lein run, but when I package it into an
uberjar using leiningen, and run it using java -jar, it fails with:
Exception in thread "main" java.sql.SQLException:
No suitable driver found for jdbc:sqlserver....
This error only happens when I attempt to use both the MySQL database and
the SQL Server database. If I use any one of them on its own, the jar file
runs fine using java -jar.
My project.clj is as follows:
(defproject sqlserver-clojure "1.0.0-SNAPSHOT"
:description "A minimal example of the MySQL/SQLServer conflict"
:dependencies [[org.clojure/clojure "1.4.0"]
[com.microsoft/sqljdbc4 "3.0"]
[clojureql "1.0.4"]
[mysql/mysql-connector-java "5.1.6"]]
:main sqlserverclojure.core)

The problem is most likely that when making the uber-jar, you are not copying some files (eg .properties or XML config) that are required by the driver, or you are overwriting files that exist in both JDBC drivers.
A good example of overwriting is the META-INF/services/java.sql.Driver file which all JDBC 4 drivers have. This file contains a list of all classes in the jar implementing java.sql.Driver, so that the java.sqlDriverManager class can automatically load all Driver implementations using ServiceLoader.
If you create an uber-jar with multiple JDBC drivers, you either need to make sure this file contains the union of all these files, or your application needs to explicitly load the drivers you need with Class.forName("<name of the java.sql.Driver implementation>") for each required driver and not depend on the JDBC 4 driver autoloading.
Also verify that the process you use to create the uber-jar copies all resources and not just .class files!
Better yet (in my opinion), don't use an uber-jar, but keep the dependent .jar files external and reference them in the Class-Path entry of the META-INF/MANIFEST.MF file of your application, this saves you a lot of hassle to get your uber-jar working correctly (or verify that it is actually working correctly).

Adding this for my own reference since I've not touched Java before and struggle with Java interop.
Add
(. Class (forName "com.microsoft.sqlserver.jdbc.SQLServerDriver"))
In the namespace with your jdbc clojure function calls.

Related

Setting classpath for Oracle JDBC jar in centos

I am fairly new to Linux, I am trying to set my jar files for OJDBC in my classpath but so far have not found any good examples for a beginner such as me.
I will list the my paths for Jar file below. Can someone provide me with example or how to step by step set my class path with the commands. I would really appreciate it. I would like to set this path in my project which I am using it in.
Jar file:
/home/ssingh/Downloads/oracle.jar
Project:
/opt/savi/Workspace/SgRecc/bin/PerVal.class
Setting up the Class Path
To use the driver, the JAR archive named postgresql.jar if you built from source, otherwise it will likely be (named with the following convention: postgresql-[server version].*[build number].jdbc[JDBC version]*.jar, for example postgresql-8.0-310.jdbc3.jar) needs to be included in the class path, either by putting it in the CLASSPATH environment variable, or by using flags on the java command line.
For instance, assume we have an application that uses the JDBC driver to access a database, and that application is installed as /usr/local/lib/myapp.jar. The PostgreSQLâ„¢ JDBC driver installed as /usr/local/pgsql/share/java/postgresql.jar. To run the application, we would use:
export CLASSPATH=/usr/local/lib/myapp.jar:/usr/local/pgsql/share/java/postgresql.jar:.
java MyApp

MySQL JDBC: no suitable driver found

I have developed a program that pulls the data from a remote sql server and pushes it to local mysql server .I have a jar file exported for this .
Now I am trying to run this jar file on different machine to do the same task .All the IP's and ports have been changed accordingly .There is no IDE on this machine .
When i am running this jar file , i get an error saying "No suitable driver found for jdbc:sqlserver:/ 172 .* "
I have installed the jdbc driver in program files .
So what do i have to do to run this jar file .
You need to add the library to the runtime classpath. A straightforward way would be to export it as a dependency in the jar (although there might be licencing issues with that).
How are you creating the jar?
Add the jdbc driver in your classpath, not in your "program files".... Check the documentation of the JVM http://docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html
All you need to run a Java program is a Java executable and class files or zipped/jared class files and other files needed by class files. So 1st step is locate your java executable, maybe c:\java.exe or /home/yourhome/java, and 2nd step is gather all your classes or zip/jar archive and put them in a String split by ':' on Unix or Unix-like or ';' on windows. 3rd step is to identify your main class, which is the only entry of your program.
In the end, use YOUR_JAVA_EXECYTABLE -classpath YOUR_CLASS_PATH YOUR_MAIN_CLASS. works fine for most scenarios.
Forget anything about "installed" a program or driver, which is just put some some in system's classpath or path or anything like this.

How a java application should discover extensions in runtime?

I want to look for extension jars in a predefined directory and examine their manifest. Those which match should be loaded, those which do not - should be unloaded.
Now, I can do it a primitive way - mandate that each extension pass the name of its bootstrapper on the command line and then for each jar found in the directory try and load any of the given bootstrapper types. Something like this:
java -jar myapp.jar --pluginDir=c:/a/b/c --exts="classA;classB;classC"
Then myapp would iterate over all the files inside the pluginDir and try to load each of classA, classB or classC. Once a classX is successfully loaded, it is removed from the list. The search stops when either all the extensions are found and loaded or there are no more jars in the plugin dir.
A slightly more javaish approach seems to be writing something in the manifest of extension jars and check the manifest of each found jar.
Can anyone show a working code snippet of this approach or of anything better, if there is?
EDIT
A quote from the postgre JDBC driver README file (see https://stackoverflow.com/a/12480373/80002):
INSTALLING THE DRIVER
To install the driver, the postgresql.jar file has to be in the classpath.
ie: under LINUX/SOLARIS (the example here is my linux box):
export CLASSPATH=.:/usr/local/pgsql/share/java/postgresql.jar
There is ServideLoader class for this purpose. JDBC drivers are built on this principle. Hope, it helped.

How to run database program outside the Netbeans IDE?

I am really new to database and this is my first program in database using java Netbeans 7.1 --- It is summer on our country now and I am a student with the course I.T. Our next subject on programming is about database and since there's no class I spend my time learning database for preparation for the next school semester and I refer to this site as my guide for the first database program I currently making now.
http://www.homeandlearn.co.uk/java/databases_and_java_forms.html
I did everything in the tutorial and I actually done doing the program.
The final thing I did is I clean and build the program since I want the program to run with out opening the netbeans again I downloaded the JRE and make my database_form.jar as a jar executable. "database_form" the name of my Netbeans Project. I do that by making javaw in JRE.7 as my dafault when opening any jar files.
Anyway, this is how i run the program.
Running Program in Netbeans IDE
Using Netbeans, before my program works I first need to "Start Server" on JavaDB. because if I didn't do that an Exception occurred "Err. connecting to server localhost 1527 and so on"
Running Program using jar executable alone.
The Problem is there's an Exception and Err in connecting still occurred.
What I want to achieve?
I want the program to run without opening the Netbeans IDE and going to Java DB to click the "Start Server", I dont want to do that anymore. Or my second option is to start the server using command prompt so that I just have to make a bat file so that whenever I open my program database_form.jar I just place the bat file on my desktop and run it.
Second Problem!
Actually, I already try my second option by using command prompt to start the server but I forgot how I did it, I just found it on some website the only thing I remember is the Exception says "Failed to lunch the server because the database Employees is missing. Employees is the name of my created database.
The O.S. I am using is Windows 7.
Thank you for all the reply and sorry for the long text I just want to be specific, :D
Right, from your description there seems to be a couple of things you are confusing.
First, databases are typically run as servers with multiple clients connecting to them thus allowing they contain to be shared. When you start Java DB you are starting the Java DB database server.
That said, lightweight databases, such as Java DB can be run in an embedded mode as explained here. Remember that the directory you point to with the derby.system.home property will need to contain the database files, if not you'll need to create that programatically too.
Second, there's various ways to run a Java application outside of an IDE, but jars themselves are not executable in the same way an exe file is in Windows.
The simplest way is to call the java executable passing the necessary classpath and the name of the class containing the main method. For example if I had a class called com.example.Application that had been compiled to a directory C:\dev\example\classes the following command line would run the application:
java -cp C:\dev\example\classes com.example.Application
If there were dependencies on external libraries, as there will be in your case on the Derby JDBC driver, then those would also need including in the classpath resulting in something like:
java -cp C:\dev\example\classes;C:\dev\lib\derby.jar com.example.Application
There's a full set of document on the Java launcher here.
Now, back to the jar. Like I said, jars are not executable but there is something that's know as an 'executable jar'. This is the same as any jar except there are some special additions to the manifest to specify the application entry point or main-class and the class-path as described here.
Once the main-class and class-path are specified in the jar's manifest, the following command line would run the application:
java -jar C:\dev\example.jar
You can even associate the jar extension with the java exe and double clicking the jar will cause the application to launch (though on a dev machine it's probably more useful that the jar extension be associated with WinZip or simlar in order to open that jar).
The default database in Netbeans is Derby/JavaDB. So you need to:
add the jar of javadb/derby in our classpath (it maybe already present, as it is bundled with java when you install it in Ubuntu)
setup a path with the jdbc URI to save the database data
I personally recommend the usage of hsqldb or H2 for this: they support in-memory database, very useful for stand alone project with no persistence data or for tests.
If you use window, add ODBC Data Sources from Administrative Tools to your Java Derby driver and run jar.

What files needed for JDBC connection to MySQL?

I get the following error when attempting to connect to the MySQL database on my employer's local server:
Unable to load database driver
Details : java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
BUILD SUCCESSFUL (total time: 0 seconds)
I think it's pretty clear that this is because I don't have my files set up properly. Only problem is, I don't know what I need, and where it needs to go. Is the Driver a .class file? Where can I download it? Where in my filesystem (ubuntu, fwiw) do I put the file so that "Class.forName("com.mysql.jdbc.Driver").newInstance();" works?
Thanks for all your help, m8s.
Yes, it is a .class file that uses a others .class files. You call all these collections of files, a library and in this particular case, the library is also named: "jdbc driver".
These libraries are usually .jar files, so in your case you may try:
http://www.mysql.com/products/connector/j/
To download the MySQL JDBC driver.
You should put it in your classpath
You can download the connector here (the .jar you need is inside the .zip/.tar.gz):
http://dev.mysql.com/downloads/connector/j/
The .jar needs to be in a classpath available to your application.

Categories