Thread View: borland.public.jbuilder.java.language
10 messages
10 total messages
Started by George
Tue, 28 Mar 2006 14:18
changing class path at run time
Author: George
Date: Tue, 28 Mar 2006 14:18
Date: Tue, 28 Mar 2006 14:18
15 lines
1256 bytes
1256 bytes
I want to load JDBC drivers on demand. The user tells me the driver class name and where the jar files are located and my app loads the driver. Or so I would like. The following code does not work:
try {
System.setProperty("java.class.path", path + ";" + "C:\\MyDrivers\\ojdbc14.jar" );
Class.forName("oracle.jdbc.OracleDriver");
} catch (Exception ex) {
ex.printStackTrace();
}
The code works if I include the jar file on the java command line invocation. What am I doing wrong?
TIA
George
Re: changing class path at run time
Author: George
Date: Tue, 28 Mar 2006 15:12
Date: Tue, 28 Mar 2006 15:12
19 lines
1383 bytes
1383 bytes
"George" <me@here.com> wrote:
>
>I want to load JDBC drivers on demand. The user tells me the driver class name and where the jar files are located and my app loads the driver. Or so I would like. The following code does not work:
>
>try {
> System.setProperty("java.class.path", path + ";" + "C:\\MyDrivers\\ojdbc14.jar" );
> Class.forName("oracle.jdbc.OracleDriver");
> } catch (Exception ex) {
> ex.printStackTrace();
> }
>
>
>The code works if I include the jar file on the java command line invocation. What am I doing wrong?
>
>TIA
>George
>
>Never mind. I just found out about URLClassLoader.
Re: changing class path at run time
Author: Paul Furbacher [TeamB]
Date: Tue, 28 Mar 2006 16:23
Date: Tue, 28 Mar 2006 16:23
42 lines
2335 bytes
2335 bytes
George wrote:
> "George" <me@here.com> wrote:
>> I want to load JDBC drivers on demand. The user tells me the
>> driver class name and where the jar files are located and my app
>> loads the driver. Or so I would like. The following code does
>> not work:
>>
>> try { System.setProperty("java.class.path", path + ";" +
>> "C:\\MyDrivers\\ojdbc14.jar" );
>> Class.forName("oracle.jdbc.OracleDriver"); } catch (Exception ex)
>> { ex.printStackTrace(); }
>>
>>
>> The code works if I include the jar file on the java command line
>> invocation. What am I doing wrong?
>>
>> TIA George
>>
>> Never mind. I just found out about URLClassLoader.
Yes. There are several open source projects (e.g., OR mappers)
which have tools that provide you with this capability. One
which comes to mind is objectstyle.org's Cayenne Modeler.
You might want to study their code to see if you can enhance
what you already have accomplished. (It's always good to see
how other folks approach a problem.)
--
Paul Furbacher (TeamB)
Save time, search the archives:
http://info.borland.com/newsgroups/ngsearch.html
Is it in Joi Ellis's Faq-O-Matic?
http://www.visi.com/~gyles19/fom-serve/cache/1.html
Finally, please send responses to the newsgroup only.
That means, do not send email directly to me.
Thank you.
Re: changing class path at run time
Author: George
Date: Tue, 28 Mar 2006 20:00
Date: Tue, 28 Mar 2006 20:00
62 lines
3120 bytes
3120 bytes
"Paul Furbacher [TeamB]" <pfurbacher@mac.com> wrote:
>George wrote:
>> "George" <me@here.com> wrote:
>>> I want to load JDBC drivers on demand. The user tells me the
>>> driver class name and where the jar files are located and my app
>>> loads the driver. Or so I would like. The following code does
>>> not work:
>>>
>>> try { System.setProperty("java.class.path", path + ";" +
>>> "C:\\MyDrivers\\ojdbc14.jar" );
>>> Class.forName("oracle.jdbc.OracleDriver"); } catch (Exception ex)
>>> { ex.printStackTrace(); }
>>>
>>>
>>> The code works if I include the jar file on the java command line
>>> invocation. What am I doing wrong?
>>>
>>> TIA George
>>>
>>> Never mind. I just found out about URLClassLoader.
>
>Yes. There are several open source projects (e.g., OR mappers)
>which have tools that provide you with this capability. One
>which comes to mind is objectstyle.org's Cayenne Modeler.
>You might want to study their code to see if you can enhance
>what you already have accomplished. (It's always good to see
>how other folks approach a problem.)
>
>
>--
>
>
>Paul Furbacher (TeamB)
>
> Save time, search the archives:
> http://info.borland.com/newsgroups/ngsearch.html
>
> Is it in Joi Ellis's Faq-O-Matic?
> http://www.visi.com/~gyles19/fom-serve/cache/1.html
>
> Finally, please send responses to the newsgroup only.
> That means, do not send email directly to me.
> Thank you.
I guess I spoke too soon.
I'm having trouble going the URLClassLoader route. The code below succeeds in loading the Oracle jdbc driver...however the call to DriverManager.getConnection() returns saying "No suitable driver"...
George
try {
File f = new File(System.getProperty("user.dir") + "\\ojdbc14.jar");
URL url = new URL("file:///"+ f.getAbsolutePath());
URL [] urlList = new URL[1];
urlList[0] = url;
URLClassLoader cld = new URLClassLoader(urlList);
Class cl = cld.loadClass("oracle.jdbc.OracleDriver");
Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@STPDB1P:1521:STP20P1", "fo", "fo");
} catch (Exception ex) {
ex.printStackTrace();
}
Re: changing class path at run time
Author: Paul Furbacher [TeamB]
Date: Tue, 28 Mar 2006 21:50
Date: Tue, 28 Mar 2006 21:50
62 lines
2944 bytes
2944 bytes
George wrote:
> I guess I spoke too soon.
>
> I'm having trouble going the URLClassLoader route. The code below
> succeeds in loading the Oracle jdbc driver...however the call to
> DriverManager.getConnection() returns saying "No suitable
> driver"...
>
> George
>
> try {
> File f = new File(System.getProperty("user.dir") + "\\ojdbc14.jar");
> URL url = new URL("file:///"+ f.getAbsolutePath());
> URL [] urlList = new URL[1];
> urlList[0] = url;
> URLClassLoader cld = new URLClassLoader(urlList);
> Class cl = cld.loadClass("oracle.jdbc.OracleDriver");
> Connection connection =
DriverManager.getConnection(
"jdbc:oracle:thin:@STPDB1P:1521:STP20P1", "fo", "fo");
> } catch (Exception ex) {
> ex.printStackTrace();
> }
If I look at how the Cayenne folks do it (Andrei Adamchik,
specifically) in
org.objectstyle.cayenne.modeler.FileClassLoadingService
I notice that the new classloader is instantiated with a
parent classloader.
That's different from how you have done it. Maybe that's
the difference; try
URLClassLoader cld =
new URLClassLoader(
new URL [] { url },
this.getClass().getClassLoader() );
Also, have you stepped through the above code in the
debugger and ascertained that "cl" is not null? You
hinted that you have when you wrote "... succeeds in
loading the Oracle jdbc driver...", but I just want to
be sure.
--
Paul Furbacher (TeamB)
Save time, search the archives:
http://info.borland.com/newsgroups/ngsearch.html
Is it in Joi Ellis's Faq-O-Matic?
http://www.visi.com/~gyles19/fom-serve/cache/1.html
Finally, please send responses to the newsgroup only.
That means, do not send email directly to me.
Thank you.
Re: changing class path at run time
Author: Shankar Unni
Date: Wed, 29 Mar 2006 01:51
Date: Wed, 29 Mar 2006 01:51
41 lines
2878 bytes
2878 bytes
George wrote:
> URLClassLoader cld = new URLClassLoader(urlList);
> Class cl = cld.loadClass("oracle.jdbc.OracleDriver");
> Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@STPDB1P:1521:STP20P1", "fo", "fo");
This is really unlikely to work. Even if you had created "cld" with its
parent set to ThisClass.getClass().getClassLoader(), you'd still have
this hierarchy:
ThisClass <- loaded by base class loader
OracleDriver <- loaded by "cld" (assuming that ojdbc14.jar is not
in your regular classpath)
Remember that each class is loaded *in its own classloader* only. It is
not visible to classes loaded by its parent classloader, or by classes
loaded by other classloaders unrelated to its classloader.
So, OracleDriver in the above example is only visible to classes loaded
by "cld", or by other classloaders that are children of "cld".
There's more to what Cayenne is doing than just making cld's parent the
calling class' classloader. Check carefully to see how they make the
driver visible.
I strongly suspect that they are doing something like this:
URLClassLoader cld = new URLClassLoader(urlList);
Class driverClass = cld.loadClass("oracle.jdbc.OracleDriver");
// call the default constructor of the driver class
// using reflection:
Object driverObj = driverClass.newInstance();
At this point, assuming that oracle.jdbc.OracleDriver has a default
constructor (should have), you'll see that the driver is now registered,
and DriverManager.getConnection() should now work.
PS. Check the documentation to see if the preferred class is
oracle.jdbc.OracleDriver, or oracle.jdbc.driver.OracleDriver. My memory
is that Oracle now prefers that you use the latter name..
Re: changing class path at run time
Author: George X
Date: Wed, 29 Mar 2006 20:31
Date: Wed, 29 Mar 2006 20:31
68 lines
3811 bytes
3811 bytes
Shankar Unni <shankarunni@netscape.net> wrote:
>George wrote:
>
>> URLClassLoader cld = new URLClassLoader(urlList);
>> Class cl = cld.loadClass("oracle.jdbc.OracleDriver");
>> Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@STPDB1P:1521:STP20P1", "fo", "fo");
>
>This is really unlikely to work. Even if you had created "cld" with its
>parent set to ThisClass.getClass().getClassLoader(), you'd still have
>this hierarchy:
>
> ThisClass <- loaded by base class loader
>
> OracleDriver <- loaded by "cld" (assuming that ojdbc14.jar is not
>in your regular classpath)
>
>Remember that each class is loaded *in its own classloader* only. It is
>not visible to classes loaded by its parent classloader, or by classes
>loaded by other classloaders unrelated to its classloader.
>
>So, OracleDriver in the above example is only visible to classes loaded
>by "cld", or by other classloaders that are children of "cld".
>
>There's more to what Cayenne is doing than just making cld's parent the
>calling class' classloader. Check carefully to see how they make the
>driver visible.
>
>I strongly suspect that they are doing something like this:
>
> URLClassLoader cld = new URLClassLoader(urlList);
> Class driverClass = cld.loadClass("oracle.jdbc.OracleDriver");
> // call the default constructor of the driver class
> // using reflection:
> Object driverObj = driverClass.newInstance();
>
>At this point, assuming that oracle.jdbc.OracleDriver has a default
>constructor (should have), you'll see that the driver is now registered,
>and DriverManager.getConnection() should now work.
>
>PS. Check the documentation to see if the preferred class is
>oracle.jdbc.OracleDriver, or oracle.jdbc.driver.OracleDriver. My memory
>is that Oracle now prefers that you use the latter name..
Paul & Shankar,
Please excuse my obtuseness.
I think I have incorporated your suggestions as in the code below. However, DriverManager.getConnection still throws a SQLException of "No suitable driver".
Paul, to answer your question, yes, the call to cld.loadClass does return a non-null reference.
Thanks.
George
try {
TestSys testSys = new TestSys(); // an instance of this class
File f = new File(System.getProperty("user.dir") + "\\ojdbc14.jar");
URL url = new URL("file:///"+ f.getAbsolutePath());
URL [] urlList = new URL[1];
urlList[0] = url;
URLClassLoader cld = new URLClassLoader(urlList, testSys.getClass().getClassLoader());
Class cl = cld.loadClass("oracle.jdbc.driver.OracleDriver");
Object driverObj = cl.newInstance();
Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@STPDB1P:1521:STP20P1", "fo", "fo");
} catch (Exception ex) {
ex.printStackTrace();
}
Re: changing class path at run time
Author: Paul Furbacher [TeamB]
Date: Thu, 30 Mar 2006 03:34
Date: Thu, 30 Mar 2006 03:34
62 lines
3010 bytes
3010 bytes
Try this:
public void getConnection(
String classname,
String filename,
String dbUrl,
Properties props) {
try {
File f = new File(filename);
URL[] urlList = new URL[] { f.toURL() };
URLClassLoader cld =
new URLClassLoader(
urlList,
this.getClass().getClassLoader());
Driver driver =
(Driver)cld.loadClass(classname).newInstance();
Connection connection = driver.connect(dbUrl, props);
/* instead of
Connection connection =
DriverManager.getConnection(dbUrl, props);
*/
}
catch (Exception ex) {
ex.printStackTrace();
}
}
What I missed was the fact that you have to use
the driver instance itself in this scenario, not
the DriverManager whose class loader will never
know about the dynamically loaded class ... at least
I think that's the explanation. [Feel free to correct
me if I'm wrong.]
[Thanks to the Cayenne contributors, Andrei Adamchik in particular,
for this solution. If you want to see it yourself, see the class,
org.objectstyle.cayenne.conn.DriverDataSource. It's unfortunate
that Cayenne is not more widely known -- my gut feeling is that
it's a heck of a lot smoother an experience than Hibernate, which
to me is very quirky. Cayenne has just admitted as a Jakarta
Incubator project.
http://incubator.apache.org/projects/cayenne.html
I'm hoping that will boost its prominence.]
--
Paul Furbacher (TeamB)
Save time, search the archives:
http://info.borland.com/newsgroups/ngsearch.html
Is it in Joi Ellis's Faq-O-Matic?
http://www.visi.com/~gyles19/fom-serve/cache/1.html
Finally, please send responses to the newsgroup only.
That means, do not send email directly to me.
Thank you.
Re: changing class path at run time
Author: George Xavier
Date: Sat, 01 Apr 2006 02:28
Date: Sat, 01 Apr 2006 02:28
83 lines
3774 bytes
3774 bytes
Yes, this works. Thank you.
I guess my mental block was here : "...you have to use the driver instance
itself in this scenario,
not the DriverManager whose class loader will never know about the
dynamically loaded class .....".
Anyway to get back to the issue which started this all: looks like the
runtime never revisits the value of java.class.path after the VM has
started. Wonder why.
Thanks again.
George X.
P.S Sorry I accidentally emailed you instead of the newsgroup in posting my
reply.
"Paul Furbacher [TeamB]" <pfurbacher@mac.com> wrote in message
news:442b51bb$1@newsgroups.borland.com...
> Try this:
>
> public void getConnection(
> String classname,
> String filename,
> String dbUrl,
> Properties props) {
> try {
> File f = new File(filename);
> URL[] urlList = new URL[] { f.toURL() };
> URLClassLoader cld =
> new URLClassLoader(
> urlList,
> this.getClass().getClassLoader());
> Driver driver =
> (Driver)cld.loadClass(classname).newInstance();
> Connection connection = driver.connect(dbUrl, props);
> /* instead of
> Connection connection =
> DriverManager.getConnection(dbUrl, props);
> */
> }
> catch (Exception ex) {
> ex.printStackTrace();
> }
> }
>
>
> What I missed was the fact that you have to use
> the driver instance itself in this scenario, not
> the DriverManager whose class loader will never
> know about the dynamically loaded class ... at least
> I think that's the explanation. [Feel free to correct
> me if I'm wrong.]
>
> [Thanks to the Cayenne contributors, Andrei Adamchik in particular,
> for this solution. If you want to see it yourself, see the class,
> org.objectstyle.cayenne.conn.DriverDataSource. It's unfortunate
> that Cayenne is not more widely known -- my gut feeling is that
> it's a heck of a lot smoother an experience than Hibernate, which
> to me is very quirky. Cayenne has just admitted as a Jakarta
> Incubator project.
>
> http://incubator.apache.org/projects/cayenne.html
>
> I'm hoping that will boost its prominence.]
>
>
> --
>
>
> Paul Furbacher (TeamB)
>
> Save time, search the archives:
> http://info.borland.com/newsgroups/ngsearch.html
>
> Is it in Joi Ellis's Faq-O-Matic?
> http://www.visi.com/~gyles19/fom-serve/cache/1.html
>
> Finally, please send responses to the newsgroup only.
> That means, do not send email directly to me.
> Thank you.
Re: changing class path at run time
Author: Shankar Unni
Date: Mon, 03 Apr 2006 19:26
Date: Mon, 03 Apr 2006 19:26
18 lines
2019 bytes
2019 bytes
George Xavier wrote: > Anyway to get back to the issue which started this all: looks like the > runtime never revisits the value of java.class.path after the VM has > started. Wonder why. That's definitely true. The system class loader reads the value of this property *once*, and that's it. It probably has to do with the overhead of getting the value and parsing it, and it would be rather expensive to do that for each class loaded (even a trivial program loads over a hundred classes). If you want a dynamic system class path, you need to interpose a URLClassLoader in between. Or create your own class loader class (not hard to do) which can extend from URLClassLoader, and make it the system class loader by passing in "-Djava.system.class.loader=your.classloader.class.Name".
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads