This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 63957 - Cannot reconnect to derby database
Summary: Cannot reconnect to derby database
Status: VERIFIED FIXED
Alias: None
Product: db
Classification: Unclassified
Component: Derby (show other bugs)
Version: 5.x
Hardware: PC Windows XP
: P3 blocker (vote)
Assignee: Andrei Badea
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-09-09 10:07 UTC by _ lcincura
Modified: 2005-11-21 11:18 UTC (History)
1 user (show)

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments
Code which reproduces the issue outside NetBeans (1.06 KB, text/plain)
2005-09-10 18:14 UTC, Andrei Badea
Details

Note You need to log in before you can comment on or make changes to this bug.
Description _ lcincura 2005-09-09 10:07:52 UTC
NetBeans IDE 5.0 [200509051800] on jdk 1.5.0_05

1) start with clean userdir
2) switch to Runtime|Databases and use context menu to add driver
3) add driver file derby.jar (embeded appache derby) and click OK
4) select 'Apache Derby (Embedded)' node and from context menu invoke Connect
Using...
5) in the connect dialog write connect string 'jdbc:derby:test;create=true' and
click OK
6) select new connected database node and from context menu invoke Disconnect
7) select the node again and from context menu invoke Connect...
8) in the connect dialog click OK => the connection fails with message 'Failed
to start database test, see the next exception for details'. Another problem is
there is no exception with the details anywhere.
Comment 1 Martin Schovanek 2005-09-09 10:44:20 UTC
Reproducible only on Win platform. Cannot reproduce on Linux and Mac OS X.
Comment 2 Andrei Badea 2005-09-10 18:12:36 UTC
Caused by NetBeans using a new class loader each time a database connection is
made (the class loaders are used to load the JDBC drivers, since they aren't on
the IDE classpath). The attached Java code reproduces the bug (run *without*
derby.jar on the classpath, since this would cause the jar to be loaded using
the bootstrap class loader). Not sure if this is a bug in Derby or not.

A solution to this issue could be to cache the class loader for each connection.
But while evaluating this bug I also found out that NetBeans doesn't properly
shut down the Derby instance started when making the connection to an embedded
database. If a user developing a JDBC app using embedded Derby would connect
from NetBeans to the embedded database used by his app, he won't be able to
connect to this database from the application until NetBeans is restarted. So a
more correct fix would be to shut down Derby each time a connection to an
embedded database is closed.

Adding Oyvind to CC in case he has any comments.
Comment 3 Andrei Badea 2005-09-10 18:14:00 UTC
Created attachment 24676 [details]
Code which reproduces the issue outside NetBeans
Comment 4 bakksjo 2005-09-21 14:13:03 UTC
It's not a Derby bug, it's a feature. I'll try to explain:

When Derby is used in embedded mode, the Derby system is initialized the first
time the (embedded) JDBC driver is loaded. In embedded mode, we can view the
Derby system as a server which is serving only one application - the application
it is embedded in. Loading the driver means starting the server.

Now, it is completely possible to load the embedded JDBC driver in multiple
class loaders, but that means loading multiple instances of the Derby system.
This corresponds to starting multiple instances of traditional (non-embeddable)
database servers. Now, that is perfectly legal, but for obvious reasons, they
cannot share resources - they are individual server instances running on the
same machine (and, in the case of Derby, in the same JVM, but they are still
separate systems). The problem arises when two connections - through two
distinct server instances - try to access the same database. At any time, no
more than one server may be responsible for a particular database.

Shutting down the database each time a connection is closed is not a good
solution, since that would kill all your other open connections to the same
database when one of them closes. Also, it will generate a lot of overhead and
be much slower. Shutting down the Derby *system* (not just the database) each
time a connection is closed will be even worse.

Bottom line: In embedded mode, applications must get all connections to a
particular database X through the same Derby system, which means: from the same
JDBC driver (loaded with the same classloader). The Derby system should be shut
down when NetBeans exits.

In client/server mode, Derby behaves similar to other DBMSs: You start the
server process separately, connect to it through a network protocol, and it does
not matter to the server which classloader loaded the client JDBC driver, how
many drivers are loaded etc.
Comment 5 Andrei Badea 2005-09-21 15:02:29 UTC
Oyvind, thank you for the explanation. It still seems to the that shutting down
the database and maybe even the instance would cause no harm. Currently each
time a you invoke the Connect action on a connection a new class loader is
created for loading the respective driver. For Derby this causes a new instance
to be created. The class loader, and therefore the instance, is not shared among
connections. Note that this means that you cannot have more than one database
connection with the same Derby database URL (since a new connection would access
the same database, but from a new Derby instance, which is disallowed by Derby).

