Creating a user registration system in play 2.6.x (scala) using mysql

in #utopian-io6 years ago (edited)

Welcome to my tutorial where I will be teaching you how to develop a user registration web application using play 2.6.x. This tutorial promises to be exciting as you will be learning how to access a MySQL database and store data by combining slick and Scala play. Hopefully by following my series you will be able to develop web applications using play

Repository

https://github.com/playframework/playframework

What Will I Learn?

In this tutorial you will learn how to create a user registration system using the play framework for scala and MySQL database. You will also learn the following

  • Importing a project into IntelliJ IDEA
  • Setting up a play project to access a MySQL database
  • Navigating a play application by using routes
  • Setting up controllers
  • Passing data to views

Requirements

The following are required in order to properly follow along this tutorial the following are required

  • An IDE (Preferably IntelliJ IDEA)
  • SBT
  • Play framework

Difficulty Level

Intermediate

Tutorial

The first thing you need to do is to download the play slick framework package from here. After dowloading the package, unzip it and put it in a directory on your hard drive.

Rename the folder to suit your purpose, in our case we will call the project scala-user-register.

Open command prompt (on windows) and type cd followed by the project path and hit enter.

Then type sbt to start our download dependencies.

Next, Open IntelliJ IDEA click on import project and click on next

uncheck library sources and click finish. Next, select the file to import and click okay

select sbt.

Your workspace should look something like this

Screenshot (69).png

Adding some dependencies

We need to add some dependencies for play slick and play evolutions, so we go to this locationtest/build.sbt and type in the following dependencies

libraryDependencies += "com.typesafe.play" %% "play-slick" % "3.0.3"
libraryDependencies += "com.typesafe.play" %% "play-slick-evolutions" % "3.0.3" 

We need to add the MySQL dependency so that we can access a MySQL database. By default play accesses the h2 database, so you will have to add the dependencies for the database you want to access.

So to add the MySQL depency add the following code to the build.sbt file

libraryDependencies += "mysql" % "mysql-connector-java" % "5.1.34"

The next thing we need to do is apply some configurations to the conf/application.conf file. The some of the configurations we will be adding includes the database name, username and password. So open the conf/application.conf file and the following code

slick.dbs.default.driver = "slick.driver.MySQLDriver$"
slick.dbs.default.db.driver = "com.mysql.jdbc.Driver"
slick.dbs.default.db.url = "jdbc:mysql://localhost/yourDBName"
slick.dbs.default.db.user = "root"
slick.dbs.default.db.password = ""

yourDB name is the name of the database, and you can set yours as desired. The username is root and the password is blank. This setting is usually for localhost, but you might have to change these values when deploying on a live server.

Now that our database has been setup we update our changes, so go back to your command prompt and type update

Creating the models

Now that we have setup MySQL for our application, its time to start building our scala play application. So first we need to create our model, to do that create a folder inside the app package and call it models.

After creating our models package we create a case class (file> New > Scala class), in this case we will be calling this class User. To initialize the class type the following code

case class User (id: Int, fullname: String, phone: Int, email: String, age: Int)

We want to send the values as JSON to the client so we use the JSON library to serialize a User class, but first we must import the play json library package, we can do this by typing the following code:

import play.api.libs.json._

To serialize our data into JSON we type the following

object User {
  implicit val userJsonFormat = Json.format[User]
}

We need to create another model class that will enable us convert our model into slick objects, so inside the app/models
package we would create class, for this example i will name mine UserData.

After doing that, let's initialize our class

class UserData (dbConfProvider: DatabaseConfigProvider)(implicit ec: ExecutionContext)  {

inside our class let's get the JDBC provider and make some important imports

private val dbConfig = dbConfigProvider.get[JdbcProfile]
import dbConfiguration._
import profile._

So now let's define our table, and give it properties. We can do that by creating a private class inside our UserData class our private class will be called 'UsersTable', but our actual table will be called 'users'.

private class UserTable(tag: Tag) extends Table[User](tag, "users") {

Now let's define our columns, we will be creating 5 columns and the id column will be set as primary key and will auto increment

def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
    def name = column[String]("fullname")
    def phone = column[Int]("phone")
    def email = column[String]("email")
    def age = column[Int]("age")

The O.primaryKey, and O.AutoInc statements mean that the id column has been set as primary key and will auto increment. Whereas we have set the name, phone, email and age to String, Int, String and Int respectively.

Still inside the UserTable private class we need to define the table's default projection, as this would enable us to pass the id, name, phone, email and age data to the User case class apply and unapply methods.

def * = (id, name, phone, email, age) <> ((User.apply _).tupled, User.unapply)

So the complete code for the above will look something like this:

private class UserTable(tag: Tag) extends Table[User](tag, "users") {
    def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
    def name = column[String]("fullname")
    def phone = column[Int]("phone")
    def email = column[String]("email")
    def age = column[Int]("age")
    def * = (id, name, phone, email, age) <> ((User.apply _).tupled, User.unapply)

Now that our tables have been defined, it's time to start querying our database, but first we need
to create a table query object which will map to. To do that we type the following code

  private val allUsers = TableQuery[UserTable]

Now let's type a query to insert a user into the database, for that we will create a method called createUser. This method will take 4 parameters, name, phone, email and age. We will not be adding the id paramter because it will just auto increment each time a user is added to the database.

def createUser(name: String, phone: Int, email: String, age: Int): Future[User] = db.run 

We need to create a projection for the other columns (name, phone, email, age) except the id column which will be inserted automatically

(allUsers.map(p => (p.name, p.phone, p.email, p.age))

We return the id, so as to know which id was generated for each user, also we define a transformation for the returned value which combines our parameters with the returned id

returning allUsers.map (_.id)
into ((namePhone, id) => User(id, namePhone._1, namePhone._2, namePhone._3, namePhone._4))

We now insert a user into the database


) += (name, phone, email, age)

Creating the controllers

Let's create a method that would display all the users stored in the database, we would call this method listUsers, it would not take in any parameters since we are displaying a particular user.

Now that we have completed our model we now move on to the controller, inside the app/controllers package we will create a new scala class (right click controllers package> new > scala class) and call it UserController. We define the UserController class by typing the following code

class UserController @Inject () (repo: UserData, cc: MessagesControllerComponents)(implicit ec: ExecutionContext)
                              extends MessagesAbstractController(cc)

We will now create mapping for our form

 val userForm: Form[CreateUserForm] = Form 

Let's apply the form parameters (name, phone, email and age) and apply the apply and unapply methods

 mapping(
      "name" -> text,
      "phone" ->number,
      "email" -> text,
      "age" -> number
    )(CreateUserForm.apply)(CreateUserForm.unapply)

we will now create the index method which is called by default, when the homepage loads. This method will display our form

def index = Action { implicit request =>
    Ok(views.html.index(userForm))
  }

still inside our UserController class we will create a method called addUser, this method we receive request from our
form, bind the form data insert data inside the database if no errors

def addUser = Action.async { implicit request =>
    userForm.bindFromRequest.fold(
      errorForm => {
        Future.successful(Ok(views.html.index(errorForm)))
      }, 
      person => {
        repo.createUser(person.name, person.phone, person.email, person.age).map { _ =>
          Redirect(routes.UserController.index).flashing("success" -> "user successfully created")
        }
      }
    )
  }

lastly in our controller, we will create a class for a form and it contains our form properties
(name,phone,email,age) as paramters

Updating the routes

Play uses the methods in the routes file to navigate your website. When a GET request is made to return a particular web page, play uses routes determine which controller and method to return

To locate our 'routes' file, navigate to conf/routes and type in the following code

GET     /                         controllers.UserController.index
POST    /user                     controllers.UserController.addUser

Play evolution

Play uses evolution to keep track of changes made in the database. The evolution script is found in 1.sql in the conf/evolutions.default package. My 1.sql script looks something like this

# --- !Ups
create table users (
      id BIGINT AUTO_INCREMENT PRIMARY KEY,
      name VARCHAR(100) NOT NULL,
      phone VARCHAR(100) NOT NULL,
      email VARCHAR(100) NOT NULL,
      age INT(3) NOT NULL
);
# --- !Downs
drop table "users" if exists;

You will be asked to run this script, before running your application

Passing data to our views

The views package is where the templates for our application can be found. There are 2 view templates index.scala.html and main.scala.html, we will be creating our form inside index.scala.html, found in app/views

let's define our userform and make an implicit request

@(userFormDef: Form[CreateUserForm])(implicit request: MessagesRequestHeader) 

we will create flash messages to display a success message or errors if any

@import helper._
@request.flash.get("success").map { key =>
@request.messages(key)
}

Our form uses a post method to send data to the controller. The form action is set to the addUser method in the UserController controller class.

@main("Welcome to Play") {
@form(routes.UserController.addUser())

Our form input type is text, and the name of the various types are name, phone, email and age

@inputText(userFormDef("name"))
        @inputText(userFormDef("phone"))
        @inputText(userFormDef("email"))
        @inputText(userFormDef("age"))
        @CSRF.formField

Now let's add a submit button to our form

<div class="buttons">
<input type="submit" value="Add User"/>
</div>

Running our application

Now its time to run our application, in IntelliJ Idea click on terminal, then type sbt after that type run. You should get something similar to the screen shot below

Screenshot (63)..jpg

The next thing you need to do is to open up your browser and type localhost:9000 click on "apply this script now!" and it will run the script to create the table. After clicking on the button the form appears for you to fill.

Screenshot (64).jpg

fill the form and click on add user, and the user will be added to the database

Screenshot (65).jpg

Code

The code used in this tutorial can be found here

Sort:  

Thank you for your contribution.

  • The repository no longer receives updates for a long time. Please do tutorials where the repository has updates that are less than 6 months old.

Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

Thanks for pointing that out

Coin Marketplace

STEEM 0.20
TRX 0.13
JST 0.030
BTC 65702.61
ETH 3485.24
USDT 1.00
SBD 2.51