Posts Tagged ‘play framework’


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.


It may sound like an obvious point, but until recently the major reason I had for setting my applications to use PROD mode when I move my applications to a production environment, was so that my source code would not be visible in the event of a server side error. However, whilst looking through the source code today, I found a major compelling reason to never use Dev mode in a production environment.

First of all though, here a few things that Play does when you move into production mode that makes it a good idea to use the setting.

  • Play precompiles your source code for you, and does not check for code changes on the fly, adding a slight performance benefit
  • Play starts the application immediately (including any bootstrap jobs), rather than waiting for the first request, again adding a small performance benefit for first use
  • The 500 (server error) and 404 (page not found) pages do not show source code or your routes configuration, but instead show a standard error page
  • Runs more HTTP threads to handle incoming requests (unless specifically set in the application.conf). The exact value set is number of processors + 1

So all sounds pretty sensible, but not entirely critical. So, here is why it is critical.

/@kill

Just like the @tests and @documentation URLs that can be used in Play, there is a largely unknown URL called @kill. As the name suggests, it simply performs a System.exit(0), which shuts down the Play server. The code first checks that the system is in Dev mode, and if it is, and the @kill request was received, the server is killed.

You will also get a nice output message printed to the logs @KILLED. Not exactly what you want your average user to be able to do on your shiny new application. Not that your average user will know that this feature exists, but it is better to be safe than sorry.

I assume that this facility has been made available, so that if you are running your application in a development set up, you can terminate the application remotely directly from the browser, without having to worry about accessing the server that it is running on. I can’t really think of any other good reasons why you would want to use this feature over simply terminating the command line or using the play stop command.

If you want to try it, just go to http://localhost:9000/@kill (assuming you have not changed your port, and you are running your play server locally in Dev mode).

So stick to PROD mode. Not only is it a better way to run your applications, it protects you from unwarranted server shut downs.