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

A custom codec that fails to write the name causes a NPE

    • Type: Icon: Bug Bug
    • Resolution: Unresolved
    • Priority: Icon: Minor - P4 Minor - P4
    • None
    • Affects Version/s: None
    • Component/s: BSON

      The following exception is thrown when the writer doesn't write the name:

      Exception in thread "main" java.lang.NullPointerException: Cannot invoke "org.bson.BsonBinaryWriter$Context.getContextType()" because the return value of "org.bson.BsonBinaryWriter.getContext()" is null
      	at org.bson.BsonBinaryWriter.writeCurrentName(BsonBinaryWriter.java:403)
      	at org.bson.BsonBinaryWriter.doWriteBinaryData(BsonBinaryWriter.java:160)
      	at org.bson.AbstractBsonWriter.writeBinaryData(AbstractBsonWriter.java:368)
      	at com.mongodb.internal.connection.BsonWriterDecorator.writeBinaryData(BsonWriterDecorator.java:81)
      	at com.mongodb.internal.connection.IdHoldingBsonWriter.writeBinaryData(IdHoldingBsonWriter.java:155)
      

      Seems getContext() can return null and this error could be friendlier to describe why.

      Here is a Kotlin based example that triggers the error (the Java equivalent would also error).

      @JvmInline
      value class Image(@Contextual val binary: BsonBinary)
      
      class ImageCodec : Codec<Image> {
          override fun encode(writer: BsonWriter, value: Image, encoderContext: EncoderContext) {
              writer.writeBinaryData(value.binary)
          }
      
          override fun decode(reader: BsonReader, decoderContext: DecoderContext): Image {
              return Image(reader.readBinaryData())
          }
      
          override fun getEncoderClass(): Class<Image> = Image::class.java
      }
      
      fun main() {
      
          val codecRegistry = CodecRegistries.fromRegistries(
              CodecRegistries.fromCodecs(ImageCodec()),
              MongoClientSettings.getDefaultCodecRegistry()
          )
      
          val mongoClient = MongoClient.create("mongodb://localhost/")
      
          val db = mongoClient.getDatabase("test")
              .withCodecRegistry(codecRegistry)
      
          val img = Image(BsonBinary("asdfasdf".toByteArray()))
      
          val collection = db.getCollection<Image>("test")
          collection.drop()
      
          println(collection.insertOne(img))
          println(collection.find().toCollection(mutableListOf()))
      
          mongoClient.close()
      }
      

      A full fix for this bug should consider the behavior or all BsonWriter implementations, as it looks like BsonBinaryWriter is not the only one that will NPE:

      java.lang.NullPointerException: Cannot invoke "org.bson.BsonDocument.put(String, org.bson.BsonValue)" because "this.container" is null
      	at org.bson.BsonDocumentWriter$Context.add(BsonDocumentWriter.java:226)
      	at org.bson.BsonDocumentWriter.write(BsonDocumentWriter.java:207)
      	at org.bson.BsonDocumentWriter.doWriteBoolean(BsonDocumentWriter.java:109)
      	at org.bson.AbstractBsonWriter.writeBoolean(AbstractBsonWriter.java:381)
      

            Assignee:
            Unassigned Unassigned
            Reporter:
            ross@mongodb.com Ross Lawley
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: