Category Archives: play! framework

Testing your plugin with multiple version of Play

So, you’ve written a plugin for Play…are you sure it works?

I’ve been giving Deadbolt some love recently, and as part of the work I’ve added a test application for functional testing. This is an application that uses all the features of Deadbolt, and is driven by HTTP calls by REST-Assured. Initially, it was based on Play 2.3.5 but this ignores the supported Play versions of 2.3.1 through to 2.3.4. Additionally, those hard-working people on the Play team at Typesafe keep cranking out new feature-filled versions.

On top of that, support for Scala 2.10.4 and 2.11.1 is required so cross-Scala version testing is needed.

Clearly, testing your plugin against a single version of Play is not enough. Seems like some kind of continuous integration could help us out here…

Building on Travis CI

Deadbolt builds on Travis CI, a great CI platform that’s free for open-source projects. This runs the tests, and publishs snapshot versions to Sonatype. I’m not going into detail on this, because there’s already a great guide over at Cake Solutions. You can find the guide here: http://www.cakesolutions.net/teamblogs/publishing-artefacts-to-oss-sonatype-nexus-using-sbt-and-travis-ci-here…

I’ve made some changes to the build script because the plugin code is not at the top level of the repositry; rather, it resides one level down. The repository looks like this:

deadbolt-2-java
  |-code        # plugin code lives here
  |-test-app    # the functional test application

As a result, the .travis.yml file that defines the build, looks like this.

language: scala
jdk:
- openjdk6
scala:
- 2.11.1
script:
- cd code
- sbt ++$TRAVIS_SCALA_VERSION +test
- cd ../test-app
- sbt ++$TRAVIS_SCALA_VERSION +test
- cd ../code
- sbt ++$TRAVIS_SCALA_VERSION +publish-local
after_success:
- ! '[[ $TRAVIS_BRANCH == "master" ]] && { sbt +publish; };'
env:
global:
- secure: foo
- secure: bar

This sets the Java version (people get angry when I don’t provide Java 6-compatible versions), and defines a script as the build process. Note the cd commands used to switch between the plugin directory and the test-app directory.

This script already covers the cross-Scala version requirement – prefixing a command with +, e.g. +test, will execute that command against all versions of Scala defined in your build.sbt. It’s important to note that although only Scala 2.11.1 is defined in .travis.yml, SBT itself will take care of setting the current build version based on build.sbt.

crossScalaVersions := Seq("2.11.1", "2.10.4")

Testing multiple versions of Play

However, the version of Play used by the test-app is still hard-coded to 2.3.5 in test-app/project/plugins.sbt.

addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.5")

Happily, .sbt files are not just configuration files but actual code. This means we can change the Play version based on environment properties. A default value of 2.3.5 is given to allow the tests to run locally without having to set the version.

addSbtPlugin("com.typesafe.play" % "sbt-plugin" % System.getProperty("playTestVersion", "2.3.5"))

Finally, we update .travis.yml to take advantage of this.

language: scala
jdk:
- openjdk6
scala:
- 2.11.1
script:
- cd code
- sbt ++$TRAVIS_SCALA_VERSION +test
- cd ../test-app
- sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.1 +test
- sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.2 +test
- sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.3 +test
- sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.4 +test
- sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.5 +test
- cd ../code
- sbt ++$TRAVIS_SCALA_VERSION +publish-local
after_success:
- ! '[[ $TRAVIS_BRANCH == "master" ]] && { sbt +publish; };'
env:
global:
- secure: foo
- secure: bar

This means the following steps occur during the build:

  • sbt ++$TRAVIS_SCALA_VERSION +test
    • Run the plugin tests against Scala 2.11.1
    • Run the plugin tests against Scala 2.10.4
  • sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.1 +test
    • Run the functional tests of the test-app against Scala 2.11.1 and Play 2.3.1
    • Run the functional tests of the test-app against Scala 2.10.4 and Play 2.3.1
  • sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.2 +test
    • Run the functional tests of the test-app against Scala 2.11.1 and Play 2.3.2
    • Run the functional tests of the test-app against Scala 2.10.4 and Play 2.3.2
  • sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.3 +test
    • Run the functional tests of the test-app against Scala 2.11.1 and Play 2.3.3
    • Run the functional tests of the test-app against Scala 2.10.4 and Play 2.3.3
  • sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.4 +test
    • Run the functional tests of the test-app against Scala 2.11.1 and Play 2.3.4
    • Run the functional tests of the test-app against Scala 2.10.4 and Play 2.3.4
  • sbt ++$TRAVIS_SCALA_VERSION -DplayTestVersion=2.3.5 +test
    • Run the functional tests of the test-app against Scala 2.11.1 and Play 2.3.5
    • Run the functional tests of the test-app against Scala 2.10.4 and Play 2.3.5

If all these steps pass, the after_success branch of the build script will execute. If any of the steps fail, the build will break and the snapshots won’t be published.

You can take a look at a repository using this approach here: https://github.com/schaloner/deadbolt-2-java.

The resulting Travis build is available here: https://travis-ci.org/schaloner/deadbolt-2-java.

Deadbolt 2.3.2 released

