Description
In JAVA-2416 support to set multiple marks on BsonReader was added.
Unfortunately I have trouble using these.
It's somehow hard to explain the observed behaviour and it might even be the case I misunderstand the implemented logic.
Have a look at the following simple java program.
It is expected to work as follows:
- A Pojo is created and persisted in the database. -> this works fine
- The Codec for Pojo (PojoCodec) should decode this entity -> doe not work
Decoding explained:
A marker is retrieved from the reader. When something goes wrong (exception) the reader should backoff (mark.reset()) and the current entitiy skipped. This does actually work fine.
If now, a second marker is set on the reader, things do not work any longer.
After resetting the first marker a call to reader.skipValue() will throw the following exception:
Exception in thread "main" java.lang.IllegalArgumentException |
at java.nio.Buffer.position(Buffer.java:244) |
at org.bson.ByteBufNIO.position(ByteBufNIO.java:118) |
Here the program to reproduce the behaviour.
|
|
import com.mongodb.MongoClient; |
import com.mongodb.MongoClientOptions; |
import com.mongodb.ServerAddress; |
import com.mongodb.client.MongoCollection; |
import org.bson.BsonReader; |
import org.bson.BsonReaderMark; |
import org.bson.BsonWriter; |
import org.bson.codecs.Codec; |
import org.bson.codecs.DecoderContext; |
import org.bson.codecs.EncoderContext; |
import org.bson.codecs.configuration.CodecRegistries; |
import org.bson.codecs.configuration.CodecRegistry; |
import org.bson.types.ObjectId; |
|
|
public class MarkerTest { |
|
|
CodecRegistry codecRegistry = CodecRegistries.fromCodecs(new PojoCodec()); |
|
|
static class Pojo { |
ObjectId id;
|
String stringField;
|
|
|
public String getStringField() { |
return stringField; |
}
|
|
|
public void setStringField(String stringField) { |
this.stringField = stringField; |
}
|
|
|
@Override |
public String toString() { |
final StringBuilder sb = new StringBuilder("Pojo{"); |
sb.append("id=").append(id); |
sb.append(", stringField='").append(stringField).append('\''); |
sb.append('}'); |
return sb.toString(); |
}
|
}
|
|
|
|
|
/** |
* Resilient codec that skips entities, in case of exceptions during decoding
|
*/
|
static class PojoCodec implements Codec<Pojo> { |
@Override |
public Pojo decode(BsonReader reader, DecoderContext decoderContext) { |
Pojo pojo = null; |
BsonReaderMark mark = null; |
|
|
try { |
mark = reader.getMark();
|
reader.readStartDocument();
|
pojo = new Pojo(); |
// reading fields and set in Pojo |
pojo.setStringField(readFields(reader));
|
reader.readEndDocument();
|
return pojo; |
|
|
} catch (Exception e) { |
System.out.println(e);
|
mark.reset();
|
reader.skipValue();
|
}
|
return pojo; |
}
|
|
|
private String readFields(BsonReader reader) { |
// the following mark, even if never needed, causes the above mark.reset() to reset the reader to the wrong position |
BsonReaderMark markInReadingFields = reader.getMark();
|
|
|
reader.readName();
|
reader.readObjectId();
|
//simulate random decoding exception.... |
if (true) throw new RuntimeException("Some random exception occurred"); |
reader.readName();
|
return reader.readString(); |
}
|
|
|
@Override |
public void encode(BsonWriter writer, Pojo pojo, EncoderContext encoderContext) { |
writer.writeStartDocument();
|
writer.writeName("stringField"); |
writer.writeString(pojo.getStringField());
|
writer.writeEndDocument();
|
}
|
|
|
@Override |
public Class<Pojo> getEncoderClass() { |
return Pojo.class; |
}
|
}
|
|
|
public void testMultipleMarker() { |
|
|
MongoClientOptions mongoClientOptions = new MongoClientOptions.Builder().codecRegistry(codecRegistry).build(); |
MongoClient mongoClient = new MongoClient(new ServerAddress("localhost", 27017), mongoClientOptions); |
|
|
Pojo pojo = new Pojo(); |
pojo.setStringField("test"); |
System.out.println("Pojo = " + pojo); |
|
|
MongoCollection<Pojo> pojoMongoCollection = mongoClient.getDatabase("test").getCollection("pojos").withDocumentClass(Pojo.class); |
pojoMongoCollection.insertOne(pojo);
|
|
|
Pojo readPojo = pojoMongoCollection.find().first();
|
System.out.println("Decoded pojo = " + readPojo); |
}
|
|
|
public static void main(String[] args) { |
new MarkerTest().testMultipleMarker(); |
}
|
}
|
Attachments
Issue Links
- is related to
-
JAVA-2416 BSONReader mark - add support to unset a mark (in contrast to resetting), and add support for multiple marks
-
- Closed
-