Problems when persisting pojos with propertiets of delcared type "java.lang.Object"

486 views
Skip to first unread message

Tom

unread,
Nov 2, 2015, 9:49:52 AM11/2/15
to Morphia
Hey,

Morphia 1.0.1 does not reliably persist Pojos which declares a property of type java.lang.Object, e.g.:

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?

Reply all
Reply to author
Forward
0 new messages