Search code examples
scalaplayframeworkdependency-injectionguiceguice-3

Play Framework: Dependency Inject Action Builder


since Play Framework 2.4 there is the possibility to use dependency injection (with Guice).

Before I used objects (for example AuthenticationService) in my ActionBuilders:

object AuthenticatedAction extends ActionBuilder[AuthenticatedRequest] {
  override def invokeBlock[A](request: Request[A], block: (AuthenticatedRequest[A]) => Future[Result]): Future[Result] = {
    ...
    AuthenticationService.authenticate (...)
    ...
  }
}

Now AuthenticationService is not an object anymore, but a class. How can I still use the AuthenticationService in my ActionBuilder?


Solution

  • Define your action builders inside a trait with the authentication service as an abstract field. Then mix them into your controllers, into which you inject the service. For example:

    trait MyActionBuilders {
      // the abstract dependency
      def authService: AuthenticationService
    
      def AuthenticatedAction = new ActionBuilder[AuthenticatedRequest] {
        override def invokeBlock[A](request: Request[A], block(AuthenticatedRequest[A]) => Future[Result]): Future[Result] = {
          authService.authenticate(...)
          ...
        }
      }
    }
    

    and the controller:

    @Singleton
    class MyController @Inject()(authService: AuthenticationService) extends Controller with MyActionBuilders {    
      def myAction(...) = AuthenticatedAction { implicit request =>
        Ok("authenticated!")
      }
    }