Click here to Skip to main content
15,884,298 members
Articles / Programming Languages / Scala

Akka : ‘hello world’

Rate me:
Please Sign up or sign in to vote.
4.33/5 (3 votes)
25 Jul 2016CPOL6 min read 16.6K   4   7
This time we will look at a simple example of Akka.

So last time, I outlined the road map for this series of articles on Akka, and posted up some information from the Akka creators on what they had to say about Akka.

This time, we will look at a simple example of Akka.

But just before we do that, let’s talk a bit more about WHY I think Akka is great stuff.

I have been a .NET programmer for many years and have seen asynchronous programming come in many different flavors now:

  • Asynchronous delegates
  • BackgroundWorker
  • Task (TPL)
  • Async Await
  • RX
  • Concurrent collections
  • Critical sections (synchronized sections of code)

All of these pretty much have their JVM equivalent, and what you would have likely seen if you have used the .NET or JVM equivalents is the use of locks from time to time. For example, under the covers, the concurrent collections would still use some locking (monitor enter/exit) to achieve the critical sections.

This is all good stuff, and has got better to work with over the years, but there could be a better more elegant lock free way of working with concurrent/parallel programming.

For me, this is what Akka brings to the table. Instead of working with shared state that MUST be protected when writing multithreaded code, we simply don’t use any shared state and create dedicated micro sized bits of code that deal with one thing and one thing only. These are called “Actors”.

Actors do NOT share state, instead they work independently of each other and rely on message passing. Where the message payload should give the actor either everything it needs to do its job (or at the very least enough information to perhaps look things up, say an Id such that Actor can look up the entity required by its Id field).

At no point will we be using locks within actors.

Ok so that is my mini-rant/intro over. Let's now carry on and have a look at what it takes to write some Akka code in Scala.

What Libs Do We Need?

As I mentioned in the introduction post, I will be using Scala exclusively to do this series of posts. As such, I shall also be using SBT to do the build side of things.

So for this post, we are only showing how to use simple actors so we don’t have to pull in that many dependencies, we can keep things simple and use the following “build.sbt” file, where I am pulling in the following 2 dependencies:

  • Basic Akka stuff
  • Joda time
name := "HelloWorld"
 
version := "1.0"
 
scalaVersion := "2.11.8"
 
libraryDependencies ++= Seq(
  "com.typesafe.akka" % "akka-actor_2.11" % "2.4.8",
  "joda-time" % "joda-time" % "2.9.4")

NOTE: This SBT set of dependencies may grow in subsequent articles, but where it does require pulling in more Akka JARs I will show that when the time comes.

How Do We Create An Actor System?

To use the Akka actor system, we must first create an Akka system that is the fabric that all actors run under. This is easily achieved as follows:

object Demo extends App {
 
  //create the actor system
  val system = ActorSystem("HelloSystem")
 
  //---------------------------
  //   EXTRA STUFF WILL GO HERE
  //---------------------------
 
 
  //shutdown the actor system
  system.terminate()
 
  StdIn.readLine()
}

Note that you should ensure that the Akka system is also shutdown correctly.

The example I show here is a simple console type application, so my startup/shutdown logic is all in the same file, but in a real production app, things may be more complex (well, they should be I would hope).

How Do We Create An Actor?

Now that we have an actor system, the next thing we need to do is create some actors that will live within the actor system. I used the word live as a ownership type of arrangement.

So how do we create an actor exactly?

Well luckily this too is dead simple. We just need to inherit from Actor and provide an implementation for the receive method to handle the different messages that may be sent to the actor.

Recall that an actor works by receiving messages and acting upon them.

Here is what the skeleton code may look like:

import akka.actor.Actor
 
class HelloActor extends Actor {
  def receive = {
    //DO THE MESSAGE HANDLING HERE
  }
}

We will talk more about the receive method in a while, for now, just know that you must implement this method for an Akka actor to work correctly

Difference Between Tell And Ask

Just before we get on to seeing the examples, let's just take a brief diversion where we talk about the difference between ask and tell.

When we ask (? method in scala) an actor, we expect a response by way of a Future[T], this is an asynchronous operation.

When we tell (! method in scala) an actor something, this is analogous to fire and forget (of course the receiving actor could send a response back to the initiating actor via a different message, but that’s a different story), this is an asynchronous operation that returns immediately.

Sender

We have not covered this ground yet, but we will in one of the subsequent posts, but for now all you need to know is that when you are sending messages to an actor, you do so by a construct called actorRef which is a kind of like a handle to an actor.

There are special types of actorRef, one such case being “sender” who is the initiator actorRef of the message being received (if we are talking from the context of the receiving actor). You will see “sender” used in the examples below.

How Do We Send A Message To An Actor?

Here is how we would send a message to an actor. This is a tell (!) so is fire and forget.

import akka.actor._
import akka.pattern.ask
import akka.util.Timeout
import scala.concurrent.{Await, ExecutionContext, Future}
import scala.concurrent.duration._
import scala.language.postfixOps
import scala.io.StdIn
import scala.util.{Success, Failure}
import ExecutionContext.Implicits.global
 
object Demo extends App {
 
  //create the actor system
  val system = ActorSystem("HelloSystem")
 
  // default Actor constructor
  val helloActor = system.actorOf(Props[HelloActor], name = "helloactor")
 
  //send some messages to the HelloActor (fire and forget)
  helloActor ! "hello"
  helloActor ! "tis a fine day for Akka"
 
  //shutdown the actor system
  system.terminate()
 
  StdIn.readLine()
}

Where we have the following HelloActor implementation:

import akka.actor.Actor
 
