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.
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.
It worked perfectly for my site, http://www.adgratis.com . Thank you very much! 😉
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,
I am not sure for Play 2, I have not tried it.
how to add %{ if (play.mode.isDev()) { }% on my play framework 2.2.1 routes file ?
and I saw your answer at http://stackoverflow.com/questions/8917884/localized-routes-and-url-string
I have tried it and show an error like
Compilation error
HTTP Verb (GET, POST, …), include (->) or comment (#) expected
please help me….how to fix it ?
Play 2 uses a different syntax…this is specifically a Play 1 trick.