Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 489
Tim Joseph Avatar asked Jun 28 '15 10:06

Tim Joseph


People also ask

Is Play framework still used?

Play is rock-solid and used by hundreds of thousands of Java and Scala developers every month. Play is still extremely relevant to today's application and web development and has a passionate and very capable community around it ensuring that it has many good years left.

What is action in play framework?

What is an Action? Most of the requests received by a Play application are handled by an action. An action is basically a Java method that processes the request parameters, and produces a result to be sent to the client. public Result index(Http. Request request) { return ok("Got request " + request + "!"

What is the dependency injection?

In object-oriented programming (OOP) software design, dependency injection (DI) is the process of supplying a resource that a given piece of code requires. The required resource, which is often a component of the application itself, is called a dependency.


2 Answers

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!")
  }
}
like image 110
Mikesname Avatar answered Sep 22 '22 09:09

Mikesname


I didn't like the way one was required to inherit in the above example. But apparently it's possible to simply wrap a object inside class:

class Authentication @Inject()(authService: AuthenticationService) {
  object AuthenticatedAction extends ActionBuilder[Request] {
    def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
      // Do your thing wit the authService...
      block(request)
    }
  }
}

class YourController @Inject() (val auth: Authentication) extends Controller (
  def loggedInUser = auth.AuthenticatedAction(parse.json) { implicit request =>
    // ...
  }
}
like image 41
Ciantic Avatar answered Sep 19 '22 09:09

Ciantic