db-derby-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Rick Hillegas <rick.hille...@gmail.com>
Subject Re: So, Derby works...
Date Thu, 09 Jul 2020 23:12:38 GMT
If we were implementing all of this now, we would not separate 
AutoloadedDriver from EmbeddedDriver. But Derby co-evolved with the JDK 
from the start. By the time that Java introduced driver autoloading, we 
already had legacy customers whose applications we did not want to 
disturb. We did not completely achieve that goal, but we tried.

Class.forName("org.apache.derby.jdbc.EmbeddedDriver" ) boots the Derby 
engine, loading its classes into memory. Some legacy applications came 
to expect this side-effect. However, we did not want to boot the Derby 
engine and incur all of that classloading as a side-effect of an 
application trying to connect to another vendor's database driver. That 
is what would have happened had derby.jar designated EmbeddedDriver as 
the autoloaded driver. So we created a new, largely vacuous placeholder 
driver, the AutoloadedDriver, which does NOT boot the Derby engine as a 
side-effect of simply being faulted into a classloader. That is the 
driver which derby.jar designates as Derby's autoloaded driver.

This is a great deal of complexity for something which ought to be very 
straightforward, but it is the cost we paid to keep abreast of an 
evolving JDBC interface while maintaining backward compatibility.

Hope this helps,

On 7/8/20 4:50 PM, Russell Bateman wrote:
> The mock driver supports a sort of bogus URL ("jdbc:mock") that it 
> recognizes for its purpose which is only to respond to a single query 
> with canned data (whereas I'll be able to populate Derby with as much 
> and whatever data I ever want). Of course, its driver doesn't ever do 
> anything "real," though it supports a few metadata methods (and the 
> MockConnectionimplements Connectionand supports a whole pile of 
> methods that stub out most actions and unimaginatively return the 
> canned data).
> Yes, your suggestion #3 works well and solves that particular problem 
> of an empty driver list. (The list is empty instead of containing the 
> mock driver because I separated the packages. DriverManagerdoes some 
> reflection desperately looking for classes that might have drivers.) 
> The list now has the Derby driver in it:
> Down inside DriverManager's private getConnection(), walking the 
> driver list using the IntelliJ IDEA debugger, I see:
>    *aDriver* = {DriverInfo@2097}
> "driver[className=org.apache.derby.jdbc.*AutoloadedDriver*@6bb4dd34]"
>    *con* = {EmbeddedConnection@2585}
>    "org.apache.derby.impl.jdbc.*EmbedConnection*@1414013111 (XID =
>    164), (SESSIONID = 1), (DATABASE = memory:sys), (DRDAID = null) "
> I have to admit that I'm not to the point yet where I grok why I'm 
> seeing AutoloadedDriverwhen I forced Java to verify EmbeddedDriver. I 
> got no errors doing that; I did it just before making the call to 
> getConnection():
>    Class.forName( "org.apache.derby.jdbc.EmbeddedDriver" );
>    DriverManager.getConnection(
>    "jdbc:derby:memory:sampledb;created=true", "sa", "sa" );
> I have learned a great deal more about JDBC drivers than I had planned 
> thanks to deciding to use Derby, replacing this old test mock and with 
> your help which I hugely appreciate!
> Russ
> On 7/8/20 5:15 PM, Rick Hillegas wrote:
>> It's hard to say what's going on, but the instability in your 
>> experiments is hard to reconcile against the deterministic code paths 
>> involved in JDBC autoloading.
>> I can only speculate about what is causing this instability:
>> 1) What JDBC URLs does your MockDriver claim to support?
>> 2) Is something tricky being done to the classpath, creating a 
>> situation in which the Derby jars are not visible when you invoke 
>> DriverManager.getConnection()?
>> 3) What happens when you do a 
>> Class.forName("org.apache.derby.jdbc.EmbeddedDriver")? What are the 
>> chain of errors raised? For the record, this is the recommended JDBC 
>> way to fault in a driver which was missed at autoloading time. 
>> Autoloading occurs on the very first call to 
>> DriverManager.getConnection() during the lifetime of the JVM.
>> Hope this helps,
>> -Rick
>> On 7/8/20 10:37 AM, Russell Bateman wrote:
>>> ...again, don't know what I changed.* I'm only depending on 
>>> /derby-
>>> What I think is going on is an artifact of being side-by-side with 
>>> another JDBC driver implementation.
>>> I was hoping to keep the original mocked test driver working 
>>> alongside the Derby implementation at least until I'm able to 
>>> abolish it in every case. Just as used to be the case, it's 
>>> registered thus:
>>>     DriverManager.registerDriver( new MockDriver() );
>>> However, this is not how it works for Derby. It just happens on the 
>>> basis of having the JAR linked (in /pom.xml/). The problem comes 
>>> that, because the MockDriveris explicitly registered, when we go to 
>>> create a Derby connection:
>>>     java.sql.Connection connection = DriverManager.getConnection( 
>>> "jdbc:derby:memory:sampledb;create=true" );
>>> ...DriverManagertakes as license to create an instance of the old 
>>> test mock because that is the (only) driver in its 
>>> registeredDriverslist. *I moved the Derby-based code out of the same 
>>> Java package to solve this?
>>> Thanks again. I'm sorry for having made this annoying.
>>> Russ

View raw message