Hi,

>>>>> "KM" == Kathey Marsden <[EMAIL PROTECTED]> wrote:

KM> If you shutdown derby with
KM> DriverManager.getConnection("jdbc:derby:;shutdown=true");
KM> then set the next property and start it back up again, will that work?

This seems to be a necessary but not sufficient condition, see
non-obvious requirement below.

>>>>> "OB" == Oyvind Bakksjo <[EMAIL PROTECTED]> wrote:
OB> Yes, system properties are VM-wide, but they can be changed at any time. 
OB> The problem is if the properties are read and used only once, when the 
OB> driver is loaded, since it is impossible to instruct a class loader to 
OB> "unload" anything.

Derby docs says this can be achieved by forcing the garbage collector to
run, cf the hint I found here, see quote below.

http://incubator.apache.org/derby/docs/devguide/tdevdvlp20349.html

(quote): To restart Derby successfully, the JVM needs to unload
         org.apache.derby.jdbc.EmbeddedDriver, so that it can reload
         it when it restarts Derby. (Loading the local driver starts
         Derby.)  You cannot explicitly request that the JVM unload a
         class, but you can ensure that the EmbeddedDriver class is
         unloaded by using a System.gc() to force it to garbage
         collect classes that are no longer needed. Running with -nogc
         or -noclassgc definitely prevents the class from being
         unloaded and makes you unable to restart Derby in the same
         JVM.

I found the following idiom worked:

            <set properties>
            Class.forName(driver).newInstance();   <--- newInstance can be 
dropped 1. time!!
            <use derby>
            DriverManager.getConnection("jdbc:derby:;shutdown=true");

            System.gc();                           <--- in vain?

            <set new properties>
            Class.forName(driver).newInstance();   <---- but necessary here!
            <use derby with new properties>
            DriverManager.getConnection("jdbc:derby:;shutdown=true");

Note: newInstance() was needed the second time around.  Plain
"Class.forName(driver)" wont do, it gives:

  SQLException: 08001:No suitable driver

when I try to make a connection, i.e. the driver has not
(re)registered itself with the DriverManager The driver's static
initializer hasn't been run (again), cf. description in JDBC 3.0 spec
section 9.2. This leads me to believe the driver hasn't been evicted
by the gc() call after all. Why not? Did I miss something?

However, adding newInstance() makes it work.  Checking the code, I
found this in EmbeddedDriver, which explains why it works; the
constructor forces a reboot.

        static {

                EmbeddedDriver.boot();            
        }

        // Boot from the constructor as well to ensure that
        // Class.forName(...).newInstance() reboots Cloudscape
        // after a shutdown inside the same JVM.
        public EmbeddedDriver() {
                EmbeddedDriver.boot();
        }

Hmm... Should Derby docs mention using newInstance? Is it Kosher? The
JDBC spec doesnt say anything about using newInstance...

Not only Derby needs this, however, cf. also this discussion I found:

https://lists.xcf.berkeley.edu/lists/advanced-java/2000-September/012601.html

Dag

Reply via email to