Re: driver initialization and connection separation
- From: Lew <noone(at)lwsc(dot)ehost-services(dot)com>
- To: pgsql-jdbc(at)postgresql(dot)org
- Subject: Re: driver initialization and connection separation
- Date: Sat, 30 Jan 2010 21:08:50 -0500
- Message-id: <hk2onk$djr$1@news.albasani.net> <text/plain>
Richard Troy wrote:
The application can connect to any RDBMS, Postgres, Oracle, Ingres,
whatever, and reconnect to any other, whenever the user wants. But once it
has connected to Postgres using the SSL feature, all future connections
using Postgres will use SSL. The only solution thus far is to kill the
application and then start it again - there is no switching between using
SSL and not using SSL, even though the driver is officially reloaded using
Class.forName(driverClassName).
As Oliver pointed out, that does not reload the driver.
Note that the official Java documentation from Sun says that doing so is
equivalent to Class.forName(className, true, currentLoader) which is using
the method for.Name(name, initialize, ClassLoader) - I cited a URL to
their site to support this.
Once a class loader has loaded the class, it does not reload it again but
determines that it already has done so.
To me this says that subsequent executions of Class.forName("driver")
should yield identical results as with the first time it's executed, but
To you, maybe, but not in reality. Your perception will match reality once
you've read the documentation.
<http://java.sun.com/javase/6/docs/api/java/lang/ClassLoader.html>
If you use a different class loader you can load the class again, but that
poses other gotchas.
that's demonstrably not true with Postgres - it "remembers" that it was
asked to use SSL in the past and it continues to want to do so in the
future.
Remembering that it used SSL is not curable by failing to reload the class.
It seems to me that there's something missing from the initialization
code, namely to remove the SSL features if the driver was already loaded.
The class is not re-initialized since you're using the same class loader and
it was already initialized once. Ergo, nothing is missing from the
initialization.
It should only be loaded when a URL asking for it comes along with the
option ssl=true (for example). However, one could easily argue that it's
not the initialization code that needs help but the code that constructs a
new connection; it makes just as much sense that the request for a new
connection give the appropriate type of connection, with or without SSL
depending on whether the option in the URL was specified.
According to how I read
<http://jdbc.postgresql.org/documentation/84/connect.html>
you should be able to get a non-SSL connection by not specifying the "ssl"
property in the version of 'DriverManager.getConnection()' that takes a
'Properties' argument.
...I readily admit I haven't tried making multiple, simultaneous
connections from the same instance of the driver; I presume that's
possible but I've never needed. It seems to me this is
much more a question of each individual connection than the driver itself.
You use the driver with static methods, such as
'DriverManager.getConnection()'. AFAICS there is no access directly to driver
instances.
...Your follow-on comment (below) about classes being initialized only
once isn't helpful here because it isn't clear to me whether this is a
case of initializing an object or loading _code_ that instantiates
He wasn't talking about initializing objects. He was talking about
initialization of the driver *class*, and it's entirely relevant. Whether
it's helpful to you or not depends on whether you assimilate and act upon the
information.
objects. In other words, even though I've been using Java since it's first
release, I've never before had to worry about the code that instantiates
objects changing while my code is running, so I haven't thought about it
Again, this is not about instantiation. You really should think about it much.
much. To my mind, each instance of my objects which then instantiate other
objects - like JDBC connection objects - should get clean, separate and
distinct objects, so in effect the driver code is loaded multiple times.
Not how it works. Your mind needs to change on this.
But as I said, I could be wrong - I don't know much about how the JVM
manages code that's loaded, but my suspicion is that it'll manage the
individual instances of loading the same driver separately.
Nope. It's not about instances.
Meanwhile, I just added this bit of code prior to the call to
Class.forName():
for (Enumeration fu = DriverManager.getDrivers(); fu.hasMoreElements();)
{
DriverManager.deregisterDriver((java.sql.Driver)fu.nextElement());
}
As I said, I don't have to worry about multiple connections within a
single instance of this class, so deregistering all the drivers is fine -
I am not so sure about that. It seems like an awful lot of work, and how will
it reregister? Once loaded and initialized, a class will not reinitialize
unless it's actually garbage collected first. Since registration is part of
intialization, and you don't get to reinitialize, I don't think you'll get the
class to re-register. Deregistration is not idiomatic and I expect it will
cause heartache. Better go with a conventional approach.
there should only ever be one connection and we're about to replace it. If
there's an unacceptable performance hit for unloading a driver when it
Deregistration != unloading.
isn't needed, then I'll think about adding to this. But if it works, it's
staying! -smile- I'll probably test it in the next few minutes...
Better would be to use the correct approach, which might be the
'DriverManager.getConnection()' call to which I just alluded. I haven't
tested it yet - why don't you and let us know how it works?
--
Lew
Home |
Main Index |
Thread Index