Java MongoDB connection pool - java

I am using Java with MongoDB. Here I am opening MongoClient in each method. I only need to open it once through out the class and close it once.
public class A
{
public String name()
{
MongoClient mongo = new MongoClient(host, port);
DB db = mongo.getDB(database);
DBCollection coll = db.getCollection(collection);
BasicDBObject doc = new BasicDBObject("john", e.getName())
}
public String age()
{
MongoClient mongo = new MongoClient(host, port);
DB db = mongo.getDB(database);
DBCollection coll = db.getCollection(collection);
BasicDBObject doc = new BasicDBObject("age", e.getAge())
}
}

You can use a Singleton pattern to guarantee only one instance of MongoClient class per application. Once you obtain the instance of MongoClient, you can perform your operations and don't need to explicitly manage operations like MongoClient.close, as this object manages connection pooling automatically.
In your example, you can initialize the MongoClient in a static variable.

Related

Connection to MongoDB using Morphia (Java)

I am developing a Java Restful web application and planning to use MongoDB with Morphia as ODM . As I am new to MongoDB, I needed a few suggestions.
The best way to handle db connections is to make use of db connection pool, which mongoClient takes care of.
Morphia morphia = new Morphia();
ServerAddress addr = new ServerAddress("127.0.0.1", 27017);
String databaseName = "test";
MongoClient mongoClient = new MongoClient(addr);
Datastore datastore = morphia.createDatastore(mongoClient, databaseName);
So I need to reuse the above datastore and not create a new instance upon every request as it can waste a lot of resources and affect performance. Should I be implementing the above as singleton class? Can someone help me through this?
Also can someone explain as to how I can set up configuration for db connections such as max connections per host, connection timeout in Morphia using MongoClientOptions?
Check out the config in this demo github.com/xeraa/morphia-demo
/**
* MongoDB providing the database connection for main.
*/
public class MongoDB {
public static final String DB_HOST = "127.0.0.1";
public static final int DB_PORT = 27017;
public static final String DB_NAME = "morphia_demo";
private static final Logger LOG = Logger.getLogger(MongoDB.class.getName());
private static final MongoDB INSTANCE = new MongoDB();
private final Datastore datastore;
private MongoDB() {
MongoClientOptions mongoOptions = MongoClientOptions.builder()
.socketTimeout(60000) // Wait 1m for a query to finish, https://jira.mongodb.org/browse/JAVA-1076
.connectTimeout(15000) // Try the initial connection for 15s, http://blog.mongolab.com/2013/10/do-you-want-a-timeout/
.maxConnectionIdleTime(600000) // Keep idle connections for 10m, so we discard failed connections quickly
.readPreference(ReadPreference.primaryPreferred()) // Read from the primary, if not available use a secondary
.build();
MongoClient mongoClient;
mongoClient = new MongoClient(new ServerAddress(DB_HOST, DB_PORT), mongoOptions);
mongoClient.setWriteConcern(WriteConcern.SAFE);
datastore = new Morphia().mapPackage(BaseEntity.class.getPackage().getName())
.createDatastore(mongoClient, DB_NAME);
datastore.ensureIndexes();
datastore.ensureCaps();
LOG.info("Connection to database '" + DB_HOST + ":" + DB_PORT + "/" + DB_NAME + "' initialized");
}
public static MongoDB instance() {
return INSTANCE;
}
// Creating the mongo connection is expensive - (re)use a singleton for performance reasons.
// Both the underlying Java driver and Datastore are thread safe.
public Datastore getDatabase() {
return datastore;
}
}
you can like this:
private MongoClient mongoClient = null;
private String mongoUrl="xxxx";//You can also use spring injection,#Value(value = "${db.mongo.url}")
private static final Morphia MORPHIA = new Morphia();
public Datastore getMORPHIADB(String dbName) {
if (mongoClient == null) {
//初始化
init();
}
return MORPHIA.createDatastore(mongoClient, dbName);
}
#PostConstruct
public void init() {
try {
//此处其它参数我们不做配置,采用默认配置MongoClientOptions.Builder里面配置连接池的参数
MongoClientOptions.Builder options = new MongoClientOptions.Builder()
.connectionsPerHost(30); //连接池大小(默认初始化为100个,原来老版本是10个)
MongoClientURI mongoClientURI = new MongoClientURI(mongoUrl, options);
mongoClient = new MongoClient(mongoClientURI);
} catch (MongoClientException e) {
LOGGER.error("建立MongoClient异常");
}
}
#PreDestroy
public synchronized void closeConnection() {
if (mongoClient != null) {
mongoClient.close();
}
}
when need use, you can like this:
private Datastore datastore = mongoConnService.getMORPHIADB("xxx");

Define Max connection pool size in MongoDB + Java

For my Application, I am trying to set min and maximum pool size for the connection. So, Can anyone help me how to do it with mongo Client.
Also not I saw the options through the MOngoClientURI but is there any other option with MongoClientOption or MongoClient.
My Current Code:
public void buildMongoClient() {
mongoClient = new MongoClient(dbHostName, dbPort);
mongoDatabase = mongoClient.getDatabase(DATABASE);
}
You can try something like this.
public void buildMongoClient() {
MongoClientOptions.Builder clientOptions = new MongoClientOptions.Builder();
clientOptions.minConnectionsPerHost();//min
clientOptions.connectionsPerHost();//max
mongoClient = new MongoClient(new ServerAddress(dbHostName, dbPort), clientOptions.build);
mongoDatabase = mongoClient.getDatabase(DATABASE);
}

