All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sandinh.akuice.AkkaGuiceSupport.scala Maven / Gradle / Ivy

The newest version!
package com.sandinh.akuice

import java.lang.reflect.Method
import akka.actor.Actor
import com.google.inject.assistedinject.FactoryModuleBuilder
import com.google.inject.{Binder, AbstractModule}
import scala.reflect.ClassTag

trait AkkaGuiceSupport {
  self: AbstractModule =>

  private def accessBinder: Binder = {
    val method: Method = classOf[AbstractModule].getDeclaredMethod("binder")
    if (!method.isAccessible) {
      method.setAccessible(true)
    }
    method.invoke(this).asInstanceOf[Binder]
  }

  /** Bind an actor factory.
    *
    * This is useful for when you want to have child actors injected, and want to pass parameters into them, as well as
    * have Guice provide some of the parameters.  It is intended to be used with Guice's AssistedInject feature.
    *
    * Let's say you have an actor that looks like this:
    *
    * {{{
    * class MyChildActor @Inject() (db: Database, @Assisted id: String) extends Actor {
    * ...
    * }
    * }}}
    *
    * So `db` should be injected, while `id` should be passed.  Now, define a trait that takes the id, and returns
    * the actor:
    *
    * {{{
    * trait MyChildActorFactory {
    * def apply(id: String): Actor
    * }
    * }}}
    *
    * Now you can use this method to bind the child actor in your module:
    *
    * {{{
    * class MyModule extends AbstractModule with AkkaGuiceSupport {
    *   def configure = {
    *     bindActorFactory[MyChildActor, MyChildActorFactory]
    *   }
    * }
    * }}}
    *
    * Now, when you want an actor to instantiate this as a child actor, inject `MyChildActorFactory`:
    *
    * {{{
    * class MyActor @Inject() (myChildActorFactory: MyChildActorFactory) extends Actor with ActorInject {
    *
    * def receive {
    *   case CreateChildActor(id) =>
    *     val child: ActorRef = injectActor(myChildActoryFactory(id))
    *     sender() ! child
    * }
    * }
    * }}}
    *
    * @tparam ActorClass The class that implements the actor that the factory creates
    * @tparam FactoryClass The class of the actor factory */
  def bindActorFactory[ActorClass <: Actor: ClassTag, FactoryClass: ClassTag]: Unit = {
    accessBinder.install(new FactoryModuleBuilder()
      .implement(classOf[Actor], implicitly[ClassTag[ActorClass]].runtimeClass.asInstanceOf[Class[_ <: Actor]])
      .build(implicitly[ClassTag[FactoryClass]].runtimeClass))
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy