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