Re: Classloading issue with Berkley DB
Will, This is the intend reply. I use both Ingres and PostgreSQL databases in my applications and use the JDBC api to interact with the database. To do this, I created in IngresDataSourceFactory that implements org.osgi.service.jdbc.DataSourceFactory.DataSourceFactory bundle so my application bundles just @Reference Datasource. I also loaded the Ingres JDBC driver as a wrapped jar, `bundle:install wrap:mvn:` Karaf/OSGi and configuration take care of the rest after the datasource is in Karaf is created. See the following. https://karaf.apache.org/manual/latest/#_creating_bundles_for_non_osgi_third_party_dependencies https://karaf.apache.org/manual/latest/#_datasources_jdbc Paul Spencer
Classloading issue with Berkley DB
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.(DatabaseImpl.java:2002) at com.sleepycat.je.dbi.DatabaseImpl.initWithEnvironment(DatabaseImpl.java:390) at com.sleepycat.je.dbi.DatabaseImpl.(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.(BDBQueue.java:88) at com.qpoint.caterwaul.connect.queue.BDBQueue.(BDBQueue.java:52) at com.qpoint.caterwaul.connect.queue.RichBDBQueue.(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
Classloading issue with Berkley DB
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.(DatabaseImpl.java:2002) at com.sleepycat.je.dbi.DatabaseImpl.initWithEnvironment(DatabaseImpl.java:390) at com.sleepycat.je.dbi.DatabaseImpl.(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.(BDBQueue.java:88) at com.qpoint.caterwaul.connect.queue.BDBQueue.(BDBQueue.java:52) at com.qpoint.caterwaul.connect.queue.RichBDBQueue.(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