CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-typesafe-akka--akka-actor-2-13

Akka Actor library - a toolkit for building highly concurrent, distributed, and resilient message-driven applications for Java and Scala using the Actor Model.

Overview
Eval results
Files

actor-lifecycle.mddocs/

Actor Creation and Lifecycle

Actor creation, configuration, and lifecycle management including Props-based instantiation, actor reference handling, and actor selection mechanisms. This covers the complete lifecycle from actor creation through termination.

Capabilities

Props-based Actor Configuration

Props provides immutable configuration for actor creation, including dispatcher, mailbox, and deployment settings.

/**
 * Immutable configuration object for creating actors
 */
final case class Props(
  deploy: Deploy = Deploy.NoScopeGiven,
  clazz: Class[_],
  args: immutable.Seq[Any] = immutable.Seq.empty
) {
  /** Configure the dispatcher for the actor */
  def withDispatcher(dispatcher: String): Props
  
  /** Configure the mailbox for the actor */
  def withMailbox(mailbox: String): Props
  
  /** Configure the router for the actor */
  def withRouter(r: RouterConfig): Props
  
  /** Configure deployment settings */
  def withDeploy(d: Deploy): Props
}

object Props {
  /** Create Props for Java actor classes with arguments */
  def create[T <: Actor](clazz: Class[T], args: AnyRef*): Props
  
  /** Create Props with creator function (Scala API) */
  def apply[T <: Actor: ClassTag](): Props
  def apply[T <: Actor: ClassTag](creator: => T): Props
  
  /** Empty Props instance */
  val empty: Props
}

Usage Examples:

import akka.actor.{Props, Actor}

// Simple actor creation
class MyActor extends Actor {
  def receive = {
    case msg => println(s"Received: $msg")
  }
}

// Props without arguments
val props1 = Props[MyActor]()

// Props with constructor arguments
class ParameterizedActor(name: String, value: Int) extends Actor {
  def receive = {
    case msg => println(s"$name($value): $msg")
  }
}

val props2 = Props(new ParameterizedActor("test", 42))

// Props with configuration
val configuredProps = Props[MyActor]()
  .withDispatcher("my-dispatcher")
  .withMailbox("bounded-mailbox")

Actor Creation and Factory Methods

ActorRefFactory provides methods for creating actors and obtaining actor selections.

/**
 * Factory for creating actor references
 */
trait ActorRefFactory {
  /** Create an actor with auto-generated name */
  def actorOf(props: Props): ActorRef
  
  /** Create an actor with specified name */  
  def actorOf(props: Props, name: String): ActorRef
  
  /** Get an actor selection by string path */
  def actorSelection(path: String): ActorSelection
  
  /** Get an actor selection by ActorPath */
  def actorSelection(path: ActorPath): ActorSelection
}

/**
 * Actor context providing creation capabilities within actors
 */
trait ActorContext extends ActorRefFactory {
  /** Reference to this actor */
  def self: ActorRef
  
  /** The actor system this actor belongs to */
  def system: ActorSystem
  
  /** The parent actor reference */
  def parent: ActorRef
  
  /** Iterator over child actor references */
  def children: immutable.Iterable[ActorRef]
  
  /** Lookup child actor by name */
  def child(name: String): Option[ActorRef]
  
  /** Watch another actor for termination */
  def watch(subject: ActorRef): ActorRef
  
  /** Stop watching an actor */
  def unwatch(subject: ActorRef): ActorRef
  
  /** Stop this actor */
  def stop(actor: ActorRef): Unit
  
  /** Become a new behavior */
  def become(behavior: Actor.Receive, discardOld: Boolean = true): Unit
  
  /** Revert to previous behavior */
  def unbecome(): Unit
}

Usage Examples:

import akka.actor.{ActorSystem, Props}

val system = ActorSystem("MySystem")

// Create actor with generated name
val actor1 = system.actorOf(Props[MyActor]())

// Create actor with specific name  
val actor2 = system.actorOf(Props[MyActor](), "myActor")

// Within an actor, create child actors
class ParentActor extends Actor {
  val child = context.actorOf(Props[MyActor](), "child")
  
  def receive = {
    case "create" => 
      val newChild = context.actorOf(Props[MyActor]())
      context.watch(newChild)
    case Terminated(ref) =>
      println(s"Child $ref terminated")
  }
}

Actor References and Addressing

