Uploaded image for project: 'Java Driver'
  1. Java Driver
  2. JAVA-2767

bson: fails decoding when id property is named id instead of _id

    • Type: Icon: Bug Bug
    • Resolution: Works as Designed
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: 3.6.1
    • Component/s: POJO
    • None

      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.

            Assignee:
            ross@mongodb.com Ross Lawley
            Reporter:
            jcodagnone Juan F. Codagnone
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: