Can the embedded JDBC driver and the client JDBC driver co-exist?

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Can the embedded JDBC driver and the client JDBC driver co-exist?

Steinar Bang
In my project[1] I am using a derby in-memory database with the embedded
driver for unit testing and integration testing.  I am using PostgreSQL
as the production server.

I am using Liquibase[2] to set up the schema for both Derby and
PostgreSQL, and I'm also using Liquibase to set up the test data in the
derby database.

What I wanted to do, was to dump the test database to a Derby network
server and do some tests on the data.  My changes worked fine in
PostgreSQL but not in the derby tests, and I wanted the chance to take a
look at them.

So what I did was add a pseudo unit test to a test class, that would
connect to "jdbc:derby://localhost:1527/ukelonn"[3].

When I tried running that test, it was unable to find the driver.

So I googled a bit more, and added a dependency to the derby client
jar in the test scope[4].

But then the unit test failed with the following error:
 java.lang.ClassCastException: org.apache.derby.jdbc.ClientDriver cannot be cast to org.apache.derby.jdbc.InternalDriver
        at org.apache.derby.jdbc.BasicEmbeddedDataSource40.findDriver(Unknown Source)
        at org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource.createPooledConnection(Unknown Source)
        at org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource.getPooledConnection(Unknown Source)
        at no.priv.bang.ukelonn.bundle.db.test.UkelonnDatabaseProviderTest.addUkelonnSchemaAndDataToDerbyServer(UkelonnDatabaseProviderTest.java:296)

Are the problems caused by me having both the embedded driver and the
network driver loaded into the same java application (in this case: the
same JUnit test)?

If there is a conflict between the embedded JDBC driver and the client
JDBC driver, is there a way around the conflict, other than creating a
separate maven project just to upload the liquibase files?

Thanks!


- Steinar



References:
 [1] <https://github.com/steinarb/ukelonn>
 [2] <http://www.liquibase.org>
 [3] <https://github.com/steinarb/ukelonn/blob/scratch/derby-test-writing-to-network-server/ukelonn.bundle.db.test/src/test/java/no/priv/bang/ukelonn/bundle/db/test/UkelonnDatabaseProviderTest.java#L283>
 [4] <https://github.com/steinarb/ukelonn/commit/513d94690bd86cd42116190e2b58ce2a71fb80e6>


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Can the embedded JDBC driver and the client JDBC driver co-exist?

Bryan Pendleton-3
I suspect your problems are caused by having two different versions of the Derby jars intermingled. The behavior of CLASSPATH is complex, especially for things like the JDBC 4.0 autoload features, and Derby jars are often packaged and bundled into other software packages, making it easy to have multiple copies of the Derby code without realizing it.

Sometimes, running with "-verbose:class" will give you a clue about which Derby code is being loaded from which location on the CLASSPATH.

But, perhaps you are encountering some other problem that isn't clear to me.

Can you isolate your problematic code as a minimum viable test case and share it?

Ideally, start by taking a very simple test program such as the one from the Derby tutorial (http://db.apache.org/derby/docs/10.13/getstart/twwdactivity3_Setup.html) and then make the minimum necessary changes to it to demonstrate the problem you're having.

Then share that code with the list.

thanks,

bryan

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Can the embedded JDBC driver and the client JDBC driver co-exist?

Steinar Bang
>>>>> Bryan Pendleton <[hidden email]>:

> I suspect your problems are caused by having two different versions of
> the Derby jars intermingled. The behavior of CLASSPATH is complex,
> especially for things like the JDBC 4.0 autoload features, and Derby
> jars are often packaged and bundled into other software packages,
> making it easy to have multiple copies of the Derby code without
> realizing it.

Ok, I interpret this answer to be that there shouldn't be any problems
with pulling the embedded driver and the client driver into the same
java program?

The google hits when searching answers to this issue has hinted at
having two different versions of derby in the classpath, so this is what
I have looked at before postign a question here.

The maven dependencies look OK, but an inlined derby in a different jar
is a definite possibility.

I'll try investigating this possibility before trying to isolate a test
case.

Thanks!


- Steinar

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Can the embedded JDBC driver and the client JDBC driver co-exist?

Bryan Pendleton-3


On Sat, Aug 12, 2017 at 9:47 AM, Steinar Bang <[hidden email]> wrote:
 

Ok, I interpret this answer to be that there shouldn't be any problems
with pulling the embedded driver and the client driver into the same
java program?



Yes, that's my belief.

You might experience higher-level behavior differences. There have been, in the past, subtle differences between the way the two drivers behave, so you might encounter such differences (e.g., https://issues.apache.org/jira/browse/DERBY-2453). Those known differences are cataloged in the Derby JIRA, so you could search there if you need more details.

But as far as including both JDBC drivers into the same JVM, and opening multiple connections, some with the one driver and some with the other, I believe that should work fine.

You can't simultaneously access the identical physical database with multiple connections this way, of course, because your embedded connections to a particular physical database on your machine will lock out the Derby Network Server's attempts to provide connections to that same database (and vice versa).

So either connect to different databases with these different driver types, or close your connections (and shut down the embedded engine) prior to opening client connections to a Derby Network Server serving the same database.

Anyway, yes, please try to figure out if you have any CLASSPATH conflicts, and please do let us know the results of your investigations!

thanks,

bryan
 

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Can the embedded JDBC driver and the client JDBC driver co-exist?

Steinar Bang
>>>>> Bryan Pendleton <[hidden email]>:

> Anyway, yes, please try to figure out if you have any CLASSPATH conflicts,
> and please do let us know the results of your investigations!

The reason for my problems turned out to be quite simple.

I'm using the pax-jdbc DerbyDataSourceFactory in my derby database
bundle, so I was using that class in my unit test as well, assuming it
would be able to create the correct kind of data source, depending on
the JDBC URL.

However, when I looked at the source of the
DerbyDataSourceFactory.createDataSource() method, it looked like this:

    public DataSource createDataSource(Properties props) throws SQLException {
        EmbeddedDataSource ds = new EmbeddedDataSource();
        setProperties(ds, props);
        return ds;
    }

...and an EmbeddedDataSource won't be able to create a client
connection... or so I think...?

So instead I created a client datasource directly, and that worked fine:
        boolean createUkelonnDatabase = true;
        ClientConnectionPoolDataSource dataSource = new ClientConnectionPoolDataSource();
        dataSource.setServerName("localhost");
        dataSource.setDatabaseName("ukelonn");
        dataSource.setPortNumber(1527);
        if (createUkelonnDatabase) {
            dataSource.setCreateDatabase("create");
        }
        PooledConnection connect = dataSource.getPooledConnection();

With this connection, Liquibase can do its thing, and set up the schema
and data in the server.

Thanks again!

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Can the embedded JDBC driver and the client JDBC driver co-exist?

Bryan Pendleton-3
Excellent news! Thanks for digging down to uncover the source of the problem, and thanks for sharing your discoveries with us.

I know very little about pax-jdbc, but it seems like useful software; it would be nice if it cleanly supported both the Embedded and Client-Server driver configurations of Derby.

Perhaps you could forward your findings on to the pax-jdbc community, to see if they think it might be possible to enhance their software?

In the meantime, it's great to hear that you have a solution that is working for you.

bryan

Loading...