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 it’s 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:
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
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. It’s 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
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.Authenticatefunction 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).