Search code examples
scalaakkaactorakka-cluster

Instantiate Actor System for my code design


I am refactoring akka code and ended up in a situation where I am not able to instantiate the actors in the actor system

I have a BaseActor which has all the common functionality used by my other actors

trait baseActor extends Actor with timeout {
  implicit val system = context.system
  implicit val dispatcher = system.dispatchers.lookup("myCustomDispatcher")
  implicit val ldapService = ldapSerice
}

I have also a Person Service to do mostly CRUD operations on Ldap

trait PersonService {
  def addUser(user:User)(implicit ldapSerice:Ldapservice) = ???
  def getUser(uuid:String)(implicit ldapSerice:Ldapservice): User = ???
}

but uses the ldapservice implicitly, assume that I need this ldap service to make ldap connecting and calls, As some other developer has implemented it so I have to follow the same pattern

While I am trying to instantiate the actor system from the Main class I am not sure how to pass that actor system to the base actor. so all the child actors created can use that

object Main extends App {
   val system = ActorSystem(config.settings.getString("systemName"))
   val myActor = system.actorOf(Props[MyActor],"MyActor")
}

My actor

class myactor extends baseActor with PersonService{
  overide def receive: Unit = {
    case "create" => addUser
    case "delete" => //my business logic
  }
}

While it does not throw any compilations errors during the run time it is throws exception not able to create actor because of dispatcher is not configured but however I can see in the configuration file It is here.

enter image description here


hostName = "localhost"

//get the data from environment variable
//hostName = {?HOST_NAME} //If environment variable exist pick that value or override

akka {
    #loggers = ["akka.event.Logging$DefaultLogger"]
    loggers = ["akka.event.slf4j.Slf4jLogger"]
    loglevel = "DEBUG"
    logging-filter="akka.event.slf4j.Slf4jLoggingFilter"

    debug {
        receive = on
        lifecycle = on
        event-stream = on
    }
}

clusterLdap {
    version = 10
    name = "MyApplication"
    ldap {
        hostName = ""
        port = 20681
        bindDN = ""
        password = ""
        name = ""
        permissions = ["read","write","bind"]
    }
}
akka {
    provider = "cluster"
    wfm-dispatcher = {
        type = dispatcher
        executor = "fork-join-executor"
        fork-join-executor {
            parallelism-min = 4
            parallelism-factor = 2.0
            parallelism-max = 8
        }
    }
    remote {
        netty.tcp {
            hostName = "localhost"
            port = 2022
        }
    }
    
    cluster {
     seedNodes = ["akka.tcp://MyCluster@localhost:2541"]
     roles = ["service"]
    }
}


Solution

  • In the Akka Documentation on Classic Dispatchers, it notes:

    The dispatcher you specify in withDispatcher and the dispatcher property in the deployment configuration is in fact a path into your configuration. So in this example it’s a top-level section, but you could for instance put it as a sub-section, where you’d use periods to denote sub-sections, like this: "foo.bar.my-dispatcher"

    In the configuration above, the dispatcher path is "akka.wfm-dispatcher", so that's the string you'll need to use to look it up. Alternatively, you can put the dispatcher configuration at the top level rather than inside the akka section, and look it up as "wfm-dispatcher".

    Also note that the code above won't actually use your custom dispatcher to run these actors. To configure the actor to run with your dispatcher (assuming the configuration file is unchanged), you can use:

    system.actorOf(Props[MyActor].withDispatcher("akka.wfm-dispatcher"),"MyActor")