Writing modules for Play 2, part 1: Get something working

A couple of weeks ago, I migrated the Play! framework 1.x version of Deadbolt to the Play 2 platform, and was surprised at the lack of information on creating modules. This topic was covered in detail in the Play 1.x docs, and this made creating modules very simple. Clearly, something needed to be done – and so this is the first in a three-part series on creating modules and plugins for Play 2.

It’s important to note this is not a definitive guide – instead, it’s a collection of the information and techniques I’ve used when working on my own modules.

I’m going to assume you already have a working installation of Play 2 – if you don’t, head over to http://www.playframework.org/documentation/2.0/Installing for details on how to set this up.

In this first part, we’re going to cover the fundamentals of creating and publishing the module, and adding a sample application. The next two parts will go into greater depth on plugins, interceptors, tags and other useful tools.

First, a small note on the difference between a module and a library. In Play 1.x, a module was created using “play new-module” and distributed via the module repository. Up until Play 1.1, modules were controlled through application.conf entries, and libraries were added locally. From Play 1.2, both modules and libraries were controlled through the dependency management mechanism based on Ivy. In both cases, though, there was a clear concept of module (something tightly integrated with Play, which followed its conventions on package structure, etc) and a library (a general third-party library).

In Play 2, the line is blurred to some degree. Modules are now distributed in the same way as libraries, though Ivy or Maven, and the package structure can be arbitrary so you can have a traditional com.example.whatever structure. From this point of view, the only real difference between modules and libraries is that modules use the Play API directly.

Secondly, a note on language. Since both Java and Scala are natively supported by Play 2, you can implement your module in either language. If the module has its own API that applications can use, the superb interoperability between Java and Scala means your language choice is – in most cases – irrelevant to whichever application uses your API.

1. Getting started

As a simple introduction, we’re going to create a basic logging module that – following industry best practices – writes output to the console window. This module is called mylogger, because it’s Monday and I’m not feeling very creative right now. This module is going to be (mainly) written in Java.

You can think of a Play 2 module as being a Play 2 application with a couple of files missing. So, you create a module in the same way as you would an application. Go to, or create, a directory where you keep your projects, and use “play new mylogger” to create the app. Choose option 2 when prompted, to create a simple Java app.

steve@hex:/tmp$ play new mylogger
       _            _
 _ __ | | __ _ _  _| |
| '_ \| |/ _' | || |_|
|  __/|_|\____|\__ (_)
|_|            |__/

play! 2.0, http://www.playframework.org

The new application will be created in /tmp/mylogger

What is the application name?
> mylogger

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

  1 - Create a simple Scala application
  2 - Create a simple Java application
  3 - Create an empty project

> 2

OK, application mylogger is created.

Have fun!

Because we’re going to have a sample application alongside the module, we’re going to change the directory structure a little. At the moment, it looks like this:

mylogger
– app
– conf
– project
– public
– target
– .gitignore
– README

In the mylogger directory, create two new directories, project-code and samples. Copy all the files listed above into the project-code directory. You should now have

mylogger
– samples
– project-code
     – app
     – conf
     – project
     – public
     – target
     – .gitignore
     – README

The conf directory contains two files – routes, and application.conf.

- application.conf needs to be present for Play to recognise mylogger/project-code as a Play application, so we can’t delete it but we can remove everything it contains. Any configuration your module needs should be added to the application.conf of the “real” application.
- routes *must* be deleted. If you don’t do this, it may/will supercede the routes file of whichever application uses it, and this is A Bad Thing (mainly because nothing will work).

With application.conf emptied and routes deleted, type “play” in the project-code to start the Play console.

