MongoDB Backend

MongoDbBackend is a drop-in alternative to SqliteBackend. Everything you learned in the Data Store guide — repositories, the caching layer, async reads/writes, flushing, key serialization — applies unchanged. Only the bottom layer of the stack changes.

Each repository namespace becomes a MongoDB collection; each entry is stored as a document of the form { "_id": <key>, "value": <json> }.

Build dependency

The MongoDB driver is not bundled — add it to your own plugin:

// build.gradle.kts
dependencies {
    implementation("org.mongodb:mongodb-driver-sync:5.8.0")
}

Setup

Pass a MongoDbBackend to DataStore.builder just like any other backend — the same entry point SQLite uses. The MongoDbBackend constructor throws IOException if it can’t connect.

import com.crimsonwarpedcraft.cwcommons.store.DataStore;
import com.crimsonwarpedcraft.cwcommons.store.MongoDbBackend;
import java.io.IOException;

DataStore store;

// In onEnable()
try {
    store = DataStore.builder(new MongoDbBackend("mongodb://localhost:27017", "myDatabase"))
        .name("myplugin")
        .build();
} catch (IOException e) {
    getLogger().severe("MongoDB backend failed: " + e.getMessage());
    getServer().getPluginManager().disablePlugin(this);
    return;
}

The builder’s default mapper sets field visibility, so plain POJOs and records both serialize correctly. Override it with .mapper(...) only to add serializers or change Jackson settings.

Shutting down

The builder’s store owns the backend, so a single store.close() flushes pending writes, stops the I/O thread, and closes the MongoDB connection:

// In onDisable()
store.close();    // flushes, stops the I/O thread, and closes the MongoClient

If you share one MongoDbBackend across several stores, build them with .closeBackend(false) and close the backend yourself after closing the stores.

Choosing a cache mode on a shared database

The cache mode matters more with MongoDB, because a Mongo database is often shared by several servers (a proxy network, for example):

  • One server owns the data → keep the default CACHE_AND_FLUSH for the same batching speed as SQLite. Use WRITE_THROUGH_ATOMIC instead if that one server must not lose writes to a crash before the next flush.
  • Multiple servers read/write the same collections → use CacheMode.NONE. Because the in-memory cache is per-process, a cached node keeps serving its own copy of a key and never sees another node’s update; NONE removes the cache so every read reflects MongoDB’s latest state and every write goes straight through.
DataStore.builder(backend).cacheMode(CacheMode.NONE).build()

Switching from SQLite

Only the backend construction changes; every repository(), get(), put(), flush(), and close() call is identical.

// SQLite — the Bukkit builder seeds the file backend and Bukkit serializers
DataStore store = new BukkitDataStoreBuilder("myplugin", getDataFolder()).build();

// MongoDB — the same builder, a different backend
DataStore store = DataStore.builder(new MongoDbBackend(uri, databaseName))
    .name("myplugin")
    .build();

This site uses Just the Docs, a documentation theme for Jekyll.