class HelloActor extends Actor {
  def receive = {
    case "hello" => println("world")
    case _       => println("unknown message")
  }
}

See how for this simple actor we only ever deal with 2 things in the receive method:

  • “Hello”
  • Anything else

It is considered good practice to ensure that you handle the correct messages and deal with unknown messages too.

How Do We Wait For A Response From An Actor?

So we just saw a tell (fire and forget) but how about an ask. This is slightly harder but not much, we simply have to deal with the fact that a Future[T] will be the result of an ask. There are numerous ways of dealing with that, assuming we have the following actor:

import akka.actor.Actor
 
class AskActor extends Actor {
  def receive = {
    case GetDateMessage => sender ! new org.joda.time.DateTime().toDate().toString()
    case _       => println("unknown message")
  }
}

Here are some examples of how to deal with the result of the ask:

import akka.actor._
import akka.pattern.ask
import akka.util.Timeout
import scala.concurrent.{Await, ExecutionContext, Future}
import scala.concurrent.duration._
import scala.language.postfixOps
import scala.io.StdIn
import scala.util.{Success, Failure}
import ExecutionContext.Implicits.global
 
object Demo extends App {
 
  //create the actor system
  val system = ActorSystem("HelloSystem")
 
  // default Actor constructor
  val askActor = system.actorOf(Props[AskActor], name = "askactor")
 
  //send some messages to the AskActor, we want a response from it
 
  // (1) this is one way to "ask" another actor for information
  implicit val timeout = Timeout(5 seconds)
  val future1 = askActor ? GetDateMessage
  val result1 = Await.result(future1, timeout.duration).asInstanceOf[String]
  println(s"result1=$result1")
 
  // (2) a slightly different way to ask another actor for information
  val future2: Future[String] = ask(askActor, GetDateMessage).mapTo[String]
  val result2 = Await.result(future2, 5 second)
  println(s"result2=$result2")
 
  // (3) don't use blocking call at all, just use future callbacks
  val future3: Future[String] = ask(askActor, GetDateMessage).mapTo[String]
  future3 onComplete {
    case Success(result3) =>  println(s"result3=$result3")
    case Failure(t) => println("An error has occured: " + t.getMessage)
  }
 
 
  //shutdown the actor system
  system.terminate()
 
  StdIn.readLine()
}

Piping Futures

Another use case you may have is that you may want to use Future[T] internally within the actor code and send Future[T] around from actor to actor. Akka also supports this by the use of the pipe pattern, which you can use like this where we are piping the Future[List[Int]] back to the sender.

import akka.actor._
import akka.pattern.pipe
import scala.concurrent.{ExecutionContext, Future}
import ExecutionContext.Implicits.global
 
class FutureResultActor extends Actor {
  def receive = {
    case GetIdsFromDatabase => {
      Future(List(1,2,3)).pipeTo(sender)
    }
    case _       => println("unknown message")
  }
}

Where the code that initiated the sending of the GetIdsFromDatabase message looks like this (the sender in the code above):

import akka.actor._
import akka.pattern.ask
import akka.util.Timeout
import scala.concurrent.{Await, ExecutionContext, Future}
import scala.concurrent.duration._
import scala.language.postfixOps
import scala.io.StdIn
import scala.util.{Success, Failure}
import ExecutionContext.Implicits.global
 
object Demo extends App {
 
  //create the actor system
  val system = ActorSystem("HelloSystem")
 
  // default Actor constructor
  val futureResultActor = system.actorOf(Props[FutureResultActor], name = "futureresultactor")
 
  //send some messages to the FutureResultActor, we expect a Future back from it
  val future4: Future[List[Int]] = ask(futureResultActor, GetIdsFromDatabase).mapTo[List[Int]]
  future4 onComplete {
    case Success(result4) =>  println(s"result4=$result4")
    case Failure(t) => println("An error has occured: " + t.getMessage)
  }
 
 
  //shutdown the actor system
  system.terminate()
 
  StdIn.readLine()
}

Where is the Code?

As previously stated, all the code for this series will end up in this GitHub repo:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)

- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence

Both of these at Sussex University UK.

Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2016
  • Codeproject MVP 2016
  • Microsoft C# MVP 2015
  • Codeproject MVP 2015
  • Microsoft C# MVP 2014
  • Codeproject MVP 2014
  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Comments and Discussions

 
SuggestionScreen shot of Error & Output Pin
Bhuvanesh Mohankumar26-Jul-16 3:18
Bhuvanesh Mohankumar26-Jul-16 3:18 
GeneralRe: Screen shot of Error & Output Pin
Sacha Barber26-Jul-16 3:35
Sacha Barber26-Jul-16 3:35 
GeneralRe: Screen shot of Error & Output Pin
Bhuvanesh Mohankumar27-Jul-16 18:40
Bhuvanesh Mohankumar27-Jul-16 18:40 
GeneralRe: Screen shot of Error & Output Pin
Sacha Barber27-Jul-16 19:29
Sacha Barber27-Jul-16 19:29 
Nearly finished the 2nd part, hope to have it up today

GeneralRe: Screen shot of Error & Output Pin
Sacha Barber28-Jul-16 20:26
Sacha Barber28-Jul-16 20:26 
GeneralRe: Screen shot of Error & Output Pin
Bhuvanesh Mohankumar29-Jul-16 20:46
Bhuvanesh Mohankumar29-Jul-16 20:46 
PraiseSeries of articles on Akka Pin
Bhuvanesh Mohankumar26-Jul-16 3:16
Bhuvanesh Mohankumar26-Jul-16 3:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.