So it seems that shutting down the Derby instance upon disconnecting a
connection is OK, since there would only be one connection using that instance
-- the one you are just disconnecting.

BTW I think in the future we should cache and reuse the class loaders instead of
creating new ones. That would allow multiple connections to the same Derby
database, and we should shut down the database (not the instance) when the last
connection is disconnected.
Comment 6 bakksjo 2005-09-21 15:49:59 UTC
What is the reason for using a separate classloader for each connection?
Although it works better for traditional client/server databases than for
Embedded Derby, it still consumes a lot more memory than necessary, by loading
the JDBC driver multiple times.

If reusing the classloader is not an option at this time, I agree that shutting
down the instance when closing the connection will be an improvement. However,
it is not intuitive to the user why the second connection to the database fails.
(Especially since the 'next exception' is not shown.)
Comment 7 Andrei Badea 2005-09-21 16:48:20 UTC
Re. the separate class loader: there isn't any good reason I can think of, aside
from simplicity. But then again, it has never caused any problems (except from
more memory usage and a memory leak caused by each driver loaded by a new class
loader registering itself to DriverManager). Anyway, I plan to fix this, but it
looks like too big a change for it to be made so late in the 5.0 release schedule.

Re. the intuitivity: what's worse is that on Linux a user making the second
connection won't be noticed of anything and the db could be corrupted (except if
we set the derby.database.forceDatabaseLock property). But then we must make
really sure we shutdown the Derby instance, which cannot be guaranteed. For
example one could kill the NetBeans process or restart the machine and NetBeans
wouldn't get a change to shutdown the Derby instance correctly. We must
definitely display the next exception in the "Connection failed" dialog, since
Derby displays quite a meaningful message when derby.database.forceDatabaseLock
is true and a db.lck file exists.
Comment 8 bakksjo 2005-09-22 09:35:52 UTC
Shouldn't this issue have 'derby' as its subcomponent value?
Comment 9 Andrei Badea 2005-09-22 09:56:40 UTC
I guess it should. Reassigning to db/derby.
Comment 10 Andrei Badea 2005-10-17 15:24:38 UTC
Fixed. Now shutting down the Derby engine upon disconnect, setting
derby.database.forceDatabaseLock=true and displaying the whole chain of SQL
exceptions upon connect.

Checking in src/org/netbeans/modules/db/explorer/DatabaseConnection.java;
/cvs/db/src/org/netbeans/modules/db/explorer/DatabaseConnection.java,v  <-- 
DatabaseConnection.java
new revision: 1.43; previous revision: 1.42
done
Checking in src/org/netbeans/modules/db/explorer/DbDriverManager.java;
/cvs/db/src/org/netbeans/modules/db/explorer/DbDriverManager.java,v  <-- 
DbDriverManager.java
new revision: 1.2; previous revision: 1.1
done
RCS file:
/cvs/db/src/org/netbeans/modules/db/explorer/DerbyConectionEventListener.java,v
done
Checking in src/org/netbeans/modules/db/explorer/DerbyConectionEventListener.java;
/cvs/db/src/org/netbeans/modules/db/explorer/DerbyConectionEventListener.java,v
 <--  DerbyConectionEventListener.java
initial revision: 1.1
done
Checking in src/org/netbeans/modules/db/explorer/actions/ConnectAction.java;
/cvs/db/src/org/netbeans/modules/db/explorer/actions/ConnectAction.java,v  <-- 
ConnectAction.java
new revision: 1.38; previous revision: 1.37
done
Checking in src/org/netbeans/modules/db/explorer/infos/ConnectionNodeInfo.java;
/cvs/db/src/org/netbeans/modules/db/explorer/infos/ConnectionNodeInfo.java,v 
<--  ConnectionNodeInfo.java
new revision: 1.41; previous revision: 1.40
done
Checking in test/unit/src/org/netbeans/modules/db/explorer/DbDriverManagerTest.java;
/cvs/db/test/unit/src/org/netbeans/modules/db/explorer/DbDriverManagerTest.java,v
 <--  DbDriverManagerTest.java
new revision: 1.2; previous revision: 1.1
done
Comment 11 Martin Schovanek 2005-11-21 11:18:29 UTC
VERIFIED