How do I instantiate an object from this class? I have another class where I would like to use the MongoUtils
class as defined below. This class is from reactivemongo
package controllers
import javax.inject.Inject
import scala.concurrent.Future
import play.api.Logger
import play.api.mvc.{ Action, Controller }
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import play.api.libs.functional.syntax._
import play.api.libs.json._
// Reactive Mongo imports
import reactivemongo.api.Cursor
import play.modules.reactivemongo.{ // ReactiveMongo Play2 plugin
MongoController,
ReactiveMongoApi,
ReactiveMongoComponents
}
// BSON-JSON conversions/collection
import reactivemongo.play.json._
import play.modules.reactivemongo.json.collection._
/*
* Example using ReactiveMongo + Play JSON library.
*
* There are two approaches demonstrated in this controller:
* - using JsObjects directly
* - using case classes that can be turned into JSON using Reads and Writes.
*
* This controller uses JsObjects directly.
*
* Instead of using the default Collection implementation (which interacts with
* BSON structures + BSONReader/BSONWriter), we use a specialized
* implementation that works with JsObject + Reads/Writes.
*
* Of course, you can still use the default Collection implementation
* (BSONCollection.) See ReactiveMongo examples to learn how to use it.
*/
class MongoUtils @Inject() (val reactiveMongoApi: ReactiveMongoApi)
extends Controller with MongoController with ReactiveMongoComponents {
/*
* Get a JSONCollection (a Collection implementation that is designed to work
* with JsObject, Reads and Writes.)
* Note that the `collection` is not a `val`, but a `def`. We do _not_ store
* the collection reference to avoid potential problems in development with
* Play hot-reloading.
*/
def collection: JSONCollection = db.collection[JSONCollection]("persons")
def index = Action { Ok("works") }
def create(name: String, age: Int) = Action.async {
val json = Json.obj(
"name" -> name,
"age" -> age,
"created" -> new java.util.Date().getTime())
collection.insert(json).map(lastError =>
Ok("Mongo LastError: %s".format(lastError)))
}
def createFromJson = Action.async(parse.json) { request =>
import play.api.libs.json.Reads._
/*
* request.body is a JsValue.
* There is an implicit Writes that turns this JsValue as a JsObject,
* so you can call insert() with this JsValue.
* (insert() takes a JsObject as parameter, or anything that can be
* turned into a JsObject using a Writes.)
*/
val transformer: Reads[JsObject] =
Reads.jsPickBranch[JsString](__ \ "firstName") and
Reads.jsPickBranch[JsString](__ \ "lastName") and
Reads.jsPickBranch[JsNumber](__ \ "age") reduce
request.body.transform(transformer).map { result =>
collection.insert(result).map { lastError =>
Logger.debug(s"Successfully inserted with LastError: $lastError")
Created
}
}.getOrElse(Future.successful(BadRequest("invalid json")))
}
def findByName(name: String) = Action.async {
// let's do our query
val cursor: Cursor[JsObject] = collection.
// find all people with name `name`
find(Json.obj("name" -> name)).
// sort them by creation date
sort(Json.obj("created" -> -1)).
// perform the query and get a cursor of JsObject
cursor[JsObject]()
// gather all the JsObjects in a list
val futurePersonsList: Future[List[JsObject]] = cursor.collect[List]()
// transform the list into a JsArray
val futurePersonsJsonArray: Future[JsArray] =
futurePersonsList.map { persons => Json.arr(persons) }
// everything's ok! Let's reply with the array
futurePersonsJsonArray.map { persons =>
Ok(persons)
}
}
}
So far I have tried val mongoutil = new MongoUtils(reactiveMongoApi = play.modules.reactivemongo)
but apparently it does not work.
You can use Play’s dependency injection mechanism to resolve instance of ReactiveMongoApi which is the interface to MongoDB. The steps could be:
Add the lines below to application.conf
play.modules.enabled += "play.modules.reactivemongo.ReactiveMongoModule"
play.modules.enabled += "modules.CommonModule"
modules.CommonModule is the place you define your bindings, so that Guice, a DI framework integrated with Play 2.4, knows which implementation to be used for a particular interface. For example,
package modules
import com.google.inject.AbstractModule
import dao.impl.UserDaoMongo
import dao.UserDao
import play.api.{Configuration, Environment}
import services.{UserService, UserServiceImpl}
case class CommonModule(environment: Environment, configuration: Configuration) extends AbstractModule {
def configure() {
bindDAOs()
bindServices()
}
private def bindDAOs(): Unit = {
bind(classOf[UserDao]).to(classOf[UserDaoMongo])
}
def bindServices(): Unit = {
bind(classOf[UserService]).to(classOf[UserServiceImpl])
}
}
In addition, it is a good practice to make controllers singleton. For example:
import javax.inject.{Singleton, Inject}
@Singleton
class UserController @Inject()(userService: UserService) extends Controller {
Please read this to know how to use Reactivemongo with Play framework. On the other hand, this is a complete example: https://github.com/luongbalinh/play-mongo