Search code examples
javamongodbmorphia

Mongo connection leak with morphia


I have a Servlet with static Mongo = new Mongo() and Morphia morphia = new Morphia() objects. Each time GET is invoked, I do the following:

doGet(...){
...
datastore = morphia.createDatastore(mongo, dbName);
...
}

I don't close datastore, because there is no close method. Each time i invoke the servlet, number of used connections in mongo grow:

{ "current" : 113, "available" : 706, "totalCreated" : NumberLong(122) }
> db.serverStatus().connections { "current" : 115, "available" : 704, "totalCreated" : NumberLong(124) }
> db.serverStatus().connections { "current" : 116, "available" : 703, "totalCreated" : NumberLong(125) }
> db.serverStatus().connections { "current" : 121, "available" : 698, "totalCreated" : NumberLong(130) }
> db.serverStatus().connections { "current" : 122, "available" : 697, "totalCreated" : NumberLong(131) }
> db.serverStatus().connections { "current" : 128, "available" : 691, "totalCreated" : NumberLong(137) }

what is the right way to close connections with mongo and morphia and where the connection is really leaking? Thanks.


Solution

  • You can create a singleton Datastore object

    public enum MongoDBHelper { // the best way to implement singletons, due to the author of Effective Java  
    INSTANCE;
    
    private DB db;
    private Datastore datastore;
    
    private final String SERVER_URL = "...";
    private final int SERVER_PORT = ...;
    private final String USERNAME= "...";
    private final String PASSWORD = "...";
    private final String DATABASE_NAME = "...";
    
    private MongoDBHelper() {
    
        try {
    
            MongoClient mongoClient = new MongoClient(SERVER_URL, SERVER_PORT);
    
            this.db = mongoClient.getDB(DATABASE_NAME);
            this.db.authenticate(USERNAME,PASSWORD.toCharArray());
    
            Morphia morphia = new Morphia();
    
            this.datastore = morphia.createDatastore(mongoClient, DATABASE_NAME);
    
            morphia.mapPackage("package");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    
    }
    
    public DB getDB() {
        return this.db;
    }
    
    public Datastore getDatastore() {
        return this.datastore;
    }
    }
    

    and now you can reuse the same Datastore object in your application

     Datastore datastore = MongoDBHelper.INSTANCE.getDatastore()