make mongoClient object/any object available across the application

Hello i am working with mongodb java driver. In their documentation, they mentioned that,
The MongoClient class is designed to be thread safe and shared among threads.
Typically you create only 1 instance for a given database cluster and use it across
your application.
So, I want to make this object available for every user. how can i do this?
The best way to do this is to use Singleton design pattern. This is the code-
public class MongoDBManager {
public MongoClient mongoClient = null;
String host = "127.0.0.1";
static MongoDBManager mongo=new MongoDBManager();
private MongoDBManager() {
try {
mongoClient = new MongoClient( host , 27017);
} catch (UnknownHostException e) {
System.err.println("Connection errors");
e.printStackTrace();
}
}
public static MongoDBManager getInstance(){
return mongo;
}
}
Call only MongoDBManager.getInstance() whenever you need connection. only one object will be used.

Everything using MongoDB must throw UnknownHostException

I'm working on a plugin for a Bukkit (Minecraft) Server. I want to be able to write stuff to my MongoDB database, but any methods that include creating a mongoClient must throw an UnknownHostException, as well as everything it's nested in. For example: The listener class listens for a player login, which will trigger the login utilities class, which will trigger the database class. And all of them need to throw the exception. The problem is that adding the exception to all of them creates this error (or maybe something else is causing it): server log
This is a portion of the database class if it helps:
public static boolean checkForPlayer(String playername) throws UnknownHostException{
BasicDBObject query = new BasicDBObject();
query.put("username", playername);
//create client
MongoClient mongo = new MongoClient("some_address", 27017);
//create database
DB db = mongo.getDB("test");
//create collection
DBCollection table = db.getCollection("test");
//create cursor
DBCursor cursor = table.find(query);
if(!cursor.hasNext()){
return false;
}
return true;
}
I'm not very good at java so the problem might be something silly :/
You have to add the mongodb driver to the class path. http://docs.mongodb.org/ecosystem/tutorial/getting-started-with-java-driver/#getting-started-with-java-driver

How do I change my java code to use replset? with Spring Data and MongoDB

I would like to know how to change my java code to support replset with spring-data and MongoDB.
I have 3 MongoDB servers running.. example:
./mongod --dbpath=/home/jsmith/tmp/db1 --replSet=spring --port=27017
./mongod --dbpath=/home/jsmith/tmp/db2 --replSet=spring --port=27027
./mongod --dbpath=/home/jsmith/tmp/db3 --replSet=spring --port=27037
if I do rs.status() I can see that if the db on 27017 goes down then one of the others become primary so I know that mongoDB is working right but in my java code if I try to run it I get the following error:
Exception in thread "main" org.springframework.dao.DataAccessResourceFailureException: can't call something : /127.0.0.1:27017/demo
Its looking only on port 27017
here is my mongodbconfig:
#Configuration
#EnableMongoRepositories
#ComponentScan(basePackageClasses = {MongoDBApp.class})
#PropertySource("classpath:application.properties")
public class MongoConfiguration extends AbstractMongoConfiguration {
#Override
protected String getDatabaseName() {
return "demo";
}
#Override
public Mongo mongo() throws Exception {
return new Mongo(new ArrayList<ServerAddress>() {{ add(new ServerAddress("127.0.0.1", 27017)); add(new ServerAddress("127.0.0.1", 27027)); add(new ServerAddress("127.0.0.1", 27037)); }});
}
#Override
protected String getMappingBasePackage() {
return "com.xxxx.mongodb.example.domain";
}
}
how do I change it to support replset? but if its reading and one of the servers goes down I get a error.. anyway to make in reconnect?
The URI method should work, or there's a clearer way to initialise the replica set using a list of servers:
final List<ServerAddress> seeds = Arrays.asList(new ServerAddress("127.0.0.1", 27017),
new ServerAddress("127.0.0.1", 27027),
new ServerAddress("127.0.0.1", 27037));
final Mongo mongo = new Mongo(seeds);
This is how I do it:
String mongoURI="mongodb://myUsrName:pass#mongoServer-001.company.com:27017,mongoServer-002.company.com:27017,mongoServer-003.company.com:27017/myDBname?waitqueuemultiple=1500&w=1&maxpoolsize=40&safe=true";
MongoURI uri = new MongoURI(mongoURI);
Mongo mongo = new Mongo(uri);
I specify the 3 servers in the URI (along with extra parameters like max pool size).
The third server (mongoServer-003) is the arbiter and it doesn't store any info. The arbiter helps in the election of the primary server when the current primary goes down. Take a look at this article.
With this configuration, the app can keep working even if the primary server goes down.
You can also do it the CustomEditorConfigurer and a class that implements PropertyEditorRegistrar.
So you your configuration class needs this:
#Bean
public static CustomEditorConfigurer customEditorConfigurer(){
CustomEditorConfigurer configurer = new CustomEditorConfigurer();
configurer.setPropertyEditorRegistrars(
new PropertyEditorRegistrar[]{new ServerAddressPropertyEditorRegistrar()});
return configurer;
}
#Override
protected String getDatabaseName() {
return authenticationDb;
}
#Override
#Bean
public MongoClient mongoClient() {
MongoClient mongoClient = new MongoClient(Arrays.asList(new ServerAddress(host, port)), mongoCredentials(), mongoClientOptions());
return mongoClient;
}
public final class ServerAddressPropertyEditorRegistrar implements PropertyEditorRegistrar {
#Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(ServerAddress[].class, new ServerAddressPropertyEditor());
}
}

Categories

Resources