Actor references provide location-transparent handles to actors with addressing and path information.

/**
 * Immutable reference to an actor
 */
abstract class ActorRef extends java.lang.Comparable[ActorRef] with Serializable {
  /** Send a message to this actor */
  def tell(msg: Any, sender: ActorRef): Unit
  
  /** Send a message (Scala operator) */
  def !(message: Any)(implicit sender: ActorRef = Actor.noSender): Unit
  
  /** The path of this actor */
  def path: ActorPath
  
  /** Forward a message with original sender */
  def forward(message: Any)(implicit context: ActorContext): Unit
}

object ActorRef {
  /** Special actor reference representing no sender */
  val noSender: ActorRef = Actor.noSender
}

/**
 * Actor path representing the location of an actor
 */
trait ActorPath {
  /** The address of the actor system */
  def address: Address
  
  /** The name of this actor */
  def name: String
  
  /** The parent path */
  def parent: ActorPath
  
  /** The root path */
  def root: RootActorPath
  
  /** Child path with given name */
  def /(child: String): ActorPath
  
  /** Create descendant path */
  def descendant(names: Iterable[String]): ActorPath
  
  /** Convert to string representation */
  override def toString: String
}

/**
 * Address of an actor system
 */
final case class Address(
  protocol: String,
  system: String, 
  host: Option[String] = None,
  port: Option[Int] = None
) {
  /** Whether this address has global scope (network accessible) */
  def hasGlobalScope: Boolean = host.isDefined
  
  /** Whether this address has local scope */
  def hasLocalScope: Boolean = !hasGlobalScope
  
  /** String representation */
  override def toString = {
    val sb = new StringBuilder(protocol)
    sb.append("://").append(system) 
    if (host.isDefined) sb.append('@').append(host.get)
    if (port.isDefined) sb.append(':').append(port.get)
    sb.toString
  }
}

Actor Selection

Actor selection provides path-based lookup of actors using string paths with wildcards.

/**
 * Path-based actor lookup supporting wildcards and patterns
 */
abstract class ActorSelection {
  /** Send a message to all matching actors */
  def tell(msg: Any, sender: ActorRef): Unit
  
  /** Send a message (Scala operator) */
  def !(msg: Any)(implicit sender: ActorRef): Unit
  
  /** Forward a message to all matching actors */
  def forward(msg: Any)(implicit context: ActorContext): Unit
  
  /** Resolve to concrete actor references */
  def resolveOne(timeout: FiniteDuration): Future[ActorRef]
  
  /** Get the string path of this selection */
  def pathString: String
  
  /** Create child selection */
  def /(name: String): ActorSelection
}

object ActorSelection {
  /** Create selection from actor reference factory and path */
  def apply(anchorRef: ActorRef, path: String): ActorSelection
  def apply(anchorRef: ActorRef, path: immutable.Iterable[String]): ActorSelection
}

Usage Examples:

import akka.actor.{ActorSystem, Props}
import scala.concurrent.duration._

val system = ActorSystem("MySystem")

// Actor selection by path
val selection1 = system.actorSelection("/user/myActor")
val selection2 = system.actorSelection("akka://MySystem/user/myActor")

// Wildcard selection
val allChildren = system.actorSelection("/user/*")
val grandchildren = system.actorSelection("/user/*/child")

// Resolve selection to concrete reference
import system.dispatcher
val futureRef = selection1.resolveOne(5.seconds)
futureRef.foreach { ref =>
  println(s"Resolved actor: ${ref.path}")
}

// Within an actor
class MyActor extends Actor {
  def receive = {
    case "find" =>
      val sibling = context.actorSelection("../sibling")
      sibling ! "hello"
  }
}

Actor Lifecycle Hooks

Lifecycle hook methods for managing actor startup, restart, and termination.

/**
 * Actor lifecycle hooks - override in actor implementations
 */
trait Actor {
  /** Called before the actor starts processing messages */
  def preStart(): Unit = ()
  
  /** Called after the actor stops processing messages */
  def postStop(): Unit = ()
  
  /** Called before the actor restarts due to an exception */
  def preRestart(reason: Throwable, message: Option[Any]): Unit = {
    context.children.foreach(context.stop)
    postStop()
  }
  
  /** Called after the actor restarts */
  def postRestart(reason: Throwable): Unit = preStart()
  
