Play + Scala + Reactive Mongo
Building a “reactive” data-access layer to
mongoDB
About Us
Max Kremer
Trialfire - co-founder
founded in June 2013
Autodesk - cloud solutions architect
Datastay - co-founder...
Why “reactive”
Classic Synchronous Model:
With a traditional synchronous database driver, each
operation blocks the curren...
What is “reactive”
Fully non-blocking and asynchronous
I/O operations
Play and async I/O
• Java NIO
• Non-blocking, asynchronous IO
• Process multiple HTTP requests with a single thread
• Larg...
Example
•A Play controller using a Future result:
package controllers
import play.api.mvc.{Action, Controller}
import conc...
A word about Futures
•Represents a value that will be available later
•Execution contexts - think “thread pools”
•Futures ...
Data Access Layer
•Active Record Design Pattern
•Based on Futures
•Model = Case Class + Companion Object
•Stackable Traits
Persistence using Traits
import play.api.libs.json.Json
case class User
( id : Option[BSONObjectID]
, firstName: String
, ...
The Data Access Trait
trait DataAccess[M] {
def collectionName: String
implicit val format: Format[M]
private def db = Rea...
The Data Access Trait (cont’d)
def update(instance: M): Future[LastError] = {
instance.id map { id =>
collection.update(id...
Pros
•easy compared to sql
•no schemas
•no queries
•no migration
•it just works
conversion from/to json automatically
hand...
Cons
•Futures all the way down…
•Futures all the way up, too...
•No joins
Cons (cont’d)
case class Book
( name : String
, author: Author)
case class author(name: String) {
lazy val books: Seq[Book...
Links
reactive mongo driver:
http://reactivemongo.org/
Play ReactiveMongo plugin:
https://github.com/ReactiveMongo/Play-ea...
The End
Thanks for listening
Future[Option[Applause]]
max@trialfire.com marconi@trialfire.com
We’re hiring!
Upcoming SlideShare
Loading in …5
×

Play + scala + reactive mongo

8,338 views

Published on

Meetup presentation. Covers building a non-blocking asynchronous data-access layer using Scala, Play framework, MongoDB and the Reactive Mongo Driver

Play + scala + reactive mongo

  1. 1. Play + Scala + Reactive Mongo Building a “reactive” data-access layer to mongoDB
  2. 2. About Us Max Kremer Trialfire - co-founder founded in June 2013 Autodesk - cloud solutions architect Datastay - co-founder Acquired by Autodesk 2011 Marconi Lanna Trialfire - lead developer founded in June 2013 Too many startups since 1996 to list here
  3. 3. Why “reactive” Classic Synchronous Model: With a traditional synchronous database driver, each operation blocks the current thread until a response is received. More requests = more threads waiting = poor scalability
  4. 4. What is “reactive” Fully non-blocking and asynchronous I/O operations
  5. 5. Play and async I/O • Java NIO • Non-blocking, asynchronous IO • Process multiple HTTP requests with a single thread • Large number of concurrent requests can be handled with a few threads
  6. 6. Example •A Play controller using a Future result: package controllers import play.api.mvc.{Action, Controller} import concurrent.{ExecutionContext, Future} import ExecutionContext.Implicits.global object StuffController extends Controller { def doStuff( ) = Action { val someStuff = scala.concurrent.future { models.Stuff.fetch( ) } Async { someStuff.map(value => Ok(value)) } } }
  7. 7. A word about Futures •Represents a value that will be available later •Execution contexts - think “thread pools” •Futures are Monads •Layer of abstraction over multi-threading
  8. 8. Data Access Layer •Active Record Design Pattern •Based on Futures •Model = Case Class + Companion Object •Stackable Traits
  9. 9. Persistence using Traits import play.api.libs.json.Json case class User ( id : Option[BSONObjectID] , firstName: String , lastName : String , email : String , password : String) object User extends DataAccess[User] { def collectionName = “user” implicit val format = Json.format[User] }
  10. 10. The Data Access Trait trait DataAccess[M] { def collectionName: String implicit val format: Format[M] private def db = ReactiveMongoPlugin.db private def collection = db[JSONCollection](collectionName) def insert(instance: M): (BSONObjectID, Future[LastError]) = { val id = BSONObjectID.generate (id, collection.insert(Json.toJson(instance) ++ id)) }
  11. 11. The Data Access Trait (cont’d) def update(instance: M): Future[LastError] = { instance.id map { id => collection.update(id, Json.toJson(instance)) } getOrElse Future.successful(LastError(err = Some("Invalid ID")) } def byId(id: BSONObjectID): Future[Option[M]] = { collection.find(id).cursor.headOption map { _ flatMap { doc: JsObject => doc.asOpt[M] } } }
  12. 12. Pros •easy compared to sql •no schemas •no queries •no migration •it just works conversion from/to json automatically handled by play json api macros
  13. 13. Cons •Futures all the way down… •Futures all the way up, too... •No joins
  14. 14. Cons (cont’d) case class Book ( name : String , author: Author) case class author(name: String) { lazy val books: Seq[Book] = Book.byAuthor(this) } lazy val books: Future[Seq[Book]] = Book.byAuthor(this) val books = author.books author.books map { books => ... }
  15. 15. Links reactive mongo driver: http://reactivemongo.org/ Play ReactiveMongo plugin: https://github.com/ReactiveMongo/Play-eactiveMongo
  16. 16. The End Thanks for listening Future[Option[Applause]] max@trialfire.com marconi@trialfire.com We’re hiring!

×