After a fruitful weekend of coding (and DIY, but that’s not relevant to this), Deadbolt 2.3.2 has been released. The major change is that it’s available via Maven Central, so there’s no need to add a resolver for it.

This line can be removed from your build.sbt – don’t let the door hit its ass on the way out:

resolvers += Resolver.url("Objectify Play Repository", url("http://deadbolt.ws/releases/"))(Resolver.ivyStylePatterns)

NB Older versions of Deadbolt are not yet in Maven, so you’ll still need the resolver for versions < 2.3.2. I’ll be publishing them to Maven as and when time allows.

I used the following guides to prepare all three Deadbolt libraries (deadbolt-core, -java and -scala) to Sonatype:
Deploying to Sonatype :: http://www.scala-sbt.org/0.13/docs/Using-Sonatype.html
Publishing Scala libraries to Sonatype :: http://www.loftinspace.com.au/blog/publishing-scala-libraries-to-sonatype.html

DeadboltHandler#getSubject
The other change relates to DeadboltHandler#getSubject. Until now, this has been a synchronous call that returns the Subject itself. As of 2.3.2, it now returns something a bit nicer for a reactive architecture.

Scala
The signature of the DeadboltHandler trait has changed from def getSubject[A](request: Request[A]): Option[Subject] and is now def getSubject[A](request: Request[A]): Future[Option[Subject]]. It’s a simple procedure to update your code. In place of

override def getSubject[A](request: Request[A]): Option[Subject] = {
    Some(however you retrieve your user)
}

you can replace it with

override def getSubject[A](request: Request[A]): Future[Option[Subject]] = {
    Future(Some(however you retrieve your user))
}

Java
The signature of the DeadboltHandler interface has changed from Subject getSubject(Http.Context context) and is now F.Promise getSubject(Http.Context context).

Existing code which looks something like

public Subject getSubject(Http.Context context) {
    return AuthorisedUser.findByUserName("steve");
}

would now look like

public F.Promise getSubject(Http.Context context) {
    return F.Promise.promise(new F.Function0() {
        @Override
        public Subject apply() throws Throwable {
            return AuthorisedUser.findByUserName("steve");
        }
    });
}

All the code is available in GitHub.

If you have any questions or issues, please let me know.

Keep Playing!

JavaScript routing in Play 2 (Scala edition)

In my previous post, I covered using JavaScript routing in Play 2 Java applications. Here’s the Scala version. It’s pretty much a copy of the previous article, to make it independent.

One of the nicest features in Play 2, but one which doesn’t seem to be widely covered, is the
JavaScript routing that can be generated by the framework to make AJAX-based client code more maintainable. Here, I’m going to cover using this feature in a Scala-based Play 2 application.

Overview

It’s common to see calls in JavaScript making AJAX requests. Frequently, a library such as jQuery is used to provide support. For example, given a route

GET    /foo    controllers.Application.getAll()

a GET request can be made using the shorthand $.get method.

$.get("/foo", function( data ) {
  // do something with the response
});

A variant, in the case where parameters are required, needs a little bit more work.

GET    /foo    controllers.Application.get(personId: Long, taskId: Long)

var personId = $('#person').val();
var taskId = $('#item').val();
$.get("/foo?person=" + personId + '&task=' + taskId, 
      function( data ) {
        // do something with the response
      });

All this seems far removed from the easy style of Play applications, where interactions are idiomatic and typesafe. Happily, Play offers a feature called JavaScript routing. This allows us to use JS objects generated by the back-end, and so we can replace the code above with

var personId = $('#person').val();
var taskId = $('#item').val();
appRoutes.controllers.Application.get(personId, taskId).ajax({
  success: function( data ) {
    // do something with the response
  }
})

This will result in a GET request to /foo with personId and taskId as request parameters.

GET /foo?personId=personId&taskId=taskId

Changing the route file to use a RESTful-style URL of /foo/:personId/:taskId will result in the following call with no changes required to your JS code:

GET /foo/personId/taskId

Let’s take a look at what we need to do to achieve this.

The basics

Time to create our basic application. Using the command line, generate a new Play app

play new jsRoutingScala

Accept the default name of jsRoutingScala, and select the option for a Scala application.

 _ __ | | __ _ _  _| |
| '_ \| |/ _' | || |_|
|  __/|_|\____|\__ (_)
|_|            |__/

play! 2.1.5 (using Java 1.7.0_17 and Scala 2.10.0), http://www.playframework.org

The new application will be created in /tmp/jsRoutingScala

What is the application name? [jsRoutingScala]
> 

Which template do you want to use for this new application? 

  1             - Create a simple Scala application
  2             - Create a simple Java application

> 1
OK, application jsRoutingScala is created.

Have fun!

This will give us a basic controller called Application, and a couple of views. We still need to create a model class, so let’s do that now. In the app directory, create a package called models. In the models package, create a class called Person. Note the JSON read/write support – this will allow the controller to serialize and deserialize instances of Person between Scala and JSON.

package models

import anorm._
import anorm.SqlParser._
import play.api.Play.current
import play.api.db.DB
import play.api.libs.json._
import anorm.~