  /** Supervisor strategy for child actors */
  def supervisorStrategy: SupervisorStrategy = SupervisorStrategy.defaultStrategy
}

Usage Examples:

import akka.actor.{Actor, ActorLogging}

class LifecycleActor extends Actor with ActorLogging {
  override def preStart(): Unit = {
    log.info("Actor starting up")
    // Initialize resources
  }
  
  override def postStop(): Unit = {
    log.info("Actor shutting down")  
    // Cleanup resources
  }
  
  override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
    log.error(reason, s"Actor restarting due to error, last message: $message")
    super.preRestart(reason, message)
  }
  
  override def postRestart(reason: Throwable): Unit = {
    log.info("Actor restarted successfully")
    super.postRestart(reason)
  }
  
  def receive = {
    case "crash" => throw new RuntimeException("Intentional crash")
    case msg => log.info(s"Received: $msg")
  }
}

Actor Termination

Control and monitor actor termination through various mechanisms.

/**
 * Lifecycle control messages
 */
case object PoisonPill extends AutoReceivedMessage with PossiblyHarmful
case object Kill extends AutoReceivedMessage with PossiblyHarmful

/**
 * Termination notification message
 */
final case class Terminated(actor: ActorRef)(
  val existenceConfirmed: Boolean,
  val addressTerminated: Boolean  
) extends AutoReceivedMessage with PossiblyHarmful

/**
 * Graceful stop pattern from akka.pattern
 */
object GracefulStopSupport {
  def gracefulStop(
    actorRef: ActorRef,
    timeout: FiniteDuration,
    stopMessage: Any = PoisonPill
  )(implicit system: ActorSystem): Future[Boolean]
}

final case class GracefulStopTimeoutException(message: String) extends AkkaException(message)

Usage Examples:

import akka.actor.{Actor, ActorRef, PoisonPill, Kill, Terminated}
import akka.pattern.gracefulStop
import scala.concurrent.duration._

class WatchingActor extends Actor {
  var childRef: ActorRef = _
  
  override def preStart(): Unit = {
    childRef = context.actorOf(Props[MyActor](), "child")
    context.watch(childRef) // Watch for termination
  }
  
  def receive = {
    case "stop-child" => 
      childRef ! PoisonPill // Graceful termination
      
    case "kill-child" =>
      childRef ! Kill // Forceful termination with exception
      
    case Terminated(ref) =>
      println(s"Child $ref has terminated")
      
    case "stop-self" =>
      context.stop(self)
  }
}

// Graceful stop from outside
import system.dispatcher
val stopFuture = gracefulStop(actorRef, 5.seconds)
stopFuture.onSuccess {
  case true => println("Actor stopped gracefully")
  case false => println("Actor did not stop within timeout")
}

Deployment Configuration

Configure actor deployment including dispatchers, routers, and mailboxes.

/**
 * Deployment configuration for actors
 */
final case class Deploy(
  path: String = "",
  config: Config = ConfigFactory.empty(),
  routerConfig: RouterConfig = NoRouter,
  scope: Scope = NoScopeGiven,
  dispatcher: String = Deploy.NoDispatcherGiven,
  mailbox: String = Deploy.NoMailboxGiven
) {
  def withFallback(other: Deploy): Deploy
  def withDispatcher(dispatcher: String): Deploy
  def withMailbox(mailbox: String): Deploy
  def withRouterConfig(routerConfig: RouterConfig): Deploy
}

object Deploy {
  val NoDispatcherGiven = ""
  val NoMailboxGiven = ""
  val NoScopeGiven: Scope = NoScopeGiven
}

/**
 * Deployment scope for actor placement
 */
abstract class Scope
case object LocalScope extends Scope
case object NoScopeGiven extends Scope

Usage Examples:

import akka.actor.{Deploy, Props}
import akka.routing.RoundRobinPool

// Configure deployment in Props
val deployedProps = Props[MyActor]().withDeploy(
  Deploy()
    .withDispatcher("my-dispatcher")
    .withMailbox("bounded-mailbox") 
    .withRouterConfig(RoundRobinPool(5))
)

val routerActor = system.actorOf(deployedProps, "router")

Install with Tessl CLI

npx tessl i tessl/maven-com-typesafe-akka--akka-actor-2-13

docs

actor-behavior.md

actor-lifecycle.md

actor-system.md

events-logging.md

index.md

io.md

messaging.md

routing.md

supervision.md

utilities.md

tile.json