Writing a Play 2.0 Module

Posted on by

The intro

Hot off the press, Play 2.0 has arrived, and has been welcomed into the arms of a fast paced community that loves new things.  The day it was released, we started a new project here, and on that particular day and on this particular project we felt particularly daring.  So we decided to use Play 2.0 for our project.  New is an understatement for Play 2.0, it’s not just an incremental improvement on Play 1.x, many parts of it have been completely rewritten.  There is still much work to do, and one of the blaring gaps that has yet to be filled is modules.  At the time of writing, there is no official listing or repository of modules for Play 2.0, in stark contrast to the rich ecosystem of modules for Play 1.x.  Furthermore, there is no documentation on how to write a module.  So, given that modules tend to be very useful, and we were starting a new project, we very quickly ran into the need to write our own module, which we did, the MongoDB Jackson Mapper Play 2.0 Module.  To help the rest of the community of early Play 2.0 adopters, I’ve decided to write a (very) short guide on writing Play 2.0 modules.

The disclaimer

So did I mention that there was no documentation on writing modules, and very little in the way of example code to copy from?  What I’ve written may well be not the right way to do things.  But with no documentation, how am I to know?  All I know is that it’s working for us, and that’s good enough for me.  So if you happen to know what the right way to write Play 2.0 modules is, don’t bother commenting on this telling me that I’m wrong.  Just write the damn documentation!

The setup

In play 1.x, writing a module usually starts with running play new-module. Slight problem here:

$ play new-module
       _            _
 _ __ | | __ _ _  _| |
| '_ \| |/ _' | || |_|
|  __/|_|\____|\__ (_)
|_|            |__/ 

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

This is not a play application!

Use `play new` to create a new Play application in the current directory,
or go to an existing application and launch the development console using `play`.

You can also browse the complete documentation at http://www.playframework.org.

Ok, so that doesn’t work.  Looks like there’s no way to create a new play module.  So, I decided to simply write a vanilla SBT project.  I won’t go into the details of how to set a new SBT project up, but here’s the play specific bits that you’ll need:

resolvers ++= Seq(
    DefaultMavenRepository,
    Resolver.url("Play", url("http://download.playframework.org/ivy-releases/"))(Resolver.ivyStylePatterns),
    "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/",
    "Typesafe Other Repository" at "http://repo.typesafe.com/typesafe/repo/"
)

libraryDependencies += "play" %% "play" % "2.0"

libraryDependencies += "play" %% "play-test" % "2.0" % "test"

Now do whatever you need to do to open it up in your favourite IDE/editor (I personally use IntelliJ IDEA, so I use the sbt-idea plugin).

The code

It’s worth first noting that the module that I wanted to write only had to load a MongoDB connection pool, according to configuration supplied in application.conf, and manage the lifecycle of that pool.  The trait that needed to be implemented to do this is play.api.Plugin.  It has three methods, onStart(), onStop() and enabled().  If you’re looking for information on how to do things like intercept HTTP calls and define custom routes, then I suspect it’s easy to do (probably by just defining a routes file in your plugin), but I didn’t need to do that so I’m not going to pretend that I know how.

There’s not really much to say now, my plugin looks something like this:

class MongoDBPlugin(val app: Application) extends Plugin {
  private lazy val (mongo, db, mapper) = {
    // insert code here to initialise from application config
  }

  override def onStart() {
    // trigger lazy loading of the mongo field
    mongo
  }

  override def onStop() {
    mongo.close()
  }

  override def enabled() = !app.configuration.getString("mongodb.jackson.mapper")
      .filter(_ == "disabled").isDefined
}

The actual code does a fair bit more than this, but none of that is specific to how to write a plugin.

The finishing touch

So I’ve written my plugin, there’s now one thing left to do… tell play framework about it!  This is done by defining a play.plugins file in the the root of the classpath (in the resources folder):

1000:play.modules.mongodb.jackson.MongoDBPlugin

The leading integer defines the priority of the plugin to be loaded.  The example I saw used 1000, so I decided to use that too.

The resolution

Now all I have to do to use this module is add it as a dependency.  Play will automatically pick it up, and it will be automatically started and stopped as necessary.  Happy hacking, and if you’re starting a Play 2.0 project, and want to use MongoDB, why not try the MongoDB Jackson Mapper Module!

2 thoughts on “Writing a Play 2.0 Module

  1. We are a group of volunteers and opening a new scheme in our community.
    Your website provided us with valuable info to work on.
    You’ve done an impressive job and our whole community will be grateful to you.

    Feel free to visit my website web site

Leave a Reply

Your email address will not be published. Required fields are marked *

ERROR: si-captcha.php plugin says GD image support not detected in PHP!

Contact your web host and ask them why GD image support is not enabled for PHP.

ERROR: si-captcha.php plugin says imagepng function not detected in PHP!

Contact your web host and ask them why imagepng function is not enabled for PHP.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">