steve@hex:/tmp/mylogger/project-code$ play
[info] Loading project definition from /tmp/mylogger/project-code/project
[info] Set current project to mylogger (in build file://tmp/mylogger/project-code/)
       _            _
 _ __ | | __ _ _  _| |
| '_ \| |/ _' | || |_|
|  __/|_|\____|\__ (_)
|_|            |__/

play! 2.0, http://www.playframework.org

> Type "help play" or "license" for more information.
> Type "exit" or use Ctrl+D to leave this console.

[mylogger] $

We now have a valid Play 2 module (that, admittedly, doesn’t do anything).

If you use an IDE, this is a good time to create the project – this tutorial is IDE-agnostic, however, so you can use the guide at http://www.playframework.org/documentation/2.0/IDE if you want to do this.

2. Adding some functionality

As I mentioned above, Play 2 modules can have a more traditional package structure of com.example.whatever, but a default Play application has the tradtional app/controllers, app/models, etc, structure. We’ll keep this for now, and change it in later parts of this tutorial.

2.1 Slash and burn

In the app folder, we have the following structure as created for us by the “play new” command:

app
– controllers
     – Application.java
– views
     – index.scala.html
     – main.scala.html

For the initial iteration of this module, we don’t need any views so you can delete the views package.

You can also delete Application.java, as we’re writing this from scratch.

2.2 Add some module code

In the controllers package, create a new class called MyLogger.java. It doesn’t need to extend or implement anything, and it contains a single method:

package controllers;

/**
 * @author Steve Chaloner
 */
public class MyLogger
{
    public static void log(String message)
    {
        System.out.println("MyLogger: " + message);
    }
}

2.3 Have a beer

You’ve just written a module. Go have a beer.

2.4 Post-beer realisation

As you gaze into your now-empty glass, abuzz with the joy of creation and impending feeling of industry-wide fame, you might realize that no-one can actually get to your module because it’s sitting on your computer. You need to publish it.

3. Publish and be damned

For this example, we’re just going to publish to your local repository. In the root of your Play installation, there is a repository directory, and this is where you wil first push your module.

Before publishing, always ensure you have run a “clean”, otherwise some classes/files that you have removed from the source tree may still exist in compiled form and end up in your module jar file. If the class matches one that’s in your actual application, it can be called in place of your actual class. Which sucks.

In the Play console, use “clean” and then “publish-local” to package up your module and publish it to the local repo:

[mylogger] $ publish-local
[info] Updating {file:/tmp/mylogger/project-code/}mylogger...
[info] Packaging /tmp/mylogger/project-code/target/scala-2.9.1/mylogger_2.9.1-1.0-SNAPSHOT-sources.jar ...
[info] Done packaging.
[info] Wrote /tmp/mylogger/project-code/target/scala-2.9.1/mylogger_2.9.1-1.0-SNAPSHOT.pom
[info] Done updating.                                                                  
[info] :: delivering :: mylogger#mylogger_2.9.1;1.0-SNAPSHOT :: 1.0-SNAPSHOT :: release :: Mon Mar 19 20:57:26 CET 2012
[info] 	delivering ivy file to /tmp/mylogger/project-code/target/scala-2.9.1/ivy-1.0-SNAPSHOT.xml
[info] Compiling 1 Java source to /tmp/mylogger/project-code/target/scala-2.9.1/classes...
[info] Generating API documentation for main sources...
model contains 4 documentable templates
[info] Packaging /tmp/mylogger/project-code/target/scala-2.9.1/mylogger_2.9.1-1.0-SNAPSHOT.jar ...
[info] Done packaging.
[info] API documentation generation successful.
[info] Packaging /tmp/mylogger/project-code/target/scala-2.9.1/mylogger_2.9.1-1.0-SNAPSHOT-javadoc.jar ...
[info] Done packaging.
[info] 	published mylogger_2.9.1 to /home/steve/development/play/play-2.0/framework/../repository/local/mylogger/mylogger_2.9.1/1.0-SNAPSHOT/poms/mylogger_2.9.1.pom
[info] 	published mylogger_2.9.1 to /home/steve/development/play/play-2.0/framework/../repository/local/mylogger/mylogger_2.9.1/1.0-SNAPSHOT/jars/mylogger_2.9.1.jar
[info] 	published mylogger_2.9.1 to /home/steve/development/play/play-2.0/framework/../repository/local/mylogger/mylogger_2.9.1/1.0-SNAPSHOT/srcs/mylogger_2.9.1-sources.jar
[info] 	published mylogger_2.9.1 to /home/steve/development/play/play-2.0/framework/../repository/local/mylogger/mylogger_2.9.1/1.0-SNAPSHOT/docs/mylogger_2.9.1-javadoc.jar
[info] 	published ivy to /home/steve/development/play/play-2.0/framework/../repository/local/mylogger/mylogger_2.9.1/1.0-SNAPSHOT/ivys/ivy.xml
[success] Total time: 4 s, completed Mar 19, 2012 8:57:28 PM

If you take a look in $PLAY_HOME/repository/local, you’ll now see a directory called mylogger. Since we didn’t give an organisation name, the organisation is taken to be the same name as the module itself. Go into mylogger, and you’ll see the artifact – mylogger_2.9.1. The 2.9.1 part of the filename comes from Play itself, and is (appears to be) a versioning thing. If anyone knows more about this, please comment and let me know.

Inside mylogger_2.9.1, we have the module version, which in this case is 1.0-SNAPSHOT, and this in turn contains jar files, source jars, Maven and Iyy info, etc.

Where does all this information come from? It’s based on the project/Build.scala file. In here, you can give the name of the module, the organisation, the version, and various other pieces of information. For now, we’ll keep things as they are, but this extremely important file will be updated as we get deeper into some issues.

4. Providing a sample

You can write the best, most incredibly useful module in the world, but without a sample application to a) show it works, and b) show HOW it works, you’re going to have trouble convincing people of that. This is why we changed the directory structure back when we first created the module. Open another terminal, and go to the mylogger/samples diretory – it’s time to show what mylogger can do.

