-
Type: Bug
-
Resolution: Works as Designed
-
Priority: Major - P3
-
None
-
Affects Version/s: 3.12.2
-
Component/s: POJO
-
None
-
Environment:Java 8, Mongodb server 3.6, mongodb-driver-sync 3.12.2
When polymorphic classes are used with @BsonDiscriminator, attempts to read/deserialize POJOs that return polymorhpic results (any of the derived classes may be returned) will fail, unless you do one of two things:
- Register every class explicitly (not just the package)
- Use a concrete instead of every derived class before attempting to read it.
The suggestion initially given by mongodb support (reading from Collection<DerivedClass> instead of Collection<BaseClass> is not workable, because you cannot read a list of mixed types e.g.
MongoCursor<MessageBase> cursor = msgs.find().iterator();
while (cursor.hasNext()) { ... }
{{}}
The issue seems to be that simply registering the package as prescribed
CodecProvider pojoCodecProvider = PojoCodecProvider.builder().register(myPackage).build();
CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), CodecRegistries.fromProviders(pojoCodecProvider));
mongoClient = MongoClients.create(MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(mongodbURI))
.codecRegistry(pojoCodecRegistry).build());
collection = mongoClient.getDatabase(mongodbDatabase).getCollection(mongodbCollection, entityClass);
{{}}
is not enough. Attempting to read from the database results in the following error:
ERROR: An exception occurred when decoding using the AutomaticPojoCodec.
Decoding into a 'Derived1' failed with the following exception:
Failed to decode 'Derived1'. Decoding errored with: A class could not be found for the discriminator: 'derived1'.
A custom Codec or PojoCodec may need to be explicitly configured and registered to handle this type.
Polymorphism does work if concrete classes are first utilized before an attempt is made to read polymorphically. Please see the attached "scratch.zip" example which is built using maven. It is a CLI with three commands:
- clear: clear the table
- write: write two objects to table, then read them back polymorphically
- read: read objects polymorphically
When you run this, you'll see that the write command works as expected, returning a polymorphic list, but the read command fails if that is the first command run in a process. The only difference is that the write command first inserts Derived1 and Dervied2 before reading them back. Clearly, it must somehow convince the POJO codec to believe that the derived classes all exist before it can read them.
Changing the codec registration to
CodecProvider pojoCodecProvider = PojoCodecProvider.builder().register(Base.class, Derived1.class, Derived2.class).build(); CodecProvider pojoCodecProvider = PojoCodecProvider.builder().register(Base.class, Derived1.class, Derived2.class).build();
Works as expected.
- related to
-
JAVA-3707 Support package scanning for Discriminators
- Backlog