itun
itun

Reputation: 3521

Loading jars at runtime

I am trying to add jar file to classpath at runtime. I use this code

 public static void addURL(URL u) throws IOException {

            URLClassLoader sysloader = (URLClassLoader) ClassLoader
                    .getSystemClassLoader();
            Class<URLClassLoader> sysclass = URLClassLoader.class;

            try {
                Method method = sysclass.getDeclaredMethod("addURL", parameters);
                method.setAccessible(true);
                method.invoke(sysloader, new Object[] { u });
                System.out.println(u);
            } catch (Throwable t) {
                t.printStackTrace();
                throw new IOException("Error");
            }

        }

System out prints this url:

file:/B:/Java/Tools/mysql-connector-java-5.1.18/mysql-connector-java-5.1.18/mysql-connector-java-5.1.18-bin.jar

I was check this path carefully, this jar exist. Even this test show that com.mysql.jdbc. Driver class exists.

javap -classpath "B:\Java\Tools\mysql-connector-java-5.1.18\
mysql-connector-java-5.1.18\mysql-connector-java-5.1.18-bin.jar" com.mysql.jdbc.
Driver
Compiled from "Driver.java"
public class com.mysql.jdbc.Driver extends com.mysql.jdbc.NonRegisteringDriver i
mplements java.sql.Driver{
    public com.mysql.jdbc.Driver()       throws java.sql.SQLException;
    static {};
}

But I still get java.lang.ClassNotFoundException when I use this Class.forName(driver). What is wrong with this code?

Upvotes: 5

Views: 19264

Answers (2)

miks
miks

Reputation: 544

Ok try the alternative approach with DataSource and not directly the Driver Below is the code (working with oracle driver, i don't have my sql db, but the properties are the same) Generally using the DataSource interface is the preferred approach since JDBC 2.0 The DataSource jar was not in the classpath neither for the test below

public static void urlCLSample2() throws Exception
{

    File f = new File("C:\\_programs\\jdbc_drivers\\oracle\\v11.2\\ojdbc6.jar");

    URLClassLoader urlCl = new URLClassLoader(new URL[] { f.toURL() }, System.class.getClassLoader());
    // replace the data source class with MySQL data source class.
    Class dsClass = urlCl.loadClass("oracle.jdbc.pool.OracleDataSource");
    DataSource ds = (DataSource) dsClass.newInstance();

    invokeProperty(dsClass, ds, "setServerName", String.class, "<put your server here>");
    invokeProperty(dsClass, ds, "setDatabaseName", String.class, "<put your db instance here>");
    invokeProperty(dsClass, ds, "setPortNumber", int.class, <put your port here>);
    invokeProperty(dsClass, ds, "setDriverType",String.class, "thin");
    ds.getConnection("<put your username here>", "<put your username password here>");

    System.out.println("Got Connection");
  }

  // Helper method to invoke properties
  private static void invokeProperty(Class dsClass, DataSource ds, String propertyName, Class paramClass,
      Object paramValue) throws Exception
  {
    try
    {
      Method method = dsClass.getDeclaredMethod(propertyName, paramClass);
      method.setAccessible(true);
      method.invoke(ds, paramValue);
    }
    catch (Exception e)
    {
      throw new Exception("Failed to invoke method");
    }
  }

Upvotes: 1

miks
miks

Reputation: 544

The URL is ok, nevertheless you try to load a jar from classpath, so it means that yo need to have the file in cp first. In your case you want to load a jar that is not in classpath so you have to use URLClassLoader and for JAR you can use also the JARClassLoader If you want some sample lesson on it: http://docs.oracle.com/javase/tutorial/deployment/jar/jarclassloader.html

Here a sample I ran by myself see if helps you. It search the Logger class of Log4j that is not in my classpath, of course i got exception on invocation of the constructor since i did not pass the right params to the constructor

package org.stackoverflow;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;

public class URLClassLoaderSample
{
  public static void main(String[] args) throws Exception
  {
    File f = new File("C:\\_programs\\apache\\log4j\\v1.1.16\\log4j-1.2.16.jar");
    URLClassLoader urlCl = new URLClassLoader(new URL[] { f.toURL()},System.class.getClassLoader());
    Class log4jClass = urlCl.loadClass("org.apache.log4j.Logger");
    log4jClass.newInstance();
  }
}



Exception in thread "main" java.lang.InstantiationException: org.apache.log4j.Logger
    at java.lang.Class.newInstance0(Class.java:357)
    at java.lang.Class.newInstance(Class.java:325)
    at org.stackoverflow.URLClassLoaderSample.main(URLClassLoaderSample.java:19)

Exception due to the wrong invocation, nevertheless at this stage we already found the class

Upvotes: 5

Related Questions