4.1 A sample application is…a Play application

Since we’re writing a Play module, it makes sense to provide a Play application as the sample. Now we’re in mylogger/samples, using “play new mylogger-sample” to create the sample application. Again, choose option 2 to make a simple Java application.

4.2 Declaring dependencies

In order to use mylogger, we must declare a dependency for it in mylogger-sample/project/Build.scala. Open this file, and change

val appDependencies = Seq(
      // Add your project dependencies here,
    )

to

val appDependencies = Seq(
      "mylogger" % "mylogger_2.9.1" % "1.0-SNAPSHOT"
    )

You can see this matches the repository path of mylogger/mylogger_2.9.1/1.0-SNAPSHOT.

In a brazen act of laziness, we’re also going to declare the local repository as the place to find our module. Change

val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings(
      // Add your own project settings here      
    )

to

  val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings(
    resolvers += "Local Play Repository" at "file://path/to/play-2.0/repository/local"
  )

(but change the path to be correct for your local installation)

In the mylogger/samples/mylogger-sample directory, start up the Play console using “play”. If you use the “dependencies” command, you’ll see that mylogger is now a dependency of the application.

IMPORTANT NOTE! Since we started the Play console after changing Build.scala, the changes were automatically picked up. If you change this file while the console is open, use “reload” to make sure the changes are used.

4.2 Using your module

In your new default Play application, we’re going to add a single line to controllers/Application.java to call MyLogger:

package controllers;

import play.mvc.Controller;
import play.mvc.Result;
import views.html.index;

public class Application extends Controller
{
    public static Result index()
    {
        MyLogger.log("Here's my log message");
        return ok(index.render("Your new application is ready."));
    }
}

Note that we don’t need to import MyLogger as it’s also in the controllers package.

“run” the application and go to http://localhost:9000. A brief time later, the page will render and in the console you’ll see

[info] play - Application started (Dev)
MyLogger: Here's my log message

Reload the page a few times, and you’ll see the log message appear every time.

5. Have another beer

Congratulations, you now have a module and a working sample. It doesn’t actually add much value to your sample app, but that’s something that will be addressed in part 2. In the meantime, head over the fridge and grab yourself another beer.

You can download the complete source code for this example here

Other parts to this tutorial series

Morocco and rape

