Re: Classloading issue with Berkley DB

2024-03-18 Thread Paul Spencer
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

2024-03-18 Thread Paul Spencer
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

2024-03-18 Thread Will Hartung
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