Search code examples
mongodbmongodb-java

MongoDB java client's WriteConcern doesn't work


I am a newbie to use MongoDB. I just imported the latest MongoDB java client via Maven:

    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongo-java-driver</artifactId>
        <version>3.2.2</version>
    </dependency>

And then I wrote a very simple program to test the insert operation.

        //I use a replicaset
    MongoClient mongoClient = new MongoClient(
            Arrays.asList(new ServerAddress("10.12.16.136", 29017),
                    new ServerAddress("10.12.16.136", 29018),
                    new ServerAddress("10.12.16.136", 29019)));

    //I just want to write and ignore any database errors. (This does not work)
    mongoClient.setWriteConcern(WriteConcern.UNACKNOWLEDGED);

    //Get database and collection
    MongoDatabase database = mongoClient.getDatabase("test");
    MongoCollection<Document> collection = database.getCollection("realtime");

    //This does not work too.
    collection.withWriteConcern(WriteConcern.UNACKNOWLEDGED);

    //Make a simple object to insert. I already have a document with the same _id in the database and I don't want to see the exception via the WriteConcern operation.
    Document doc = Document("longitude", longitude)
            .append("latitude", latitude)
            .append("velocity", velocity)
            .append("soc", soc)
            .append("_id", 12345678);

    //WriteConcern.UNACKNOWLEDGED doesn't work. An exception will be raised.
    collection.insertOne(doc);

How can I do the right thing?


Solution

  • That's because collection.withWriteConcern(WriteConcern.UNACKNOWLEDGED); generates a new MongoCollection object with a different write concern which you never use:

    /** * Create a new MongoCollection instance with a different write concern. * * @param writeConcern the new {@link com.mongodb.WriteConcern} for the collection * @return a new MongoCollection instance with the different writeConcern */

    MongoCollection withWriteConcern(WriteConcern writeConcern);

    The following code:

    MongoCollection<Document> dup = collection.withWriteConcern(WriteConcern.UNACKNOWLEDGED);
    ...
    dup.insertOne(doc);
    

    should work, i.e. no error raised.

    As for the MongoClient level write concern which is not propagated to the database:

    public MongoDatabase getDatabase(final String databaseName) {
        MongoClientOptions clientOptions = getMongoClientOptions();
        return new MongoDatabaseImpl(databaseName, clientOptions.getCodecRegistry(), clientOptions.getReadPreference(),
                clientOptions.getWriteConcern(), createOperationExecutor());
    }
    

    As you can see, the write concern is taken from MongoClientOptions ignoring the parameter value passed to mongoClient.setWriteConcern() method, which may be a bug.

    So, to set a global write concern properly, you will have to create an instance of MongoClientOptions:

     MongoClientOptions options = MongoClientOptions
         .builder()
         .writeConcern(WriteConcern.UNACKNOWLEDGED)
         .build();
    

    and pass it to the MongoClient constructor.