Issue Details (XML | Word | Printable)

Key: NUCCORE-1234
Type: Bug Bug
Status: Open Open
Priority: Testcase Required Testcase Required
Assignee: Unassigned
Reporter: Hooman Valibeigi
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
DataNucleus Core

OSGI incompliant class loading issue in MetaDataManager

Created: 05/Jul/14 03:14 PM   Updated: 17/Aug/14 04:18 PM
Component/s: MetaData
Affects Version/s: 3.2.13
Fix Version/s: None

Environment: karaf

Datastore: PostgreSQL
Severity: Development


 Description  « Hide
line 2073 of class MetaDataManager

> Class cls = referenceClass.getClassLoader().loadClass(class_name);

This line is causing the following exception in my app. The exception gives no hint as what the actual problem is.

Caused by: org.datanucleus.exceptions.NucleusException: Attempt to create PersistentIDROF with null mappingDefinition
        at org.datanucleus.store.rdbms.query.PersistentClassROF.<init>(PersistentClassROF.java:107)
        at org.datanucleus.store.rdbms.RDBMSStoreManager.newResultObjectFactory(RDBMSStoreManager.java:3837)
        at org.datanucleus.store.rdbms.scostore.MapKeySetStore.iterator(MapKeySetStore.java:269)
        at org.datanucleus.store.types.SCOUtils.populateMapDelegateWithStoreData(SCOUtils.java:934)[79:org.datanucleus:3.2.13]
        at org.datanucleus.store.types.backed.Map.loadFromStore(Map.java:308)[79:org.datanucleus:3.2.13]
        at org.datanucleus.store.types.backed.Map.initialise(Map.java:255)[79:org.datanucleus:3.2.13]
        at org.datanucleus.store.types.SCOUtils.createSCOWrapper(SCOUtils.java:256)[79:org.datanucleus:3.2.13]
        at org.datanucleus.store.types.SCOUtils.newSCOInstance(SCOUtils.java:142)[79:org.datanucleus:3.2.13]
        at org.datanucleus.store.rdbms.mapping.java.AbstractContainerMapping.replaceFieldWithWrapper(AbstractContainerMapping.java:399)
        at org.datanucleus.store.rdbms.mapping.java.AbstractContainerMapping.postFetch(AbstractContainerMapping.java:417)
        at org.datanucleus.store.rdbms.request.FetchRequest.execute(FetchRequest.java:420)
        at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.fetchObject(RDBMSPersistenceHandler.java:324)
        at org.datanucleus.state.AbstractStateManager.loadFieldsFromDatastore(AbstractStateManager.java:1122)
        at org.datanucleus.state.JDOStateManager.loadUnloadedFieldsInFetchPlan(JDOStateManager.java:3000)
        at org.datanucleus.state.JDOStateManager.isLoaded(JDOStateManager.java:3214)


I have split persistent capable classes into 2 separate osgi bundles.
One includes only the interfaces with no jdo annotations.
The other contains impl classes and I have annotated persistent fields correctly using
@Extension(vendorName = "datanucleus", key = "implementation-classes", bla bla bla
and
@Extension(vendorName = "datanucleus", key = "key-implementation-classes", bla bla bla

One of these classes has a java.util.Map field with a persistent capable key type.
When I try to fetch an object of that type the above exception occurs.
I did not have any problem with fields of other types like Set.

After lots of investigation I found a possible bug at line 2073 of class MetaDataManager
This way of class loading is not osgi friendly.

Sort Order: Ascending order - Click to sort in descending order
Andy Jefferson added a comment - 05/Jul/14 08:38 PM
Suggest you download the code (from GitHub, single command to do that), update the class in question to get it working, and then build it (mvn clean install). Then test it, and contribute a Git Pull request, or patch

Hooman Valibeigi added a comment - 06/Jul/14 12:04 PM - edited
Here's a testcase for this issue: https://bitbucket.org/hoomanv/nuccore-1234

I think the fix would be to use the primary ClassLoader (PropertyNames.PROPERTY_CLASSLOADER_PRIMARY)

Andy Jefferson added a comment - 08/Jul/14 02:52 PM
you can easily enough try just that (or the "clr" argument passed in) and let everyone know if that works for you

Hooman Valibeigi added a comment - 08/Jul/14 05:05 PM
We found a workaround for this.
The trick is to make impl-bundle's classes visible to the api-bundle's classloader.
That is achieved by adding the necessary impl packages to the Import-Package section of the api-bundle's MANIFEST.MF and keep their resolution optional (resolution:=optional)
This way the interface's classloader will be able to load the impl classes.
I have tested this and it gets rid of the exception I mentioned above.

This is just a workaround, the real fix would be to use a proper classloader.