If you’re a regular reader of this blog, you’ve possibly noticed a complete lack of political content. That’s exactly how I like it. However, I read an article earlier about Morocco that, as a father of a daughter*, makes me sick. It appears that in Morocco, it’s a girl’s responsibility to keep her virginity intact – even if she’s raped. That’s right – even if one of the most disgusting, cowardly crimes imaginable is perpetrated against you if you’re still a virgin, it’s your fault and you bring shame to your family.

Whoever devised this concept – even though it’s a national law, I refuse to refer to it as such – is evil.

I’m not religious. My wife’s not religious. My family is not religious. We have no concept of sin, as that’s a religious thing, but we are good people and we live in a way that is respectful to others. When I think of evil, I think of Biblical stories which use concepts of sin and evil.

You want to know my definition of evil? I can’t give it to you. I haven’t thought that much about it. But the thought of attaching blame to a rape victim – read that last word, VICTIM – and then forcing her to marry her attacker as a way of providing the rapist with a get-out-of-jail-free card…I don’t even need to think about that. It’s evil.

My daughter has been asking when we’ll go on holiday again. I’ve already started looking at places, and Morocco was one of those places. It’s not any more, and it won’t be until it decides that fundamental human rights apply to women too.

* I just re-read this after posting, and the “father of a daughter” line reads, to me, that if I didn’t have a daughter then I wouldn’t care. This is not the case – what is happening in Morocco is offensive to, I believe**, everyone.

** If you’re not offended by it, please explain to me why.

Play 2, Akka, Websockets, Backbone.js and Leaflet – just having fun, really

A few weeks ago, I started playing around with Backbone.js. At the end of last week, I noticed something on Twitter about Leaflet. I’ve been a long-time devotee of the Play! framework, as you may be aware if you’ve ever read this blog before.

Play 2 was released yesterday. This seems like a perfect time to mix them all together, just for fun*

I originally looked at combining Backbone and Leaflet to create markers on a map, which was a fun and easy 20 minutes – it was pure client-side code, simple to do and unbelievably pointless. Unless the map markers could be shared across multiple users, it was ultimately useless. That’s when I decided to hijack and re-purpose Play 2′s websocket-chatroom sample application- I thought it would be nice to have the places you mark on your map pop up in real-time on the map that other people are looking at, and the chatroom code required minimal tweaking to do this.

At this point, I should apologise. I just got back from the gym, and I’m too tired to think coherently enough to write good blog prose. Luckily, we’re about to head into the technical details

On start-up, mapcrap acts like a tradional MVC app – it gets the existing map places from the database via a RESTful call, and displays them on the map. From this point on, everything is then driven by websocket interactions. When you create a place, instead of it being persisted via REST, the JSON of the place is sent over the websocket. The server-side app then persists the place and broadcasts it to every user’s websocket using Akka.

in.onMessage(new F.Callback()
{
    public void invoke(JsonNode event)
    {
        Place place = Json.fromJson(event,
                                    Place.class);
        place.createdOn = new Date();
        place.save();
        defaultMap.tell(new MapEvent(userId,
                                     place));
    }
});

The locally-added place isn’t added to the local collection of places directly – instead, it receives it through the broadcast. This is a lazy way of getting around Backbone collections not accepting duplicate models.

When the client receives a push message informing it that a new place has been added, it adds the place to the Backbone collection of places – in turn, the event listener on the collection triggers the addition of a popup to the map.

this.model.bind("add", function(place){
  var view =new PopupContentView({model:place});
  var latlng = new L.LatLng(place.get('latitude'), place.get('longitude'));
  var messagePopup = new L.Popup({autoPan:false, closeButton:false});
  messagePopup.setLatLng(latlng);
  messagePopup.setContent(view.render().el);
  self.options["map"].addLayer(messagePopup);
}, this);

