My initial idea for this blog post was to prepare some sample project which shows how typed actors can communicate with each other. But no. You can read about this in the docs. What’s more, it will take few major Akka releases till Akka Typed gets final (it’s experimental now), meaning all of this can have different shape by then.
I would like to emphasize some notable differences made to Akka programming model and my thoughts on these improvements.
Some say Akka in current state has one big drawback
You can send anything you want to an actor and nothing bad happens. It was done that way, because an Actor can change it’s behavior after its creation meaning it’s hard to statically type check this. Akka Typed is the newest attempt at solving the issue, after Typed Actors which are deprecated now. With earlier approaches with Channel (Akka 1.2), TypedChannels (Akka 2.1). There are rumors the Akka team believes this one will reach the final version.
So, what’s different from untyped Akka? First and foremost, with Typed Actors we have to forget about
Actor trait. What defines an Actor is it’s behavior wrapped over messages an Actor is going to handle. Testing actors is simpler with Akka Typed - there’s no need to resort to TestKit and spin an actor system. The behavior can be tested in isolation.
Best definition comes from Scaladoc: The behavior of an actor defines how it reacts to the messages that it receives. The message may either be of the type that the Actor declares and which is part of the ActorRef signature, or it may be a system Signal that expresses a lifecycle event of either this actor or one of its child actors.
There is no
context.become() as each behavior must return another in reaction to an event - the same or a new one. There are a few types of behaviors and you will find some of them described below:
PartialFunctionflagging all unmatched messages as
Samebehavior returned by default
Total, but with
Signals support too, all handled as
Behavior decorators extract certain variables from surrounding Actor context upon receiving first message or signal, they wrap nested
ActorRefwhile receiving the first signal or message
ActorContextwhile receiving the first signal or message
Currently Actor’s lifecycle is based on callbacks. It doesn’t sound like a good fit for messaging approach, isn’t it? Now it changes.
Each behavior receives
ActorContext upon creation where lifecycle is based on
Signals, which are handled the same way as regular messages. I think these names are self explanatory.
With Typed Actors we lose
sender() method, which turned out to be problematic or error prone as the real sender always depends on the context in which it is being invoked. All actors we wan’t to communicate with must be passed through as part of the message.
Please take a look at following example.
 - For untyped actor, you can use
context.become() to pass state and maintain it, as alternative to less functional approach where state is handled in a mutable
var variable. As each message must return a behavior, you can pass the state to it directly.
 - creates child actor to handle defined messages and pass them accordingly to parent
 - behaviors can also receive other Actor references created either by main/parent actor or found by
 - return new behavior
 - only expose
FoodOrdered to the outside, so internal command
StoreFood from  is handled only by this Actor itself
Receptionist system wide Actor is the replacement for
context.actorSelection(). Other Actors can register their identity together with protocols they implement, allowing them to be found later. Here’s an example
Personally I find this code a bit confusing.
You create a
Receptionist and you register an
Actor of given behavior for a given key. Then, you have to define where to reply with confirmation that given Actor was indeed registered. You do this by passing to
replyTo argument an Actor of type
ActorRef[Receptionist.Registered[FridgeCommand]] which sounds like type for already registered Actor. That Actor will receive message
Registered[T](key: ServiceKey[T], address: ActorRef[T]) as registration confirmation.
If you want to find what is already registered, you have to
asking is forbidden. You again have to pass
replyTo argument, but now an Actor of type
ActorRef[Receptionist.Listing[FridgeCommand]] which sounds like a result of the
Find command to me.
Keep in mind that both Actors I passed to
replyTo arguments are of different types, meaning two different Actor behaviors have to register and look for an Actor, but they must be of the same command type.
It’s going to make a lot of noise to find an Actor while processing a message as you will have to prepare various Actor behaviors or Actors and send few messages just to get an Actor you want to send message to. Looks like a step toward abandoning
Typed module is not yet released in any lib version so you have to build it by yourself. You will need few more tools to install before building Akka by yourself. Then, after you clone Akka source code from master branch build libs with
sbt -Dakka.parallelExecution=true -Dakka.scaladoc.diagrams=false publishLocal
I see more verbose code with Typed Actors, especially the way you work with Receptionist to register and find actors, but having the ability to check Actor definition correctness at compile time is a huge advantage. Because messages are responsible for propagating
replyTo information, I believe some patterns will need to emerge to make our code more DRY. Anyway, this is great achievement toward more type safe Akka future.
Thanks for reading - @LeszekGruchala