2

I have an application which deals with jdbc. It supposes to be used in any PC where there is JRE, but it does not suppose that use will use -cp command line or change his/her classpath variables. So the user has my application, JRE and a jdbc driver somewhere in file system. Now he or she enters a database connection information including path to jdbc driver jar and then make sql request. The problem is that I don't now how to make jdbc driver classes to be accessible in this application. The same way as the user explicitly add a driver to classpath.

itun
  • 3,439
  • 12
  • 51
  • 75
  • If your app. has a GUI, supply it along with the driver using [Java Web Start](http://stackoverflow.com/tags/java-web-start/info). This makes it easy for the user. – Andrew Thompson May 16 '12 at 21:26

3 Answers3

2

I just altered part of the miks answer for your other posting.

Executing the following code got me a success.

import java.io.File;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLClassLoader;

public class URLClassLoaderSample {
  public static void main( String [] args ) throws Exception {
    File f = new File( "/home/ravinder/Desktop/mysql-connector-java-5.1.18-bin.jar" );
    URLClassLoader urlCl = new URLClassLoader( new URL[] { f.toURL() }, System.class.getClassLoader() );

    Class mySqlDriver = urlCl.loadClass( "com.mysql.jdbc.Driver" );
    System.out.println( mySqlDriver.newInstance() );
    System.out.println( "Is this interface? = " + mySqlDriver.isInterface() );

    Class interfaces[] = mySqlDriver.getInterfaces();
    int i = 1;
    for( Class _interface : interfaces ) {
        System.out.println( "Implemented Interface Name " + ( i++ ) + " = " + _interface.getName() );
    } // for(...)

    Constructor constructors[] = mySqlDriver.getConstructors();
    for( Constructor constructor : constructors ) {
        System.out.println( "Constructor Name = " + constructor.getName() );
        System.out.println( "Is Constructor Accessible? = " + constructor.isAccessible() );
    } // for(...)
  } // psvm(...)
} // class URLClassLoaderSample

Output seen is as follows:

com.mysql.jdbc.Driver@60aeb0
Is this interface? = false
Implemented Interface Name 1 = java.sql.Driver
Constructor Name = com.mysql.jdbc.Driver
Is Constructor Accessible? = false

And I don't understand what I should with log4jClass variable in my case *(com.mysql.jdbc.Driver)
Let me hope now you got it.

Community
  • 1
  • 1
Ravinder Reddy
  • 23,692
  • 6
  • 52
  • 82
  • I still cannot do that because I don't create or do something with jdbc Driver. It use JDBC framework, not my code directly. From my results I can say that it does not work. And I believe that your code works. – itun May 17 '12 at 02:44
  • Can you show me an example where your code use com.mysql.jdbc.Driver (make import com.mysql.jdbc.Driver) compiled with this dependency, but you launch your application without this jar in your classpath and you load this jar at runtime? – itun May 17 '12 at 02:47
  • @itun - We need not explicitly import a database driver. Unless you want to know some driver specific info like `DriverPropertyInfo`, `version`, etc., you don't require a reference variable to a *specific* jdbc driver. If you have one and if that class is not in the searchable classpath, it obviously fails. Meaning you should not have any such direct references like "`pkgd.Driver driver = (pkgd.Driver) Class.forName(...`". Please read notes on `java.sql.DriverManager` which suggests ways to avoid *`Class.forName()`* i.e. you may not require to load a connector jar from a custom path. – Ravinder Reddy May 17 '12 at 13:15
1

The best solution in this instance would be to distribute the required driver with your application and include either an executable wrapper or a shell script that sets the required variables accordingly. That allows the user to use it out of the box without having to mess with any complicated configuration and also doesn't require them to download any additional files.

Chris Thompson
  • 35,167
  • 12
  • 80
  • 109
  • I cannot do that. Any other solutions? – itun May 16 '12 at 22:53
  • @itun, well you need to somehow supply a driver, or tell them to download it. You can search the filesystem for it, but that's not a perfect solution – Chris Thompson May 16 '12 at 23:10
  • It is no a problem if user will download drivers and then enter the path for my application. It is a problem for me to load driver dynamically in my application from somewhere in file system. – itun May 16 '12 at 23:41
0

Well, jdbc uses Class.forName("org.postgresql.Driver"); to load the driver. So once, you have the jar file, and have added it to the class-path, this part is easy. Just keep a hash of driver fqn classnames to jar file names. Or you can scan the jar for the Driver class.

Here's a convienent answer to how to add the jar file to the classpath once you find it.

Community
  • 1
  • 1
Jim Barrows
  • 3,634
  • 1
  • 25
  • 36
  • That is what I exactly did: http://stackoverflow.com/questions/10624907/loading-jars-at-runtime. But for some reason it does not work. – itun May 16 '12 at 21:40
  • java.lang.ClassNotFoundException when I use this Class.forName(" com.mysql.jdbc.Driver") – itun May 16 '12 at 21:55
  • There's no error when loading the jar file then? Class.forName is not using the same classloader you used to load the jar file. Make sure you use the one you loaded the jar file with. – Jim Barrows May 16 '12 at 21:59
  • I used SystemClass loader. What is the loader which Class.forName uses? – itun May 16 '12 at 22:01
  • It uses the caller's class loader, which is the SystemClass loader probably. So you need to use classLoaderICreated.loadClass() – Jim Barrows May 16 '12 at 22:05
  • URLClassLoader urlCl = new URLClassLoader(new URL[] { f.toURL()},System.class.getClassLoader()); Class log4jClass = urlCl.loadClass("org.apache.log4j.Logger"); – Jim Barrows May 16 '12 at 22:15
  • And see your example, it does what you want. – Jim Barrows May 16 '12 at 22:16
  • I tried to do this but it does not work. Mb this example is working because it creates a class instance from the loaded class. But I need to load drivers which use jdbc, not my code. – itun May 16 '12 at 22:19
  • And I don't understand what I should with log4jClass variable in my case *(com.mysql.jdbc.Driver). – itun May 16 '12 at 22:20
  • @itun - replace `log4JClass` with `mySqlDriver` and Change `File f` to load your `mysql....jar` from its path. It should work. – Ravinder Reddy May 17 '12 at 00:43
  • Why I need variable mySqlDriver? – itun May 17 '12 at 00:45
  • `Class mySqlDriver = urlCl.loadClass("com.mysql.jdbc.Driver"); mySqlDriver.newInstance();` – Ravinder Reddy May 17 '12 at 01:36
  • Still does not work. SQL Error: 0, No suitable driver found for jdbc:mysql://localhost:3306/information_schema – itun May 17 '12 at 01:57