Dependency Injection

The Finatra framework uses Dependency Injection (DI) and it is important to understand the concept – specifically how it relates to effective testing which helps to explain the motivations of the framework.

Dependency Injection is one way to implement the Inversion of Control (IoC) programming principle. More importantly Dependency Injection is a design pattern and does not refer to any specific implementation of a library.

Finatra does use the Google Guice Dependency Injection library which is also available for service writers if they choose to use Dependency Injection. However, the framework was designed around the principle of Dependency Injection, not the Guice library implementation with a primary goal to build testability of code into the framework.

With that, a great place to start on understanding the reasoning behind Dependency Injection is the Motivation section of the Google Guice framework.

Attention

You are not required to use Google Guice Dependency Injection when using Finatra. Creating servers, wiring in controllers and applying filters can all be done without using any dependency injection. However, you will not be able to take full-advantage of Finatra’s testing features.

A simple example of Finatra’s Dependency Injection integration is adding controllers to Finatra’s HttpRouter by type:

class Server extends HttpServer {
  override def configureHttp(router: HttpRouter) {
    router.add[MyController]
  }
}

As mentioned, it is also possible to do this without using Guice: simply instantiate your controller and add the instance to the router:

class NonDIServer extends HttpServer {
  val myController = new MyController(...)

  override def configureHttp(router: HttpRouter) {
    router.add(myController)
  }
}

Dependency Injection and Testing

There are many resources around this topic but we recommend taking a look at The Tao of Testing: Chapter 3 - Dependency Injection as a primer for how Dependency Injection can help to write more testable code.