[JAVA-2767] bson: fails decoding when id property is named id instead of _id Created: 01/Feb/18  Updated: 27/Oct/23  Resolved: 02/Feb/18

Status: Closed
Project: Java Driver
Component/s: POJO
Affects Version/s: 3.6.1
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Juan F. Codagnone Assignee: Ross Lawley
Resolution: Works as Designed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
related to JAVA-2750 Pojo codec conversion missing id field Closed

 Description   

Hi,

I'm trying to decode a BSON written by other system using the BSON library and I'm unable to decode correctly. I'm just reading values from mongodb (this app read-only, data stored is legacy).

The bson has an id property (instead of the classical _id) embeded inside other object, and its never set the java property.

The first patch show the decoding issue for a simpler doc:

From 8e00ddd5b65177bacf87facf55fb2680797bfca0 Mon Sep 17 00:00:00 2001
From: "Juan F. Codagnone" <juan@leak.com.ar>
Date: Thu, 1 Feb 2018 16:22:11 -0300
Subject: [PATCH] Test that shows id properties aren't read from bson
 
---
 .../unit/org/bson/codecs/pojo/PojoCustomTest.java  | 26 ++++++++++++++++++++++
 1 file changed, 26 insertions(+)
 
diff --git a/bson/src/test/unit/org/bson/codecs/pojo/PojoCustomTest.java b/bson/src/test/unit/org/bson/codecs/pojo/PojoCustomTest.java
index d47dd959f..e66a07f5b 100644
--- a/bson/src/test/unit/org/bson/codecs/pojo/PojoCustomTest.java
+++ b/bson/src/test/unit/org/bson/codecs/pojo/PojoCustomTest.java
@@ -265,6 +265,32 @@ public final class PojoCustomTest extends PojoTestCase {
                 fromCodecs(new SimpleEnumCodec()));
         roundTrip(registry, new SimpleEnumModel(SimpleEnum.BRAVO), "{ 'myEnum': 1 }");
     }
+    
+    static class Foo {
+        private ObjectId id;
+        
+        public Foo() {
+            
+        }
+        public ObjectId getId() {
+            return id;
+        }
+
+        public void setId(final ObjectId id) {
+            this.id = id;
+        }
+    }
+    
+    @Test
+    public void testIdWithoutUndescore() {
+        final CodecRegistry registry = getCodecRegistry(getPojoCodecProviderBuilder(Foo.class, SimpleEnumModel.class));
+        final Codec<Foo> codec = registry.get(Foo.class);
+        final org.bson.io.OutputBuffer encoded = encode(DOCUMENT_CODEC, org.bson.BsonDocument.parse("{ 'id' : { '$oid' : '59a79beb24345d0004fe1a44' } }"));
+        final Foo result = decode(codec, encoded);
+        org.junit.Assert.assertNotNull(result);
+        // fails
+        org.junit.Assert.assertEquals(new ObjectId("59a79beb24345d0004fe1a44"), result.getId());
+    }
 
     @Test
     @SuppressWarnings("unchecked")
-- 
2.14.3

You might say that the field should be named like _id, and I might agree.
Removing the following lines of codes make the tests succeed (and breaks others):

