Category Archives: play! framework

Deadbolt 2 in 10 minutes – Scala edition

Deadbolt 2 is an authorization library for Play 2, and features APIs for both Java- and Scala-based applications. It allows you to apply constraints to controller actions, and to customize template rendering based on the current user.

Here’s a short, fast guide to getting started with the Scala version.

Dependencies

Add the dependency to your build

"be.objectify" %% "deadbolt-scala" % "2.4.2"

Add the Deadbolt module to your Play application

play {
    modules {
        enabled += be.objectify.deadbolt.scala.DeadboltModule
    }
}

If you’re already running your app in activator, don’t forgot to reload the project.

Domain model

Implement the Subject, Role and Permission traits.

  • Subject represents, typically, a user
  • A Role is a single system privilege, e.g. **admin**, **user** and so on. A subject can have zero or more roles.
  • A Permission is a can be used with regular expression matching, e.g. a subject with a permission of `printers.admin` can access a resource constrained to `printers.*`, `*.admin`, etc. A subject can have zero or more permissions.

Hooks

Implement the be.objectify.deadbolt.scala.DeadboltHandler trait. This implementation (or implementations – you can more than one) is used to

  • get the current user – getSubject
  • run a pre-authorization task that can block further execution – beforeAuthCheck
  • handle authorization failure – onAuthFailure
  • provide a hook into the dynamic constraint types – getDynamicResourceHandler

You only need to implement be.objectify.deadbolt.scala.DynamicResourceHandler if you’re planning to use Dynamic or Pattern.CUSTOM constraints. Dynamic constraints are tests implemented entirely by your code. This trait has two functions:

  • isAllowed is used by the Dynamic constraint
  • checkPermission is used by the Pattern constraint when the pattern type is CUSTOM

Implement the be.objectify.deadbolt.scala.HandlerCache trait. This is used by Deadbolt to obtain instances of DeadboltHandler‘s, and has two concepts

  1. A default handler. You can always use a specific handler in a template or controller, but if nothing is specified a well-known instance will be used.
  2. Named handlers.

An example implementation follows, based on the sample app.

@Singleton
class MyHandlerCache extends HandlerCache {
    val defaultHandler: DeadboltHandler = new MyDeadboltHandler

    // HandlerKeys is an user-defined object, containing instances of a case class that extends HandlerKey  
    val handlers: Map[Any, DeadboltHandler] = Map(HandlerKeys.defaultHandler -> defaultHandler,
                                                  HandlerKeys.altHandler -> new MyDeadboltHandler(Some(MyAlternativeDynamicResourceHandler)),
                                                  HandlerKeys.userlessHandler -> new MyUserlessDeadboltHandler)

    // Get the default handler.
    override def apply(): DeadboltHandler = defaultHandler

    // Get a named handler
    override def apply(handlerKey: HandlerKey): DeadboltHandler = handlers(handlerKey)
}

Finally, expose your handlers to Deadbolt. To do this, you will need to create a small module that binds your handler cache by type…

package com.example.modules

import be.objectify.deadbolt.scala.cache.HandlerCache
import play.api.inject.{Binding, Module}
import play.api.{Configuration, Environment}
import com.example.security.MyHandlerCache

class CustomDeadboltHook extends Module {
    override def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = Seq(
        bind[HandlerCache].to[MyHandlerCache]
    )
}

…and add it to your application.conf

play {
    modules {
        enabled += be.objectify.deadbolt.scala.DeadboltModule
        enabled += com.example.modules.CustomDeadboltHook
    }
}

Using compile-time dependency injection

If you prefer to wire everything together with compile-time dependency, you don’t need to create a custom module or add DeadboltModule to play.modules.

Instead, dependencies are handled using a custom ApplicationLoader. To make things easier, various Deadbolt components are made available via the be.objectify.deadbolt.scala.DeadboltComponents trait. You will still need to provide a couple of things, such as your HandlerCache implementation, and you’ll then have access to all the usual pieces of Deadbolt.

Here’s an example ApplicationLoader for compile-time DI.

class CompileTimeDiApplicationLoader extends ApplicationLoader  {
  override def load(context: Context): Application 
             = new ApplicationComponents(context).application
}

