libraryDependencies += "com.typesafe.akka" % "akka-actor_2.11" % "2.4.8"
Actor for string output:
class OutputActor extends Actor {
override def receive: Receive = {
case message => println(message)
}
}
Actor for string modifying:
class AppendActor(outputActor: ActorRef) extends Actor {
override def receive: Receive = {
case message: String =>
val changed = s"Hello, $message!"
outputActor ! changed
case unknown =>
println(s"unknown message: $unknown")
}
}
object HelloWorld extends App {
val system = ActorSystem("HelloWorld")
val outputActor = system.actorOf(Props[OutputActor], name = "output")
val appendActor = system.actorOf(Props(classOf[AppendActor], outputActor), name = "appender")
appendActor ! "Akka" // send test message
Thread.sleep(500) // wait for async evaluation
system.terminate() // terminate actors system
}
Program output:
Hello, Akka!
Consider a communication happening between a Employee and its HR Department.
Broadly these are explained in the following six steps when a message is passed to the actor:
Employee creates something called an ActorSystem.
It uses the ActorSystem to create something called as ActorRef. The message(MSG) is sent to the ActorRef (a proxy to HR Actor).
Actor ref passes the message along to a Message Dispatcher.
The Dispatcher enqueues the message in the target Actor’s MailBox.
The Dispatcher then puts the Mailbox on a Thread (more on that in the next section).
The MailBox dequeues a message and eventually delegates that to the actual HR Actor’s receive method.
/** The Main Program consider it as a Employee Actor that is sending the requests **/
object EmployeeActorApp extends App{
//Initialize the ActorSystem
val actorSystem=ActorSystem("HrMessageingSystem")
//construct the HR Actor Ref
val hrActorRef=actorSystem.actorOf(Props[HrActor])
//send a message to the HR Actor
hrActorRef!Message
//Let's wait for a couple of seconds before we shut down the system
Thread.sleep (2000)
//Shut down the ActorSystem.
actorSystem.shutdown()
}
/** The HRActor reads the message sent to it and performs action based on the message Type **/
class HRActor extends Actor {
def receive = {
case s: String if(s.equalsIgnoreCase(“SICK”)) => println("Sick Leave applied”)
case s: String if(s.equalsIgnoreCase(“PTO”)) => println("PTO applied “)
}
}
Add this dependency to your project POM:
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-actor_2.11</artifactId>
<version>2.4.4</version>
</dependency>
Create an Actor
public class HelloWorldActor extends AbstractActor {
public HelloActor() {
receive(ReceiveBuilder
.match(SayHello.class, this::sayHello)
.match(SayBye.class, this::sayBye)
.build());
}
private void sayHello(final SayHello message) {
System.out.println("Hello World");
}
private void sayHello(final SayBye message) {
System.out.println("Bye World");
}
public static Props props() {
return Props.create(HelloWorldActor.class);
}
}
Create a Junit test for the actor
public class HelloActorTest {
private ActorSystem actorSystem;
@org.junit.Before
public void setUp() throws Exception {
actorSystem = ActorSystem.create();
}
@After
public void tearDown() throws Exception {
JavaTestKit.shutdownActorSystem(actorSystem);
}
@Test
public void testSayHello() throws Exception {
new JavaTestKit(actorSystem) {
{
ActorRef helloActorRef = actorSystem.actorOf(HelloWorldActor.props());
helloActorRef.tell(new SayHello(), ActorRef.noSender());
helloActorRef.tell(new SayBye(), ActorRef.noSender());
}
};
}
}