Class loading problem with private packages in OSGi environment

#1

Our Business Objects are the JPA entities. We develop our product domain driven. This means we have several domains. Each domain is split into business layer and persistence layer (others are not relevant here). Per domain and per layer, we have an OSGI bundles. The business layer should have no dependency down (an exception is the dependency to the ObjectDB for the enhanced entities).  The persistence Layers have a dependency to the business layer and to the central DataAccess Layer. The Central DataAccess Layer has a dependency on JPA & ObjectDB and to all domains, because there are the entities. (more details see http://www.objectdb.com/database/forum/891)
So far everything well.

But now we have in the Business Layer private packages that are not exported.
The entities implement interfaces from these private packages.

If ObjectDB now want to load such entity tries ObjectDB also load the private interface. Why is this necessary, is not clear to us.

Correct way would ObjectDB use the classloader of the bundle of the entity. And not his own.
The change of the context class loader is no option, since there are several bundles with entities.

 

We have found a solution with which we can work around the problem. This solution, we do not like, because it feels like a hack.
We have modified the ObjectDB bundle with "Eclipse-Buddy classloading".
“Eclipse-BuddyPolicy: dependent, global”
dependent: Allows access to all packages (also private) of a bundle which itself has a dependency on the ObjectDB bundle.
global: Allows access to all public packages of all bundles. This can be realized with a dependency of ObjectDB to the entity bundles. (It is therefore not necessary.)

Creating a small example would be possible. But we want to avoid as long as it is not necessary.

 

What would be a good solution to this problem?
Can you adapt or expand ObjectDB so that we do not need to make changes.

Important for us is that we find a solution that always works in the future.

#2

> If ObjectDB now want to load such entity tries ObjectDB also load the private interface. Why is this necessary, is not clear to us.

The ObjectDB type manager loads all the interfaces in order to support persistent interfaces, a feature of JDO that is not supported by JPA. We can check if this could be disabled by a configuration parameter.

> Correct way would ObjectDB use the classloader of the bundle of the entity. And not his own.

ObjectDB is in another bundle and can only access classes and interfaces in other bundles if they are exported. ObjectDB needs the ability to access these types directly and not just by loading the implementing classes (for the persistent interfaces feature).

> Creating a small example would be possible. But we want to avoid as long as it is not necessary.

No need. The subject is clear.

> What would be a good solution to this problem? Can you adapt or expand ObjectDB so that we do not need to make changes.

We will check the option to disable interface loading, but is this issue only related to interfaces and not for other private non exported types (such as super classes and persistent field types)?

ObjectDB Support
#3

> We will check the option to disable interface loading, but is this issue only related to interfaces and not for other private non exported types (such as super classes and persistent field types)?

That sounds good.

We have not yet the case. But we can imagine that our entities contain transient fields of the private non-exported types.
Would that a new issue with your solution?

#4

Please try build 2.6.0_03.

It should silently ignore missing implemented interfaces and field types.

ObjectDB Support
#5

Wonderful. So it's working.

Thank you for the quick update.

#6

Hello,

as already reported, this solution works in our application.
But now we can't open the database file with the ObjectDB Explorer.

Can you also customize the Explorer that it ignore missing implemented interfaces and field types?

#7

The Explorer does not need access to real types, so missing types are not expected to cause issues (also in previous versions). Could you please post a stack trace of the error (from the log file) or provide a sample database file that can be used to reproduce the exception?

ObjectDB Support
#8

Hello,

following the stack trace in the log of the database explorer.

The interface CodeArchitectureExt is a private interface of an entity class in an osgi-bundle.

 

[2015-03-06 15:52:51 #1 store]
Database 'E:\Prometheus\trunk\EPProduct\com.btc.ep.product.homedir\development\data\eppdb.odb' is opened by 6536@developer

[2015-03-06 15:52:53 #2 explorer]
[ObjectDB 2.6.0] javax.persistence.PersistenceException
Failed to generate dynamic type com.btc.ep.architecture.ccode.bl.impl.CodeArchitectureImpl (error 361)
at com.objectdb.Explorer$1.run(Explorer.java:57)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Caused by: com.objectdb.o.UserException: Failed to generate dynamic type com.btc.ep.architecture.ccode.bl.impl.CodeArchitectureImpl
at com.objectdb.o.MSG.d(MSG.java:75)
at com.objectdb.o.ACL.d(ACL.java:167)
at com.objectdb.o.STL.g(STL.java:97)
at com.objectdb.o.TYM.findClass(TYM.java:1046)
at com.objectdb.o.ACL.loadClass(ACL.java:131)
at java.lang.ClassLoader.loadClass(Unknown Source)
at com.objectdb.o.TYM.ay(TYM.java:1014)
at com.objectdb.o.UTY.initSysType(UTY.java:331)
at com.objectdb.o.TYS.l(TYS.java:166)
at com.objectdb.o.TYM.ae(TYM.java:511)
at com.objectdb.o.TYM.<init>(TYM.java:194)
at com.objectdb.o.OMF.ap(OMF.java:836)
at com.objectdb.o.OMF.ao(OMF.java:788)
at com.objectdb.jpa.EMF.ao(EMF.java:238)
at com.objectdb.o.OMF.an(OMF.java:690)
at com.objectdb.jpa.EMF.createEntityManager(EMF.java:257)
... 17 more
Caused by: java.lang.NoClassDefFoundError: com/btc/ep/architecture/ccode/bl/ext/CodeArchitectureExt
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at com.objectdb.o.ACL.d(ACL.java:155)
... 31 more
Caused by: java.lang.ClassNotFoundException: com.btc.ep.architecture.ccode.bl.ext.CodeArchitectureExt
at com.objectdb.o.TYM.findClass(TYM.java:1043)
at com.objectdb.o.ACL.loadClass(ACL.java:131)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 35 more
#9

The stack trace indicates using of ObjectDB 2.6.0. The fix was added at 2.6.0_03 (see #4 above).

Although the Explorer can handle missing types also before this fix, these missing types are limited to managed classes that can be generated by the Explorer automatically, rather than missing referenced types, so please ignore the comment on #7 above.

ObjectDB Support
#10

We have the same problem with data explorer version 2.6.1.

[2015-03-06 16:25:55 #1 store]

Database 'E:\Prometheus\trunk\EPProduct\com.btc.ep.product.homedir\development\data\eppdb.odb' is opened by 4084@developer

[2015-03-06 16:25:57 #2 explorer]
[ObjectDB 2.6.1] javax.persistence.PersistenceException
Failed to generate dynamic type com.btc.ep.architecture.ccode.bl.impl.CodeArchitectureImpl (error 361)
at com.objectdb.Explorer$1.run(Explorer.java:57)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:694)
at java.awt.EventQueue$3.run(EventQueue.java:692)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
Caused by: com.objectdb.o.UserException: Failed to generate dynamic type com.btc.ep.architecture.ccode.bl.impl.CodeArchitectureImpl
at com.objectdb.o.MSG.d(MSG.java:75)
at com.objectdb.o.ACL.d(ACL.java:167)
at com.objectdb.o.STL.g(STL.java:97)
at com.objectdb.o.TYM.findClass(TYM.java:1046)
at com.objectdb.o.ACL.loadClass(ACL.java:131)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at com.objectdb.o.TYM.ay(TYM.java:1014)
at com.objectdb.o.UTY.initSysType(UTY.java:345)
at com.objectdb.o.TYS.l(TYS.java:166)
at com.objectdb.o.TYM.ae(TYM.java:511)
at com.objectdb.o.TYM.<init>(TYM.java:194)
at com.objectdb.o.OMF.ap(OMF.java:836)
at com.objectdb.o.OMF.ao(OMF.java:788)
at com.objectdb.jpa.EMF.ao(EMF.java:238)
at com.objectdb.o.OMF.an(OMF.java:690)
at com.objectdb.jpa.EMF.createEntityManager(EMF.java:257)
... 17 more
Caused by: java.lang.NoClassDefFoundError: com/btc/ep/architecture/ccode/bl/ext/CodeArchitectureExt
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
at java.lang.ClassLoader.defineClass(ClassLoader.java:643)
at com.objectdb.o.ACL.d(ACL.java:155)
... 31 more
Caused by: java.lang.ClassNotFoundException: com.btc.ep.architecture.ccode.bl.ext.CodeArchitectureExt
at com.objectdb.o.TYM.findClass(TYM.java:1043)
at com.objectdb.o.ACL.loadClass(ACL.java:131)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
... 35 more
#11

What is the relationship between CodeArchitectureExt and CodeArchitectureImpl?

Please try to run the Explorer with a classpath that contains all your classes.

ObjectDB Support
#12

The relationship between CodeArchitectureExt and CodeArchitectureImpl is that the entity class CodeArchitectureImpl implements the private OSGi interface CodeArchitectureExt.

You have provided a fix in ObjectDB 2.6.0_03. Why can't you fix the same issue in the database explorer?

We don't want to run the database explorer with a special classpath.

#13

Please try build 2.6.1_03. Although it looks similar to the previous dependency issue (from your point of view) it is actually different code that is used by the Explorer and Server when entity classes are not available in the classpath.

ObjectDB Support

Reply