Notes:

  • The easiest way to see this working is to open two browsers and point them both at http://localhost:9000
  • Left-click on the map to open a “create place” popup. If you’ve entered an avatar URL in the Avatar URL text box, this image will also be displayed in the pop-up
  • Enter a message, and click Create! – the pop-up will (or should, at least) appear on your map and the map in the other browser window
  • This doesn’t work in Internet Explorer, because it doesn’t support web sockets
  • If you want to try this on a network, change the URL in models.js from localhost to a hostname/IP address
  • This isn’t on Heroku because, the last I heard at, web sockets are not supported there

You can download the mapcrap – you’ll need Play 2.0 to run it.
Instructions:

  • Unzip it
  • cd into the directory
  • play
  • run
  • Point your browsers at http://localhost:9000

If you have any problems, please let me know!

* My parents are staying with me this week. My dad asked, “what is this good for?” about 2 hours ago. The explanation of the joy of coding and the satisfaction of writing something vaguely cool is still, sporadically, going on.

Play is seven-league boots

This blog has a lot of entries related to how-tos with the Play! framework, but one thing it’s missing is possibly an explanation of why I use Play so much.

It’s simple – I consider Play to be seven-league boots.

From Wikipedia (so it must be true):

Seven-league boots are an element in European folklore. The boots allow the wearer to take great strides—seven leagues each step—resulting in great speed. The boots are often presented by a magical character to the protagonist to aid in the completion of a significant task.

I couldn’t have said it better myself – great strides and great speed for significant tasks*.

* Also, Play comes from Zexenity, a French company, so it ticks the European box too

Play 2 modules – rewriting Deadbolt for the new generation of Play

Back in 2010, when I was young and full of beans, I wrote an authorization module called Deadbolt for the Play! framework in its 1.x incarnation. It was originally written to fulfil some needs I had for projects I was working on, but proved to be pretty popular with a wider audience. There’s no download counter at the Play module repository, unfortunately, so I have no idea how widely it’s used – but it is used, and that’s always nice to hear about.

Fast-forward to 2012, to when I’m old and full of gas, and Play is now at 2.0 RC3. It’s totally backwards-incompatible with the 1.x projects, which some people have complained about, but I personally applaud – as long as this doesn’t happen with every major release. It’s also totally backwards-incompatible with 1.x modules, which means that Deadbolt required some updating of its own.

Let’s get the negative issue out of the way before I get started on the nitty-gritty. In Play 1, you created a new module by typing “play new-module ” into your shell, and you were good to go. With Play 2 and its concept of modular applications, it seems the concept of modules has to some degree become blurred and there’s a lack of documentation to really address issues such as packaging, etc. It’s possible – or probable – that I’ve just missed the existing docs, so I’ll be following up on this with a future post that looks at creating a module from scratch.

And now, to the good bits.

The original Deadbolt was built in such a way that it had a few interfaces (it didn’t impose any persistence issues on you) and a few fairly monolithic classes that handled the authorization checks. You could apply static and dynamic checks with

@With(Deadbolt.class)
public class MyController extends Controller
{
    // static check - user must have the foo AND bars roles
    @Restrict({"foo", "bar"})
    public static void index() {...}

    // static check - user must have the foo OR bars role
    @Restrictions({@Restrict("foo"), @Restrict("bar")})
    public static void view() {...}

    // dynamic check - application-specific security check
    @RestrictedResource("foo")
    public static void edit() {...}
}

In the application, it was nice and unobtrusive – you add a few annotations (either at the view, controller or controller method level) and you have fine-grained authorization control over your application. Later additions let you give content type hints to make it easier to secure web services and ajax calls, or to unsecure or loosely secure elements.

In the actual implementation of Deadbolt however, there was a lot of monolithic code – the Deadbolt class itself covered all the dynamic and static checks, as well as the checks from the views. It worked well, but I was never particularly satisfied with the actual code that went into making it.

The re-write for Deadbolt 2 has taken – to my great joy and general happiness – a completely different approach thanks to the new architecture of Play 2. Each annotation – @Restrict, @Restrictions, @Dynamic, etc, – has an associated action which is invoked prior to the method. When mixing controller and method restrictions, the method restrictions are applied first which allows the more-specific restriction to apply to the resource. This behaviour was also present in the original Deadbolt, but it required a lot of framework-provided reflection and duplicate code. The result, to take a short example, is the @RoleHolderPresent annotation – this particular restriction will prevent access to anyone who isn’t logged into your application.

