ClassLoader and JDBC problem

hi everyone!

i found the Mckoi db on the web and tried to play with it. below is the beginning of app code that runs great from the command line with the following:

java -cp ../../mckoidb.jar:. SimpleApplicationDemo

however, after i tried that and got all happy, i decided to create a custom class loader in the code below, so the i could run the app as in:

java SimpleApplicationDemo

when i do that, the program throws the exception telling me about the path not being correct

the only mods i did to the original demo code is the 'import java.net.*;' and what i put in the comments - ' startd modified code' and 'end modified code'

by the way: i only get the exception when the following line is commented out: Class.forName("com.mckoi.JDBCDriver").newInstance();

when i uncomment it, (without touching ANYTHING ELSE) and run it with the "-cp" switch everything works perfectly. any thoughts on that? i'm working on a small standalone app and need to hook it up with a small standalone db. i would like to keep the user from ever having to know what a classpath is :> any help will be greatly appreciated :> - ps i'm running it on Max OS X

import java.sql.*;

import java.net.*;

public class SimpleApplicationDemo {

/**

* The demonstation 'main' method.

*/

public static void main(String[] args) {

System.out.println();

// Register the Mckoi JDBC Driver

try {

// - start modified code --

URL jar = new URL("file: ../../mckoidb.jar");

URL[] classPath = new URL[]{jar};

ClassLoader loader = URLClassLoader.newInstance(classPath);

Class db = Class.forName("com.mckoi.JDBCDriver", true, loader);

// - end modified code --

// below is the orginal code

//Class.forName("com.mckoi.JDBCDriver").newInstance();

}

catch (Exception e) {

System.out.println(

"Unable to register the JDBC Driver.\n" +

"Make sure the classpath is correct.\n" +

"For example on Win32; java -cp ../../mckoidb.jar;. SimpleApplicationDemo\n" +

"On Unix; java -cp ../../mckoidb.jar:. SimpleApplicationDemo");

return;

}

[2221 byte] By [tomek_vectora] at [2007-9-19]
# 1

part of your code reads as

URL jar = new URL("file: ../../mckoidb.jar");

This will not throw you any exceptions but your protocol is a little out. So you ClassLoader will not be able to find you mckoidb.jar because you URL is incorrect

It should read as:

URL jar = new URL("file://../../mckoidb.jar");

Try it out :-)

noelkeea at 2007-7-8 > top of java,Core,Core APIs...
# 2
... just tried that, still no luck :<
tomek_vectora at 2007-7-8 > top of java,Core,Core APIs...
# 3
Have you tried this?String jarFile = "classes12.zip";java.net.URL jar = getClass().getResource(jarFile);java.net.URL[] classPath = new java.net.URL[]{jar};ClassLoader loader = java.net.URLClassLoader.newInstance(classPath);
jquattroa at 2007-7-8 > top of java,Core,Core APIs...
# 4

i believe i got the loader loading, but now i'm getting another problem.

everything seems to work fine until the end of this chunk of code.

at the end the sql exception gets thrown with the message being:

"Unable to make a connection to the database.

The reason: No suitable driver"

should i maybe re post this to the JDBC forum?

//-

import java.sql.*;

import java.net.*;

public class SimpleApplicationDemo {

/**

* The demonstation 'main' method.

*/

public static void main(String[] args) {

System.out.println();

// Register the Mckoi JDBC Driver

try {

// - start modified code --

URL[] urlsToLoadFrom = new URL[]{new URL("file:../../mckoidb.jar")};

URLClassLoader loader = new URLClassLoader(urlsToLoadFrom);

Class JDBCDriver = Class.forName("com.mckoi.JDBCDriver", true, loader);

// - end modified code --

// below is the orginal code - when uncommented works with:

// java -cp ../../mckoidb.jar:. SimpleApplicationDemo

//Class.forName("com.mckoi.JDBCDriver").newInstance();

}

catch (Exception e) {

System.out.println(

"Unable to register the JDBC Driver.\n" +

"Make sure the classpath is correct.\n" +

"For example on Win32; java -cp ../../mckoidb.jar;. SimpleApplicationDemo\n" +

"On Unix; java -cp ../../mckoidb.jar:. SimpleApplicationDemo");

return;

}

// This URL specifies we are connecting with a local database. The

// configuration file for the database is found at './ExampleDB.conf'

String url = "jdbc:mckoi:local://ExampleDB.conf";

// The username/password for the database. This is set when the database

// is created (see SimpleDatabaseCreateDemo).

String username = "user";

String password = "pass1212";

// Make a connection with the database.

Connection connection;

try {

connection = DriverManager.getConnection(url, username, password);

}

catch (SQLException e) {

System.out.println(

"Unable to make a connection to the database.\n" +

"The reason: " + e.getMessage());

return;

}

tomek_vectora at 2007-7-8 > top of java,Core,Core APIs...
# 5

Not sure what the question is, but just to clarify...

you can't load a jdbc driver using a classloader.

At least not like other classes. (I believe that is the general consensus in the jdbc forum.)

Someone, in the jdbc forum, found an alternative solution for dynamic driver loading. You will have to search to find it.

jschella at 2007-7-8 > top of java,Core,Core APIs...
# 6

Hi tomek_vector,

Okie dokie, this is what happened in your code.

1) you loaded your mckoid.jar driver on a different classloader. ie. loader

2) you are attempting to get the connection with the classloader which your SimpleApplicationDemo is on.

ie. you are on different ClassLoaders when you loaded the JDBC driver and when you attempt to get the database connection are different. This cannot be done. You must be on the same ClassLoader

What I would do is:

a) have another main program create the ClassLoader.

b) load the orginal SimpleApplicationDemo with this ClassLoader. (see (a))

c) now instantiate the SimpleApplicationDemo. (your code must be in the constructor)

Now everything would be rosy :-)

Regards,

Noel

noelkeea at 2007-7-8 > top of java,Core,Core APIs...
# 7

>

> you can't load a jdbc driver using a classloader.

>

I disagree with this. Our very first "Hello World" program is loaded with the SystemClassLoader in the first place. Plus the fact that I have created an application with everything running on a ClassLoader which I defined. this includes the JDBC driver.

noelkeea at 2007-7-8 > top of java,Core,Core APIs...
# 8

> >

> > you can't load a jdbc driver using a classloader.

> >

>

>

> I disagree with this. Our very first "Hello World"

> program is loaded with the SystemClassLoader in the

> first place. Plus the fact that I have created an

> application with everything running on a ClassLoader

> which I defined. this includes the JDBC driver.

>

It would be better to say that you cannot create a Connection using java.sql.DriverManager for a JDBC driver when your getConnection() call is running in a classloader different from the one used to load the JDBC driver. If all your code is loaded using the same custom classloader it would probably work although I haven't tried it.

Col

colbella at 2007-7-8 > top of java,Core,Core APIs...
# 9
... i'll give this a whack, just running short on time here :>, thanks for the tips so far
tomek_vectora at 2007-7-8 > top of java,Core,Core APIs...