Search code examples
scaladependency-injectionsingletonakkaakka-actor

ActorSystem singleton injection


In my project, I have to use actors and schedulers. All my need can be accomplished by using one actor system only. But I need the schedulers and actors in more than one class. So my question, if I should inject the actor system in each class like below, will it create only one actor System or more than one? I don't want to create more than one actor system since it is not a recommended practice.

import akka.actor.ActorSystem

@Singleton
class someClass @Inject()(actorSystem: ActorSystem){....} // abstract class ActorSystem extends ActorRefFactory

@Singleton
class anotherClass @Inject()(actorSystem: ActorSystem){....}

Or I should create another object and declare an actor system within it and use it everywhere like this:

import akka.actor._

object actorSystemObject {
    val system: ActorSystem = ActorSystem()
}

Which method will be better and standard?


Solution

  • Assuming you are using guice, try providing a singleton like so

    @Provides
    @Singleton
    def getActorSystem: ActorSystem = ActorSystem()
    

    for example

    import akka.actor.ActorSystem
    import com.google.inject.{AbstractModule, Guice, Inject, Injector, Provides, Singleton}
    import scala.jdk.CollectionConverters._
    
    class MyModule extends AbstractModule {
      @Provides
      @Singleton
      def getActorSystem: ActorSystem = ActorSystem()
    }
    
    @Singleton
    class SomeClass @Inject()(actorSystem: ActorSystem) {
      println(actorSystem.hashCode())
    }
    
    @Singleton
    class SomeOtherClass @Inject()(actorSystem: ActorSystem) {
      println(actorSystem.hashCode())
    }
    
    object Hello extends App {
      val injector: Injector = Guice.createInjector(List(new MyModule).asJava)
      injector.getInstance(classOf[SomeClass])
      injector.getInstance(classOf[SomeOtherClass])
    }
    

    which outputs something like

    1731656333
    1731656333
    

    where we see the same ActorSystem is injected as evident by the same hashCode.

    Say we remove @Singleton provider like so

    @Provides
    def getActorSystem: ActorSystem = ActorSystem()
    

    then hashCodes differ, for example,

    2050462663
    1117871068