case class Person(id: Pk[Long] = NotAssigned, name: String)

object Person {

  val simple = {
    get[Pk[Long]]("person.id") ~
      get[String]("person.name") map {
      case id~name => Person(id, name)
    }
  }

  def insert(person: Person) = {
    DB.withConnection { implicit connection =>
      SQL(
        """
          insert into person values (
            (select next value for person_seq),
            {name}
          )
        """
      ).on(
        'name -> person.name
      ).executeInsert()
    } match {
      case Some(long) => long
      case None       => -1
    }
  }

  def delete(id: Long) = {
    DB.withConnection { implicit connection =>
      SQL("delete from person where id = {id}").on('id -> id).executeUpdate()
    }
  }

  def getAll: Seq[Person] = {
    DB.withConnection { implicit connection =>
      SQL("select * from person").as(Person.simple *)
    }
  }

  implicit object PersonReads extends Reads[Person] {
    def reads(json: JsValue): JsResult[Person] =
      JsSuccess[Person](Person(NotAssigned, (json \ "name").as[String]), JsPath())
  }

  implicit object PersonWrites extends Writes[Person] {
    def writes(person: Person) = Json.obj(
      "id" -> Json.toJson(person.id.get),
      "name" -> Json.toJson(person.name)
    )
  }
}

We’ll need a database, so edit the conf/application.conf and uncomment the following lines:

db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"

Because this example uses Anorm, we need to configure the database ourselves. In the conf folder, create a folder called evolutions that contains another folder, default. Create a file here called 1.sql, and copy the following into it:

# --- !Ups
create table person (
  id bigint not null,
  name varchar(255),
  constraint pk_person primary key (id))
;

create sequence person_seq;

# --- !Downs
SET REFERENTIAL_INTEGRITY FALSE;

drop table if exists person;

SET REFERENTIAL_INTEGRITY TRUE;

drop sequence if exists person_seq;

We’re now ready to build our controller.

The controller

In the controllers package, open the Application object. There’s already an index method, but we don’t need to change this.

The app will allow us to create, delete and get Person instances, and so we need methods to support these operations.

def getAll() = Action {
  Ok(Json.toJson(Person.getAll))
}

def delete(id: Long) = Action {
  Person.delete(id)
  Ok("Deleted " + id)
}

def create = Action { implicit request =>
  request.body.asJson match {
    case None => BadRequest
    case Some(json: JsValue) => {
      val person: Person = json.as[Person]
      val id = Person.insert(person)
      Ok(Json.obj(
        "id" -> id,
        "name" -> person.name
      ))
    }
  }
}

These methods cover our business logic, so we can add them to the routes file

GET     /person       controllers.Application.getAll()
DELETE  /person/:id   controllers.Application.delete(id: Long)
POST    /person       controllers.Application.create()

Add JS routing support

So far, so normal. We have business logic that can be accessed via HTTP calls, but no specialised JS support. We need to add another method to the controller that specifies which routes we want to be available in the JS routing object.

def jsRoutes = Action { implicit request =>
  Ok(Routes.javascriptRouter("appRoutes")(
    controllers.routes.javascript.Application.create,
    controllers.routes.javascript.Application.delete,
    controllers.routes.javascript.Application.getAll))
    .as("text/javascript")
}

This method will generate a JavaScript file that can be loaded into the client. We’ll see this when we get to the view. Because it’s something called from the client, we need to add another entry to the routes. It’s extremely important to note the placement of the route – it must precede the existing “/assets/*file” entry, otherwise that route will consume the request.

GET           /assets/js/routes             controllers.Application.jsRoutes()
GET           /assets/*file                 controllers.Assets.at(path="/public", file)

The view

Now we get to where the action is. The first step is to make our view aware of the JS routing code, and we do this by simply adding a script tag to views/main.scala.html

<script src="@controllers.routes.Application.jsRoutes()" type="text/javascript"></script>

We’re finally ready to use our JS routing object. The following code is an utterly basic single-page app that hooks into the get, create and delete functionality of the back-end. Copy and paste this code into your existing views/index.scala.html file, and then take a look at what it’s doing. You may notice this code is identical to that in the Java example.

@(message: String)

@main("Play 2 JavaScript Routing") {

    <fieldset>
        <form>
            <label for="personName">Name:
            <input type="text" name="personName" id="personName"/>
            <input type="button" value="Create" id="createPerson"/>
        </form>
    </fieldset>
    <ul id="peopleList">

    <script>
    var doc = $ (document);
    doc.ready (function() {
      // Delete a person
      doc.on ('click', '.deletePerson', function(e) {
        var target = $(e.target);
        var id = target.data('id');
        appRoutes.controllers.Application.delete(id).ajax( {
          success : function ( data ) {
            target.closest('li').remove();
          }
        });
      });

      // Create a new person
      $('#createPerson').click(function() {
        var personNameInput = $('#personName');
        var personName = personNameInput.val();
        if(personName && personName.length > 0) {
          var data = {
            'name' : personName
          };
          appRoutes.controllers.Application.create().ajax({
            data : JSON.stringify(data),
            contentType : 'application/json',
            success : function (person) {
              $('#peopleList').append('<li>' + person.name + ' <a href="#" data-id="' + person.id + '" class="deletePerson">Delete</a></li>');
                personNameInput.val('');
            }
          });
        }
      });

      // Load existing data from the server
      appRoutes.controllers.Application.getAll().ajax({
        success : function(data) {
          var peopleList = $('#peopleList');
          $(data).each(function(index, person) {
            peopleList.append('<li>' + person.name + ' <a href="#" data-id="' + person.id + '" class="deletePerson">Delete</a></li>');
          });
        }
      });
    }) ;
    </script>
}

There are three lines here that will generate calls to the server, namely

  • appRoutes.controllers.Application.delete(id).ajax
  • appRoutes.controllers.Application.create().ajax
  • appRoutes.controllers.Application.getAll().ajax

Let’s take delete as the example, since it takes a parameter.

  • appRoutes
    • Take a look at your Application class, and you’ll see the name appRoutes being given to the JS router. This forms the base of the namespace of the JS routing object, and means you can have multiple JS routing objects from different controllers imported into the same view because you can keep the names of each unique.
  • controllers.Application
    • This is the fully qualified name of the target controller. Note that it matches the FQN of the Scala object.
  • delete(id)
    • The method call, including parameters. This function will return an object called ajax which can be used to control the behaviour of the HTTP call.
  • ajax
    • This function makes the call to the server. It’s here that you add success and error callbacks, change the content-type of the request to match your back-end requirements, add PUT or POST data, etc.

Summary

That seemed like a lot of work, but most of it was creating the project. The actual JS routing represents a very small time investment, for a pretty good pay-off. It’s very easy to retrofit existing code to use this approach, and very simple to continue in this style once you experience the benefits.

Example application

You can find the example code from this article on GitHub: https://github.com/schaloner/jsRoutingScala

Java

This article covered how to use this feature from a Scala viewpoint. In a sibling article, Java support is also demonstrated. The differences between the two are minimal, and non-existent from a client-side perspective. You can read this article here.

JavaScript routing in Play 2 (Java edition)

One of the nicest features in Play 2, but one which doesn’t seem to be widely covered, is the
JavaScript routing that can be generated by the framework to make AJAX-based client code more maintainable. Here, I’m going to cover using this feature in a Java-based Play 2 application.

Overview

It’s common to see calls in JavaScript making AJAX requests. Frequently, a library such as jQuery is used to provide support. For example, given a route

GET    /foo    controllers.Application.getAll()

a GET request can be made using the shorthand $.get method.

$.get("/foo", function( data ) {
  // do something with the response
});

A variant, in the case where parameters are required, needs a little bit more work.

GET    /foo    controllers.Application.get(personId: Long, taskId: Long)

var personId = $('#person').val();
var taskId = $('#item').val();
$.get("/foo?person=" + personId + '&task=' + taskId, 
      function( data ) {
        // do something with the response
      });

All this seems far removed from the easy style of Play applications, where interactions are idiomatic and typesafe. Happily, Play offers a feature called JavaScript routing. This allows us to use JS objects generated by the back-end, and so we can replace the code above with

var personId = $('#person').val();
var taskId = $('#item').val();
appRoutes.controllers.Application.get(personId, taskId).ajax({
  success: function( data ) {
    // do something with the response
  }
})

This will result in a GET request to /foo with personId and taskId as request parameters.

GET /foo?personId=personId&taskId=taskId

Changing the route file to use a RESTful-style URL of /foo/:personId/:taskId will result in the following call with no changes required to your JS code:

GET /foo/personId/taskId

Let’s take a look at what we need to do to achieve this.

The basics

Time to create our basic application. Using the command line, generate a new Play app

play new jsRoutingJava

Accept the default name of jsRoutingJava, and select the option for a Java application.

 _ __ | | __ _ _  _| |
| '_ \| |/ _' | || |_|
|  __/|_|\____|\__ (_)
|_|            |__/

play! 2.1.5 (using Java 1.7.0_17 and Scala 2.10.0), http://www.playframework.org

The new application will be created in /tmp/jsRoutingJava

What is the application name? [jsRoutingJava]
> 

Which template do you want to use for this new application? 

  1             - Create a simple Scala application
  2             - Create a simple Java application

> 2
OK, application jsRoutingJava is created.

Have fun!

This will give us a basic controller called Application, and a couple of views. We still need to create a model class, so let’s do that now. In the app directory, create a package called models. In the models package, create a class called Person.

package models;

import play.db.ebean.Model;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.util.List;

@Entity
public class Person extends Model
{
    private static Finder FIND = new Finder<>(Long.class, Person.class);
															
    @Id
    public Long id;
	
    public String name;
	
    public static List getAll()
    {
        return FIND.all();
    }
	
    public static Person getById(Long id)
    {
        return FIND.byId(id);
    }
}

We’ll need a database, so edit the conf/application.conf and uncomment the following lines:

db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
ebean.default="models.*"

We’re now ready to build our controller.

The controller

In the controllers package, open the Application class. There’s already an index method, but we don’t need to change this.

The app will allow us to create, delete and get Person instances, and so we need methods to support these operations.

public static Result getAll()
{
    return ok(Json.toJson(Person.getAll()));
}

public static Result delete(Long id)
{
    Result result;
    Person person = Person.getById(id);
    if (person == null)
    {
        person.delete();
        result = ok(person.name + " deleted");
    }
    else
    {
        result = notFound(String.format("Person with ID [%d] not found", id));
    }
    return result;
}

public static Result create()
{
    JsonNode json = request().body().asJson();
    Person person = Json.fromJson(json, Person.class);
    person.save();
    return ok(Json.toJson(person));
}

These methods cover our business logic, so we can add them to the routes file

GET     /person       controllers.Application.getAll()
DELETE  /person/:id   controllers.Application.delete(id: Long)
POST    /person       controllers.Application.create()

Add JS routing support

So far, so normal. We have business logic that can be accessed via HTTP calls, but no specialised JS support. We need to add another method to the controller that specifies which routes we want to be available in the JS routing object.

public static Result jsRoutes()
{
    response().setContentType("text/javascript");
    return ok(Routes.javascriptRouter("appRoutes", //appRoutes will be the JS object available in our view
                                      routes.javascript.Application.getAll(),
                                      routes.javascript.Application.delete(),
                                      routes.javascript.Application.create()));
}

This method will generate a JavaScript file that can be loaded into the client. We’ll see this when we get to the view. Because it’s something called from the client, we need to add another entry to the routes. It’s extremely important to note the placement of the route – it must precede the existing “/assets/*file” entry, otherwise that route will consume the request.

GET           /assets/js/routes             controllers.Application.jsRoutes()
GET           /assets/*file                 controllers.Assets.at(path="/public", file)

The view

Now we get to where the action is. The first step is to make our view aware of the JS routing code, and we do this by simply adding a script tag to views/main.scala.html

<script src="@controllers.routes.Application.jsRoutes()" type="text/javascript"></script>

We’re finally ready to use our JS routing object. The following code is an utterly basic single-page app that hooks into the get, create and delete functionality of the back-end. Copy and paste this code into your existing views/index.scala.html file, and then take a look at what it’s doing.

@(message: String)

@main("Play 2 JavaScript Routing") {

    <fieldset>
        <form>
            <label for="personName">Name:
            <input type="text" name="personName" id="personName"/>
            <input type="button" value="Create" id="createPerson"/>
        </form>
    </fieldset>
    <ul id="peopleList">

    <script>
    var doc = $ (document);
    doc.ready (function() {
      // Delete a person
      doc.on ('click', '.deletePerson', function(e) {
        var target = $(e.target);
        var id = target.data('id');
        appRoutes.controllers.Application.delete(id).ajax( {
          success : function ( data ) {
            target.closest('li').remove();
          }
        });
      });

      // Create a new person
      $('#createPerson').click(function() {
        var personNameInput = $('#personName');
        var personName = personNameInput.val();
        if(personName && personName.length > 0) {
          var data = {
            'name' : personName
          };
          appRoutes.controllers.Application.create().ajax({
            data : JSON.stringify(data),
            contentType : 'application/json',
            success : function (person) {
              $('#peopleList').append('<li>' + person.name + ' <a href="#" data-id="' + person.id + '" class="deletePerson">Delete</a></li>');
                personNameInput.val('');
            }
          });
        }
      });

      // Load existing data from the server
      appRoutes.controllers.Application.getAll().ajax({
        success : function(data) {
          var peopleList = $('#peopleList');
          $(data).each(function(index, person) {
            peopleList.append('<li>' + person.name + ' <a href="#" data-id="' + person.id + '" class="deletePerson">Delete</a></li>');
          });
        }
      });
    }) ;
    </script>
}

There are three lines here that will generate calls to the server, namely

  • appRoutes.controllers.Application.delete(id).ajax
  • appRoutes.controllers.Application.create().ajax
  • appRoutes.controllers.Application.getAll().ajax

Let’s take delete as the example, since it takes a parameter.

  • appRoutes
    • Take a look at your Application class, and you’ll see the name appRoutes being given to the JS router. This forms the base of the namespace of the JS routing object, and means you can have multiple JS routing objects from different controllers imported into the same view because you can keep the names of each unique.
  • controllers.Application
    • This is the fully qualified name of the target controller. Note that it matches the FQN of the Java class.
  • delete(id)
    • The method call, including parameters. This function will return an object called ajax which can be used to control the behaviour of the HTTP call.
  • ajax
    • This function makes the call to the server. It’s here that you add success and error callbacks, change the content-type of the request to match your back-end requirements, add PUT or POST data, etc.

Summary

That seemed like a lot of work, but most of it was creating the project. The actual JS routing represents a very small time investment, for a pretty good pay-off. It’s very easy to retrofit existing code to use this approach, and very simple to continue in this style once you experience the benefits.

Happy new year.

Example application

You can find the example code from this article on GitHub: https://github.com/schaloner/jsRoutingJava

Scala

This article covered how to use this feature from a Java viewpoint. In a sibling article, Scala support is also demonstrated. The differences between the two are minimal, and non-existent from a client-side perspective. The Scala article will be available soon is available here.

Functional tests in Play! 2 with REST-assured

In the Play! documentation, several flavours of functional testing are mentioned, including starting a HTTP server for the duration of the test – this is very useful for testing web services. In code, this looks like

import static play.test.Helpers.*;
...
@Test
public void testInServer() {
  running(testServer(3333), new Callback0() {
      public void invoke() {
         assertThat(
           WS.url("http://localhost:3333").get().get().status
         ).isEqualTo(OK);
      }
  });
}

A few days ago, when I was looking for a good way to test applications built on a CXF stack, I came across REST-assured. It was simple, elegant and useful so it’s the one I picked. In that case, I had to build some extra support for handling Jetty start-up and shutdown, application loading, etc.

With the full-stack approach of Play, however, you get this support for free out of the box, so all that is left is to integrate the tool of your choice. To add REST-assured to your project, edit the project/Build.scala file and add the dependency. If you already have Play running, don’t forget to reload the project for the changes to be visible.

val appDependencies = Seq(
    "com.jayway.restassured" % "rest-assured" % "1.7" % "test"
)

The above example re-written to use REST-assured then looks like this:

import static play.test.Helpers.*;
import com.jayway.restassured.RestAssured;
...
@Test
public void testInServer() {
  running(testServer(3333), new Runnable() {
      public void run() {
         RestAssured.expect().statusCode(200).when().get("http://localhost:3333");
      }
  });
}

REST-assured defaults to localhost for requests, so it’s possible to cut down on the boilerplate and use relative URLs by tweaking the configuration a little.

import static play.test.Helpers.*;
import com.jayway.restassured.RestAssured;
...
private static final int PORT = 3333;

@Before
public void setUp()
{
    RestAssured.port = PORT;
}
...
@Test
public void testInServer() {
  running(testServer(PORT), new Runnable() {
      public void run() {
         RestAssured.expect().statusCode(200).when().get("/");
      }
  });
}

I’ve written a small example that’s available on github, and here’s a sample from it which features an entity being persisted, and then retrieved for testing.

@Test
public void testGetBeer_present()
{
    running(testServer(PORT), new Runnable()
    {
        @Override
        public void run()
        {
            // Create the beer
            RestAssured.given()
                       .contentType(ContentType.JSON)
                       .content("{\"name\":\"Westmalle\"}")
                       .expect()
                       .statusCode(200)
                       .when()
                       .post("/");

            // Retrieve it by name, and bind the response body into a Beer instance
            Beer beer = RestAssured.expect()
                                   .statusCode(200)
                                   .when()
                                   .get("/Westmalle")
                                   .andReturn()
                                   .body()
                                   .as(Beer.class);
            Assert.assertEquals("Westmalle",
                                beer.name);
        }
    });
}

To run the tests, just start up Play in on your command line, and use the test command:

[play-rest-assured] $ test
[info] controllers.BeersTest
[info] + controllers.BeersTest.testGetAll_emptyDatabase
[info] + controllers.BeersTest.testGetAll_populatedDatabase
[info] + controllers.BeersTest.testGetBeer_emptyDatabase
[info] + controllers.BeersTest.testGetBeer_present
[info] + controllers.BeersTest.testUpdate
[info] 
[info] 
[info] Total for test controllers.BeersTest
[info] Finished in 6.954 seconds
[info] 5 tests, 0 failures, 0 errors
[info] Passed: : Total 5, Failed 0, Errors 0, Passed 5, Skipped 0
[success] Total time: 7 s, completed Oct 29, 2012 7:37:52 AM

Resources

Thoughts on the Belgian Play! Framework User Group dojo

The 3rd of October saw the Belgian Play! Framework User Group hold its first coding dojo and overall, it was a success. It’s the first time I’ve been involved in the organisation of anything like this, although the vast majority of the preparation was done by Ben Verbeken.

We had 17 people at the dojo, plus a DBA who stopped by for an hour because he’s interested in how developers and DBAs can work more efficiently together. We had an application specification from an idea by Andy Petrella, along with a reference implementation coded by Ben, Andy and me. We had a meeting room and refreshments provided by Cegeka. In short, we had everything we needed to have a dojo.

Ben has already covered the application in his post on the dojo, so in the spirit of DRY and general laziness I’ll kindly allow you to read about it on his site. Here, I want to cover the bits we got right, the bits we got wrong and how we can correct or improve in the future.

The good

  • The first thing we got right was to actually organise the dojo in the first place. Everything else, good or bad, stems from this.
  • In place of having two people at the front of the room, with a constant rotation of the group’s members, a wireless keyboard was used and passed to the left at the end of each 10 minute time block. This saved time, and meant that the group wasn’t split up into the watching and the watched.
  • Purely by accident, one of the most experienced members of the group (Andy) was sitting pretty much in the middle, and was the first to code after the 10 minute break. The people who coded in the first half of the dojo got an application up and running, and then Andy kicked it up a notch by adding the Twitter4J dependency and coded up to the point of actually posting to Twitter. The effect of seeing the app interact with an external system with just a few minutes’ coding sparked quite a bit of interest and discussion.
  • On the subject of Twitter, we set up a QuickQuizzz application in Twitter ready for use in the dojo. Doing this during the dojo would have been pointless, because it didn’t directly relate to Play! in any way.
  • We ended up with a working application that (pretty much) met the spec! You can find the code on github.

The bad

  • No wifi! Due to a miscommunication, we didn’t get the password for the wifi network and instead had to turn a laptop on the wired network into a wireless access point. The resulting connection was very slow!
  • No choice of IDE! We had IntelliJ set up as the IDE, but it seems that a lot of people preferred Eclipse.
  • The keyboard moved in a linear fashion, always passing to the left. This meant you knew exactly when it was your turn, but also you knew exactly when it was *no longer* your turn. This ties in with the next point, which is…
  • Each person coded only once.
  • The idea for the app was mentioned at the beginning of the dojo, but not written down in a visible place. As a result, we had to clarify the idea throughout the evening.

Improvements for the next dojo

  • Full-speed network access is a must. At least one person didn’t have Play installed at the start of the dojo, and found it impossible to download due to the poor wireless bandwidth.
  • A choice of IDEs – IntelliJ, Eclipse and Netbeans – will be offered, along with a few text editors for people that don’t like or use IDEs.
  • The next person to code should be determined by something other than seating order – maybe numbered cards picked at random, or an app that chooses a name.
  • Because the overhead on switching between coders is reduced by using a wireless keyboard instead of having people physically move, each person should be able to code for e.g. 5 minute time blocks at multiple times during the evening. This would allow everyone to code before the break, at which point the random ordering can start again.
  • The spec should be written up as a very simple bullet list. A second list, with optional functionality, could be introduced if the app has been finished and there is still time left.

And next…?

The rest of the year looks to be pretty busy, with Devoxx coming up in November, plus day jobs, everyone seems to be doing the Coursera Scala course, etc, and then it’s the holiday season again. I think we’ll hold another event early in 2013 – not necessarily a dojo this time, because we have some other ideas to keep it interesting. In the meantime, Play BE will be having another meet-up in Brussels one evening – bring your friends, bring your laptop, bring your ideas and join us there! Details will be announced on http://play-be.org soon.

PlayBe Dojo – all seats booked, and ready to go

With less than a week to go until the Belgian Play! Framework User Group holds its first coding dojo, all 20 places have now been taken.  I was half-way through a blog post to promote it when person #20 signed up, so instead I’m going to flip this over and quickly look at how having an active event can really drive up interest in your user group.

The far more organised co-founder of the usre group, Ben Verbeken, has written about the upcoming dojo here – http://ostia.be/blog/2012/09/18/playbe-first-dojo/

Here’s a chart showing sign-up activity for the group since we started it a few months ago.  We’ve had a couple of meet-ups in the meantime, and have all come into contact with like-minded others.  So far, so good – but notice the lull in sign-up activity in the middle of the chart.

In the first few days, about 18 people joined – and I think a couple of those were people who join any meetup in their area.  Since we announced the dojo, the group has pretty much doubled in size.  The lesson I’m taking from this?  Developers want to develop – having a drink and a chat is all well and good, and our past meet-ups have been good evenings, but it’s not quite the same as sitting down together and creating something new in a couple of hours.

I think that, in future, coding will be a fixture of the meet-ups.  There’s no better way to discuss development than to actually bang some code out there and then.  Using Play, you already have a head start on creating an app in a few minutes which can then be evolved by the others around you.  So, the dojo will (hopefully) be a great night with a structured plan but there’s no reason why every meet-up shouldn’t be the equivalent of several concurrent dojos.

If you would like to join the Belgian Play! Framework User Group, head over to http://play-be.org – it’s free, and there’s a lot of fun ahead of us.

Controlling distributed presentations

In a previous post, I talked about how a projector failure at the 010DEV event resulted in the presentation using laptops, smartphones and tablets to display the slides. One of the problems here, as noted by speaker Trisha Gee, is that on every device the next slide must be manually selected.

A couple of weeks ago, I came up with the idea of FilthyHackFriday – the idea being that you take a problem, and code up a quick’n’dirty solution in 30 minutes as a proof of concept. For my first FHF project, I chose to address this problem and wrote DistPres. It lets you upload Powerpoint or PDF presentations and converts each slide to an image. When you view a presentation, AJAX polling checks for changes to the current slide index and updates the view accordingly. You can control the presentation using the left and right arrow keys, and reset it to the first slide using the R key.

The use-case for this as follows. You’re in an upstairs room in a bar, trying to give a presentation but the projector doesn’t want to join in. So, you fire up DistPres and upload your presentation. Everyone points their device to your web server, and selects the correct presentation. From that point on, every time you change a slide everyone else will get the new slide automatically within a second.

Here’s an example using a presentation I downloaded from Slideshare. Three browsers – Chrome, Firefox and an Android emulator – are viewing the same presentation. When I use the left/right arrow keys (or, technically, just the right arrow key in this video), the current slide is updated in each browser within a second.

DistPres example using Chome, Firefow and an Android emulator from Steve Chaloner on Vimeo.

Notes:
– It’s quick and dirty, but it works.
– With some cleaning up it could actually be pretty handy.
– It’s written using Play 2
– Originally I wrote it using WebSockets, but that automatically excludes certain browers and devices. AJAX polling opens the field a bit more.

You can find the code on GitHub here, or download it directly from here.

Play’s Build.scala file – a very subtle gotcha

Work on the new module repository for Play is progressing nicely, but a very subtle bug was introduced into the Build.scala file. As a result, artifacts from the first repository were not being found. Can you spot the difference here? The first code snippet is correct, and the second is faulty.

val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings (
    resolvers += Resolver.url("Objectify Play Repository", url("http://schaloner.github.com/releases/"))(Resolver.ivyStylePatterns),
    resolvers += Resolver.url("Scala Tools", url("http://scala-tools.org/repo-releases/"))(Resolver.ivyStylePatterns)
  )
val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings {
    resolvers += Resolver.url("Objectify Play Repository", url("http://schaloner.github.com/releases/"))(Resolver.ivyStylePatterns)
    resolvers += Resolver.url("Scala Tools", url("http://scala-tools.org/repo-releases/"))(Resolver.ivyStylePatterns)
  }

The problem was caused by using curly brackets instead of parentheses. Note also that when using curly brackets, you can’t put a comma after the first resolver. However, the file still compiles without a problem. Very subtle, very annoying!

So, the correct form is the first snippet above – here with bold to emphasise the key points.

val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings (
    resolvers += Resolver.url("Objectify Play Repository", url("http://schaloner.github.com/releases/"))(Resolver.ivyStylePatterns),
    resolvers += Resolver.url("Scala Tools", url("http://scala-tools.org/repo-releases/"))(Resolver.ivyStylePatterns)
  )

Play 2 – modules, plugins, what’s the difference?

There seems to be some confusion regarding Play 2 modules and plugins. I imagine this is because the two are often synonymous. In Play (both versions – 1 and 2) there are distinct differences. In this post, I’m going to look at what a plugin is, how to implement one in Java and Scala, and how to import plugins from modules.

Plugins

A Play 2 plugin is a class that extends the Java class play.Plugin or has the Scala trait play.api.Plugin. This class may be something you have written in your own application, or it may be a plugin from a module.

Writing a plugin in Java

Create a new class, and have it extend play.Plugin. There are three methods available to override – onStart(), onStop() and enabled(). You can also add a constructor that takes a play.Application argument.

To have some functionality occur when the application starts, override onStart(). To have functionality occur when the application stops, override onStop(). It’s that simple! Here’s an example implementation which doesn’t override enabled().

package be.objectify.example;

import play.Application;
import play.Configuration;
import play.Logger;
import play.Plugin;

/**
 * An example Play 2 plugin written in Java.
 */
public class MyExamplePlugin extends Plugin
{
    private final Application application;

