Tezra
Tezra

Reputation: 8833

How do I ignore getters/setters with PojoCodecProvider

I'm trying to setup a MongoCollection to return/save using a data transfer object pojo, but I can't figure out how to configure the pojo codec to ignore getters/setters.

Right now I'm getting the error

Caused by: org.bson.codecs.configuration.CodecConfigurationException: Property 'iLink' in BasicRecord, has differing data types: TypeData{type=BasicLink} and TypeData{type=ILink}

I don't control the data transfer object, and there is no "iLink" property. (the property is just "link", and the object property name, which is already "link" is used for serialization/deserialization between systems. getILink is just a generic version of getLink inherited from an ILink interface)

Here is my code to build the pojo codecs

    // Create a Codec for converting BsonDate to java.time.Instant
    final HashMap<BsonType, Class<?>> replacements = new HashMap<>();
    replacements.put(BsonType.DATE_TIME, Instant.class);
    final BsonTypeClassMap bsonTypeClassMap = new BsonTypeClassMap(replacements);
    final Codec<Document> instantCodec = new DocumentCodec(MongoClient.getDefaultCodecRegistry(), bsonTypeClassMap);

    // Create class Codec
    final CodecProvider pojoCodecProvider = PojoCodecProvider.builder().register(this.type).build();

    // Combine Codecs together into one registry
    final CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries(CodecRegistries.fromCodecs(instantCodec),
            CodecRegistries.fromProviders(pojoCodecProvider), MongoClient.getDefaultCodecRegistry());

    final MongoDatabase database = this.client.getDatabase(database_name).withCodecRegistry(pojoCodecRegistry);
    this.collection = database.getCollection(collection_name, classType);

I only need for the pojo codec to use the class property fields when encoding/decoding. I have full control of building the codec part, so if I need to use reflection to build a ClassModel, that's fine.

(This is what I've tried with the ClassModel builder, but removeProperty doesn't seem to change anything the exception is thrown from the constructor, so I never have a chance to call removeProperty.)

    final ClassModelBuilder<T> builder = ClassModel.builder(this.type);
    builder.removeProperty("iLink");
    final CodecProvider pojoCodecProvider = PojoCodecProvider.builder().register(builder.build()).build();

Upvotes: 1

Views: 1724

Answers (1)

Tezra
Tezra

Reputation: 8833

The PojoCodecProvider currently (as of version 3.6.2 of mongo-java-driver) does not support turning off getter/setter properties.

You can iterate over the properties found by the builder and remove the invalid ones using a function like this (which you can wrap as a convention. Note that driver 3.6.2 is better at the discovery process than version 3.5.0).

private void stripNonProperties(final ClassModelBuilder<T> builder, Class<T> type) {
    // Need intermediary list. Can't remove from list while iterating over it
    final ArrayList<String> names = new ArrayList<>();

    for (final org.bson.codecs.pojo.PropertyModelBuilder<?> property : builder.getPropertyModelBuilders()) {
        final String name = property.getName();
        if (!isField(name, type)) {
            names.add(name);
        }
    }

    for (final String name : names) {
        builder.removeProperty(name);
    }
}

Otherwise, you will just have to covert the object in question to a version you do control.

Upvotes: 2

Related Questions