Instantiating Akka actors in a Play application with Subcut

770 views Asked by At

I have a Play 2.1 application. I am also using Subcut for dependency injection, which is already set up and working for most parts of the application, except for one.

Say I have the following snippet of actor-related code:

import akka.actor._
import com.typesafe.plugin._
import play.api.Play.current
import play.api.libs.concurrent.Akka

class FoobarActor extends Actor {
   def receive = {
     // do stuff here
   }
}

object Foobar {
  val actor = Akka.system.actorOf(Props[FoobarActor])
}

Now, say I would like to inject some objects into each instance of the FoobarActor using Subcut. This would require the actor class to extend Injectable, with the BindingModule passed into the constructor, like this:

import akka.actor._
import com.typesafe.plugin._
import play.api.Play.current
import play.api.libs.concurrent.Akka
import com.escalatesoft.subcut.inject.{Injectable, BindingModule}

class FoobarActor(implicit val bindingModule: BindingModule) extends Actor 
  with Injectable {

   val bazProvider = inject[BazProvider]
   val quuxProvider = inject[QuuxProvider]

   def receive = {
      // do stuff here  
   }
}

The question is: how is such an actor instantiated?

Typically, objects managed by Subcut are constructed in Subcut's configuration objects (i.e., objects that extend NewBindingModule), or in the case of Play's controllers, in the Global object (see play-subcut on github).

What would I replace Akka.system.actorOf(Props[FoobarActor]) with in order to override the instantiation of actors in order to pass in the binding module?

object Foobar {
  val actor = /* what goes here? */   
}
1

There are 1 answers

1
cmbaxter On BEST ANSWER

As Roland mentioned, this should be as simple as just instantiating the actor with a constructor argument. I wasn't sure the implicit would work with Akka's way of doing actor instantiation with constructor args but it seems to work okay. The code should look something like this:

class FoobarActor(implicit val bindingModule: BindingModule) extends Actor 
  with Injectable {

   val bazProvider = inject[BazProvider]
   val quuxProvider = inject[QuuxProvider]

   def receive = {
      // do stuff here  
   }
}

object FoobarActor {
  def apply(implicit bindingModule:BindingModule) = {
    Akka.system.actorOf(Props(classOf[FoobarActor], bindingModule))
  }
}

Then, if you wanted to instantiate the FoobarActor, as long as you had an implicit BindingModule in scope, you could just do:

val ref = FoobarActor()