Play Framework and Slick example updated

It was more than 3 years ago that I struggled to find a tutorial for integrating the Play Framework with Slick.

At the time I decided to write the most comprehensive tutorial I could make on how to create a full app with persistent storage using:

Play Framework - the most adopted MVC framework in the scala ecosystem,

Slick - the standard database access framework in scala,

MySQL - because I had always used Postgres and wanted to try MySQL.

I looked for existing demo apps and started removing all the boilerplate I could. I removed dependency injection, useless controllers, internationalization, etc.

Back to the present, the resulting tutorial I wrote got a very good feedback. Lot of visits, lot of comments (27 comments wow), a few github issues, and even pull requests. It was awesome to feel I was helping people getting into the scala ecosystem.

In these 3 years I got some people asking, and even contributing, to update the demo app to Play 2.5. But since I’ve been a bit away from scala, I let the tutorial become deprecated.

You can see the differences on the corresponding pull request. No big changes were needed. Let’s go through the differences step by step from the original guide:

0. Creating a new play template project

First difference: activator is no longer the way to create new projects from a template. Where before you’d do:

activator new application-name play-scala

now you do:

sbt new playframework/play-scala-seed.g8

1. Creating the model

This step suffers no major changes since it’s just plain scala code. But since Play Framework moved into Guice as the default dependency injection, we are going to stop relying in scala objects, and creating classes.

2. Application Controllers

Here we have a few more small changes, mostly due to dependency injection.

@SingletonclassApplicationController@Inject()(cc:ControllerComponents,userService:UserService)extendsAbstractController(cc)withLogging{defindex()=Action.async{implicitrequest:Request[AnyContent]=>userService.listAllUsersmap{users=>Ok(views.html.index(UserForm.form,users))}}defaddUser()=Action.async{implicitrequest:Request[AnyContent]=>UserForm.form.bindFromRequest.fold(// if any error in submitted data
errorForm=>{logger.warn(s"Form submission with error: ${errorForm.errors}")Future.successful(Ok(views.html.index(errorForm,Seq.empty[User])))},data=>{valnewUser=User(0,data.firstName,data.lastName,data.mobile,data.email)userService.addUser(newUser).map(_=>Redirect(routes.ApplicationController.index()))})}defdeleteUser(id:Long)=Action.async{implicitrequest:Request[AnyContent]=>userService.deleteUser(id)map{res=>Redirect(routes.ApplicationController.index())}}}

2. Integrate models with slick

The table definition is exactly the same as the original (for Play 2.4 tutorial), but due to dependency injection once again, we have a minor change on the way to get the database config provider:

importslick.jdbc.MySQLProfile.api._classUserTableDef(tag:Tag)extendsTable[User](tag,"user"){defid=column[Long]("id",O.PrimaryKey,O.AutoInc)deffirstName=column[String]("first_name")deflastName=column[String]("last_name")defmobile=column[Long]("mobile")defemail=column[String]("email")overridedef*=(id,firstName,lastName,mobile,email)<>(User.tupled,User.unapply)}classUsers@Inject()(protectedvaldbConfigProvider:DatabaseConfigProvider)(implicitexecutionContext:ExecutionContext)extendsHasDatabaseConfigProvider[JdbcProfile]{// the HasDatabaseConfigProvider trait gives access to the
// dbConfig object that we need to run the slick queries
valusers=TableQuery[UserTableDef]defadd(user:User):Future[String]={dbConfig.db.run(users+=user).map(res=>"User successfully added").recover{caseex:Exception=>ex.getCause.getMessage}}defdelete(id:Long):Future[Int]={dbConfig.db.run(users.filter(_.id===id).delete)}defget(id:Long):Future[Option[User]]={dbConfig.db.run(users.filter(_.id===id).result.headOption)}deflistAll:Future[Seq[User]]={dbConfig.db.run(users.result)}}

3. Evolutions

Database evolutions also keep exactly the same 🎉🎉🎉 !

4. Final Remarks

As you can see, the tutorial is still quite simple, and I hope it helps solving those small but annoying issues when starting with Play and Slick.

If you want to know everything that has changed, you should have a look at the official migration guides: Play 2.7 migration guide.