    public MyExamplePlugin(Application application)
    {
        this.application = application;
    }

    @Override
    public void onStart()
    {
        Configuration configuration = application.configuration();
        // you can now access the application.conf settings, including any custom ones you have added
        Logger.info("MyExamplePlugin has started");
    }

    @Override
    public void onStop()
    {
        // you may want to tidy up resources here
        Logger.info("MyExamplePlugin has stopped");
    }
}

Writing a plugin in Scala

Create a new Scala class, and have it extends play.api.Plugin. Just as in the Java version, there are onStart(), onStop() and enabled() methods along with an play.api.Application constructor argument. Here’s the Scala implementation:

package be.objectify.example

import play.api.{Logger, Application, Plugin}

/**
 * An example Play 2 plugin written in Scala.
 */
class MyExamplePlugin(application: Application) extends Plugin
{
  override def onStart()
  {
    val configuration = application.configuration;
    // you can now access the application.conf settings, including any custom ones you have added
    Logger.info("MyExamplePlugin has started");
  }

  override def onStop()
  {
    // you may want to tidy up resources here
    Logger.info("MyExamplePlugin has stopped");
  }
}

Hooking a plugin into your application

Regardless of the implementation language, plugins are invoked directly by Play once you have added them to the conf/play.plugins file. This file isn’t created when you start a new application, so you need to add it yourself. The syntax is <priority>:<classname>. For example, to add the example plugin to your project, you would use

10000:be.objectify.example.MyExamplePlugin

The class name is that of your plugin. The priority determines the order in which plugins start up, and just needs to be a number that is larger or smaller than that of another plugin. If you have several plugins, you can explicitly order them:

5000:be.objectify.example.MyExamplePlugin
10000:be.objectify.example.MyOtherExamplePlugin

Modules

A module can be thought of as a reusable application that you can include in your own app. It’s analogous to a third-party library that adds specific functionality. A module can contain plugins, which you can hook into your app using the conf/play.plugins file.

For example, if you’re using Deadbolt 2 you would need to add the following to your play.plugins file:

10000:be.objectify.deadbolt.DeadboltPlugin

A list of Play 2 modules can be found on the Play 2 GitHub wiki.

You can read more on creating modules for Play 2 here and here.