Part 2: Creating the First Actor
Dependency
Add the following dependency in your project:
- sbt
libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.5.32"
- Maven
<dependencies> <dependency> <groupId>com.typesafe.akka</groupId> <artifactId>akka-actor_2.12</artifactId> <version>2.5.32</version> </dependency> </dependencies>
- Gradle
dependencies { implementation "com.typesafe.akka:akka-actor_2.12:2.5.32" }
Introduction
With an understanding of actor hierarchy and behavior, the remaining question is how to map the top-level components of our IoT system to actors. It might be tempting to make the actors that represent devices and dashboards at the top level. Instead, we recommend creating an explicit component that represents the whole application. In other words, we will have a single top-level actor in our IoT system. The components that create and manage devices and dashboards will be children of this actor. This allows us to refactor the example use case architecture diagram into a tree of actors:
We can define the first actor, the IotSupervisor, with a few simple lines of code. To start your tutorial application:
- Create a new
IotSupervisor
source file in your appropriate package, e.g. in thecom.example
package - Paste the following code into the new file to define the IotSupervisor.
- Scala
-
source
package com.example import akka.actor.{ Actor, ActorLogging, Props } object IotSupervisor { def props(): Props = Props(new IotSupervisor) } class IotSupervisor extends Actor with ActorLogging { override def preStart(): Unit = log.info("IoT Application started") override def postStop(): Unit = log.info("IoT Application stopped") // No need to handle any messages override def receive = Actor.emptyBehavior }
- Java
-
source
package com.example; import akka.actor.AbstractActor; import akka.actor.ActorLogging; import akka.actor.Props; import akka.event.Logging; import akka.event.LoggingAdapter; public class IotSupervisor extends AbstractActor { private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this); public static Props props() { return Props.create(IotSupervisor.class, IotSupervisor::new); } @Override public void preStart() { log.info("IoT Application started"); } @Override public void postStop() { log.info("IoT Application stopped"); } // No need to handle any messages @Override public Receive createReceive() { return receiveBuilder().build(); } }
The code is similar to the actor examples we used in the previous experiments, but notice:
- Instead of
println()
we use theActorLogging
helper traitakka.event.Logging
, which directly invokes Akka’s built in logging facility. - We use the recommended pattern for creating actors by defining a
props()
method in the companion object of static method on the actor.
To provide the main
entry point that creates the actor system, add the following code to the new IotApp
object IotMain
class.
- Scala
-
source
package com.example import akka.actor.ActorSystem import scala.io.StdIn object IotApp { def main(args: Array[String]): Unit = { val system = ActorSystem("iot-system") try { // Create top level supervisor val supervisor = system.actorOf(IotSupervisor.props(), "iot-supervisor") // Exit the system after ENTER is pressed StdIn.readLine() } finally { system.terminate() } } }
- Java
-
source
package com.example; import java.io.IOException; import akka.actor.ActorSystem; import akka.actor.ActorRef; public class IotMain { public static void main(String[] args) throws IOException { ActorSystem system = ActorSystem.create("iot-system"); try { // Create top level supervisor ActorRef supervisor = system.actorOf(IotSupervisor.props(), "iot-supervisor"); System.out.println("Press ENTER to exit the system"); System.in.read(); } finally { system.terminate(); } } }
The application does little, other than print out that it is started. But, we have the first actor in place and we are ready to add other actors.
What’s next?
In the following chapters we will grow the application gradually, by:
- Creating the representation for a device.
- Creating the device management component.
- Adding query capabilities to device groups.