Comments (7)
I further investigated the problem. I noticed that problem vanishes as soon as I don't fetch a collection in one of the subclasses. So I can successfully read a User (see example) but not a UserGroup containing a list of users.
See my schema example:
Schema.zip
Again I'm not sure whether my annotations are right? To provide a running testcase requires more time. I could prepare something tomorrow, if you need it.
StackTrace:
Caused by: java.lang.NullPointerException
at org.datanucleus.store.mongodb.MongoDBUtils.getClassNameForIdentity(MongoDBUtils.java:199)
at org.datanucleus.store.mongodb.MongoDBStoreManager.getClassNameForObjectID(MongoDBStoreManager.java:132)
at org.datanucleus.ExecutionContextImpl.getClassNameForObjectId(ExecutionContextImpl.java:3503)
at org.datanucleus.ExecutionContextImpl.getClassDetailsForId(ExecutionContextImpl.java:3392)
at org.datanucleus.ExecutionContextImpl.findObject(ExecutionContextImpl.java:3568)
at org.datanucleus.identity.IdentityUtils.getObjectFromIdString(IdentityUtils.java:442)
at org.datanucleus.store.mongodb.fieldmanager.FetchFieldManager.getValueForContainerRelationField(FetchFieldManager.java:970)
at org.datanucleus.store.mongodb.fieldmanager.FetchFieldManager.fetchNonEmbeddedObjectField(FetchFieldManager.java:737)
at org.datanucleus.store.mongodb.fieldmanager.FetchFieldManager.fetchObjectField(FetchFieldManager.java:685)
at org.datanucleus.state.AbstractStateManager.replacingObjectField(AbstractStateManager.java:1588)
at org.datanucleus.state.StateManagerImpl.replacingObjectField(StateManagerImpl.java:1)
at de.mpg.ipp.codac.business.schema.teamwork.UserGroup.dnReplaceField(UserGroup.java)
at de.mpg.ipp.codac.business.schema.common.W7XDbNamedObject.dnReplaceFields(W7XDbNamedObject.java)
at org.datanucleus.state.StateManagerImpl.replaceFields(StateManagerImpl.java:3115)
at org.datanucleus.state.StateManagerImpl.replaceFields(StateManagerImpl.java:3141)
at org.datanucleus.store.mongodb.MongoDBUtils$1.fetchFields(MongoDBUtils.java:761)
at org.datanucleus.state.StateManagerImpl.loadFieldValues(StateManagerImpl.java:2245)
at org.datanucleus.state.StateManagerImpl.initialiseForHollow(StateManagerImpl.java:262)
at org.datanucleus.state.ObjectProviderFactoryImpl.newForHollow(ObjectProviderFactoryImpl.java:112)
at org.datanucleus.ExecutionContextImpl.findObject(ExecutionContextImpl.java:3098)
at org.datanucleus.store.mongodb.MongoDBUtils.getObjectUsingApplicationIdForDBObject(MongoDBUtils.java:756)
at org.datanucleus.store.mongodb.MongoDBUtils.getPojoForDBObjectForCandidate(MongoDBUtils.java:718)
at org.datanucleus.store.mongodb.query.LazyLoadQueryResult.getNextObject(LazyLoadQueryResult.java:324)
at org.datanucleus.store.mongodb.query.LazyLoadQueryResult$QueryResultIterator.next(LazyLoadQueryResult.java:449)
at de.mpg.ipp.codac.persistence.DataNucleusProvider.doGetObjects(DataNucleusProvider.java:293)
... 31 more
from datanucleus-mongodb.
As the documentation says clearly enough, and the issue template, a valid testcase is required for ALL problems. Failure to provide will will mean the issue is closed.
from datanucleus-mongodb.
Closing since no testcase. Attach a testcase here and it can be reopened
from datanucleus-mongodb.
Please reopen this issue, because this must be a big problem for everyone working with MongoDB and an abstract root class. I don't understand enough of the concepts of the StoreManager and StoreData to fix the problem by myself.
I commented the problems in the code for you (please scroll to see all comments) :
String org.datanucleus.store.mongodb.MongoDBUtils.getClassNameForIdentity(Object id, AbstractClassMetaData rootCmd, ExecutionContext ec, ClassLoaderResolver clr)
{
Map<String, Set<String>> classNamesByDbCollectionName = new HashMap<>();
StoreManager storeMgr = ec.getStoreManager();
Set rootClassNames = new HashSet<String>();
rootClassNames.add(rootCmd.getFullClassName());
StoreData storeData = storeMgr.getStoreDataForClass(rootCmd.getFullClassName()); //comment: since my root class is abstract there is no entry in the table storeDataMgr.storeDataByClass, so storeData is null
Table rootTable = null;
String rootTableName = "";
if (storeData != null)
{
rootTable = storeData.getTable();
rootTableName = rootTable.getName();
}
else
{
// how to access the rootTable via name?
rootTableName = rootCmd.getTable(); //comment: since storeData is null, rootTable is also null
}
classNamesByDbCollectionName.put(rootTableName, rootClassNames);
Collection<String> subclassNames = storeMgr.getSubClassesForClass(rootCmd.getFullClassName(), true, clr);
if (subclassNames != null && !subclassNames.isEmpty())
{
for (String subclassName : subclassNames)
{
AbstractClassMetaData cmd = ec.getMetaDataManager().getMetaDataForClass(subclassName, clr);
StoreData subStoreData = storeMgr.getStoreDataForClass(cmd.getFullClassName());
Table subTable = null;
String subTableName = "";
if (subStoreData != null)
{
subTable = subStoreData.getTable();
subTableName = subTable.getName();
}
else
{
// how to access the subTable via name?
subTableName = cmd.getTable();
}
// Table subTable = storeMgr.getStoreDataForClass(cmd.getFullClassName()).getTable();
// String subTableName = subTable.getName();
Set<String> classNames = classNamesByDbCollectionName.get(subTableName);
if (classNames == null)
{
classNames = new HashSet<String>();
classNamesByDbCollectionName.put(subTableName, classNames);
}
classNames.add(cmd.getFullClassName());
}
}
ManagedConnection mconn = storeMgr.getConnection(ec);
try
{
DB db = (DB) mconn.getConnection();
for (Map.Entry<String, Set<String>> dbCollEntry : classNamesByDbCollectionName.entrySet())
{
// Check each DBCollection for the id PK field(s)
String dbCollName = dbCollEntry.getKey();
if (dbCollName == null) continue; //comment: I added this. For some reason this is null for some classes, so I have to continue to prevent an NPE
Set<String> classNames = dbCollEntry.getValue();
DBCollection dbColl = db.getCollection(dbCollName);
BasicDBObject query = new BasicDBObject();
if (rootCmd.getIdentityType() == IdentityType.DATASTORE)
{
Object key = IdentityUtils.getTargetKeyForDatastoreIdentity(id);
if (storeMgr.isStrategyDatastoreAttributed(rootCmd, -1))
{
query.put("_id", new ObjectId((String) key));
}
else
{
query.put(rootTable.getDatastoreIdColumn().getName(), key);
}
}
else if (rootCmd.getIdentityType() == IdentityType.APPLICATION)
{
if (IdentityUtils.isSingleFieldIdentity(id))
{
Object key = IdentityUtils.getTargetKeyForSingleFieldIdentity(id);
int[] pkNums = rootCmd.getPKMemberPositions();
AbstractMemberMetaData pkMmd = rootCmd.getMetaDataForManagedMemberAtAbsolutePosition(pkNums[0]);
String pkPropName = rootTable.getMemberColumnMappingForMember(pkMmd).getColumn(0).getName(); //comment: since rootTable is null, this leads to an NPE
query.put(pkPropName, key);
}
else
{
int[] pkNums = rootCmd.getPKMemberPositions();
for (int i = 0; i < pkNums.length; i++)
{
AbstractMemberMetaData pkMmd = rootCmd.getMetaDataForManagedMemberAtAbsolutePosition(pkNums[i]);
String pkPropName = rootTable.getMemberColumnMappingForMember(pkMmd).getColumn(0).getName();
Object pkVal = IdentityUtils.getValueForMemberInId(id, pkMmd);
query.put(pkPropName, pkVal);
}
}
}
from datanucleus-mongodb.
Added schema and unit tests (needs little modification for connection to your local MongoDB test database):
schema.zip
DN5UnitTest.zip
I'm working with MongoDB 2.4 and the master repository for DataNucleus sources.
from datanucleus-mongodb.
Sorry, but no the DN test suite has abstract root classes and the DN test suite is run before releases, and it works great for me. The onus is on the raiser to demonstrate the problem. Just dumping some class here isn't a demonstration. As the issue template says clearly enough, we provide you with a template for testcases to minimise how much you need to do to reproduce things, and then just type "mvn clean test" and it runs. Here it is again
https://github.com/datanucleus/test-jdo
And when I dump your classes into this template I get the attached "test.zip". I run it. It passes.
If you want something reopened you kindly take this and UPDATE it and repost it here with something that reproduces a problem. Some persistable class not being known about implies metadata is not loaded for it at the time you invoke some operation, and only you know how you create your PMF (persistence-unit?, properties file? using auto-start? etc etc).
from datanucleus-mongodb.
Thank you! Your commit fixed the problem.
I didn't recognize that there is a template for testcases. Sorry! Next time I'll provide a testcase using the template.
from datanucleus-mongodb.
Related Issues (20)
- Load of query doesnt ensure that all SCOs are wrapped
- Detect attempt to add index on "_id" field
- Upgrade to v4.x of the MongoDB sync driver, support "MongoDatabase" rather than "DB"
- Check for schema existence of a class is unoptimised and should check for StoreData
- Support core-233
- Add support for "authentication database" HOT 4
- Incongruent exception on primary expressions HOT 2
- Support for ordering using unknown/invalid fields
- Resolution of inherited attributes broken if class is marked as non-cacheable HOT 8
- SSL support for mongo? HOT 1
- Support various other MongoClient properties
- Build against Mongo Java Driver v3.8.0
- Support nested embedded collection
- Support for specifying the MongoDB replica set
- Support use of @Converter on String field HOT 3
- mongodb-driver-core incompatible version downloaded from maven with mongodb-driver in datanucleus-mongodb pom.xml HOT 2
- Mongodb Authentication Database HOT 4
- Load of object doesnt check for tenantId when running multitenancy
- Move to mongodb-driver-legacy v4.3.1 HOT 1
- Add support for SoftDelete so that a delete just sets the flag rather than deleting
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from datanucleus-mongodb.