Depending on the use case you can either create the shared Actor at top level or as a child Actor to your supervisor.
Then you just pass the ActorRef either using a message or the constructor to the supervisor / child actors and keep it as Actor internal state.
The following code should illustrate it (It's Scala but it should be pretty easy to translate it to Java).
package test
import akka.actor.Actor.Receive
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import akka.stream.ActorMaterializer
object TestClass extends App {
implicit val system = ActorSystem( "ActorSystem" )
implicit val executor = system.dispatcher
implicit val materializer = ActorMaterializer( )
//Option 1 Create as top level actor and pass to supervisor with init message
val sharedActor: ActorRef = system.actorOf( Props[ SharedActor ] )
val supervisor: ActorRef = system.actorOf( Props[ SupervisorActor ] )
supervisor ! InitWithSharedActor( sharedActor )
supervisor ! "NoArgsChild"
supervisor ! "ArgsChild"
class SupervisorActor extends Actor {
private var sharedActor: Option[ ActorRef ] = None
override def preStart( ) = {
//Option 2 Init as child actor of supervisor
println( "Start Supervisor" )
sharedActor = Some( context.actorOf( Props[ SharedActor ] ) )
}
override def receive: Receive = {
case InitWithSharedActor( sa ) =>
sharedActor = Some( sa )
case "NoArgsChild" =>
//Pass to child actor in init msg
sharedActor.foreach( sa => context.actorOf( Props[ ChildActor ] ) ! InitWithSharedActor( sa ) )
case "ArgsChild" =>
//Pass to child with constructor
sharedActor.foreach( sa => context.actorOf( Props( new ChildActorWithArgs( sa ) ) ) )
}
}
class SharedActor extends Actor {
override def preStart( ) = {
println( "Start Shared Actor" )
}
override def receive: Receive = {
case _ =>
}
}
class ChildActor extends Actor {
private var sharedActor: Option[ ActorRef ] = None
override def preStart( ) = {
println( "Start NoArg Child Actor" )
}
override def receive: Receive = {
case InitWithSharedActor( sa ) => sharedActor = Some( sa )
}
}
class ChildActorWithArgs( sharedActor: ActorRef ) extends Actor {
override def preStart( ) = {
println( "Start WithArg Child Actor" )
}
override def receive: Receive = {
case _ =>
}
}
case class InitWithSharedActor( sharedActor: ActorRef )
}