user1145925
user1145925

Reputation: 1051

Mongo java driver says top level classes with generic types are not supported by PojoCodec

I am trying to use the MongoDB Reactive Streams Java Driver 1.11, moving off https://jongo.org/. It seems to be using https://mongodb.github.io/mongo-java-driver/3.10/. I have a bunch of other registered classes that are working fine. I have looked at Mongodb java: Perist POJO class with generic field, but I do not have the option of migrating all my data to remove the fields with generics. I also don't understand why I'm even seeing this error, since the MultiVal is not even a top level POJO; it's embedded in AbstractBigObject. Any help would be appreciated.

Below is the error I am seeing.

org.bson.codecs.configuration.CodecConfigurationException: Failed to decode 'BigObject'. Decoding 'nameToMultiDateVal' errored with: MultipleVal contains generic types that have not been specialised. Top level classes with generic types are not supported by the PojoCodec.

Below are some of my relevant data models:

public abstract class AbstractBigObject {
    @BsonProperty 
    private Map<String, MultiVal<LocalDate>> nameToMultiDateVal = Maps.newHashMap();
    @BsonProperty 
    private Map<String, MultiVal<Double>> nameToMultiDoubleVal = Maps.newHashMap();

    ...
}

public class BigObject extends AbstractBigObject {
    ...
}

public class MultiVal<T> {
    private List<Val<T>> options;
    private Val<T> selected;
    ...
}

@BsonDiscriminator(key = "type")
public interface Val<T> {
    ...
}

@BsonDiscriminator(key = "type", value = "dateVal")
public class DateVal implements Val<LocalDate> {
    ...
}

@BsonDiscriminator(key = "type", value = "doubleVal")
public class DoubleVal implements Val<Double> {
    ...
}

Below is how I'm setting up my codec registry.

MongoClient mongoClient = MongoClients.create(new ConnectionString(mongoConfig.getUri()));
PojoCodecProvider pojoCodecProvider = PojoCodecProvider.builder()
    .conventions(ImmutableList.of(CLASS_AND_PROPERTY_CONVENTION, ANNOTATION_CONVENTION))
    .register(
        BigObject.class,
        AbstractBigObject.class,
        MultiVal.class)
    .register(
        ClassModel.builder(Val.class).enableDiscriminator(true).build(),
        ClassModel.builder(DoubleVal.class).enableDiscriminator(true).build(),
        ClassModel.builder(DateVal.class).enableDiscriminator(true).build())
    .automatic(true)
    .build();
CodecRegistry codecRegistry = CodecRegistries.fromRegistries(
    MongoClientSettings.getDefaultCodecRegistry(),
    CodecRegistries.fromProviders(pojoCodecProvider));
mongoDb = mongoClient.getDatabase(mongoConfig.getDbName()).withCodecRegistry(codecRegistry);

So I am storing lots of BigObject in a Mongo collection. But they are unable to be decoded for the above reason. Short of changing all my data models, what else can I do? Is there any way I can specify the relevant codec(s) myself?

Upvotes: 3

Views: 2300

Answers (1)

bur&#230;quete
bur&#230;quete

Reputation: 14688

Can you try to wrap your generic types with concrete types and try again?

class DoubleMultiVal extends MultiVal<Double> {
}

class LocalDateMultiVal extends MultiVal<LocalDate> {
}

and use them in AbstractBigObject;

@BsonProperty 
private Map<String, LocalDateMultiVal> nameToMultiDateVal = Maps.newHashMap();
@BsonProperty 
private Map<String, DoubleMultiVal> nameToMultiDoubleVal = Maps.newHashMap();

Upvotes: 2

Related Questions