Scala Akka Cheatsheet

Featured

A quick wrap-up from the hello-akka example of Typesafe Inc. (http://typesafe.com/activator/template/hello-akka) so nobody has to weed thru the docs to remember the syntax after being over to the Java/C++ world for a while.

One Actor is no Actor. Actors come in systems.

Carl Hewitt , inventor of the Actor Model

Agenda

  • Create Message classes that are exchanged between Actors.
  • Define an Actor by defining a receive routine.
  • Create an ActorSystem and ask it to create an Actor for us
  • Send messages to the Actor and examine the response with the help of the Inbox.

Define messages as case objects and classes

To remember:

  • Messages must be immutable and should be Serializable (for remoting).
  • Scala’s case classes come in handy because the compiler does a lot of plumbing (http://www.scala-lang.org/old/node/107)
case object Greet
case class WhoToGreet(who: String)
case class Greeting(message: String)

Define an Actor

  • An actor usually has state.
  • Inherits from Actor base class.

Basic Pattern

def receive = { case M1 => ...; case M2 => ... }
class Greeter extends Actor {
 var greeting = ""

 def receive = {
   // Sophisticated Actors will usually use pattern matching
   case WhoToGreet(who) => greeting = s"hello, $who"
   case Greet           => sender ! Greeting(greeting)
  }
 }

Create infrastructure

  • Construct an ActorSystem using the companion Object.
  • Give the ActorSystem a name.
val system = ActorSystem("helloakka")

Create an instance of your Actor

  • Use the ActorSystem’s  actorOf  method, passing Props[Greeter] and an identifying name. Greeter is the type of our Actor.
val greeter = system.actorOf(Props[Greeter], "greeter")

Send a message

  • Use the exclamation mark method (or tell) and pass a message object that is covered by the actors case statement.
  • I tend to prefer a more explicit notation.
greeter ! WhoToGreet("akka")
greeter tell WhoToGreet("akka")
greeter.tell(WhoToGreet("akka"))
  • Akka uses Scala’s implicit parameter feature (parameter derived from context) to pass the sender’s ActorRef.
  • Use the “sender” reference provided by the Actor base class to reply with a message.

Test the Actor

Inbox is a class that is kind of a non-responding Actor that is handy to trigger an Actor (that again triggers other Actors) and collect its responses.

val inbox = Inbox.create(system)
greeter tell WhoToGreet("akka")
inbox.send(greeter, Greet)
val Greeting(message) = inbox.receive(5.seconds)

assert(message == "akka")

Thoughts on Automated Testing

Depending on the complexity of the logic it may come in handy to treat the Actor as an integration component without business logic and create separate classes that do business logic. Decoding messages and responding to them seems enough responsibility for one class. Real world receive routines quickly become convoluted or the actor class gets too many method.

Object-Oriented Software Constructions and Actor Systems

You will find that the style from Object-Oriented Software Construction is an excellent basis for writing actor systems. Controlling side-effects is essential to not violating the Actor Models rules.

Note how Actors must always be in a stable state before and after they handle an incoming message. A well-constructed real-world Actor will have explicit preconditions, postconditions and invariants. In the end it is a managed, stateful object.

Disclaimer

All example code and wisdom was adapted from the hello-akka example created by Typesafe Inc. and is not my original work.

Advertisements

Build Automation Software is still just Software

Whenever you move out of your cozy Java (-Language)/Eclipse/Maven comfort zone you recognize there is a whole plentitude of build systems coming with different environments. While you would probably associate the classic Java language with ant or Maven (or even 5000+ lines of BASH scripts written a hundred years ago), the polyglot programmer must be aware of:

  • Scala and SBT
  • Groovy and Gradle (becoming more and more popular in Java)
  • Clojure and Leiningen
  • (J)Ruby and Rake

Leaving the JVM community, there’s still C/C++ with Make (with the beloved  automake, autoconf & Co.), NANT for .NET and certainly a lot more.

How languages rub off on their build tools

There seems to be a strong need to leverage the feel and the qualities of the production language to the build system. The bad properties get inherited, too:

  • Ant and Maven rely heavily on XML (remember EJB 2.x?) and I remember that internally, domain values  are mostly Strings.
  • Non-trivial Gradle scripts lead to these “Oh, there is a coniditionally dynamically added method that makes just the release artifacts for the customers fail.”
  • SBT forces you to leave blank lines – wonder when tabbed punchcards come back.
  • Leiningen invents yet another syntax for GAV coordinates.

Business risks of 3rd party tools

Especially one-man shows and small companies should think about the impact of having yet another third-party tool that needs updates twice a year:

  • Maven Plugins have defects fixed in features that you don’t actually use and defects introduced in features your business relies on.
  • The Maven Release Plugin is still not the right way to do continuous delivery.
  • Testing of Maven plugins was cumbersome and still is no fun.
  • Using String ${properties} and not objects that provide the proper level of abstraction remains the source of many hacks in build scripts. javaCompilerConfiguration.invokeJavaC(buildChain, context) is quite different from setting untyped properties for a Maven plugin, right?

Why you might want to roll your own Build Automation System

Many people still think that programming in a general purpose language and programming by configuring a model are basically two different things. They are not. Anneke Kleppe introduced the term Mogram, which is a portmanteau of Model and Program. Think of JSON, which is data as a program. You are not configuring Maven or Gradle, you are programming them.

The problem with, say, a Maven pom.xml is, that it is hard to test its abstract behavior. Does it generate all the artifacts with the content we expect? While the plugin might be correct, you might have missed a configuration parameter or set up a wrong (or no) base path. I am always afraid when someone changes the build system – did they do more than a manual smoke test after the last-minute-change?.

Test-First development of your Build Automation System

Build Automation is extremely relevant for the delivery of the final product, still it is often treated as a kind of glorified AUTOEXEC.BAT: The build system people tinker around with plug-in configurations in the pom.xml like in the old MS-DOS days. But it’s real software!

So, why not treat it as a first class citizen? Having an easily maintainable, customized process written in your production general purpose language prevents 1500+ line build files (your coding stanadard says ~200 lines per unit max, right?), hard coded values and doomsday events on important releases.

A few Ideas

  • Use Test-First Development, TDD, all of it. I want my build system to be at least as good as the final product – when it has a defect or is not exensible I cannot deliver my products with the desired quality or in time.
    • The machines that build a consumer product often outlive the product they build for economical reasons.
  • Apply the same (or even more strict) design and coding rules.
  • Look out for self-similar structures. Even a Build Tool needs a Build Tool – but usually just not that complicated.
  • Do not use Language A to build Language B (except when A is a subset of B).  You will have more tools that may behave wrong after an innocent update.
  • Leverage compiler type checks (an ArtifactId is pretty well defined…) and IDE auto-completion.
  • Favor small build tasks over the Maven do-it-all-and-in-one-file approach (try configuring Maven to distribute an artifact to 5 different repositories, depending on different conditions.).

And please: Don’t invent yet another embedded DSL: A ten line build script is something you only find in textbooks (just like SELECT * FROM ORDERS …).

Using Scala’s Option[A] in Java

A few days ago I stated that I don’t see a pressure to move from the Java language to a new language. But of course there are some, non-“magic” concepts in other languages that might solve real problems. An example would be Scalas Option[A] class. In Java the result of an entityManager.find(MyCustomer.class, myPrimaryKey) operation is either null or a reference to an entity. A null check needs to be applied to interpret the result. This is a common idiom. It becomes problematic, if the result should never be null but sometimes is (because of a bug). It may also not be well-documented which happens with seldom-used in-house APIs.

The idea of the Scala Option[A] concept is to document that a parameter or result can be empty. In Scala usually a trivial pattern matcher is used to seperate the cases, but in Java a simple if-statement should suffice in most cases. I do not know if this really makes things easier or more difficult, but we developed something a like in cases like a (UI) selection, where there may be a selected element (or set) or not. Checking selection.isEmpty() usually leads to a disabled subview or form in the end.

Here’s a proposition of how option might look in Java. (Maybe there is an other solution already available, leave a comment if I am not up-to-date.)

package org.injava.lang;

import static org.apache.commons.lang.Validate.notNull;

/**
 * Scala's <tt>Option[A]</tt> construct in Java.
 */
public abstract class Option<A> {

    public abstract boolean isEmpty();
    /** precondition: !isEmpty() */
    public abstract A getValue();

    /** Shortcut for getValue() - it will be needed a lot */
    public A _() {
        return getValue();
    };

    public static <A> Option<A> create(final A someOrNone) {
        if (someOrNone == null) {
            return None.instance();
        }

        return new Some<A>(someOrNone);
    }

    /**
     * A shorthand for <tt>create</tt> which will be used very often when
     * interfacing with Java libraries returning nulls.
     */
    public static <A> Option<A> _(final A someOrNone) {
        return create(someOrNone);
    }

    public static class Some<A> extends Option<A> {
        private final A value;

        public Some(final A value) {
            notNull(value);
            this.value = value;
        }

        public boolean isEmpty() {
            return false;
        }

        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((value == null) ? 0 : value.hashCode());
            return result;
        }

        public boolean equals(final Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final Some other = (Some) obj;
            if (value == null) {
                if (other.value != null) {
                    return false;
                }
            } else if (!value.equals(other.value)) {
                return false;
            }
            return true;
        }

        public A getValue() {
            return value;
        }
    }

    /** Class representing the case with no result */
    public static class None<A> extends Option<A> {
        private final static None instance = new None();

        private None() { }

        public boolean isEmpty() {
            return true;
        }

        @SuppressWarnings("unchecked")
        public static <A> None<A> instance() {
            return instance;
        }

        /**
         * Should this fail or just return null? Not quite sure, but failing
         * seems right as it is a protocol violation.
         */
        public A getValue() {
            throw new IllegalStateException("Cannot getValue of Option.None");
        }
    }
}

What do you think? It might be used directly or as a delegate by more domain specific classes.

public interface EntityManager {
    public <T> Option<T> find(final Class<T> entityClass, final Object primaryKey);
    ...
}

...

public class MyRepositoryImpl {
   ...
   public MyEntity findByName(final Name name) {
       ... // resolve to primarykey (just an example)
       final Option<MyEntity> result = entityManager.find(MyEntity.class, myEntityId);
       if(result.isEmpty() {
          return MyEntity.Null.instance();
       }

       ...
}

Note that Java Generics are not as flexible as Scalas type system, so contravariance in result types will be limited (think of List<MyBaseClass>).

Option<A> does not change the world, but it is now obvious that some operation might not return a valid reference. While null checks are common and understood by most developers, I noticed in the past that even little improvements in clarity like this one can be beneficial over time. What do you think?