Hidden Features of the Play Framework Routes File

Posted: July 15, 2011 in Play Framework
Tags: , ,

Background

Today, an interesting question was raised at Stackoverflow regarding if it were possible to define Dev/Prod mode specific routes in the Routes file.

The simple answer, was that I didn’t know, but I had an theory that this could be possible, so I threw together a quick prototype to see if it would work.

The premise of the idea was that the routes file does allow scripting to take place, which I have used before to define a Context, which is the agreed way to for managing the war context when deploying to Tomact and other Servlet containers.

So, taking the idea that scriptlets are possible in the routes file, I wondered if this could be taken a step further, whereby logic could be carried out in the routes file, rather than simple assignment scriptlets.

The prototype

The prototype itself was pretty simple. I started a new play project

play new routesproto

and started the Play server.

play run routesproto

I then modified the Application.java to have a few actions, which simply returned a little text to show the action completed successfully. There was simply no need to write templates for the actions, as that was not what I wanted to prove.

public class Application extends Controller {

    public static void index() {
        render();
    }
	
    public static void noDev() {
        renderText("NoDev");
    }
    public static void noProd() { 
        renderText("NoProd");
    }
}

I then went about making my routes file Dev and Prod specific. I created a few routes per environment as follows.


# Home page
GET     /                                       Application.index

# Ignore favicon requests
GET     /favicon.ico                            404
# Map static resources from the /app/public folder to the /public path
GET     /public/                                staticDir:public

%{ if (play.mode.isProd()) { }%
GET		/route1									Application.noDev
GET		/route2									Application.noDev
GET		/route3									Application.noDev
%{ } }%


%{ if (play.mode.isDev()) { }%
GET		/route4									Application.noProd
GET		/route5									Application.noProd
GET		/route6									Application.noProd
%{ } }%

*       /{controller}/{action}                  {controller}.{action}

So, what's going on in here? Well, all the main (shared) routes are held at the top of the routes file, and then anything that becomes specific to Dev or Prod mode are placed at the bottom. As usually is the case, the catch-all should be last, so after the second if tag is closed, we follow it with the catch-all route.

The following line is responsible for the logic in our routes file.

%{ if (play.mode.isDev()) { }%

and all routes between this piece of logic, and the closing of the if statement, indicated by the following line, are enabled.

%{ } }%

This simple line simply checks what Mode the application is running in, and if it is running in Dev mode, then the routes defined in between the opening and closing parenthesis become available.

Conclusion

I do not expect this syntax to immediately find its way in to every Play application routes file, but I no doubt think that it will be useful to many of us Players. Indeed, without the Stackoverflow question, I would never have even considered experimenting whether this method was actually possible or not, so thanks to Roshan for raising the question.

About these ads
Comments
  1. bane73 says:

    This is awesome – thanks!

    I won’t get an opportunity to try for some time but this idea looks like a different version of the idea could be realized that would allow domain-specific routing to be implemented.

    Thus, an app deployed to a single PlayApps-shard might be able to uniquely-service multiple distinct domains that run the same app but with different branding.

    If so, this would allow 1 shard to service multiple low-bandwidth customers and lower the per-customer-cost.

  2. Renato says:

    It worked perfectly for my site, http://www.adgratis.com . Thank you very much! ;-)

  3. adampilks says:

    This is exactly what I need, but am I right in thinking that this will no longer work in Play 2.0? Do you know of a Play 2.0 way to do domain specific routing?

    Thanks,

Leave a Reply

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

WordPress.com Logo

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

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s