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(); } }
- is related to
-
JAVA-2416 BSONReader mark - add support to unset a mark (in contrast to resetting), and add support for multiple marks
- Closed