Re: driver initialization and connection separation - Mailing list pgsql-jdbc
From | Lew |
---|---|
Subject | Re: driver initialization and connection separation |
Date | |
Msg-id | hk2onk$djr$1@news.albasani.net Whole thread Raw |
In response to | Re: driver initialization and connection separation (Richard Troy <rtroy@ScienceTools.com>) |
List | pgsql-jdbc |
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
pgsql-jdbc by date: