Play 2.4.x & RethinkDB: Classic CRUD application backed by RethinkDB

In this blog We have created Classic CRUD application using Play 2.4.x , Scala and RethinkDB. Where Scala meets Object-Oriented things in Functional way, Play is a High Velocity Web Framework For Java & Scala and RethinkDB is the open-source, scalable database that makes building realtime apps dramatically easier.

play_full_colorscala-logoquickstartwebjarsbootswatch

Now start Building Reactive Play application with RethinkDB. So here we will try to demonstrates the CRUD functionality of RethinkDB by below details:

  • Handling asynchronous results, Handling time-outs
  • Achieving, Futures to use more idiomatic error handling.
  • Accessing RethinkDB, using Java ReQL command reference.
  • Achieving, table pagination and sorting functionality using interactive FooTable plugin.
  • Replaced the embedded JS & CSS libraries with WebJars.
  • Play and Scala-based template engine implementation
  • Integrating with a CSS framework (Twitter Bootstrap). Twitter Bootstrap requires a different form layout to the default one that the Play form helper generates, so this application also provides an example of integrating a custom form input constructor.
  • Used Bootswatch with Twitter Bootstrap to improve the look and feel of the application

This CRUD app available on Typesafe Activator. So, If you have Typesafe Activator, use its command line mode to create a new project from this template.

$ activator new PROJECTNAME play-rethinkdb

or

$ git clone git@github.com:rklick-solutions/play-rethinkdb.git

RethinkDB Dependency

The rethinkdb-driver is distributed using Maven Central so it can be easily added as a library dependency in your Play Application’s SBT build scripts, as follows:

"com.rethinkdb" % "rethinkdb-driver" % "2.2-beta-1"

RethinkDb Setup

You can use the drivers from Java like this:

import com.rethinkdb.RethinkDB;
import com.rethinkdb.gen.exc.ReqlError;
import com.rethinkdb.gen.exc.ReqlQueryLogicError;
import com.rethinkdb.model.MapObject;
import com.rethinkdb.net.Connection;

public static final RethinkDB r = RethinkDB.r;

Connection conn = r.connection().hostname("localhost").port(28015).connect();

r.db("test").tableCreate("tv_shows").run(conn);
r.table("tv_shows").insert(r.hashMap("name", "Star Trek TNG")).run(conn);

Please check RConnection.scala and RDatabase.scala

Now Play

  • The Github code for the project is at : play-rethinkdb
  • Clone the project into local system
  • To run the Play framework 2.4.x, you need JDK 8 or later
  • Install Typesafe Activator if you do not have it already. You can get it from here
  • Execute activator clean compile to build the product
  • Execute activator run to execute the product
  • play-rethinkdb should now be accessible at localhost:9000

Let’s review app views and functionality

  • Home Page: localhost:9000/employees
/**
* Display the list of employees.
*/
def list() = Action.async { implicit request =>
  empDAO.findAll().map({ employees =>
    implicit val msg = messagesApi.preferred(request)
    Ok(html.list(employees))
 }).recover {
  case t: TimeoutException =>
    Logger.error("Problem found in employee list process")
    InternalServerError(t.getMessage)
 }
} 

home_page

  • Add an employee: localhost:9000/employees/new
/**
  * Handle the 'new employee form' submission.
  */
def save = Action.async { implicit request =>
  employeeForm.bindFromRequest.fold(
    { formWithErrors =>
      implicit val msg = messagesApi.preferred(request)
      Future.successful(BadRequest(html.createForm(formWithErrors)))
    },
    employee => {
      val futureUpdateEmp = empDAO.create(employee)
      futureUpdateEmp.map { result =>
       Home.flashing("success" -> s"Employee ${employee.name} has been created")
      }.recover {
        case t: TimeoutException =>
          Logger.error("Problem found in employee update process")
          InternalServerError(t.getMessage)
      }
   })
} 

new_emp

  • Edit/Update/Delete employee: localhost:9000/employees/EMP_ID
/**
  * Handle the 'edit form' submission
  *
  * @param id Id of the employee to edit
  */
def update(id: String) = Action.async { implicit request =>
  employeeForm.bindFromRequest.fold(
    { formWithErrors =>
      implicit val msg = messagesApi.preferred(request)
      Future.successful(BadRequest(html.editForm(id, formWithErrors)))
    },
    employee => {
      val futureUpdateEmp = empDAO.update(id, employee)
      futureUpdateEmp.map { result =>
        Home.flashing("success" -> s"Employee ${employee.name} has been updated")
      }.recover {
        case t: TimeoutException =>
          Logger.error("Problem found in employee update process")
          InternalServerError(t.getMessage)
      }
    })
}

/**
  * Handle employee deletion.
  */
def delete(id: String) = Action.async {
  val futureResult = Future.successful(empDAO.deleteById(id))
  futureResult.map(i => Home.flashing("success" -> "Employee has been deleted")).recover {
    case t: TimeoutException =>
      Logger.error("Problem deleting employee")
      InternalServerError(t.getMessage)
  }
}

edit_emp

References

This is the start of using RethinkDB with Play, from next week onwards we would be working on this application to make it grow. We would look at how we can add more functionality into it , then we would be adding more modules to it together. If you have any changes then feel free to send in pull requests and we would do the merges 🙂 Stay tuned.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s