I was connecting to my MongoDB using MongoConnectionOptions in reactivemongo version 0.15.x. Now I updated to 0.20.11.
The apply() function of the MongoConnectionOptions companion object is deprecated now. The deprecation warning says to use the constructor of MongoConnectionOptions. Unfortunately this constructor is package-private.
I do not want to use the deprecated apply function mainly because my scala compiler options do not allow warnings. (And I really don't want to change this).
The official documentation only explains the deprecated version: http://reactivemongo.org/releases/0.1x/documentation/tutorial/connect-database.html
How can I still connect to the database using connection options?
The factory MongoConnectionOptions(..) will be refactored in coming next major release 1.0.x.
Anyway, you can using .default + .copy(..):
import reactivemongo.api.MongoConnectionOptions
MongoConnectionOptions.default.copy(appName = "Foo")
Moreover, options can be prepared (from config file or programmatically) as URI string.
val host = "localhost"
val port = 27017
reactivemongo.api.MongoConnection.connect(s"mongodb://${host}:${port}")
I use the following syntax and works fine for me:
val host = "localhost"
val port = "27017"
val db_name = "test"
val mongoUri = "mongodb://" + host + ":" + port + "/" + db_name
val driver = new AsyncDriver
val database = for {
uri <- MongoConnection.fromString(mongoUri)
con <- driver.connect(uri)
dn <- Future(uri.db.get)
db <- con.database(dn)
} yield db
val bsonCollection: Future[BSONCollection] = database.map(_.collection(collectionName))
Related
I am trying to get connection from default Hikaricp config. Following is application.conf
modules {
enabled += "play.api.db.DBModule"
enabled += "play.api.db.HikariCPModule"
enabled += "modules.AppModule"
}
db.default.hikaricp.dataSourceClassName=org.postgresql.ds.PGSimpleDataSource
db.default.hikaricp.dataSource.user=rp
#db.default.hikaricp.dataSource.url="postgres://rp:password#localhost/profile"
db.default.hikaricp.dataSource.password=password
db.default.hikaricp.dataSource.databaseName=profile
db.default.hikaricp.dataSource.serverName=localhost
db.default.hikaricp.connectionTestQuery = "SELECT 1"
Since Play is maintaining the connection pool. Now I am unable to find a way to get connection created above Play. I have tried the following (1, 2, 3):
//1. Injecting
import slick.jdbc.PostgresProfile.api._
class DBConnection #Inject()(db: Database) {
}
// 2. Mentioned here.
object DBConnection {
implicit val db = DatabaseConfigProvider.get[JdbcProfile](Play.current).db
//implicit val db = Database.forConfig("default") (3)
}
How can I get connection from the default connection pool?
Additional Details:
Play Framework version: 2.16.9
Scala version is 2.12.6
Postgres Dependency org.postgresql" % "postgresql" % "9.4-1206-jdbc42.
Added logs here for all three try.
You can use play.api.db.DBApi, like:
class DatabaseService #Inject()(dbApi: DBApi)
(implicit ec: DatabaseExecutionContext) {
lazy val database = dbApi.database("default")
...
}
i want to add mongoOptions to MongoClient basically i want to add ConnectionPerHost value its default is 10 i want to increase it to 20
but i am getting errors in the code i have tried with two different ways
val SERVER:ServerAddress = {
val hostName=config.getString("db.hostname")
val port=config.getString("db.port").toInt
new ServerAddress(hostName,port)
}
val DATABASE:String = config.getString("db.dbname")
method 1
val options=MongoClientOptions.apply( connectionsPerHost=20 )
val connectionMongo = MongoConnection(SERVER).addOption(options.getConnectionsPerHost)//returning Unit instead of MongoClient
val collectionMongo = connectionMongo(DATABASE)("testdb")
getting error on last line Unit does not take parameters
method 2
val mongoOption=MongoClientOptions.builder()
.connectionsPerHost(20)
.build();
getting error on MongoClientOptions.builder() line
value builder is not a member of object com.mongodb.casbah.MongoClientOptions
-
i want to set connectionsPerHost value to 20 please help what is the right way to do this
This seems to be working.
val config = ConfigFactory.load();
val hostName = config.getString("db.hostname")
val port = config.getInt("db.port")
val server = new ServerAddress(hostName, port)
val database = config.getString("db.dbname")
val options = MongoClientOptions(connectionsPerHost = 20)
val connectionMongo = MongoClient(server, options)
val collectionMongo = connectionMongo(database)("testdb")
Note that MongoConnection is deprecated.
My program requires a large number of connections to be open (Mongo). I get the error :
Too many connections open, can't open anymore
after 819 connections. I already know we can increase this limit. But that's not what I have in mind. I'm thinking of closing the MongoClient object, and then creating a new one again after 800 connections.
My thinking is that with a new mongoClient object all the connections will be closed and when I start/create it again, the connections will be opened again until 800.
Thus not giving the error. (Let me know if this approach is totally wrong/ won't give the required results.)
For this I need to know the number of connections opened ATM. Is there any way to get this information using java?
You can get connection information by using the db.serverStatus() command. It has a connections subdocument which contains the total/available connections information.
For more information :
Documentation of server status
Details of connections block
Check the number of MongoDB connections using MongoDB Scala driver:
Create a MongoDB client:
import org.mongodb.scala._
import scala.collection.JavaConverters._
import scala.concurrent.Await
import scala.concurrent.duration._
import scala.util.{Failure, Success, Try}
// To directly connect to the default server localhost on port 27017
val mongodbClient: MongoClient = MongoClient()
// Use a Connection String
val mongodbClient: MongoClient = MongoClient("mongodb://localhost")
// or provide custom MongoClientSettings
val settings: MongoClientSettings = MongoClientSettings.builder()
.applyToClusterSettings(b => b.hosts(List(new ServerAddress("localhost")).asJava).
.build()
val mongodbClient: MongoClient = MongoClient(settings)
Call getNoOfMongodbConnection by passing mongodbClient:
val result = getNoOfMongodbConnection(mongodbClient)
Method to get the number of connections(current, available and total)
def getNoOfMongodbConnection(mongodbClient: MongoClient) = {
val adminDatabase = mongodbClient.getDatabase("admin")
val serverStatus = adminDatabase.runCommand(Document("serverStatus" -> 1)).toFuture()
Try {
Await.result(serverStatus, 10 seconds)
} match {
case Success(x) => {
val connection = x.get("connections")
logger.info("Number of mongodb connection:--> " + connection)
connection
}
case Failure(ex) => {
logger.error("Got error while getting the number of Mongodb connection:---> " + ex.printStackTrace())
None
}
}
}
I am using mongo with play framework with "reactivemongo", That makes an async bridge between mongo connection and programm. For standalone projects I always use casbah lib - it has more native syntax (sometimes using of Futures in each request is not needed, and my religion does not allow me to use Async.await for blocking each request ) for me and no actors overhead, also I don't like JSON BSON conversion overhead.
But using casbah in play framework direct way(just create Mongo connection in controller ) produces connection leaks - this means you should create connection pool and control yourself, otherwords write reactivemongo.
Has anybody used casbah with mongo in production ? Where is the best and most canonical way of creating and controlling connection in play ecosystem ?
First you should check Connecting to MongoDB. Now go to this tutorial create scala project ( If you used other editor then follow scala project creation steps ).
Now check this following steps :
1> projectName/conf/application.conf add application.conf mongo Db name, collection name, port number, URL etc. play reactive mongo for ex: I added following in my application.conf
mongodb.default.host = "localhost"
mongodb.default.db = "Demo"
mongodb.default.port = "27017"
CI.default.uri = "mongodb://localhost:27017/"
2> Create a .scala file in controller folder give any name for ex. I set file name as ScalaMongoFactory and add following code in this file
import com.mongodb.casbah. {
MongoClient, MongoClientURI
}
import com.typesafe.config.ConfigFactory
object ScalaMongoFactory {
private val config = ConfigFactory.load()
private val DATABASE = config.getString("mongodb.default.db")
private val server = MongoClientURI(config.getString("CI.default.uri"))
private val client = MongoClient(server)
val database = client(DATABASE)
}
3> Now create a new .scala file in controller where you want to use mongo connection. For ex. I created checkConnection.scala file and contains like
import com.cloudinsights.scala.controllers. {
ScalaMongoFactory
}
object checkConnection {
val collection = ScalaMongoFactory.database("your collectionName")
}
There's no need to use Async.wait with reactive mongo (and you shouldn't anyway).
I guess you could use a utility object to manage your connection.
import com.mongodb.casbah.{MongoClient, MongoDB}
import play.api.Play
object MongoManager {
private val server = Play.current.configuration.getString("db.host").get
private val port = Play.current.configuration.getInt("db.port").get
object using {
def apply[A](col: String)(block: MongoDB => A): A = {
val con = MongoClient(server, port)
val a = block(con.apply(col))
con.close
a
}
def apply[A](block: MongoClient => A): A = {
val con = MongoClient(server, port)
val a = block(con)
con.close
a
}
}
object stashed {
private lazy val con = MongoClient(server, port)
def apply(col: String): MongoDB = con.apply(col)
def apply: MongoClient = con
}
}
I didn't find a play plugin for this driver.
Personally I'd recommend using the ReactiveMongo driver instead, since it can also use play's JSON library. If you're taking data from the database and feeding it through a REST api, its a nicer option.
In my project, I'm using Casbah and I reffered http://mongodb.github.io/casbah/tutorial.html tutorial. According to that I've implemented
val mongoClient = MongoClient
val db = mongoClient("db_name")
val coll = db("coll_name")
val a = MongoDBObject("hello" -> "world")
Then next step is not going to work.
coll.insert(a)
I'm using, "org.mongodb"%% "casbah" % 2.7.0-RC0
what is this issue ?
If running mongodb on localhost and the default port try changing:
val mongoClient = MongoClient()
So you call the apply method and return an instance of MongoClient not the object..
MongoFactory.coll.save(a)
use save() to save MongoDBObject.