Here’s the annotation…

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Documented
@Inherited
public @interface RoleHolderPresent
{
}

and here’s the action…

public class RoleHolderPresentAction extends AbstractDeadboltAction<RoleHolderPresent>
{
    public Result call(Http.Context ctx) throws Throwable
    {
        Result result;
        // here we check if a more specific action has already processed the call
        if (isActionUnauthorised(ctx))
        {
            result = onAccessFailure(getDeadboltHandler(configuration.handler()),
                                     configuration.content(),
                                     ctx);
        }
        else
        {
            // and here we perform the specific check for the annotation
            DeadboltHandler deadboltHandler = getDeadboltHandler(configuration.handler());
            RoleHolder roleHolder = getRoleHolder(ctx,
                                                  deadboltHandler);

            if (roleHolder != null)
            {
                markActionAsAuthorised(ctx);
                result = delegate.call(ctx);
            }
            else
            {
                markActionAsUnauthorised(ctx);
                result = onAccessFailure(deadboltHandler,
                                         configuration.content(),
                                         ctx);
            }
        }

        return result;
    }
}

For comparison, the equivalent of RoleHolderPresent was a member of a 481-line class.

The result is a much cleaner, less repetitive implementation. What duplication there is comes as a result of Java annotations not being able to implement interfaces, which is a reasonable trade-off. The result of the cleaner code – apart from the increased ease of maintenance, etc, it that it’s easier to see how to extend and improve the feature set. I for one would rather work with five twenty-line classes than one of one hundred lines.

One thing that’s missing at the moment is the Scala API. Play 2 supports Java and Scala as first-class citizens, and I want to take advantage of this to widen the potential user base of Deadbolt.

The new architecture of Play 2 is – to my mind – the result of a carefully thought out evolution of the framework, and that’s why I support the lack of backwards compatibility.

Deadbolt-2 on github: https://github.com/schaloner/deadbolt-2

backbone.js – M without the VC

I’ve recently been doing a lot of work with backbone.js, a JavaScript MVC framework that’s excellent for building clean applications that are backed by RESTful JSON web services. It offers a nice separation of concerns, supports your favourite JavaScript templating engine and is well-documented. What else could you need?

Well, sometimes the answer is a little bit less than what’s on offer. What about cases where you want to use just part of the framework? That’s also possible – in this case, I’m going to demonstrate how you can use backbone models to interact with your server-side code, but without the associated views and controllers.

Backbone models extend the framework’s Model class, and so you can get RESTful behaviour for free. On the server side (which, unsurprisingly, I’m using the Play! framework for), we have a couple of models:

@Entity
public class User extends Model
{
    public String userName;
    
    public String displayName;
    
    public String fullName;
    
    @OneToMany(cascade = CascadeType.ALL)
    public List friends;

    public static User findByUserName(String userName)
    {
        return find("byUserName", userName).first();
    }

    // builder methods not shown
}
@Entity
public class Friend extends Model
{
    @OneToOne(optional = false)
    public User user;
    
    public Friend(User user)
    {
        this.user = user;
    }
}

The User class is only going to be used on the server side, but Friends will be retrieved using a RESTful service that returns JSON.

window.Friend = Backbone.Model.extend
  ({
    urlRoot: "http://localhost:9000/api/friends",
    defaults: {
      "id": null,
      "user": null
    }
  });

window.FriendCollection = Backbone.Collection.extend
  ({
    model: Friend,
    url: "http://localhost:9000/api/friends"
  });

Once client-side instances of Friend are created, calling methods such as fetch() will result in a RESTful call based on the URL given in the model declaration. To integrate this with the server side, we add entries to the routes file. In this case, we’re only going to GET all the friends of the current user, but the same principle applies to other HTTP methods such as PUT and DELETE.

GET     /api/friends                            Friends.all

The server-side implementation is about as simple as it gets:

