We're using BerkelyDB within our application.

I did not look too hard for an OSGI module for it, it wasn't readily apparent, 
so I just hamfisted one by taking their jar and using bnd to create a bundle 
from it.

But there's a curious issue.

We have code like this:

        final DatabaseConfig dbConfig = new DatabaseConfig();
        dbConfig.setTransactional(false);
        dbConfig.setAllowCreate(allowCreate);
        dbConfig.setReadOnly(readOnly);
        dbConfig.setDeferredWrite(true);
        dbConfig.setBtreeComparator(new KeyComparator());

But when I call this:

        this.queueDatabase = dbEnv.openDatabase(null, queueName, dbConfig);

I get a Class Not Found exception. It can not find the KeyComparator class 
(which is a local class to this class that's starting the DB).

Well, it seems from a glance at the stack trace, that the BDB is serializing 
the comparator, and trying to read it back.

Caused by: com.sleepycat.je.EnvironmentFailureException: (JE 18.3.12) Exception 
while trying to load BtreeComparator UNEXPECTED_EXCEPTION: Unexpected internal 
Exception, may have side effects.
at 
com.sleepycat.je.EnvironmentFailureException.unexpectedException(EnvironmentFailureException.java:384)
at com.sleepycat.je.dbi.DatabaseImpl.bytesToObject(DatabaseImpl.java:1957)
at 
com.sleepycat.je.dbi.DatabaseImpl$ComparatorReader.<init>(DatabaseImpl.java:2002)
at com.sleepycat.je.dbi.DatabaseImpl.initWithEnvironment(DatabaseImpl.java:390)
at com.sleepycat.je.dbi.DatabaseImpl.<init>(DatabaseImpl.java:247)
at com.sleepycat.je.dbi.DbTree.doCreateDb(DbTree.java:593)
at com.sleepycat.je.dbi.DbTree.createDb(DbTree.java:486)
at com.sleepycat.je.Database.initNew(Database.java:174)
at com.sleepycat.je.Environment.setupDatabase(Environment.java:864)
at com.sleepycat.je.Environment.openDatabase(Environment.java:668)
at com.qpoint.caterwaul.connect.queue.BDBQueue.<init>(BDBQueue.java:88)
at com.qpoint.caterwaul.connect.queue.BDBQueue.<init>(BDBQueue.java:52)
at com.qpoint.caterwaul.connect.queue.RichBDBQueue.<init>(RichBDBQueue.java:49)
at 
com.qpoint.caterwaul.connect.queue.TickEventOrchestrator.start(TickEventOrchestrator.java:87)
at com.qpoint.caterwaul.connect.core.CWCore.initialize(CWCore.java:168)
... 9 more
Caused by: java.lang.ClassNotFoundException: 
com.qpoint.caterwaul.connect.queue.KeyComparator
at 
java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at 
java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:488)
at java.base/java.lang.Class.forName(Class.java:467)
at com.sleepycat.util.ClassResolver$Stream.resolveClass(ClassResolver.java:74)
at 
java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2058)
at 
java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1922)
at 
java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2248)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1757)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:538)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:496)
at com.sleepycat.je.dbi.DatabaseImpl.bytesToObject(DatabaseImpl.java:1954)
... 22 more

We see that it's calling the ObjectInputStream readObject. Which means it 
serialized the KeyComparator instance somewhere.

Now, I can't fathom why this is happening, seems an odd decision, but it's 
clear to me that it's trying to do this from within the BDB bundle, and ITS 
classloader, rather than the bundle classloader where it's being initialized. 
That would explain why it can't find the class.

So, do I need to somehow tweak the BDB bundle to import the KeyComparator 
class? Won't this be a circular dependency (my module depends on BDB which 
depends on my module), unless, of course, I break out my KeyComparator class 
into -- I don't know what I would break it into, seems a bit much to make it 
its own bundle.

While the solution would be appreciated, how are problems like this approached? 
I imagine there's rules of thumb or a top 5 "do this kind of thing" that is 
used to approach classpath issues with OSGI and Karaf.

Thanks so much.

Regards,

Will Hartung

Reply via email to