Julien Richard-Foy’s blog

Dependency injection in Scala with Play 2: it’s free

When you write a software you generally split it into several modules with no hardcoded dependencies between them so you can reuse and test them more easily: you just need to wire the different modules together at startup according to your desired configuration.

In the Java world, some tools help to perform the wiring task, e.g. Spring or Guice, but in Scala you can perform dependency injection without having to rely on an external tool, as you’ll see in this post where I’ll show how to apply the Cake pattern in the context of a Play 2 application.

An example of use case where you may want to use a dependency injection mechanism is when you write a web application which needs the user to be authenticated to perform some actions. During development time it’s generally more comfortable to bypass the authentication step (when you just want to quickly test features you are coding right now). Thus, you want to have two authentication strategies: one for the integration environment, which really asks the user its login and password, and one always succeeding without requiring any user action.

Well, how can we define an authentication process in Play 2? A simple solution is defined with the following code:

It defines a main controller with two interesting actions: login and logout. The former reads a username from the request and put it in the session while the latter clears the session. Thus, checking if a user is not a guest is just a matter of checking if there is a username in his session. Then I defined the Secured object, which provides a function executing a given action only if there is a username in the session (otherwise it renders the unauthorized template and returns an Unauthorized status code).

Given this code we can easily rewrite the index action to ensure the user is authenticated: we just wrap the Action statement into a Secured.Authenticated statement.

Well, we have a basic authentication mechanism and a convenient Authenticated construct we can use to wrap actions for which we want the user to be authenticated. Now, as previously written, we also want a mocked Authenticated construct variant which checks nothing. Its definition is straightforward:

With all that given code we can either wrap our authenticated actions with the Secured.Authenticated function, or with the MockSecured.Authenticated function to either use the “real” or the mock authentication check, but by doing this we’d hardcode the authentication strategy and that’s definitely not what we want to do.

Thus, we want to abstract over the authentication strategy, e.g. with a Security trait implemented by Secured and MockSecured.

Then, we need to express that MyApp controller depends on the Security trait. To do that we will change the MyApp object into a trait and add the Security trait to its selftype:

Now we are almost done! The index action will use the Security.Authenticate function that will be injected in the MyApp controller. So, the only remaining task is to define the injection logic.

Java based dependency injection frameworks use either XML configuration files or @Annotations to define the wirings. In Scala, you write the wirings in Scala. The good thing is that it is type-checked so the program will not compile if a dependency is missing (whereas you’d get a runtime NullPointerException with Spring, for example).

Here is a simple wiring code which will use the MockedSecured strategy if Play is in dev mode, and the Secured strategy in prod mode:

And we are done! You can find a working example on GitHub. Use the run command (in the play prompt) to run the application in dev mode (with mocked authentication) and the start command to run in prod mode (with the real authentication).

blog comments powered by Disqus