class ApplicationComponents(context: Context) 
                            extends BuiltInComponentsFromContext(context) 
                            with DeadboltComponents
                            with EhCacheComponents {

  // Define a pattern cache implementation
  // defaultCacheApi is a component from EhCacheComponents
  override lazy val patternCache: PatternCache = new DefaultPatternCache(defaultCacheApi)

  // Declare something required by MyHandlerCache
  lazy val subjectDao: SubjectDao = new TestSubjectDao

  // Specify the DeadboltHandler implementation to use
  override lazy val handlers: HandlerCache = new MyHandlerCache(subjectDao) 

  // everything from here down is application-level
  // configuration, unrelated to Deadbolt, such as controllers, routers, etc
  // ...
}

The components provided by Deadbolt are

  • scalaAnalyzer – constraint logic
  • deadboltActions – for composing actions
  • actionBuilders – for building actions
  • viewSupport – for template constraints
  • patternCache – for caching regular expressions. You need to define this yourself in the application loader, but as in the example above it’s easy to use the default implementation
  • handlers – the implementation of HandlerCache that you provide
  • configuration – the application configuration
  • ecContextProvider – the execution context for concurrent operations. Defaults to scala.concurrent.ExecutionContext.global
  • templateFailureListenerProvider – for listening to Deadbolt-related errors that occur when rendering templates. Defaults to a no-operation implementation

Once you’ve defined your ApplicationLoader, you need to add it to your application.conf.

play {
  application {
    loader=com.example.myapp.CompileTimeDiApplicationLoader
  }
}

Whichever injection approach you take, you’re now ready to secure access to controller functions and templates in your Play 2 application.

Controller constraints with the action builder

Using the ActionsBuilders class, you can quickly assemble constraints around your functions. To get started, inject ActionBuilders into your controller.

class ExampleController @Inject() (actionBuilder: ActionBuilders) extends Controller

You now have builders for all the constraint types, which we’ll take a quick look at in a minute. In the following examples I’m using the default handler, i.e. .defaultHandler() but it’s also possible to use a different handler with .key(HandlerKey) or pass in a handler directly using .withHandler(DeadboltHandler).

SubjectPresent and SubjectNotPresent

Sometimes, you don’t need fine-grained checks – you just need to see if there is a user present (or not present).

// DeadboltHandler#getSubject must result in a Some for access to be granted
def someFunctionA = actionBuilder.SubjectPresentAction().defaultHandler() { Ok(accessOk()) }

// DeadboltHandler#getSubject must result in a None for access to be granted
def someFunctionB = actionBuilder.SubjectNotPresentAction().defaultHandler() { Ok(accessOk()) }

Restrict

This uses the Subject‘s Roles to perform AND/OR/NOT checks. The values given to the builder must match the Role.name of the subject’s roles.