diff --git a/bson/src/main/org/bson/codecs/pojo/ClassModelBuilder.java b/bson/src/main/org/bson/codecs/pojo/ClassModelBuilder.java
index cb579cb76..21d8f871c 100644
--- a/bson/src/main/org/bson/codecs/pojo/ClassModelBuilder.java
+++ b/bson/src/main/org/bson/codecs/pojo/ClassModelBuilder.java
@@ -260,10 +260,6 @@ public class ClassModelBuilder<T> {
 
         for (PropertyModelBuilder<?> propertyModelBuilder : propertyModelBuilders) {
             boolean isIdProperty = propertyModelBuilder.getName().equals(idPropertyName);
-            if (isIdProperty) {
-                propertyModelBuilder.readName(ID_PROPERTY_NAME).writeName(ID_PROPERTY_NAME);
-            }
-
             PropertyModel<?> model = propertyModelBuilder.build();
             propertyModels.add(model);
             if (isIdProperty) {

My real-life case happens when decoding an embed object (that I might argue that in doesn't need to follow the _id convention):

From df327b122bf407701dc442fc2ac497d5403890ca Mon Sep 17 00:00:00 2001
From: "Juan F. Codagnone" <juan@leak.com.ar>
Date: Thu, 1 Feb 2018 16:22:11 -0300
Subject: [PATCH] Test that shows id properties aren't read from bson
 
---
 .../unit/org/bson/codecs/pojo/PojoCustomTest.java  | 76 ++++++++++++++++++++++
 1 file changed, 76 insertions(+)
 
diff --git a/bson/src/test/unit/org/bson/codecs/pojo/PojoCustomTest.java b/bson/src/test/unit/org/bson/codecs/pojo/PojoCustomTest.java
index d47dd959f..e8238cdcd 100644
--- a/bson/src/test/unit/org/bson/codecs/pojo/PojoCustomTest.java
+++ b/bson/src/test/unit/org/bson/codecs/pojo/PojoCustomTest.java
@@ -265,6 +265,82 @@ public final class PojoCustomTest extends PojoTestCase {
                 fromCodecs(new SimpleEnumCodec()));
         roundTrip(registry, new SimpleEnumModel(SimpleEnum.BRAVO), "{ 'myEnum': 1 }");
     }
+    
+    static class Foo {
+        private ObjectId id;
+        private Bar bar;
+
+        public Foo() {
+            
+        }
+        
+        public ObjectId getId() {
+            return id;
+        }
+
+        public void setId(final ObjectId id) {
+            this.id = id;
+        }
+
+        public Bar getBar() {
+            return bar;
+        }
+        public void setBar(final Bar bar) {
+            this.bar = bar;
+        }
+    }
+    
+    static class Bar {
+        private ObjectId id;
+        private String name;
+        
+        public Bar() {
+            
+        }
+
+        public ObjectId getId() {
+            return id;
+        }
+
+        public void setId(final ObjectId id) {
+            this.id = id;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+    }
+    
+    
+    @Test
+    public void testIdWithoutUndescore() {
+        final CodecRegistry registry =getCodecRegistry(getPojoCodecProviderBuilder(Foo.class, Bar.class));
+        final ObjectId a  = new ObjectId("59a79beb24345d0004fe1a44");
+        final ObjectId b  = new ObjectId("59a79beb24345d0004fe1a45");
+        final String name = "bar";
+        
+        final org.bson.io.OutputBuffer encoded = encode(DOCUMENT_CODEC, org.bson.BsonDocument.parse(
+                "{ '_id' : { '$oid' : '59a79beb24345d0004fe1a44' }, "
+              +    "'bar' : { 'id' : { '$oid' : '59a79beb24345d0004fe1a45' }, 'name' : 'bar' } }"));
+        final Codec<Foo> codec = registry.get(Foo.class);
+        final Foo result = decode(codec, encoded);
+        org.junit.Assert.assertEquals(a,    result.getId());
+        org.junit.Assert.assertEquals(name, result.getBar().getName());
+        // will fail as value is null
+        org.junit.Assert.assertEquals(b,    result.getBar().getId());
+    }
 
     @Test
     @SuppressWarnings("unchecked")
-- 
2.14.3

I don't have a proposed solution, just the report.

Regards,
Juan.



 Comments   
Comment by Ross Lawley [ 02/Feb/18 ]

Added JAVA-2768 & JAVA-2769 to add new features so that this scenario can be handled by the default annotations.

Comment by Juan F. Codagnone [ 02/Feb/18 ]

The work around of JAVA-2750 worked. We can close this issue.

Comment by Juan F. Codagnone [ 01/Feb/18 ]

I'm sorry for the duplicate.

Will try the workaround: https://jira.mongodb.org/browse/JAVA-2750?focusedCommentId=1784548&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-1784548

Comment by Jeffrey Yemin [ 01/Feb/18 ]

This may be a duplicate of JAVA-2750

Generated at Thu Feb 08 08:58:01 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.