My favorite ways of injecting dependencies in Scala

October 22, 2014

The following post is a shorter version of a post I’ve published on my former blog, Coffeebean. In this article, we will focus on dependency injection with only pure Scala code (no framework involved), resolved at compile time.

There are many ways to inject dependencies in Scala, this are my current favorite ways of doing it.

The “piece of cake” pattern

In our example, we have a Play app with a controller. But this kind of wiring would work with any Scala application.

We provide a route to find Internet links from a query string. To achieve this we will rely on the DuckDuckGO API. But for tests we would like to mock this service. As we want to be able to test our controllers, we need to be able to inject our service into the controller. To add a little more fun, the link service depends on a logging service.

The first thing to do is to define a ServicesComponent trait. This trait will embed our services :

class LogService{
  import play.api.Logger

  def log(message: String) {
    Logger.info(message)
  }
}

class LinkService(logService: LogService){
  import play.api.libs.ws.WS

  def findLinks(query: String) = {
    val duckDuckUrl = Play.current.configuration.getString("duckduck.url").getOrElse("http://api.duckduckgo.com/?format=json&q=") + query
    WS.url(duckDuckUrl).get.map{ response =>
      val results = response.json \\ "FirstURL"
      //take first result if exists
      val result = results.mkString(", ")
      logService.log("found links : " + result)
      result
    }
  }
}

trait ServicesComponent{
  val logService = new LogService
  val linkService = new LinkService(logService)
}

Now the controller can extend this trait to get dependencies from it :

trait ApplicationController extends Controller {
  this : ServicesComponent =>

  def findLinks(query: String) = Action.async {
    val links = linkService.findLinks(query)
    links.map(response => Ok(views.html.index(response)))
  }

}

object Application extends ApplicationController with ServicesComponent

this : ServicesComponent => in the ApplicationController trait means that we need to extend ServicesComponent when we instantiate an ApplicationController, to retrieve dependencies.
This notation is called Self Type or Self Reference.

Play uses objects (by default) to wire routes to controllers. This is part of the Scala world goodness, there is no need to rely on containers like Servlet/Java EE ones. As you can manage your controller objects yourself, you can do whatever you need to contruct them. At the end of the sample code above, we create the Application instance that will embed the services by extension of the ServicesComponent trait.

You can see this as a very light and flatten variation of the cake pattern, or a “Piece of Cake Pattern”! The cake pattern is often accused of getting too big too fast and being hard to manage. But here, I only use the power of Scala self types with one layer, and traits only where they are needed. Every dependency is wired inside the ServicesComponent trait.

If we want to wire another version of a service, for example for tests, we just need to extend the ServicesComponent trait and override the value :

class ControllerSpec extends Specification with Mockito {

  trait MockServices extends ServicesComponent {
    override val logService = mock[LogService]
    override val linkService = {
      val mockLinkService = mock[LinkService]
      mockLinkService.findLinks("hello") returns Future("http://coucou.com")
      mockLinkService
    }
  }

  "Application" should {

    "display query results" in {

      object Application extends ApplicationController with MockServices
      val response = Application.findLinks("hello")(FakeRequest())
      status(response) must equalTo(OK)
      contentType(response) must beSome("text/html")
      contentAsString(response) must contain("http://coucou.com")

    }
  }
}

Simple, isn’t it?

Alternative method : use a simple constructor

You can also use a simple constructor instead of the self type. As Alex N. pointed out in the comments, it can be useful if you want a single instance of your service component, that can be accessed from anywhere (for example to start/stop services at application startup/shutdown). Here again, as you can manage your controller objects yourself (no container), you can do whatever you need to contruct them.

With this method, your controller trait is now a class :

class ApplicationController(servicesComponent: ServicesComponent) extends Controller {
  import servicesComponent._

  def findLinks(query: String) = Action.async {
    val links = linkService.findLinks(query)
    ...
  }
}

Wiring is still very simple :

object ApplicationServices extends ServiceComponent
object Application extends ApplicationController(ApplicationServices)

Finally, you can test your controller with a MockServices object :

object MockServices extends ServiceComponent {
    override val ...
}
object Application extends ApplicationController(MockServices)

And you, what’s your favorite way of injecting dependencies in Scala?

Discussion, links, and tweets

comments powered by Disqus