AND is defined as an Array[String] (or more correctly, String*, OR is a List[Array[String]], and NOT is a rolename with a ! preceding it.

// subject must have the "foo" role 
def restrictedFunctionA = actionBuilder.RestrictAction("foo").defaultHandler() { Ok(accessOk()) }

// subject must have the "foo" AND "bar" roles 
def restrictedFunctionB = actionBuilder.RestrictAction("foo", "bar").defaultHandler() { Ok(accessOk()) }

// subject must have the "foo" OR "bar" roles 
def restrictedFunctionC = actionBuilder.RestrictAction(List(Array("foo"), Array("bar"))).defaultHandler() { Ok(accessOk()) }

Pattern

This uses the Subject‘s Permissions to perform a variety of checks.

// subject must have a permission with the exact value "admin.printer" 
def permittedFunctionA = actionBuilders.PatternAction("admin.printer", PatternType.EQUALITY).defaultHandler() { Ok(accessOk()) }

// subject must have a permission that matches the regular expression (without quotes) "(.)*\.printer" 
def permittedFunctionB = actionBuilders.PatternAction("(.)*\.printer", PatternType.REGEX).defaultHandler() { Ok(accessOk()) }

// the checkPermssion function of the current handler's DynamicResourceHandler will be used.  This is a user-defined test 
def permittedFunctionC = actionBuilders.PatternAction("something arbitrary", PatternType.CUSTOM).defaultHandler() { Ok(accessOk()) }

Dynamic

The most flexible constraint – this is a completely user-defined constraint that uses DynamicResourceHandler#isAllowed to determine access.

    def foo = actionBuilder.DynamicAction(name = "someClassifier").defaultHandler() { Ok(accessOk()) }

Controller constraints with action composition

Using the DeadboltActions class, you can compose constrained functions. To get started, inject DeadboltActions into your controller.

    class ExampleController @Inject() (deadbolt: DeadboltActions) extends Controller

You now have functions equivalent to those of the builders mentioned above. In the following examples I’m using the default handler, i.e. no handler is specified, but it’s also possible to use a different handler with handler = <some handler, possibly from the handler cache>.

SubjectPresent and SubjectNotPresent

// DeadboltHandler#getSubject must result in a Some for access to be granted
def someFunctionA = deadbolt.SubjectPresent() {
    Action {
        Ok(accessOk())
    }
}

// DeadboltHandler#getSubject must result in a None for access to be granted
def someFunctionB = deadbolt.SubjectNotPresent() {
    Action {
        Ok(accessOk())
    }
}

Restrict

// subject must have the "foo" role 
def restrictedFunctionA = deadbolt.Restrict(List(Array("foo")) {
    Action {
        Ok(accessOk())
    }
}

// subject must have the "foo" AND "bar" roles 
def restrictedFunctionB = deadbolt.Restrict(List(Array("foo", "bar")) {
    Action {
        Ok(accessOk())
    }
}

// subject must have the "foo" OR "bar" roles 
def restrictedFunctionC = deadbolt.Restrict(List(Array("foo"), Array("bar"))) {
    Action {
        Ok(accessOk())
    }
}

Pattern

// subject must have a permission with the exact value "admin.printer" 
def permittedFunctionA = deadbolt.Pattern("admin.printer", PatternType.EQUALITY) {
    Action {
        Ok(accessOk())
    }
}

// subject must have a permission that matches the regular expression (without quotes) "(.)*\.printer" 
def permittedFunctionB = deadbolt.Pattern("(.)*\.printer", PatternType.REGEX) {
    Action {
        Ok(accessOk())
    }
}

// the checkPermssion function of the current handler's DynamicResourceHandler will be used.  This is a user-defined test in DynamicResourceHandler#checkPermission 
def permittedFunctionC = deadbolt.Pattern("something arbitrary", PatternType.CUSTOM) {
    Action {
        Ok(accessOk())
    }
}

Dynamic

The most flexible constraint – this is a completely user-defined constraint that uses DynamicResourceHandler#isAllowed to determine access.

def foo = deadbolt.Dynamic(name = "someClassifier") {
    Action {
        Ok(accessOk())
    }
}

Template constraints

Using template constraints, you can exclude portions of templates from being generated on the server-side. This is not a client-side DOM manipulation! Template constraints have the same possibilities as controller constraints.

By default, template constraints use the default Deadbolt handler but as with controller constraints you can pass in a specific handler. The cleanest way to do this is to pass the handler into the template and then pass it into the constraints. Another advantage of this approach is you can pass in a wrapped version of the handler that will cache the subject; if you have a lot of constraints in a template, this can yield a significant gain.

One important thing to note here is that templates are blocking, so any Futures used need to be completed for the resuly to be used in the template constraints. As a result, each constraint can take a function that expresses a Long, which is the millisecond value of the timeout. It defaults to 1000 milliseconds, but you can change this globally by setting the deadbolt.scala.view-timeout value in your application.conf.

Each constraint has a variant which allows you to define fallback content. This comes in the format `<constraintName>Or`, e.g.

@subjectPresentOr {
    this is protected
} {
    this will be shown if the constraint blocks the other content
}

SubjectPresent

@import be.objectify.deadbolt.scala.views.html.{subjectPresent, subjectPresentOr}

@subjectPresent() {
    This content will be present if handler#getSubject results in a Some 
}

@subjectPresentOr() {
    This content will be present if handler#getSubject results in a Some 
} {
    fallback content
}

SubjectNotPresent

@import be.objectify.deadbolt.scala.views.html.{subjectNotPresent, subjectNotPresentOr}

@subjectNotPresent() {
    This content will be present if handler#getSubject results in a None 
}

@subjectNotPresentOr() {
    This content will be present if handler#getSubject results in a None 
} {
    fallback content
}

Restrict

@import be.objectify.deadbolt.scala.views.html.{restrict, restrictOr}

@restrict(roles = List(Array("foo", "bar"))) {
    Subject requires the foo role for this to be visible
}

@restrict(List(Array("foo", "bar")) {
     Subject requires the foo AND bar roles for this to be visible
}

@restrict(List(Array("foo"), Array("bar"))) {
     Subject requires the foo OR bar role for this to be visible
}

@restrictOr(List(Array("foo", "bar")) {
     Subject requires the foo AND bar roles for this to be visible
} {
    Subject does not have the necessary roles
}

Pattern

The default pattern type is PatternType.EQUALITY.

@import be.objectify.deadbolt.scala.views.html.{pattern, patternOr}

@pattern("admin.printer") {
    Subject must have a permission with the exact value "admin.printer" for this to be visible
}

@pattern("(.)*\.printer", PatternType.REGEX) {
    Subject must have a permission that matches the regular expression (without quotes) "(.)*\.printer" for this to be visible
}

@pattern("something arbitrary", PatternType.CUSTOM) {
    DynamicResourceHandler#checkPermission must result in true for this to be visible
}

@patternOr("admin.printer") {
    Subject must have a permission with the exact value "admin.printer" for this to be visible
} {
    Subject did not have necessary permissions
}

Dynamic

@import be.objectify.deadbolt.scala.views.html.{dynamic, dynamicOr}

@dynamic("someName") {
    DynamicResourceHandler#isAllowed must result in true for this to be visible
}

@dynamicOr("someName") {
    DynamicResourceHandler#isAllowed must result in true for this to be visible
} {
    Custom test failed
}

Execution context

By default, all futures are executed in the `scala.concurrent.ExecutionContext.global` context. If you want to provide a separate execution context, you can plug it into Deadbolt by implementing the `DeadboltExecutionContextProvider` trait.

import be.objectify.deadbolt.scala.DeadboltExecutionContextProvider

class CustomDeadboltExecutionContextProvider extends DeadboltExecutionContextProvider {
    override def get(): ExecutionContext = ???
}

NB: This provider is invoked twice, once in DeadboltActions and once in ViewSupport.

Once you’ve implemented the provider, you need to declare it in your custom module (see introduction above).

class CustomDeadboltHook extends Module {
    override def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = Seq(
        bind[HandlerCache].to[MyHandlerCache],
        bind[DeadboltExecutionContextProvider].to[CustomDeadboltExecutionContextProvider]
    )
}

What next?

If you want to explore Deadbolt further, you might want to take a look at the book I’m currently writing on it. You can find it at https://leanpub.com/deadbolt-2.

large

Deadbolt 2 in 10 minutes – Java edition

Deadbolt 2 is an authorization library for Play 2, and features APIs for both Java- and Scala-based applications. It allows you to apply constraints to controller actions, and to customize template rendering based on the current user.

Here’s a short, fast guide to getting started with the Java version.

Dependencies

Add the dependency to your build.sbt file.

"be.objectify" %% "deadbolt-java" % "2.4.3"

Add the Deadbolt module to your conf/application.conf file.

play {
	modules {
		enabled += be.objectify.deadbolt.java.DeadboltModule
	}
}

If you’re already running your app in activator, don’t forgot to reload the project.

Domain model

Implement the Subject, Role and Permission interfaces.

  • Subject represents, typically, a user.
  • A Role is a single system privilege, e.g. admin, user and so on. A subject can have zero or more roles.
  • A Permission is a can be used with regular expression matching, e.g. a subject with a permission of printers.admin can access a resource constrained to printers.*, *.admin, etc. A subject can have zero or more permissions.

Hooks

Implement the be.objectify.deadbolt.java.DeadboltHandler interface. This implementation (or implementations – you can have more than one) is used to obtain the subject, apply dynamic constraints, execute pre-authorization tasks and define the behaviour when authorization fails.

  • get the current user – getSubject
  • run a pre-authorization task that can block further execution – beforeAuthCheck
  • handle authorization failure – onAuthFailure
  • provide a hook into the dynamic constraint types – getDynamicResourceHandler

You only need to implement be.objectify.deadbolt.java.DynamicResourceHandler if you’re planning to use Dynamic or Pattern.CUSTOM constraints. Dynamic constraints are tests implemented entirely by your code. This interface has two methods:

  • isAllowed is used by the Dynamic constraint
  • checkPermission is used by the Pattern constraint when the pattern type is CUSTOM

Implement the be.objectify.deadbolt.java.HandlerCache interface. This is used by Deadbolt to obtain an instance of DeadboltHandler, and has two concepts

  1. A default handler. You can always use a specific handler in a template or controller, but if nothing is specified a well-known instance will be used.
  2. Named handlers.

An example implementation follows, based on the sample app. You can, of course, define these any way you want to.

@Singleton
public class MyHandlerCache implements HandlerCache
{
    private final DeadboltHandler defaultHandler = new MyDeadboltHandler();
    private final Map<String, DeadboltHandler> handlers = new HashMap<>();

    public MyHandlerCache()
    {
        handlers.put(HandlerKeys.DEFAULT.key, defaultHandler);
        handlers.put(HandlerKeys.ALT.key, new MyAlternativeDeadboltHandler());
        handlers.put(HandlerKeys.BUGGY.key, new BuggyDeadboltHandler());
        handlers.put(HandlerKeys.NO_USER.key, new NoUserDeadboltHandler());
    }

    @Override
    public DeadboltHandler apply(final String key)
    {
        return handlers.get(key);
    }

    @Override
    public DeadboltHandler get()
    {
        return defaultHandler;
    }
}

Finally, expose your handlers to Deadbolt. To do this, you will need to create a small module that binds your handler cache by type.

package com.example.modules

import be.objectify.deadbolt.java.cache.HandlerCache;
import play.api.Configuration;
import play.api.Environment;
import play.api.inject.Binding;
import play.api.inject.Module;
import scala.collection.Seq;
import security.MyHandlerCache;

import javax.inject.Singleton;

public class CustomDeadboltHook extends Module
{
    @Override
    public Seq<Binding<?>> bindings(final Environment environment,
                                    final Configuration configuration)
    {
        return seq(bind(HandlerCache.class).to(MyHandlerCache.class).in(Singleton.class));
    }
}

…and add it to your application.conf

play {
    modules {
        enabled += be.objectify.deadbolt.java.DeadboltModule
        enabled += com.example.modules.CustomDeadboltHook
    }
}

Ready to rock
You’re now ready to secure access to controller functions and templates in your Play 2 application.

Controller constraints with the action builder

Controller constraints are defined through annotations.

SubjectPresent and SubjectNotPresent

Sometimes, you don’t need fine-grained checked – you just need to see if there is a user present (or not present).

@SubjectPresent
public F.Promise someMethodA() {
    // method will execute if the current DeadboltHandler's getSubject returns Some
}

@SubjectNotPresent
public F.Promise someMethodB() {
    // method will execute if the current DeadboltHandler's getSubject returns None
}

Restrict

This uses the Subjects Roles to perform AND/OR/NOT checks. The values given to the builder must match the Role.name of the subject’s roles.

AND is defined as an @Group OR is an array of @Group, and NOT is a rolename with a ! preceding it.

@Restrict(@Group("foo"))
public F.Promise someMethodA() {
    // method will execute of subject has the "foo" role
}

@Restrict(@Group("foo", "bar"))
public F.Promise someMethodB() {
    // method will execute of subject has the "foo" AND "bar" roles
}

@Restrict({@Group("foo"), @Group("bar")})
public F.Promise someMethodC() {
    // method will execute of subject has the "foo"OR "bar" roles
}

Pattern

This uses the Subjects Permissions to perform a variety of checks.

@Pattern("admin.printer")
public F.Promise someMethodA() {
    // subject must have a permission with the exact value "admin.printer"
}

@Pattern(value = "(.)*\.printer", patternType = PatternType.REGEX)
public F.Promise someMethodB() {
    // subject must have a permission that matches the regular expression (without quotes) "(.)*\.printer"
}

@Pattern(value = "something arbitrary", patternType = PatternType.CUSTOM)
public F.Promise someMethodC() {
    // the checkPermssion method of the current handler's DynamicResourceHandler will be used.  This is a user-defined test
}

If you want to invert the result, i.e. deny access if there’s a match, set the invert attribute to true.

@Pattern(value = "admin.printer", invert = true)
public F.Promise someMethodA() {
    // subject with a permission with the exact value "admin.printer" will by denied
}

Dynamic

The most flexible constraint – this is a completely user-defined constraint that uses DynamicResourceHandler#isAllowed to determine access.

@Dynamic(name = "name of the test")
public F.Promise someMethod() {
    // the method will execute if the user-defined test returns true
}

Template constraints

Using template constraints, you can exclude portions of templates from being generated on the server-side. This is not a client-side DOM manipulation! Template constraints have the same possibilities as controller constraints.

By default, template constraints use the default Deadbolt handler but as with controller constraints you can pass in a specific handler. The cleanest way to do this is to pass the handler into the template and then pass it into the constraints. Another advantage of this approach is you can pass in a wrapped version of the handler that will cache the subject; if you have a lot of constraints in a template, this can yield a significant gain.

One important thing to note here is that templates are blocking, so any Futures used need to be completed for the resuly to be used in the template constraints. As a result, each constraint can take a function that expresses a Long, which is the millisecond value of the timeout. It defaults to 1000 milliseconds, but you can change this globally by setting the deadbolt.java.view-timeout value in your application.conf.

Each constraint has a variant which allows you to define fallback content. This comes in the format xOr, e.g.

@subjectPresentOr {
	this is protected
} {
	this will be shown if the constraint blocks the other content
}

SubjectPresent

@import be.objectify.deadbolt.java.views.html.{subjectPresent, subjectPresentOr}

@subjectPresent() {
    This content will be present if handler#getSubject results in a Some 
}

@subjectPresentOr() {
    This content will be present if handler#getSubject results in a Some 
} {
	fallback content
}

SubjectNotPresent

@import be.objectify.deadbolt.java.views.html.{subjectNotPresent, subjectNotPresentOr}

@subjectNotPresent() {
    This content will be present if handler#getSubject results in a None 
}

@subjectNotPresentOr() {
    This content will be present if handler#getSubject results in a None 
} {
	fallback content
}

Restrict

la and as are convenience functions for creating a List[Array] and an Array[String]

@import be.objectify.deadbolt.java.views.html.{restrict, restrictOr}
@import be.objectify.deadbolt.core.utils.TemplateUtils.{la, as}

@restrict(roles = la(as("foo", "bar"))) {
    Subject requires the foo role for this to be visible
}

@restrict(roles = la(as("foo", "bar")) {
     Subject requires the foo AND bar roles for this to be visible
}

@restrict(roles = la(as("foo"), as("bar"))) {
     Subject requires the foo OR bar role for this to be visible
}

@restrictOr(roles = la(as("foo", "bar"))) {
     Subject requires the foo AND bar roles for this to be visible
} {
	Subject does not have the necessary roles
}

Pattern

The default pattern type is PatternType.EQUALITY.

@import be.objectify.deadbolt.java.views.html.{pattern, patternOr}

@pattern(value = "admin.printer") {
    Subject must have a permission with the exact value "admin.printer" for this to be visible
}

@pattern(value = "(.)*\.printer", patternType = PatternType.REGEX) {
	Subject must have a permission that matches the regular expression (without quotes) "(.)*\.printer" for this to be visible
}

@pattern(value = "something arbitrary", patternType = PatternType.CUSTOM) {
	DynamicResourceHandler#checkPermission must result in true for this to be visible
}

@patternOr(value = "admin.printer") {
    Subject must have a permission with the exact value "admin.printer" for this to be visible
} {
	Subject did not have necessary permissions
}

Dynamic

@import be.objectify.deadbolt.java.views.html.{dynamic, dynamicOr}
    
@dynamic(name = "someName") {
    DynamicResourceHandler#isAllowed must result in true for this to be visible
}
    
@dynamicOr(name = "someName") {
    DynamicResourceHandler#isAllowed must result in true for this to be visible
} {
	Custom test failed
}

JPA

If you’re using JPA, there’s a good chance you’re going to run into issues when entity managers are used across different threads. To address this, you can put Deadbolt into blocking mode – this ensures all DB calls made in the Deadbolt layer are made from the same thread; this has performance implications, but it’s unavoidable with JPA.

To switch to blocking mode, set deadbolt.java.blocking to true in your configuration.

The default timeout is 1000 milliseconds – to change this, use deadbolt.java.blocking-timeout in your configuration.

This example configuration puts Deadbolt in blocking mode, with a timeout of 2500 milliseconds:

deadbolt {
    java {
        blocking=true
        blocking-timeout=2500
    }
}

What next?

If you want to explore Deadbolt further, you might want to take a look at the book I’m currently writing on it. You can find it at https://leanpub.com/deadbolt-2.

large

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.