class PojoWithObject { @Id String keyProperty; private Object objectProperty; }
As the type information of objectProperty is not known at compile time, I expect that the concrete class is also stored in the DB for later deserialization (as it is done when only declaring an Interface).
This works fine when persisting and loading PojoWithObject where objectProperty is instantiated as follow:
1.) success
objectProperty = new ComplexValue("abc", 1);
where
class ComplexValue {
private String valueA;
private int valueB;
}
The resulting JSON in the DB looks as expected:
{ "_id" : "anyId", "objectProperty" : { "className" : "com.XXX.persistence.mongo.integration.model.pojo.model.ComplexValue", "valueA" : "abc", "valueB" :1 } }
2.) success
Similar to a custom defined object (ComplexValue), it also works for an ArrayList of Strings
objectProperty = new ArrayList<>(Arrays.asList("abc", "def"));
The resulting JSON in the DB looks as expected:
{ "_id" : "anyId", "objectProperty" : { "className" : "java.util.ArrayList", "elementData" : ["abc", "def"], "size" : 2, "modCount" : 0 } }
3.) failure
When using simple objects, e.g. String or Integer, no class information is stored.
objectProperty = "abc";
-->
{
"_id" : "anyId",
"objectProperty" : "abc"
}
which subsequently results in a ClassCastException when loading the entity:
java.lang.RuntimeException: java.lang.ClassCastException: java.lang.String cannot be cast to com.mongodb.DBObject at org.mongodb.morphia.mapping.EmbeddedMapper.fromDBObject(EmbeddedMapper.java:173) at org.mongodb.morphia.mapping.Mapper.readMappedField(Mapper.java:642) at org.mongodb.morphia.mapping.Mapper.fromDb(Mapper.java:617) at org.mongodb.morphia.mapping.Mapper.fromDBObject(Mapper.java:310) at org.mongodb.morphia.query.MorphiaIterator.convertItem(MorphiaIterator.java:87) at org.mongodb.morphia.query.MorphiaIterator.processItem(MorphiaIterator.java:73) at org.mongodb.morphia.query.MorphiaIterator.next(MorphiaIterator.java:68) at org.mongodb.morphia.query.QueryImpl.get(QueryImpl.java:421) at org.mongodb.morphia.DatastoreImpl.get(DatastoreImpl.java:739) [...] Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to com.mongodb.DBObject at org.mongodb.morphia.mapping.EmbeddedMapper.fromDBObject(EmbeddedMapper.java:162) ... 49 more
4.) failure
When using not an ArrayList<String>, but a LinkedList<String>
objectProperty = new LinkedList<>(Arrays.asList("abc", "def"));
the following exception occurs on writing:
org.mongodb.morphia.mapping.MappingException: Error mapping field:com.XXX.persistence.mongo.integration.model.pojo.PojoWithObject.objectProperty at org.mongodb.morphia.mapping.Mapper.toDBObject(Mapper.java:578) at org.mongodb.morphia.mapping.Mapper.toDBObject(Mapper.java:558) at org.mongodb.morphia.DatastoreImpl.entityToDBObj(DatastoreImpl.java:949) at org.mongodb.morphia.DatastoreImpl.save(DatastoreImpl.java:996) at org.mongodb.morphia.DatastoreImpl.save(DatastoreImpl.java:1080) at org.mongodb.morphia.DatastoreImpl.save(DatastoreImpl.java:1063) [...] Caused by: org.mongodb.morphia.mapping.MappingException: A type could not be found for the field null.null at org.mongodb.morphia.mapping.MappedField.discoverType(MappedField.java:211) at org.mongodb.morphia.mapping.MappedField.<init>(MappedField.java:101) at org.mongodb.morphia.mapping.EphemeralMappedField.<init>(EphemeralMappedField.java:36) at org.mongodb.morphia.mapping.MappedField.discoverType(MappedField.java:189) at org.mongodb.morphia.mapping.MappedField.discover(MappedField.java:117) at org.mongodb.morphia.mapping.MappedField.<init>(MappedField.java:95) at org.mongodb.morphia.mapping.MappedClass.discover(MappedClass.java:217) at org.mongodb.morphia.mapping.MappedClass.<init>(MappedClass.java:145) at org.mongodb.morphia.mapping.Mapper.getMappedClass(Mapper.java:242) at org.mongodb.morphia.mapping.Mapper.toDBObject(Mapper.java:564) at org.mongodb.morphia.mapping.Mapper.toDBObject(Mapper.java:558) at org.mongodb.morphia.mapping.EmbeddedMapper.toDBObject(EmbeddedMapper.java:38) at org.mongodb.morphia.mapping.Mapper.writeMappedField(Mapper.java:668) at org.mongodb.morphia.mapping.Mapper.toDBObject(Mapper.java:576) ... 48 more
5.) failure
When using an ArrayList of a custom type
objectProperty = new ArrayList<>(Arrays.asList(new ComplexValue("abc", 1), new ComplexValue("def", 2)));
the following exception occurs on writing:
org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class com.XXX.persistence.mongo.integration.model.pojo.model.ComplexValue. at org.bson.codecs.configuration.CodecCache.getOrThrow(CodecCache.java:46) at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:63) at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:37) at com.mongodb.DBObjectCodec.writeValue(DBObjectCodec.java:210) at com.mongodb.DBObjectCodec.encodeIterable(DBObjectCodec.java:269) at com.mongodb.DBObjectCodec.writeValue(DBObjectCodec.java:198) at com.mongodb.DBObjectCodec.encodeMap(DBObjectCodec.java:220) at com.mongodb.DBObjectCodec.writeValue(DBObjectCodec.java:196) at com.mongodb.DBObjectCodec.encode(DBObjectCodec.java:128) at com.mongodb.DBObjectCodec.encode(DBObjectCodec.java:61) at com.mongodb.CompoundDBObjectCodec.encode(CompoundDBObjectCodec.java:48) at com.mongodb.CompoundDBObjectCodec.encode(CompoundDBObjectCodec.java:27) at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63) at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29) at com.mongodb.connection.RequestMessage.addDocument(RequestMessage.java:216) at com.mongodb.connection.RequestMessage.addCollectibleDocument(RequestMessage.java:182) at com.mongodb.connection.UpdateMessage.encodeMessageBody(UpdateMessage.java:66) at com.mongodb.connection.RequestMessage.encode(RequestMessage.java:132) at com.mongodb.connection.WriteProtocol.sendMessage(WriteProtocol.java:107) at com.mongodb.connection.WriteProtocol.execute(WriteProtocol.java:59) at com.mongodb.connection.UpdateProtocol.execute(UpdateProtocol.java:61) at com.mongodb.connection.UpdateProtocol.execute(UpdateProtocol.java:36) at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:155) at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:219) at com.mongodb.connection.DefaultServerConnection.update(DefaultServerConnection.java:84) at com.mongodb.operation.UpdateOperation.executeProtocol(UpdateOperation.java:66) at com.mongodb.operation.BaseWriteOperation$1.call(BaseWriteOperation.java:113) at com.mongodb.operation.BaseWriteOperation$1.call(BaseWriteOperation.java:106) at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:186) at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:177) at com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:106) at com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:58) at com.mongodb.Mongo.execute(Mongo.java:747) at com.mongodb.Mongo$2.execute(Mongo.java:730) at com.mongodb.DBCollection.executeWriteOperation(DBCollection.java:327) at com.mongodb.DBCollection.replaceOrInsert(DBCollection.java:405) at com.mongodb.DBCollection.save(DBCollection.java:394) at org.mongodb.morphia.DatastoreImpl.save(DatastoreImpl.java:1006) at org.mongodb.morphia.DatastoreImpl.save(DatastoreImpl.java:1080) at org.mongodb.morphia.DatastoreImpl.save(DatastoreImpl.java:1063) [...]
How to deal with such Pojos? Are these already known issues which will be fixed in the next releases?