public class Friends extends Controller
{
    public static void all()
    {
        User user = User.findByUserName(session.get("userName"));
        renderJSON(user.friends);
    }
}

At this point, we now have everything in place to make RESTful calls and react to the asynchronous results.

<script type="text/javascript">
    function showFriends() {
        var friends = new FriendCollection();
        // Retrieve the data from the server, do something with it on a successful return
        friends.fetch({
            success: function() {
                // do something with the result.  All friends in the collection can be accessed by iterating over (or directly accessing) friends.models 
            }
        });
    }
</script>

Who are my <a href="javascript:showFriends()">friends</a>?

In just a few lines of code, you have smooth, clean access to your web services and a declarative model that can easily be kept in sync with your server-side models.

A complete working example can be found here. Unzip it, cd into the bbm directory, type “play run” and point your browser at http://localhost:9000.

EDIT: Please note this is written using Play 1.x. I guess I need to get in the habit of clarifying which version of Play I’m using now that Play 2.0 is nearly ready!

EDIT 2: Just to keep things even, here’s an simplified implementation in Play 2.

GoDaddy hosting issues…I’m getting pretty damn tired of them

I’ve noticed recently that a lot of accesses to my website result in “ERR_CONNECTION_RESET”, so in other words my website is frequently unavailable. Checking this out with my host, GoDaddy, it seems to be a known issue that’s affecting a lot of people at the moment and not much is happening about it.

Luckily, I’m involved in a commercial relationship with them…I pay, they provide. When they fail to do so, I vote with my feet and my wallet. As soon as possible, this whole site is moving over to another provider which focuses less on hyperbole and more on uptime and solving problems.

Fail.

Secure your web services and AJAX calls with Deadbolt

Deadbolt makes it very easy to add authorization to your Play! application. However, until now, it’s been harder to add the same constraints to web services and AJAX-invoked methods – which is to say, the mechanism worked, but when access failed the response was always HTML. Less, in this asynchronous world, than useful.

Play takes HTML as the default response format when you invoke the Controller#render method. If your application typically, or even occasionally, returns another format then you have a problem. Unless you configure your routes file to specify the response format, or do some content negotiation from the client, you’re pretty much stuck with HTML. The impact for Deadbolt is that while your DeadboltHandler implementation has an onAccessFailure method, there’s no easy way to check what format you’re working with.

If you want to specify a default response format for when DeadboltHandler#onAccessFailure is invoked, you can add an entry to the application.conf file to do this:

deadbolt.default-response-format=json

This will set the request.format field to whatever response type you have set, which will in turn determine which template is called when you invoke render()…html will result in .html templates being rendered, json will result in .json templates being rendered, foo will result in .foo templates, and so on.

If you have an application that returns a mix of response types, then setting a default format may not be of much use to you. In these cases, you may want to use annotations
to give you some hints. There are two built-in annotations with Deadbolt, @JSON and @XML. You can apply these to a controller or to an individual method. When present,
the request format will be set to json or xml respectively before your DeadboltHandler’s onAccessFailure method is invoked.

@With(Deadbolt.class)
public class Foo extends Controller
{
    @Restrict("bar")
    @XML
    public static void getSomeXml()
    {
        // render some XML
    }

    @Restrict("bar")
    @JSON
    public static void getSomeJSON()
    {
        // render some JSON
    }
}

Note that you can annotate a controller with @JSON but have an @XML method in there, and vice-versa.

What about when the next great format is invented? That’s where you have to do your own work. You can add your own annotations to controllers or methods and check for them in your onAccessFailure implementation before you call render.

One important note – whichever forbidden method you invoke from onAccessFailure cannot be a redirect. The easiest way to do this is to create a 403 file in the views/errors directory of your application for each format type, and invoke Deadbolt.forbidden() from your onAccessFailure implementation. See samples-and-tests/content-types for an example.

Ideally, the content types would be specified in the routes file but since route wildcards are both possible and extremely useful, you sometimes need to get implementation-specific.

Eat your own dog food, but throw in some unknown biscuits for variety

