A simple Akka (actors) remote example

While doing some crazy things with SARAH, I realized that the best way to solve a particular problem was to use remote Akka actors. I haven’t had the opportunity to work with Akka much since finishing the Scala Cookbook, so I dug around trying to find a simple Akka remote “Hello, world” example. Unable to find a good one, I read some stuff, and created it myself.

The way my example works is that there are “local” and “remote” aspects to it. I set them up as two SBT projects underneath a main directory. I include a detailed discussion below on how to run the code, but in short, to get things running you first start the remote application in one JVM, and then start the local application in a second JVM. When the local application starts, it begins a short conversation with the remote.

If you want to jump in, you can clone my code from Github at this URL. Everything else in this article shows the code, and describes how it works.

Assumptions

Before going on, it’s important to note my assumptions about you, the reader. I assume:

  1. You’re familiar with Scala.
  2. You’re comfortable with SBT. (I used SBT 0.13.x with this code).
  3. You’ve used Akka actors locally.

The “remote” application

As mentioned, this project consists of a local application and a remote application. The remote application is contained in the directory named HelloRemote, and consists of three files:

  1. The SBT build.sbt file.
  2. The Scala code.
  3. An application.conf file to configure the actor system.

The directory structure looks like this:

HelloRemote/
|-- build.sbt
|-- src
    |-- main
    │   |-- java
    │   |-- resources
    │   │   +-- application.conf
    │   +-- scala
    │       +-- remote
    │           +-- HelloRemote.scala
    +-- test
        |-- java
        |-- resources
        +-- scala

Here’s the source code for HelloRemote.scala:

package remote

import akka.actor._

object HelloRemote extends App  {
  val system = ActorSystem("HelloRemoteSystem")
  val remoteActor = system.actorOf(Props[RemoteActor], name = "RemoteActor")
  remoteActor ! "The RemoteActor is alive"
}

class RemoteActor extends Actor {
  def receive = {
    case msg: String =>
        println(s"RemoteActor received message '$msg'")
        sender ! "Hello from the RemoteActor"
  }
}

Here’s the source code for application.conf:

akka {
  //loglevel = "DEBUG"
  actor {
    provider = "akka.remote.RemoteActorRefProvider"
   }
   remote {
     transport = "akka.remote.netty.NettyRemoteTransport"
     //log-sent-messages = on
     //log-received-messages = on
     netty {
       hostname = "127.0.0.1"
       port = 5150
     }
   }
}

An important thing to note from that configuration file is that the server listens on port 5150 (my preferred port ... something to do with Van Halen).

Finally, here are the contents of the build.sbt file:

name := "HelloRemote"

version := "1.0"

scalaVersion := "2.10.1"

resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"

libraryDependencies ++= Seq(
  "com.typesafe.akka" %% "akka-actor" % "2.1.1",
  "com.typesafe.akka" %% "akka-remote" % "2.1.1"
)

(The latest version of Akka at the time of this publication is 2.2.3. I don’t remember why I used 2.1.1, other than the fact that I started this a few months ago.)

The “local” application

The local application is contained in the directory named HelloLocal, and consists of the same three files:

  1. The SBT build.sbt file.
  2. The Scala code.
  3. An application.conf file to configure the actor system.

The directory structure looks like this:

HelloLocal/
|-- build.sbt
|-- src
    |-- main
    │   |-- java
    │   |-- resources
    │   │   +-- application.conf
    │   +-- scala
    │       +-- local
    │           +-- Local.scala
    +-- test
        |-- java
        |-- resources
        +-- scala

Here’s the source code for HelloLocal.scala:

package local

import akka.actor._

object Local extends App {

  implicit val system = ActorSystem("LocalSystem")
  val localActor = system.actorOf(Props[LocalActor], name = "LocalActor")  // the local actor
  localActor ! "START"                                                     // start the action

}

class LocalActor extends Actor {

  // create the remote actor
  val remote = context.actorFor("akka://HelloRemoteSystem@127.0.0.1:5150/user/RemoteActor")
  var counter = 0

  def receive = {
    case "START" =>
        remote ! "Hello from the LocalActor"
    case msg: String =>
        println(s"LocalActor received message: '$msg'")
        if (counter < 5) {
            sender ! "Hello back to you"
            counter += 1
        }
  }
}

Note how the remote actor reference is created; along with the configuration files, it’s one of the few secret ingredients to this recipe (assuming you already know how to use actors locally, i.e., in one JVM).

Here’s the source code for this project’s application.conf file:

akka {
  //loglevel = "DEBUG"
  actor {
    provider = "akka.remote.RemoteActorRefProvider"
  }
  remote {
    transport = "akka.remote.netty.NettyRemoteTransport"
    //log-sent-messages = on
    //log-received-messages = on
    netty {
      hostname = "127.0.0.1"
      port = 0
    }
  }
}

Finally, here are the contents of the build.sbt file:

name := "HelloLocal"

version := "1.0"

scalaVersion := "2.10.1"

resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"

libraryDependencies ++= Seq(
  "com.typesafe.akka" %% "akka-actor" % "2.1.1",
  "com.typesafe.akka" %% "akka-remote" % "2.1.1"
)

Running the code

Follow these steps to run the code:

  1. cd into the HelloRemote directory.
  2. Type sbt run to start the remote actor system.
  3. In a separate terminal window, cd into the HelloLocal directory.
  4. Type sbt run to start the local actor system.

When the local actor system starts, it will send an initial message to the remote actor system. The remote actor will send a reply through its sender reference, and this will continue five times. When the action stops, stop each system by pressing Ctrl-C.

Notes

A few notes:

The code on Github

As mentioned earlier, you can clone my project from Github at this URL:

There’s a short README file there as well.

Problems

If you have any problems with this code, edit the application.conf file in the src/main/resources directory of each project, and remove the comments from the debug-related lines. That may help to show any problems.

Summary

In summary, if you’re looking for a simple Akka remote “Hello, world” example, I hope you find this code useful.

I want to keep this example simple, so I intend to leave this code as is (unless anyone reports any problems). If/when I have some more free time I’ll create another project with a few more “real world” enhancements to this. (But alas, free time is scarce these days.)

Post new comment

The content of this field is kept private and will not be shown publicly.