Stackable actor traits with Akka and Scala explained

Stackable actors seem to be very popular pattern when working with Akka. At some point many engineers realize that it would be nice to extract common receive behaviour into separate traits and compose them as needed. I’ve read couple blog posts about this technique but I feel none of them was really good at explaining how stackable actors work.

The idea

Lets assume our project consists of number of actors. There is nothing wrong about the entire platform, neither particular actor. As our project grows from time to time we have a need to add common functionality to all the actors, or specific subset of them. Let it be logging of received messages, or measuring time spent in receive method or anything else common.

Easiest solution would be add desired functionality to one of the actors and then copy/paste it. Slightly improved version would be to create parent class for our actors and put all the common features in there. Child actors would just have to make sure they call parent methods and proper time. Problem is this parent class quickly turns into a kitchen sink? And you can’t really trust that dozens of child actors will use parent in proper way, always.

Ideally it would be nice to implement actors as usual and just mix in behaviours we are interested in. Something like:

The usual. But how to make sure that all, or just specific, messages are also processed by mixed in traits? And at the same time how not to introduce new API that differs too much from the well known and established actor API?

Stackable actor

Introducing StackableActor. A trait that makes stacking (mixing) actors easy and at the same time does not introduce much different API.

How it works. The receive method checks if wrappedReceive is defined for a message and if so calls it. Otherwise it calls unhandled. It basically passes responsibility of handling messages to wrappedReceive.

wrappedReceive is a variable that holds current way of handling messages. That’s where our case statements will go. It’s a variable so that we can change behaviour of our actors on the fly by assigning to it different partial function to handle messages in different way.

wrappedBecome is our new context.become. It simply assigns new partial function to variable wrappedReceive. This way we can change behaviour of actor on the fly just like we would do it using context.become.

New actors

Implementation of our actors does not have to change much when using  stackable actors. There are only three things to learn:

  • do not define receive method, instead implement your own message handling method and give it meaningful name (it’s a good practice anyway)
  • somewhere in constructor of the actor call wrappedBecome to set initial behaviour of actor, passing to it the method mentioned in previous point; comparing regular actors you would assign your method to receive
  • whenever behaviour of actor needs to change instead of calling context.become, use wrappedBecome

Not much different than working with regular actors Instead of receive method we have our own method called initialReceive and we call wrappedBecome in the constructor passing initialReceive so that the actor can start handling messages. There is no need to call super.receive, no need to overwrite any specific abstract method. A lot of freedom to implement actors as we want.

Stackable traits

Our stackable traits require a bit more attention. The trait needs to overwrite receive method and must not forget to call super.receive. That’s the mechanism of stacking the traits. Particular trait will handle message of specific type (or any message) and will call super.receive to let next trait in the line have chance to handle it in its way.

The below example is a trait that for every message it receives it writes to a log an entry just before processing the message, and right after processing it.

But stackable trait does not have to wrap all received messages in exactly same logic. One can imagine a trait that wraps only some types of messages and transparently passes forward all other messages to the next trait on the stack. For example there might be HttpLogging trait that logs all received HTTP requests and passes forward other messages it might receive (eg. HttpConnectionClosed):

With a bit of bravery we can even manipulate received messages before they get processed by our actor. We might have a trait that adds unique request ID to our message, or tracing information, fixes some common and safe to fix message issues (like formatting). The point is the message we pass to super.receive does not have to be exactly the same message as the actor has received. However be careful manipulating messages this way. It’s too easy to obscure message flow or break something.

Putting it all together

Having couple stackable traits implemented we can keep our actors clean and just mix in common features. Without magic or tedious super.receive wiring. Lets take a look at the very first code snipped from the post converted into stackable actor.

When our actor receives a message it will be first handled by NiceLogging trait. This trait, beside wrapping interesting messages, needs to call super.receive for all messages it receives. This way our message can bubble to SomeMeasurement, which does the same. It intercepts some (or all) messages, wraps them, and forwards all messages by calling super.receive. Eventually we end up in last trait, for which super.receive is the receive from StackableActor. The one that tests wrappedReceive for being able to handle a message and if so using it, or treating the message as unhandled.


Stackable actor can simplify how we think about actors. It allows extracting common behaviour from actors and composing them with actors in more clean, manageable way.

There are few key differences between this implementation and some other examples I’ve found when learning how to stack actors:

  • receive of particular trait can have more than one statement to wrap different messages in different ways; it might be not obvious for people new to Akka; just remember to call super.receive in each case and to have case for handling “all other messages” as well
  • wrappedReceive is a variable (as opposed to, for example) abstract method
  • so that wrappedBecome is trivial to implement
  • and engineers working on particular actors have more decision freedom


Object oriented programming in JavaScript

OOP paradigm is probably most discussed topic in JavaScript and most popular type of library extending the language. I believe that first approach to make JS object model more usable was made by Douglas Crockford, in 2002. 11 years have passed and honestly nothing remotely close to common OOP toolset has been offered. Inheritance, interfaces, visibility scope… all these tiny features that make OOP easier are still no there or are hacked in very peculiar way. I was already thinking we’ll have to wait another 10 or so years for popular browser to fully implement ECMA 2, and 3, and 5 to get these abstracts and private and so on to be generally available. Wait no more. Someone did amazing job bringing all the missing “keywords” into JavaScript way and in rather clean way. And wrapped as AMD. And faster than vanilla classes. Get ready to experience dejavu.

Dejavu package comes in two versions. Strict and loose, or better call them development and production. The development one does all the heavy checks of method signatures and full interface implementations. It makes library slow but hey, if you do not implement a method of an interface your tool should warn you. The loose version is suited for production. It’s extremely fast but the speed is gained by removing all the heaving checking. Thus if your class is missing a method of an interface it is implementing and you run your code with loose version of dejavu you won’t be warned. Code will execute and will work… or not.

Feature list is extensive. Dejavu provides syntax for:

  • concrete, abstract and final classes as well interfaces
  • working JavaScript instanceof for classes and new function instanceOf for interfaces
  • private and protected (visibility)
  • static members and constants
  • “super” for calling super (parent) implementation of methods, including constructor
  • verification of method signatures
  • context binding
  • freezing and unfreezing objects

It also lets you define singletons and do classes mixins but I hope no one uses these features.

Since dejavu homepage provides complete examples of all features I’m not going to duplicate the effort and write practically copy/paste tutorial. I’ll just borrow one of example classes:

Convinced? Go to dejavu homepage and improve your JavaScript OOP coding experience.