Well, the example app that Jorge Aliss asked me to write to demonstrate a combination of SecureSocial and Deadbolt is working, and working nicely, and as soon as I’ve prettied it up a bit I’ll be releasing it to github and pushing it out to, probably, Heroku.

Deadbolt came about as a result of two projects I worked on that required a specific approach to security that wasn’t addressed by any existing modules of the Play! framework. I wrote and released the module, and it’s been updated every time a new feature was needed by my own projects or through a request by someone else. To use the vernacular, I eat my own dog food.

Let’s call me person A, and I eat my own dog food. Other people – let’s aggregate them into a single entity, person B…person B also eats my dog food, and delicious it is too. Based on my own experiences, Deadbolt dog food covers all the nutritional needs of my own highly-specialized pedigree dogs, and happily, also satisfies person B’s pet food requirements. Good enough…but what about when you suddenly switch dog – and nutritional requirements – and need something completely different? Then you suddenly might find that the dog food you’ve lovingly created and molded has a huge gap right where the vitamins should be.

End of dog food analogy. It’s getting annoying.

The demo app I’ve written – SociallySecure – allows you to log in through various social open auth providers and create an account which can then have other OAuth accounts linked to it. Once they’re linked, you can log in through any of them and get into your personal SociallySecure account. The key account is Twitter (at the moment – this is just a demo!) because security is applied to your tweets when someone is viewing your account page. If you’re friends, or you’ve decided your tweets should be public, the user can see all the exceptional and banal things you’ve tweeted along with those of the people you follow. If you’ve decided your tweets are visible only to friends, when someone views your user page then your tweets are not visible. Fairly simple stuff, but enough to demonstrate dynamic security.

Fairly simple stuff – except for the part where I’m not only considering the user privileges of the logged-in user, but that user’s privileges in relation to another user.

Deadbolt offers dynamic checks in the form of the #restrictedresource tag at the view level, and @RestrictedResource annotation at the controller level. If you’re in the controller level, you can already calculate what you need. In the view level, you’re pretty much screwed unless you’re able to pass in additional information. This is what the latest version of Deadbolt gives you, and without it you have a much more restricted version of dynamic security unless you *really* jump through some hoops.

If you’re curious about how this works, you can pass a map of string parameters to a tag argument called resourceParameters – this map is then available in your RestrictedResourceHandler. You can use it in two ways:

  • The string key/value pairs can be used by you directly
  • The value can be used to do a lookup in the request, or session, or cache, or whatever

The point of this blog post, however, is to emphasize than if you’re going to release something as open source, you’ll have a much higher chance of meeting developer needs if, once you’ve covered all your own use cases, sit down for a couple of hours with another developer and ask them to use it to develop something reasonably complex. It’s pretty much what you’ll see when releasing a product – you can test it to hell and back, but within a couple of hours of it going live you can pretty much guarantee that a user has found a bug.

Think of crucially missing gaps in your code as bugs. The code works perfectly well when it’s running according to what you have in mind, but as soon as it hits the real world then you’ll find that not everyone thinks like you.

Using SecureSocial in your local dev environment

Jorge Aliss has asked me (about 3 months ago, mea culpa) to write an example application that integrates the Deadbolt authorization module with his excellent SecureSocial module.

The application is currently in development as I take a five minute break to write this, and I thought I would share a handy shortcut for developing your own SecureSocial apps on your local box.

If you’re using, for example, Twitter to provide your OAuth service then you’ll need to provide a callback URL. Since you’re on your local computer, which doesn’t necessarily have its own external IP address then there are a couple of hacks you can use. One involves changing your hosts file to resolve an external URL to your local server.

Another, far easier – and lazier – method, is to use a URL shortener to provide the same situation. bit.ly doesn’t seem to allow request parameters, but goo.gl does. Simply create a shortened URL for http://localhost:9000/securesocial.securesocial/authenticate?type=twitter (adjust as necessary for port, OAuth provider, etc) and use that as the callback address in the application your register with the OAuth provider.