Pallavi
Pallavi

Reputation: 101

Loading and connecting to mysql jdbc driver runtime

I am currently working in a requirement where I need to load the mysql driver runtime and connect to the database using java.

I am using URLClassLoader to load the jar file

File f = new File("D:/Pallavi/workspace/WarInstallation/mysql-connector-java-5.0.4-bin.jar"); //Jar path

URLClassLoader urlCl = new URLClassLoader(new URL[] { f.toURL()},System.class.getClassLoader()); 
Class sqldriver = urlCl.loadClass("com.mysql.jdbc.Driver"); // Runtime loading

Driver ds = (Driver) sqldriver.newInstance(); //Compilation failing as "sqldriver" class of type Driver is not found

//I am using now java.sql.Driver to remove the compilation error

sqldriver = Class.forName("com.mysql.jdbc.Driver", true, sqldriver.getClassLoader()).newInstance(); //Runtime fail.. "Driver" Class not Found Exception.

Although the class loads fine I can't establish a Database connection (No suitable driver found for ...) no matter which driver I try.

Please suggest a way to load the jdbc "com.mysql.jdbc.Driver" class runtime. Let me know, if you need any further information, as this is urgent.

Thanks in advance.

Upvotes: 2

Views: 3569

Answers (2)

Ravinder Reddy
Ravinder Reddy

Reputation: 23992

I have three questions before I answer to your issues:

  1. Statement 1:

    ya, I have set the classpath of mysql jar in the environment variables, do we need to set it through system properties?

    Q1: Why are to relying on custom class loader, when a class is readily available to the System class loader from the class path?
    You don't need explicit class path to mysql***.jar to use custom class loader.

  2. Statement 2:

    Class sqldriver = urlCl.loadClass("com.mysql.jdbc.Driver"); // Runtime loading
    //Compilation failing as "sqldriver" class of type Driver is not found
    Driver ds = (Driver) sqldriver.newInstance();

    Q2: Claiming Compilation failing ... is very conflicting. Is your compiler looking for such class to generate your class!?
    I am sure it is not. May be the error is at run time with a java.lang.ClassNotFoundException: com.mysql.jdbc.Driver. And I also suspect the comment should go with your Statement 3 below.
    If it is a CNFE, your file path to mysql***.jar is wrong. Fix it first.

  3. Statement 3:

    //I am using now java.sql.Driver to remove the compilation error
    //Runtime fail.. "Driver" Class not Found Exception. sqldriver = Class.forName("com.mysql.jdbc.Driver", true, sqldriver.getClassLoader()).newInstance();

    Q3: Claiming ... "Driver" Class not Found Exception is suspectful. Because, this statement won't get compiled. Then how can it be a Runtime fail. ..!?
    I also suspect the comment should go with your Statement 2 above.
    And here, you need to call newInstance() and then cast to java.sql.Driver before assigning to sqlDriver variable. Because Class.forName( ... only returns a Class object associated with the class or interface with the given string name.
    If issue at Statement 2 above is fixed, you can apply this fix to test further.

Let me hope you got these statements clarified.


I have a working sample code below, with a tested output shown for you.

import java.io.File; // and others as required

public class MySQLDriveClassLoader {
  public static void main( String [] args ) throws Exception {
    //File f = new File( "/home/ravinder/soft-dump/mysql-connector-java-5.1.18-bin.jar" );
    File f = new File( "E:\\Soft_Dump\\mysql-connector-java-5.0.4\\mysql-connector-java-5.0.4-bin.jar" );
    URLClassLoader urlCl = new URLClassLoader( new URL[] { f.toURI().toURL() }, System.class.getClassLoader() );

    Class mySqlDriver = urlCl.loadClass( "com.mysql.jdbc.Driver" );

    //*** Start: DEBUG *************************
    //mySqlDriver.con // On pressing CTRL+SPACEBAR, after .con, IDE shows "No default proposals"
    // meaning it still is not an instance of Driver, and hence can't call a method from Driver class.

    //Incompatible conditional operand types Class and Driver
    //System.out.println( mySqlDriver instanceof java.sql.Driver ) );

    System.out.println( "mySqlDriver: " + mySqlDriver );
    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(...)
    //*** End  : DEBUG *************************

    Driver sqlDriverInstance = ( Driver ) mySqlDriver.newInstance();
    System.out.println( "sqlDriverInstance: " + sqlDriverInstance );

    Connection con = null;
    try {
      /******************************************************************
      // You may fail to register the above driver
      // hence don't depend on DriverManager to get Connected
      //DriverManager.registerDriver( sqlDriverInstance );
      //Driver driver = DriverManager.getDriver( "com.mysql.jdbc.Driver" ); // ( "jdbc:mysql" );
      Enumeration<Driver> enumDrivers = DriverManager.getDrivers();
      while ( enumDrivers.hasMoreElements() ) {
        Driver driver = enumDrivers.nextElement();
        System.out.println( "driver: " + driver );
      } // while drivers
      //******************************************************************/

      String dbUrl = "jdbc:mysql://:3306/test";
      Properties userDbCredentials = new Properties();
      userDbCredentials.put( "user", "root" );
      userDbCredentials.put( "password", "password" );

      // No suitable driver found for ...
      //con = DriverManager.getConnection( dbUrl, "root", "password" );

      // safely use driver to connect
      con = sqlDriverInstance.connect( dbUrl, userDbCredentials );
      System.out.println( "con: " + con );

      Statement stmt = con.createStatement();
      String sql = "select now()";
      ResultSet rs = stmt.executeQuery( sql );
      if ( rs.next() ) {
        System.out.println( rs.getString( 1 ) );
      } // if rs
    } catch( Exception e ) {
      e.printStackTrace(); // only for quick debug
    } finally {
      try { if ( con != null ) con.close(); } catch ( Exception ignoreThis ) {}
    }
  } // psvm(...)
} // class MySQLDriveClassLoader

A successful compilation and run, resulted following output:

mySqlDriver: class com.mysql.jdbc.Driver
Is this interface? = false
Implemented Interface Name 1 = java.sql.Driver
Constructor Name = com.mysql.jdbc.Driver
Is Constructor Accessible? = false
sqlDriverInstance: com.mysql.jdbc.Driver@1270b73
con: com.mysql.jdbc.Connection@32fb4f
2012-05-29 03:52:12.0

Upvotes: 1

mprabhat
mprabhat

Reputation: 20323

DriverManager ignores classes loaded at runtime, it will work only for classes loaded by the System class loader.

You can create a Dummy driver class which encapsulates your actual database driver. Source code can be found here.

Off topic:

File.toURL is deprecated, instead get URL from File using toURL on URI

URLClassLoader urlCl = new URLClassLoader(new URL[] { f.toURI().toURL()},System.class.getClassLoader()); 

Upvotes: 0

Related Questions