_id field not populated in pojo when in parent class

I am new to MongoDb and am having a problem getting the _id field in Mongo to populate in a pojo when the user field is in a parent class. Other fields in the parent class populate just fine. I am trying to figure out what I need to do to get this to work. When I eliminate the parent class, and move everything to a single class, then the _id field is populated just fine.

I’ve reproduced the problem in a simple bit of test code, but I can’t upload, so embedding here. Basically, an abstract parent class with the id field and another field, then a child pojo with a single field which extends the abstract class.

import org.bson.codecs.pojo.annotations.BsonId;
import org.bson.codecs.pojo.annotations.BsonProperty;
import org.bson.types.ObjectId;

public abstract class AbstractPojo {
    private ObjectId id;
    private String parentValue;

    public AbstractPojo() {
    }

    @BsonId
    @BsonProperty("_id")
    public ObjectId getId() {
        return id;
    }

    public void setId(ObjectId id) {
        this.id = id;
    }

    @BsonProperty("parentValue")
    public String getParentValue() {
        return parentValue;
    }

    public void setParentValue(String parentValue) {
        this.parentValue = parentValue;
    }
}

import org.bson.codecs.pojo.annotations.BsonProperty;

public class TestPojo2 extends AbstractPojo {
    private String value;

    public TestPojo2() {
    }

    @BsonProperty("value")
    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}


    public static void main(String[] args) {
        try {
            TestMongoDbInstance.start();
            
            // Configuration
            MongoClientSettings clientSettings = MongoClientSettings.builder()
                .applyConnectionString(new ConnectionString(TestMongoDbInstance.getConnectionString()))
                .build();
            
            PojoCodecProvider pojoCodecProvider = PojoCodecProvider.builder().automatic(true).build();
            CodecRegistry codecRegistry = CodecRegistries.fromRegistries(MongoClientSettings.getDefaultCodecRegistry(),
                                                             CodecRegistries.fromProviders(pojoCodecProvider));            
            MongoClient mongoClient =  MongoClients.create(clientSettings);
            MongoDatabase mongoDb = mongoClient.getDatabase("testdb").withCodecRegistry(codecRegistry);

            // Insert an instance
            TestPojo2 obj = new TestPojo2();
            obj.setValue("Some Value");
            obj.setParentValue("Some Common Value");
            InsertOneResult insRes = mongoDb.getCollection("coll", TestPojo2.class).insertOne(obj);
            System.out.println("InsertedId: " + insRes.getInsertedId().asObjectId());
            
            // Read the instance
            FindIterable<TestPojo2> readRes = mongoDb.getCollection("coll", TestPojo2.class).find();
            TestPojo2 readObj = readRes.first();
            
            System.out.println("Read Instance: ");
            System.out.println("     id: " + readObj.getId());
            System.out.println("  value: " + readObj.getValue());
            System.out.println("  parentValue: " + readObj.getParentValue());
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                TestMongoDbInstance.stop();
            } catch (Exception e) {
                System.err.println("Failed stopping Mongo");
                e.printStackTrace();
            }
        }
    }

When I run this, what I get in the console is;

InsertedId: BsonObjectId{value=6682e39975b35503dac3253f}
Read Instance: 
     id: null
  value: Some Value
  parentValue: Some Common Value

If I use mongosh to look at the object directly in mongo, this is what is there;

testdb> db.coll.find()
[
  {
    _id: ObjectId('6682e39975b35503dac3253f'),
    parentValue: 'Some Common Value',
    value: 'Some Value'
  }
]

As I mentioned above, if I eliminate the abstract parent class and collapse the _id field directly in to the pojo it works just fine.

Is there something I am missing with this? I am still trying to figure out the annotations and configuration, maybe I am missing something there that would help with this.

I appreciate all the help I can get!

Hi @Scott_A_Stanley and welcome to the community forum.

The issue seem to be with the annotations being used with the _id in the above code. I would recommend you going through the code example available on Java-Mapping POJOs to get started and understand how the annotations have been made.

Please reach out in case you have issue while following the article.

Regards
Aasawari

@Aasawari I am not sure I see what the issue is with the annotations on the _id that you are referring to. The Java-Mapping POJOs quickstart does not really talk about mapping the ID attribute, so does not discuss the BsonId annotation. Are you referring to the fact I wrote the annotations as

    @BsonProperty("_id")

instead of

    @BsonProperty(value = "_id")

??

If so, the value = is optional when the annotation is single valued and the element is called value, Java Tutorials : Annotation Basics.

I did modify my test code to add the value = on all of my BsonProperty annotations just to make sure and I see the same behavior as before.

Thanks. I haven’t seen this quickstart guide, I’ll go through it. I’ve just been going through the Document Data Format: POJOs and POJO Customization sections in the documentation.

I did discover after a bit of trial and error that if I move the annotations to the actual attributes instead of the getters and setters then this works.