I use Google Guice for dependency injection in most of my projects. I also use Akka Actors a lot for solving concurrency related tasks in my projects. I often write code like

val a = injector . getInstance ( classOf [ A ]) val b = injector . getInstance ( classOf [ B ]) val c = injector . getInstance ( classOf [ C ]) val actorSystem = injector . getInstance ( classOf [ ActorSystem ]) val myActorRef : ActorRef = actorSystem . actorOf ( Props ( new MyActor ( a , b , c )))

And while this works. I still resent that now I have two ways of creating objects in my project. One via Guice approach of injector.getInstance and then a second approach which is specific for actors actorOf(Props(...)) mechanism listed above. I always wished that I could use Guice consistently to get instances of actors and classes alike.

In this blog, we’ll try to do just that. Lets write up a minimal actor which will be used in this example.

package com.abhi.logic class Logic { def add ( i : Int , j : Int ) : Int = i + j } package com.abhi.actor class MyActor ( logic : Logic ) extends Actor { def receive = { case msg : Msg => sender () ! logic . add ( msg . i , msg . j ) } } case class Msg ( i : Int , j : Int )

So I have written all my business logic in a simple class (which I can test easily) and now I am using my logic class as a dependency inside of the actor.

BTW, I am using the codingwell/scala-guice library to integrate Guice with my Scala project. Let us code up the Module required to perform all dependency injection.

class MyModule extends AbstractModule with ScalaModule { def configure () : Unit = { bind [ ActorSystem ]. toInstance ( ActorSystem ()) bind [ Logic ] } @Provides @Singleton @Named ( "MyActor" ) def getMyActor ( actorSystem : ActorSystem , logic : Logic ) = { actorSystem . actorOf ( Props ( new MyActor ( logic ))) } }

You can see that I am using the @Named approach to get the right instance. This is required because all actors in the end are created as ActorRef so we can’t use the getInstance[T] approach because the T is same for all actors. So we use names.

If our project had 100 actors. We will have one @provides method for each actor with a unique name. We can easily specify all our dependencies as parameters of this method. Since they have been bound earlier in the configure method, we get them transparently in the @provides method.

This also means that if tomorrow my actor starts depending on Logic1, Logic2, and Logic3 classes, I have just one place to make the change. the users of the actor don’t see the dependencies.

Now we need a small utility class which will make it easy for the clients to looking the named instances.

object ActorUtil { implicit class ActorInjector ( injector : Injector ) = { getActor ( name : String ) : ActorRef = { injector . getInstance ( Key . get ( classOf [ ActorRef ], Names . named ( name ))) } } }

We are creating this utility class so that our client code can easily lookup actors by their names. These names are what we have configured in the @Provides method for each actor.

Now let us write a client for our actors

import ActorUtil._ val injector = Guice . createInjector ( new MyModule ) val myActor = injector . getActor ( "MyActor" ) val msg = ( myActor ? MyMsg ( 10 , 20 )). mapTo [ Int ]

If I was writing a class which needed the MyActor as a dependency. I could write

@Singleton class MyClass @Inject ()( @Named ( "MyActor" ) myactor : ActorRef ) { myactor ! Msg (...) }

That’s pretty clean because now I can get instances of my actors using Guice mechanisms. This leads to more consistent coding style.

The full code of this example is located here