SlideShare a Scribd company logo
Akka Typed
Johan Andrén, Akka Team
Øredev Malmö, 2018-11-20
Next generation
message driven
systems with Akka
Johan Andrén
Akka Team
Stockholm Scala User Group
@apnylle
markatta.com/codemonkey/
johan.andren@lightbend.com
Build powerful reactive, concurrent,
and distributed applications more easily
Akka
What’s in the toolkit?
Actors – simple & high performance concurrency
Cluster, Cluster tools – tools for building distributed
systems
Streams – reactive streams implementation
Persistence – CQRS + Event Sourcing for Actors
HTTP – fully async streaming HTTP Server
Alpakka – Reactive Streams Integrations a’la Camel
Actors – simple & high performance concurrency
Cluster, Cluster tools – tools for building distributed
systems
Streams – reactive streams implementation
Persistence – CQRS + Event Sourcing for Actors
HTTP – fully async streaming HTTP Server
Alpakka – Reactive Streams Integrations a’la Camel
Typed
Typed
Typed
(already type-safe)
(already type-safe)
(already type-safe)
What is coming soon?
(already type-safe)
Languages
Complete APIs for both Java and Scala
Actor
Message
Inbox
MessageMessage
actorRef.tell(message)
Akka Actor fundamentals
The only way for the rest of the
application to interact with the actor
• mutate state (including spawning a child actor)
• send messages to other actors
• change its behavior
Actor
Message
Inbox
MessageMessage
An Actor can…
MVS
(Minimum Viable Sample)
Na-na na-na na-na na-naSample-time!
Also known as “hello world”
import akka.actor.typed.ActorRef;
import akka.actor.typed.ActorSystem;
import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.Behaviors;
import java.io.IOException;
public class Sample1 {
static class Hello {
public final String who;
public Hello(String who) {
this.who = who;
}
}
final static Behavior<Hello> greetingBehavior =
Behaviors.receive(Hello.class)
.onMessage(Hello.class, (context, message) -> {
context.getLog().info("Hello {}!", message.who);
return Behavior.same();
}).build();
public static void main(String[] args) throws IOException {
ActorSystem<Hello> actorSystem =
ActorSystem.create(greetingBehavior, "my-system");
ActorRef<Hello> rootActor = actorSystem;
rootActor.tell(new Hello("Johan"));
rootActor.tell(new Hello(“Øredev audience"));
System.out.println("Press that any-key to terminate");
System.in.read();
actorSystem.terminate();
}
}
public class Sample1 {
static class Hello {
public final String who;
public Hello(String who) {
this.who = who;
}
}
final static Behavior<Hello> greetingBehavior =
Behaviors.receive(Hello.class)
.onMessage(Hello.class, (context, message) -> {
context.getLog().info("Hello {}!", message.who);
return Behavior.same();
}).build();
public static void main(String[] args) throws IOException {
ActorSystem<Hello> actorSystem =
ActorSystem.create(greetingBehavior, "my-system");
ActorRef<Hello> rootActor = actorSystem;
rootActor.tell(new Hello("Johan"));
public class Sample1 {
static class Hello {
public final String who;
public Hello(String who) {
this.who = who;
}
}
final static Behavior<Hello> greetingBehavior =
Behaviors.receive(Hello.class)
.onMessage(Hello.class, (context, message) -> {
context.getLog().info("Hello {}!", message.who);
return Behavior.same();
}).build();
public static void main(String[] args) throws IOException {
ActorSystem<Hello> actorSystem =
ActorSystem.create(greetingBehavior, "my-system");
ActorRef<Hello> rootActor = actorSystem;
rootActor.tell(new Hello("Johan"));
}
}
final static Behavior<Hello> greetingBehavior =
Behaviors.receive(Hello.class)
.onMessage(Hello.class, (context, message) -> {
context.getLog().info("Hello {}!", message.who);
return Behavior.same();
}).build();
public static void main(String[] args) throws IOException {
ActorSystem<Hello> actorSystem =
ActorSystem.create(greetingBehavior, "my-system");
ActorRef<Hello> rootActor = actorSystem;
rootActor.tell(new Hello("Johan"));
rootActor.tell(new Hello(“Øredev audience"));
System.out.println("Press that any-key to terminate");
System.in.read();
actorSystem.terminate();
}
}
}
}
final static Behavior<Hello> greetingBehavior =
Behaviors.receive(Hello.class)
.onMessage(Hello.class, (context, message) -> {
context.getLog().info("Hello {}!", message.who);
return Behavior.same();
}).build();
public static void main(String[] args) throws IOException {
ActorSystem<Hello> actorSystem =
ActorSystem.create(greetingBehavior, "my-system");
ActorRef<Hello> rootActor = actorSystem;
rootActor.tell(new Hello("Johan"));
rootActor.tell(new Hello(“Øredev audience"));
System.out.println("Press that any-key to terminate");
System.in.read();
actorSystem.terminate();
}
}
import akka.actor.typed.{ActorRef, ActorSystem, Behavior}
import akka.actor.typed.scaladsl.Behaviors
import scala.io.StdIn
object Sample1 {
case class Hello(who: String)
val greetingBehavior: Behavior[Hello] =
Behaviors.receive { (ctx, hello) =>
ctx.log.info(s"Hello ${hello.who}!")
Behaviors.same
}
def main(args: Array[String]): Unit = {
val system = ActorSystem(greetingBehavior, "my-system")
val rootActor: ActorRef[Hello] = system
rootActor ! Hello("Johan")
rootActor ! Hello(“Øredev audience")
println("Press the any-key to terminate")
StdIn.readLine()
system.terminate()
}
}
Let’s do another one
right away
The mystery of the changing state
🔎
interface Command {}
static class ChangeGreeting implements Command {
public final String newGreeting;
public ChangeGreeting(String newGreeting) {
this.newGreeting = newGreeting;
}
}
static class Hello implements Command {
public final String who;
public Hello(String who) {
this.who = who;
}
}
public static Behavior<Command> dynamicGreetingBehavior(String greeting) {
return Behaviors.receive(Command.class)
.onMessage(Hello.class, (context, message) -> {
context.getLog().info(greeting + " " + message.who + "!");
return Behavior.same();
}).onMessage(ChangeGreeting.class, (context, changeGreeting) ->
dynamicGreetingBehavior(changeGreeting.newGreeting)
).build();
}
public static void main(String[] args) throws IOException {
var actorSystem =
ActorSystem.create(dynamicGreetingBehavior("Hello"), "my-system");
actorSystem.tell(new Hello("Johan"));
actorSystem.tell(new ChangeGreeting("Hej"));
actorSystem.tell(new Hello(“Øredev audience"));
}
interface Command {}
static class ChangeGreeting implements Command {
public final String newGreeting;
public ChangeGreeting(String newGreeting) {
this.newGreeting = newGreeting;
}
}
static class Hello implements Command {
public final String who;
public Hello(String who) {
this.who = who;
}
}
public static Behavior<Command> dynamicGreetingBehavior(String greeting) {
return Behaviors.receive(Command.class)
.onMessage(Hello.class, (context, message) -> {
context.getLog().info(greeting + " " + message.who + "!");
return Behavior.same();
}).onMessage(ChangeGreeting.class, (context, changeGreeting) ->
dynamicGreetingBehavior(changeGreeting.newGreeting)
).build();
}
static class Hello implements Command {
public final String who;
public Hello(String who) {
this.who = who;
}
}
public static Behavior<Command> dynamicGreetingBehavior(String greeting) {
return Behaviors.receive(Command.class)
.onMessage(Hello.class, (context, message) -> {
context.getLog().info(greeting + " " + message.who + "!");
return Behavior.same();
}).onMessage(ChangeGreeting.class, (context, changeGreeting) ->
dynamicGreetingBehavior(changeGreeting.newGreeting)
).build();
}
public static void main(String[] args) throws IOException {
var actorSystem =
ActorSystem.create(dynamicGreetingBehavior("Hello"), "my-system");
actorSystem.tell(new Hello("Johan"));
actorSystem.tell(new ChangeGreeting("Hej"));
actorSystem.tell(new Hello(“Øredev audience"));
}
public static Behavior<Command> dynamicGreetingBehavior(String greeting) {
return Behaviors.receive(Command.class)
.onMessage(Hello.class, (context, message) -> {
context.getLog().info(greeting + " " + message.who + "!");
return Behavior.same();
}).onMessage(ChangeGreeting.class, (context, changeGreeting) ->
dynamicGreetingBehavior(changeGreeting.newGreeting)
).build();
}
public static void main(String[] args) throws IOException {
var actorSystem =
ActorSystem.create(dynamicGreetingBehavior("Hello"), "my-system");
actorSystem.tell(new Hello("Johan"));
actorSystem.tell(new ChangeGreeting("Hej"));
actorSystem.tell(new Hello(“Øredev audience"));
}
sealed trait Command
case class Hello(who: String) extends Command
case class ChangeGreeting(newGreeting: String) extends Command
def dynamicGreetingBehavior(greeting: String): Behavior[Command] =
Behaviors.receive { (ctx, message) =>
message match {
case Hello(who) =>
ctx.log.info(s"$greeting ${who}!")
Behaviors.same
case ChangeGreeting(newGreeting) =>
dynamicGreetingBehavior(newGreeting)
}
}
def main(args: Array[String]): Unit = {
val system = ActorSystem(dynamicGreetingBehavior("Hello"), "my-system")
system ! Hello("Johan")
system ! ChangeGreeting("Hej")
system ! Hello(“Øredev audience")
}
But I don’t like it
(the FP style, that is)
static class DynamicGreetingBehavior extends AbstractBehavior<Command> {
private final ActorContext<Command> context;
private String greeting;
public DynamicGreetingBehavior(String initialGreeting, ActorContext<Command> context) {
this.context = context;
greeting = initialGreeting;
}
@Override
public Receive<Command> createReceive() {
return receiveBuilder()
.onMessage(Hello.class, this::onHello)
.onMessage(ChangeGreeting.class, this::onChangeGreeting)
.build();
}
private Behavior<Command> onHello(Hello hello) {
context.getLog().info(greeting + " " + hello.who + "!");
return Behaviors.same();
}
private Behavior<Command> onChangeGreeting(ChangeGreeting changeGreeting) {
greeting = changeGreeting.newGreeting;
return Behaviors.same();
}
}
static class DynamicGreetingBehavior extends AbstractBehavior<Command> {
private final ActorContext<Command> context;
private String greeting;
public DynamicGreetingBehavior(String initialGreeting, ActorContext<Command> contex
this.context = context;
greeting = initialGreeting;
}
@Override
public Receive<Command> createReceive() {
return receiveBuilder()
.onMessage(Hello.class, this::onHello)
.onMessage(ChangeGreeting.class, this::onChangeGreeting)
.build();
}
private Behavior<Command> onHello(Hello hello) {
context.getLog().info(greeting + " " + hello.who + "!");
return Behaviors.same();
}
static class DynamicGreetingBehavior extends AbstractBehavior<Command> {
private final ActorContext<Command> context;
private String greeting;
public DynamicGreetingBehavior(String initialGreeting, ActorContext<Command> contex
this.context = context;
greeting = initialGreeting;
}
@Override
public Receive<Command> createReceive() {
return receiveBuilder()
.onMessage(Hello.class, this::onHello)
.onMessage(ChangeGreeting.class, this::onChangeGreeting)
.build();
}
private Behavior<Command> onHello(Hello hello) {
context.getLog().info(greeting + " " + hello.who + "!");
return Behaviors.same();
}
private String greeting;
public DynamicGreetingBehavior(String initialGreeting, ActorContext<Command> contex
this.context = context;
greeting = initialGreeting;
}
@Override
public Receive<Command> createReceive() {
return receiveBuilder()
.onMessage(Hello.class, this::onHello)
.onMessage(ChangeGreeting.class, this::onChangeGreeting)
.build();
}
private Behavior<Command> onHello(Hello hello) {
context.getLog().info(greeting + " " + hello.who + "!");
return Behaviors.same();
}
private Behavior<Command> onChangeGreeting(ChangeGreeting changeGreeting) {
greeting = changeGreeting.newGreeting;
return Behaviors.same();
}
}
public static void main(String[] args) {
ActorSystem<Command> system = ActorSystem.<Command>create(
Behaviors.setup((context) ->
new DynamicGreetingBehavior("Hello", context)),
"my-system"
);
system.tell(new Hello("Johan"));
system.tell(new ChangeGreeting(“Hej"));
system.tell(new Hello(“Øredev audience"));
}
• Discoverability, how are things related
• More compile time type-safety, less runtime debugging

Types helps productivity!
(and results in more reliable systems in production)
The need for strong/strict typing
“Sending the wrong message to an actor is
actually quite uncommon”
– Myself
Burglar Alarm
• enabled/disabled with a pin code
• accepts notifications about “activity”
• if enabled on activity, sound the alarm
“Realistic” Example
DIY
interface AlarmMessage {}
static class EnableAlarm implements AlarmMessage {
public final String pinCode;
public EnableAlarm(String pinCode) {
this.pinCode = pinCode;
}
}
static class DisableAlarm implements AlarmMessage {
public final String pinCode;
public DisableAlarm(String pinCode) {
this.pinCode = pinCode;
}
}
static class ActivityEvent implements AlarmMessage { }
public static Behavior<AlarmMessage> enabledAlarm(String pinCode) {
return Behaviors.receive(AlarmMessage.class)
.onMessage(
DisableAlarm.class,
// predicate
(disable) -> disable.pinCode.equals(pinCode),
(context, message) -> {
context.getLog().info("Correct pin entered, disabling alarm");
return disabledAlarm(pinCode);
}
).onMessage(ActivityEvent.class, (context, activityEvent) -> {
context.getLog().warning("EOEOEOEOEOE ALARM ALARM!!!");
return Behaviors.same();
}).build();
}
public static Behavior<AlarmMessage> disabledAlarm(String pinCode) {
return Behaviors.receive(AlarmMessage.class)
.onMessage(EnableAlarm.class,
// predicate
(enable) -> enable.pinCode.equals(pinCode),
(context, message) -> {
context.getLog().info("Correct pin entered, enabling alarm");
return enabledAlarm(pinCode);
}
).build();
}
public static void main(String[] args) {
var system = ActorSystem.create(enabledAlarm("0000"), "my-system");
system.tell(new ActivityEvent());
system.tell(new DisableAlarm("1234"));
system.tell(new ActivityEvent());
system.tell(new DisableAlarm("0000"));
system.tell(new ActivityEvent());
system.tell(new EnableAlarm("0000"));
}
sealed trait AlarmMessage
case class EnableAlarm(pinCode: String) extends AlarmMessage
case class DisableAlarm(pinCode: String) extends AlarmMessage
case object ActivityEvent extends AlarmMessage
def enabledAlarm(pinCode: String): Behavior[AlarmMessage] =
Behaviors.receive { (context, message) =>
message match {
case ActivityEvent =>
context.log.warning("EOEOEOEOEOE ALARM ALARM!!!")
Behaviors.same
case DisableAlarm(`pinCode`) =>
context.log.info("Correct pin entered, disabling alarm");
disabledAlarm(pinCode)
case _ => Behaviors.unhandled
}
}
def disabledAlarm(pinCode: String): Behavior[AlarmMessage] =
Behaviors.receivePartial {
case (context, EnableAlarm(`pinCode`)) =>
context.log.info("Correct pin entered, enabling alarm")
enabledAlarm(pinCode)
}
def main(args: Array[String]): Unit = {
val system = ActorSystem.create(enabledAlarm("0000"), "my-system")
system.tell(ActivityEvent)
system.tell(DisableAlarm("1234"))
system.tell(ActivityEvent)
system.tell(DisableAlarm("0000"))
system.tell(ActivityEvent)
system.tell(EnableAlarm("0000"))
system.tell(ActivityEvent)
}
Request-response with other actors
• In untyped actors the sender was
auto-magically available
• In Akka Typed the recipient of
response has to be encoded in
message (why?)
Request-response with other actors
Actor<ProtocolA> Actor<ProtocolB>
RequestForB
ActorRef<ResponseFromB>
ResponseFromBProtocolA
?
Request-response with other actors
Actor<ProtocolA> Actor<ProtocolB>
RequestForB
ActorRef<ResponseFromB>
ResponseFromBProtocolA
ResponseFromB -> ProtocolA
?
One off with Ask
context.ask(
ResponseFromB.class,
actorB,
Timeout.create(Duration.ofSeconds(5)),
(ActorRef<ResponseFromB> respondTo) -> new RequestForB(respondTo),
(ResponseFromB res, Throwable failure) -> {
if (res != null) return new ProtocolAMessage(res);
else throw new RuntimeException("Request failed", failure);
}
);
Long live the adapter
ActorRef<ResponseFromB> adapter = context.messageAdapter(
ResponseFromB.class,
(responseFromB) -> new ProtocolAMessage(responseFromB)
);
actorB.tell(new RequestForB(adapter));
Keeping parts of the protocol to ourselves
ActorRef<ProtocolA> actorRef = …
ActorRef<SubProtocolA> moreNarrowActorRef = actorRef.narrow();
ProtocolA
SubProtocolA SubProtocolA2
Actor Model vs Network
Interaction already modelled as immutable messages

Data travels over the network in packages, changes has to be explicitly
sent back.
At most once

Data reaches a node on the other side at most once, but can be lost,
already part of model!
A recipient of a message can reply directly to sender

Regardless if there were intermediate recipients of the message
Messages not limited to request response

Messages can flow in either direction when two systems are connected.
Local
ActorSystem
Message
Message
Actor
Actor
Actor
JVM 2
JVM 1
Distributed
ActorSystem
ActorSystem
Message
Message
Actor
Actor
Actor
Akka Cluster + Akka Typed
ActorSystem ActorSystem
ActorSystem
Receptionist
Typed Receptionist
Receptionist
Receptionist
ActorRef<AlarmMessage>
Sensor-Actor
Subscribe(key, actorRef)
Receptionist
Typed Receptionist
Receptionist
Receptionist
Register(Key<AlarmMessage>,
ActorRef<AlarmMessage>)
ActorRef<AlarmMessage>
Sensor-Actor
Receptionist
Typed Receptionist
Receptionist
Receptionist
ActorRef[AlarmMessage]
Sensor-Actor
Listing(key, actorRefs)
Receptionist
Typed Receptionist
Receptionist
Receptionist
ActorRef<AlarmMessage>
Sensor-Actor
ActorRef<AlarmMessage>
AlarmMessage
Distributed Burglar Alarm
• we can have any number of
nodes
• a sensor on any node can
report activity to the alarm
Example
DYI
Distributed
static final ServiceKey<ActivityEvent> serviceKey =
ServiceKey.create(ActivityEvent.class, "alarm");
interface AlarmMessage extends Serializable {}
static class EnableAlarm implements AlarmMessage {
public final String pinCode;
public EnableAlarm(String pinCode) {
this.pinCode = pinCode;
}
}
static class DisableAlarm implements AlarmMessage {
public final String pinCode;
public DisableAlarm(String pinCode) {
this.pinCode = pinCode;
}
}
static class ActivityEvent implements AlarmMessage { }
static final ServiceKey<ActivityEvent> serviceKey =
ServiceKey.create(ActivityEvent.class, "alarm");
interface AlarmMessage extends Serializable {}
static class EnableAlarm implements AlarmMessage {
public final String pinCode;
public EnableAlarm(String pinCode) {
this.pinCode = pinCode;
}
}
static class DisableAlarm implements AlarmMessage {
public final String pinCode;
public DisableAlarm(String pinCode) {
this.pinCode = pinCode;
}
}
static class ActivityEvent implements AlarmMessage { }
public static Behavior<AlarmMessage> alarm(String pinCode) {
return Behaviors.setup((context) -> {
ActorRef<Receptionist.Command> receptionist =
context.getSystem().receptionist();
receptionist.tell(
Receptionist.register(serviceKey, context.getSelf().narrow()));
return enabledAlarm(pinCode);
});
}
public static class SensorBehavior extends AbstractBehavior<TriggerCommand> {
private final ActorContext<TriggerCommand> context;
private Set<ActorRef<ActivityEvent>> alarms = Collections.EMPTY_SET;
public SensorBehavior(ActorContext<TriggerCommand> context) {
this.context = context;
// we need to transform the messages from the receptionist protocol
// into our own protocol:
ActorRef<Receptionist.Listing> adapter = context.messageAdapter(
Receptionist.Listing.class,
(listing) -> new AlarmActorUpdate(listing.getServiceInstances(serviceKey))
);
ActorRef<Receptionist.Command> receptionist = context.getSystem().receptionist();
receptionist.tell(Receptionist.subscribe(serviceKey, adapter));
}
@Override
public Behaviors.Receive<TriggerCommand> createReceive() {
return receiveBuilder()
.onMessage(TriggerSensor.class, this::onTrigger)
.onMessage(AlarmActorUpdate.class, this::onAlarmActorUpdate)
.build();
}
private Behavior<TriggerCommand> onTrigger(TriggerSensor trigger) {
final ActivityEvent activityEvent = new ActivityEvent();
if (alarms.isEmpty()) context.getLog().warning("Saw trigger but no alarms known yet");
alarms.forEach((alarm) ->
alarm.tell(activityEvent)
);
return Behaviors.same();
}
private Behavior<TriggerCommand> onAlarmActorUpdate(AlarmActorUpdate update) {
context.getLog().info("Got alarm actor list update");
alarms = update.alarms;
return Behaviors.same();
}
}
public static class SensorBehavior extends AbstractBehavior<TriggerCommand> {
private final ActorContext<TriggerCommand> context;
private Set<ActorRef<ActivityEvent>> alarms = Collections.EMPTY_SET;
public SensorBehavior(ActorContext<TriggerCommand> context) {
this.context = context;
// we need to transform the messages from the receptionist protocol
// into our own protocol:
ActorRef<Receptionist.Listing> adapter = context.messageAdapter(
Receptionist.Listing.class,
(listing) -> new AlarmActorUpdate(listing.getServiceInstances(serviceKey))
);
ActorRef<Receptionist.Command> receptionist = context.getSystem().receptionist();
receptionist.tell(Receptionist.subscribe(serviceKey, adapter));
}
@Override
public Behaviors.Receive<TriggerCommand> createReceive() {
return receiveBuilder()
.onMessage(TriggerSensor.class, this::onTrigger)
.onMessage(AlarmActorUpdate.class, this::onAlarmActorUpdate)
.build();
}
private Behavior<TriggerCommand> onTrigger(TriggerSensor trigger) {
final ActivityEvent activityEvent = new ActivityEvent();
);
ActorRef<Receptionist.Command> receptionist = context.getSystem().receptionist();
receptionist.tell(Receptionist.subscribe(serviceKey, adapter));
}
@Override
public Behaviors.Receive<TriggerCommand> createReceive() {
return receiveBuilder()
.onMessage(TriggerSensor.class, this::onTrigger)
.onMessage(AlarmActorUpdate.class, this::onAlarmActorUpdate)
.build();
}
private Behavior<TriggerCommand> onTrigger(TriggerSensor trigger) {
final ActivityEvent activityEvent = new ActivityEvent();
if (alarms.isEmpty()) context.getLog().warning("Saw trigger but no alarms known yet");
alarms.forEach((alarm) ->
alarm.tell(activityEvent)
);
return Behaviors.same();
}
private Behavior<TriggerCommand> onAlarmActorUpdate(AlarmActorUpdate update) {
context.getLog().info("Got alarm actor list update");
alarms = update.alarms;
return Behaviors.same();
}
}
public static void main(String[] args) throws Exception {
ActorSystem<AlarmMessage> system1 =
ActorSystem.create(alarm("0000"), "my-cluster");
ActorSystem<TriggerCommand> system2 =
ActorSystem.create(sensorBehavior(), "my-cluster");
ActorSystem<TriggerCommand> system3 =
ActorSystem.create(sensorBehavior(), "my-cluster");
// first join the first node to itself to form a cluster
Cluster node1 = Cluster.get(system1);
node1.manager().tell(Join.create(node1.selfMember().address()));
// then have node 2 and 3 join that cluster
Cluster node2 = Cluster.get(system2);
node2.manager().tell(Join.create(node1.selfMember().address()));
Cluster node3 = Cluster.get(system3);
node3.manager().tell(Join.create(node1.selfMember().address()));
Scanner in = new Scanner(System.in);
while (true) {
// then have node 2 and 3 join that cluster
Cluster node2 = Cluster.get(system2);
node2.manager().tell(Join.create(node1.selfMember().address()));
Cluster node3 = Cluster.get(system3);
node3.manager().tell(Join.create(node1.selfMember().address()));
Scanner in = new Scanner(System.in);
while (true) {
try {
System.out.println("Enter 2 or 3 to trigger activity on that node");
int chosenNode = Integer.parseInt(in.next());
System.out.println("Triggering sensor on node " + chosenNode);
if (chosenNode == 2) system2.tell(new TriggerSensor());
else if (chosenNode == 3) system3.tell(new TriggerSensor());
} catch (Exception ex) {
// we don't care, loop!
}
}
}
Summary
• On message - message another actor, change
state or behavior
• Types gives better guardrails and makes
understanding the system easier
• We can use the same abstraction for local and
distributed
GitHub repo with all samples in this talk
https://bit.ly/2OKRFxD
Akka typed docs
doc.akka.io/docs/akka/2.5/typed/index.html
More resources
blog.akka.io - news and articles
discuss.akka.io - forums
developer.lightbend.com - samples
github.com/akka/akka - sources and getting involved
Further reading
Questions?
GitHub repo with all samples in this talk
https://bit.ly/2OKRFxD
http://akka.io
@apnylle
johan.andren@lightbend.com
Thanks for listening!
Ad

More Related Content

What's hot (20)

Akka Actor presentation
Akka Actor presentationAkka Actor presentation
Akka Actor presentation
Gene Chang
 
Building reactive distributed systems with Akka
Building reactive distributed systems with Akka Building reactive distributed systems with Akka
Building reactive distributed systems with Akka
Johan Andrén
 
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka StreamsFresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Konrad Malawski
 
Akka streams - Umeå java usergroup
Akka streams - Umeå java usergroupAkka streams - Umeå java usergroup
Akka streams - Umeå java usergroup
Johan Andrén
 
Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015
Jiayun Zhou
 
Developing distributed applications with Akka and Akka Cluster
Developing distributed applications with Akka and Akka ClusterDeveloping distributed applications with Akka and Akka Cluster
Developing distributed applications with Akka and Akka Cluster
Konstantin Tsykulenko
 
Actor Model Akka Framework
Actor Model Akka FrameworkActor Model Akka Framework
Actor Model Akka Framework
Harinath Krishnamoorthy
 
Async - react, don't wait - PingConf
Async - react, don't wait - PingConfAsync - react, don't wait - PingConf
Async - react, don't wait - PingConf
Johan Andrén
 
Akka lsug skills matter
Akka lsug skills matterAkka lsug skills matter
Akka lsug skills matter
Skills Matter
 
Sane Sharding with Akka Cluster
Sane Sharding with Akka ClusterSane Sharding with Akka Cluster
Sane Sharding with Akka Cluster
miciek
 
Fullstack Conference - Proxies before proxies: The hidden gems of Javascript...
Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript...Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript...
Fullstack Conference - Proxies before proxies: The hidden gems of Javascript...
Tim Chaplin
 
Reactive integrations with Akka Streams
Reactive integrations with Akka StreamsReactive integrations with Akka Streams
Reactive integrations with Akka Streams
Konrad Malawski
 
Scala usergroup stockholm - reactive integrations with akka streams
Scala usergroup stockholm - reactive integrations with akka streamsScala usergroup stockholm - reactive integrations with akka streams
Scala usergroup stockholm - reactive integrations with akka streams
Johan Andrén
 
Introduction to Akka - Atlanta Java Users Group
Introduction to Akka - Atlanta Java Users GroupIntroduction to Akka - Atlanta Java Users Group
Introduction to Akka - Atlanta Java Users Group
Roy Russo
 
Reactive Streams / Akka Streams - GeeCON Prague 2014
Reactive Streams / Akka Streams - GeeCON Prague 2014Reactive Streams / Akka Streams - GeeCON Prague 2014
Reactive Streams / Akka Streams - GeeCON Prague 2014
Konrad Malawski
 
Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...
Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...
Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...
Codemotion
 
Akka persistence == event sourcing in 30 minutes
Akka persistence == event sourcing in 30 minutesAkka persistence == event sourcing in 30 minutes
Akka persistence == event sourcing in 30 minutes
Konrad Malawski
 
The dark side of Akka and the remedy
The dark side of Akka and the remedyThe dark side of Akka and the remedy
The dark side of Akka and the remedy
krivachy
 
Networks and Types - the Future of Akka @ ScalaDays NYC 2018
Networks and Types - the Future of Akka @ ScalaDays NYC 2018Networks and Types - the Future of Akka @ ScalaDays NYC 2018
Networks and Types - the Future of Akka @ ScalaDays NYC 2018
Konrad Malawski
 
Distributed Consensus A.K.A. "What do we eat for lunch?"
Distributed Consensus A.K.A. "What do we eat for lunch?"Distributed Consensus A.K.A. "What do we eat for lunch?"
Distributed Consensus A.K.A. "What do we eat for lunch?"
Konrad Malawski
 
Akka Actor presentation
Akka Actor presentationAkka Actor presentation
Akka Actor presentation
Gene Chang
 
Building reactive distributed systems with Akka
Building reactive distributed systems with Akka Building reactive distributed systems with Akka
Building reactive distributed systems with Akka
Johan Andrén
 
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka StreamsFresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Konrad Malawski
 
Akka streams - Umeå java usergroup
Akka streams - Umeå java usergroupAkka streams - Umeå java usergroup
Akka streams - Umeå java usergroup
Johan Andrén
 
Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015
Jiayun Zhou
 
Developing distributed applications with Akka and Akka Cluster
Developing distributed applications with Akka and Akka ClusterDeveloping distributed applications with Akka and Akka Cluster
Developing distributed applications with Akka and Akka Cluster
Konstantin Tsykulenko
 
Async - react, don't wait - PingConf
Async - react, don't wait - PingConfAsync - react, don't wait - PingConf
Async - react, don't wait - PingConf
Johan Andrén
 
Akka lsug skills matter
Akka lsug skills matterAkka lsug skills matter
Akka lsug skills matter
Skills Matter
 
Sane Sharding with Akka Cluster
Sane Sharding with Akka ClusterSane Sharding with Akka Cluster
Sane Sharding with Akka Cluster
miciek
 
Fullstack Conference - Proxies before proxies: The hidden gems of Javascript...
Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript...Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript...
Fullstack Conference - Proxies before proxies: The hidden gems of Javascript...
Tim Chaplin
 
Reactive integrations with Akka Streams
Reactive integrations with Akka StreamsReactive integrations with Akka Streams
Reactive integrations with Akka Streams
Konrad Malawski
 
Scala usergroup stockholm - reactive integrations with akka streams
Scala usergroup stockholm - reactive integrations with akka streamsScala usergroup stockholm - reactive integrations with akka streams
Scala usergroup stockholm - reactive integrations with akka streams
Johan Andrén
 
Introduction to Akka - Atlanta Java Users Group
Introduction to Akka - Atlanta Java Users GroupIntroduction to Akka - Atlanta Java Users Group
Introduction to Akka - Atlanta Java Users Group
Roy Russo
 
Reactive Streams / Akka Streams - GeeCON Prague 2014
Reactive Streams / Akka Streams - GeeCON Prague 2014Reactive Streams / Akka Streams - GeeCON Prague 2014
Reactive Streams / Akka Streams - GeeCON Prague 2014
Konrad Malawski
 
Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...
Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...
Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...
Codemotion
 
Akka persistence == event sourcing in 30 minutes
Akka persistence == event sourcing in 30 minutesAkka persistence == event sourcing in 30 minutes
Akka persistence == event sourcing in 30 minutes
Konrad Malawski
 
The dark side of Akka and the remedy
The dark side of Akka and the remedyThe dark side of Akka and the remedy
The dark side of Akka and the remedy
krivachy
 
Networks and Types - the Future of Akka @ ScalaDays NYC 2018
Networks and Types - the Future of Akka @ ScalaDays NYC 2018Networks and Types - the Future of Akka @ ScalaDays NYC 2018
Networks and Types - the Future of Akka @ ScalaDays NYC 2018
Konrad Malawski
 
Distributed Consensus A.K.A. "What do we eat for lunch?"
Distributed Consensus A.K.A. "What do we eat for lunch?"Distributed Consensus A.K.A. "What do we eat for lunch?"
Distributed Consensus A.K.A. "What do we eat for lunch?"
Konrad Malawski
 

Similar to Next generation message driven systems with Akka (20)

Concurrency and scalability with akka
Concurrency and scalability  with akkaConcurrency and scalability  with akka
Concurrency and scalability with akka
Bardia Heydari
 
Getting the most out of Java [Nordic Coding-2010]
Getting the most out of Java [Nordic Coding-2010]Getting the most out of Java [Nordic Coding-2010]
Getting the most out of Java [Nordic Coding-2010]
Sven Efftinge
 
Painless Persistence with Realm
Painless Persistence with RealmPainless Persistence with Realm
Painless Persistence with Realm
Christian Melchior
 
Taming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, Macoscope
Macoscope
 
jQuery for beginners
jQuery for beginnersjQuery for beginners
jQuery for beginners
Divakar Gu
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Domenic Denicola
 
Reactive Programming in .Net - actorbased computing with Akka.Net
Reactive Programming in .Net - actorbased computing with Akka.NetReactive Programming in .Net - actorbased computing with Akka.Net
Reactive Programming in .Net - actorbased computing with Akka.Net
Sören Stelzer
 
Message-based communication patterns in distributed Akka applications
Message-based communication patterns in distributed Akka applicationsMessage-based communication patterns in distributed Akka applications
Message-based communication patterns in distributed Akka applications
Andrii Lashchenko
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on Android
Tomáš Kypta
 
Server Side Swift: Vapor
Server Side Swift: VaporServer Side Swift: Vapor
Server Side Swift: Vapor
Paweł Kowalczuk
 
Laurens Van Den Oever Xopus Presentation
Laurens Van Den Oever Xopus PresentationLaurens Van Den Oever Xopus Presentation
Laurens Van Den Oever Xopus Presentation
Ajax Experience 2009
 
Greach, GroovyFx Workshop
Greach, GroovyFx WorkshopGreach, GroovyFx Workshop
Greach, GroovyFx Workshop
Dierk König
 
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Ryosuke Uchitate
 
CDI, Seam & RESTEasy: You haven't seen REST yet!
CDI, Seam & RESTEasy: You haven't seen REST yet!CDI, Seam & RESTEasy: You haven't seen REST yet!
CDI, Seam & RESTEasy: You haven't seen REST yet!
Dan Allen
 
Тарас Олексин - Sculpt! Your! Tests!
Тарас Олексин  - Sculpt! Your! Tests!Тарас Олексин  - Sculpt! Your! Tests!
Тарас Олексин - Sculpt! Your! Tests!
DataArt
 
Testing basics for developers
Testing basics for developersTesting basics for developers
Testing basics for developers
Anton Udovychenko
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Thomas Fuchs
 
OWASP Proxy
OWASP ProxyOWASP Proxy
OWASP Proxy
Security B-Sides
 
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen ChinHacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
jaxconf
 
比XML更好用的Java Annotation
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotation
javatwo2011
 
Concurrency and scalability with akka
Concurrency and scalability  with akkaConcurrency and scalability  with akka
Concurrency and scalability with akka
Bardia Heydari
 
Getting the most out of Java [Nordic Coding-2010]
Getting the most out of Java [Nordic Coding-2010]Getting the most out of Java [Nordic Coding-2010]
Getting the most out of Java [Nordic Coding-2010]
Sven Efftinge
 
Painless Persistence with Realm
Painless Persistence with RealmPainless Persistence with Realm
Painless Persistence with Realm
Christian Melchior
 
Taming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, Macoscope
Macoscope
 
jQuery for beginners
jQuery for beginnersjQuery for beginners
jQuery for beginners
Divakar Gu
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Domenic Denicola
 
Reactive Programming in .Net - actorbased computing with Akka.Net
Reactive Programming in .Net - actorbased computing with Akka.NetReactive Programming in .Net - actorbased computing with Akka.Net
Reactive Programming in .Net - actorbased computing with Akka.Net
Sören Stelzer
 
Message-based communication patterns in distributed Akka applications
Message-based communication patterns in distributed Akka applicationsMessage-based communication patterns in distributed Akka applications
Message-based communication patterns in distributed Akka applications
Andrii Lashchenko
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on Android
Tomáš Kypta
 
Laurens Van Den Oever Xopus Presentation
Laurens Van Den Oever Xopus PresentationLaurens Van Den Oever Xopus Presentation
Laurens Van Den Oever Xopus Presentation
Ajax Experience 2009
 
Greach, GroovyFx Workshop
Greach, GroovyFx WorkshopGreach, GroovyFx Workshop
Greach, GroovyFx Workshop
Dierk König
 
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Ryosuke Uchitate
 
CDI, Seam & RESTEasy: You haven't seen REST yet!
CDI, Seam & RESTEasy: You haven't seen REST yet!CDI, Seam & RESTEasy: You haven't seen REST yet!
CDI, Seam & RESTEasy: You haven't seen REST yet!
Dan Allen
 
Тарас Олексин - Sculpt! Your! Tests!
Тарас Олексин  - Sculpt! Your! Tests!Тарас Олексин  - Sculpt! Your! Tests!
Тарас Олексин - Sculpt! Your! Tests!
DataArt
 
Testing basics for developers
Testing basics for developersTesting basics for developers
Testing basics for developers
Anton Udovychenko
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Thomas Fuchs
 
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen ChinHacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
jaxconf
 
比XML更好用的Java Annotation
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotation
javatwo2011
 
Ad

More from Johan Andrén (10)

Asynchronous stream processing with Akka Streams
Asynchronous stream processing with Akka StreamsAsynchronous stream processing with Akka Streams
Asynchronous stream processing with Akka Streams
Johan Andrén
 
VJUG24 - Reactive Integrations with Akka Streams
VJUG24  - Reactive Integrations with Akka StreamsVJUG24  - Reactive Integrations with Akka Streams
VJUG24 - Reactive Integrations with Akka Streams
Johan Andrén
 
Introduction to akka actors with java 8
Introduction to akka actors with java 8Introduction to akka actors with java 8
Introduction to akka actors with java 8
Johan Andrén
 
Scala frukostseminarium
Scala frukostseminariumScala frukostseminarium
Scala frukostseminarium
Johan Andrén
 
Introduction to Akka
Introduction to AkkaIntroduction to Akka
Introduction to Akka
Johan Andrén
 
Async – react, don't wait
Async – react, don't waitAsync – react, don't wait
Async – react, don't wait
Johan Andrén
 
Akka frukostseminarium
Akka   frukostseminariumAkka   frukostseminarium
Akka frukostseminarium
Johan Andrén
 
Macros and reflection in scala 2.10
Macros and reflection in scala 2.10Macros and reflection in scala 2.10
Macros and reflection in scala 2.10
Johan Andrén
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
Johan Andrén
 
Duchess scala-2012
Duchess scala-2012Duchess scala-2012
Duchess scala-2012
Johan Andrén
 
Asynchronous stream processing with Akka Streams
Asynchronous stream processing with Akka StreamsAsynchronous stream processing with Akka Streams
Asynchronous stream processing with Akka Streams
Johan Andrén
 
VJUG24 - Reactive Integrations with Akka Streams
VJUG24  - Reactive Integrations with Akka StreamsVJUG24  - Reactive Integrations with Akka Streams
VJUG24 - Reactive Integrations with Akka Streams
Johan Andrén
 
Introduction to akka actors with java 8
Introduction to akka actors with java 8Introduction to akka actors with java 8
Introduction to akka actors with java 8
Johan Andrén
 
Scala frukostseminarium
Scala frukostseminariumScala frukostseminarium
Scala frukostseminarium
Johan Andrén
 
Introduction to Akka
Introduction to AkkaIntroduction to Akka
Introduction to Akka
Johan Andrén
 
Async – react, don't wait
Async – react, don't waitAsync – react, don't wait
Async – react, don't wait
Johan Andrén
 
Akka frukostseminarium
Akka   frukostseminariumAkka   frukostseminarium
Akka frukostseminarium
Johan Andrén
 
Macros and reflection in scala 2.10
Macros and reflection in scala 2.10Macros and reflection in scala 2.10
Macros and reflection in scala 2.10
Johan Andrén
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
Johan Andrén
 
Ad

Recently uploaded (20)

The Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdfThe Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdf
drewplanas10
 
Download YouTube By Click 2025 Free Full Activated
Download YouTube By Click 2025 Free Full ActivatedDownload YouTube By Click 2025 Free Full Activated
Download YouTube By Click 2025 Free Full Activated
saniamalik72555
 
EASEUS Partition Master Crack + License Code
EASEUS Partition Master Crack + License CodeEASEUS Partition Master Crack + License Code
EASEUS Partition Master Crack + License Code
aneelaramzan63
 
FL Studio Producer Edition Crack 2025 Full Version
FL Studio Producer Edition Crack 2025 Full VersionFL Studio Producer Edition Crack 2025 Full Version
FL Studio Producer Edition Crack 2025 Full Version
tahirabibi60507
 
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Andre Hora
 
Douwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License codeDouwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License code
aneelaramzan63
 
How to Optimize Your AWS Environment for Improved Cloud Performance
How to Optimize Your AWS Environment for Improved Cloud PerformanceHow to Optimize Your AWS Environment for Improved Cloud Performance
How to Optimize Your AWS Environment for Improved Cloud Performance
ThousandEyes
 
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
AxisTechnolabs
 
PDF Reader Pro Crack Latest Version FREE Download 2025
PDF Reader Pro Crack Latest Version FREE Download 2025PDF Reader Pro Crack Latest Version FREE Download 2025
PDF Reader Pro Crack Latest Version FREE Download 2025
mu394968
 
Expand your AI adoption with AgentExchange
Expand your AI adoption with AgentExchangeExpand your AI adoption with AgentExchange
Expand your AI adoption with AgentExchange
Fexle Services Pvt. Ltd.
 
Solidworks Crack 2025 latest new + license code
Solidworks Crack 2025 latest new + license codeSolidworks Crack 2025 latest new + license code
Solidworks Crack 2025 latest new + license code
aneelaramzan63
 
Exploring Code Comprehension in Scientific Programming: Preliminary Insight...
Exploring Code Comprehension  in Scientific Programming:  Preliminary Insight...Exploring Code Comprehension  in Scientific Programming:  Preliminary Insight...
Exploring Code Comprehension in Scientific Programming: Preliminary Insight...
University of Hawai‘i at Mānoa
 
F-Secure Freedome VPN 2025 Crack Plus Activation New Version
F-Secure Freedome VPN 2025 Crack Plus Activation  New VersionF-Secure Freedome VPN 2025 Crack Plus Activation  New Version
F-Secure Freedome VPN 2025 Crack Plus Activation New Version
saimabibi60507
 
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
steaveroggers
 
Avast Premium Security Crack FREE Latest Version 2025
Avast Premium Security Crack FREE Latest Version 2025Avast Premium Security Crack FREE Latest Version 2025
Avast Premium Security Crack FREE Latest Version 2025
mu394968
 
Download Wondershare Filmora Crack [2025] With Latest
Download Wondershare Filmora Crack [2025] With LatestDownload Wondershare Filmora Crack [2025] With Latest
Download Wondershare Filmora Crack [2025] With Latest
tahirabibi60507
 
Kubernetes_101_Zero_to_Platform_Engineer.pptx
Kubernetes_101_Zero_to_Platform_Engineer.pptxKubernetes_101_Zero_to_Platform_Engineer.pptx
Kubernetes_101_Zero_to_Platform_Engineer.pptx
CloudScouts
 
Automation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath CertificateAutomation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath Certificate
VICTOR MAESTRE RAMIREZ
 
Designing AI-Powered APIs on Azure: Best Practices& Considerations
Designing AI-Powered APIs on Azure: Best Practices& ConsiderationsDesigning AI-Powered APIs on Azure: Best Practices& Considerations
Designing AI-Powered APIs on Azure: Best Practices& Considerations
Dinusha Kumarasiri
 
Get & Download Wondershare Filmora Crack Latest [2025]
Get & Download Wondershare Filmora Crack Latest [2025]Get & Download Wondershare Filmora Crack Latest [2025]
Get & Download Wondershare Filmora Crack Latest [2025]
saniaaftab72555
 
The Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdfThe Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdf
drewplanas10
 
Download YouTube By Click 2025 Free Full Activated
Download YouTube By Click 2025 Free Full ActivatedDownload YouTube By Click 2025 Free Full Activated
Download YouTube By Click 2025 Free Full Activated
saniamalik72555
 
EASEUS Partition Master Crack + License Code
EASEUS Partition Master Crack + License CodeEASEUS Partition Master Crack + License Code
EASEUS Partition Master Crack + License Code
aneelaramzan63
 
FL Studio Producer Edition Crack 2025 Full Version
FL Studio Producer Edition Crack 2025 Full VersionFL Studio Producer Edition Crack 2025 Full Version
FL Studio Producer Edition Crack 2025 Full Version
tahirabibi60507
 
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Exceptional Behaviors: How Frequently Are They Tested? (AST 2025)
Andre Hora
 
Douwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License codeDouwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License code
aneelaramzan63
 
How to Optimize Your AWS Environment for Improved Cloud Performance
How to Optimize Your AWS Environment for Improved Cloud PerformanceHow to Optimize Your AWS Environment for Improved Cloud Performance
How to Optimize Your AWS Environment for Improved Cloud Performance
ThousandEyes
 
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
AxisTechnolabs
 
PDF Reader Pro Crack Latest Version FREE Download 2025
PDF Reader Pro Crack Latest Version FREE Download 2025PDF Reader Pro Crack Latest Version FREE Download 2025
PDF Reader Pro Crack Latest Version FREE Download 2025
mu394968
 
Expand your AI adoption with AgentExchange
Expand your AI adoption with AgentExchangeExpand your AI adoption with AgentExchange
Expand your AI adoption with AgentExchange
Fexle Services Pvt. Ltd.
 
Solidworks Crack 2025 latest new + license code
Solidworks Crack 2025 latest new + license codeSolidworks Crack 2025 latest new + license code
Solidworks Crack 2025 latest new + license code
aneelaramzan63
 
Exploring Code Comprehension in Scientific Programming: Preliminary Insight...
Exploring Code Comprehension  in Scientific Programming:  Preliminary Insight...Exploring Code Comprehension  in Scientific Programming:  Preliminary Insight...
Exploring Code Comprehension in Scientific Programming: Preliminary Insight...
University of Hawai‘i at Mānoa
 
F-Secure Freedome VPN 2025 Crack Plus Activation New Version
F-Secure Freedome VPN 2025 Crack Plus Activation  New VersionF-Secure Freedome VPN 2025 Crack Plus Activation  New Version
F-Secure Freedome VPN 2025 Crack Plus Activation New Version
saimabibi60507
 
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
steaveroggers
 
Avast Premium Security Crack FREE Latest Version 2025
Avast Premium Security Crack FREE Latest Version 2025Avast Premium Security Crack FREE Latest Version 2025
Avast Premium Security Crack FREE Latest Version 2025
mu394968
 
Download Wondershare Filmora Crack [2025] With Latest
Download Wondershare Filmora Crack [2025] With LatestDownload Wondershare Filmora Crack [2025] With Latest
Download Wondershare Filmora Crack [2025] With Latest
tahirabibi60507
 
Kubernetes_101_Zero_to_Platform_Engineer.pptx
Kubernetes_101_Zero_to_Platform_Engineer.pptxKubernetes_101_Zero_to_Platform_Engineer.pptx
Kubernetes_101_Zero_to_Platform_Engineer.pptx
CloudScouts
 
Automation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath CertificateAutomation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath Certificate
VICTOR MAESTRE RAMIREZ
 
Designing AI-Powered APIs on Azure: Best Practices& Considerations
Designing AI-Powered APIs on Azure: Best Practices& ConsiderationsDesigning AI-Powered APIs on Azure: Best Practices& Considerations
Designing AI-Powered APIs on Azure: Best Practices& Considerations
Dinusha Kumarasiri
 
Get & Download Wondershare Filmora Crack Latest [2025]
Get & Download Wondershare Filmora Crack Latest [2025]Get & Download Wondershare Filmora Crack Latest [2025]
Get & Download Wondershare Filmora Crack Latest [2025]
saniaaftab72555
 

Next generation message driven systems with Akka

  • 1. Akka Typed Johan Andrén, Akka Team Øredev Malmö, 2018-11-20 Next generation message driven systems with Akka
  • 2. Johan Andrén Akka Team Stockholm Scala User Group @apnylle markatta.com/codemonkey/ [email protected]
  • 3. Build powerful reactive, concurrent, and distributed applications more easily Akka
  • 4. What’s in the toolkit? Actors – simple & high performance concurrency Cluster, Cluster tools – tools for building distributed systems Streams – reactive streams implementation Persistence – CQRS + Event Sourcing for Actors HTTP – fully async streaming HTTP Server Alpakka – Reactive Streams Integrations a’la Camel
  • 5. Actors – simple & high performance concurrency Cluster, Cluster tools – tools for building distributed systems Streams – reactive streams implementation Persistence – CQRS + Event Sourcing for Actors HTTP – fully async streaming HTTP Server Alpakka – Reactive Streams Integrations a’la Camel Typed Typed Typed (already type-safe) (already type-safe) (already type-safe) What is coming soon? (already type-safe)
  • 6. Languages Complete APIs for both Java and Scala
  • 7. Actor Message Inbox MessageMessage actorRef.tell(message) Akka Actor fundamentals The only way for the rest of the application to interact with the actor
  • 8. • mutate state (including spawning a child actor) • send messages to other actors • change its behavior Actor Message Inbox MessageMessage An Actor can…
  • 9. MVS (Minimum Viable Sample) Na-na na-na na-na na-naSample-time! Also known as “hello world”
  • 10. import akka.actor.typed.ActorRef; import akka.actor.typed.ActorSystem; import akka.actor.typed.Behavior; import akka.actor.typed.javadsl.Behaviors; import java.io.IOException; public class Sample1 { static class Hello { public final String who; public Hello(String who) { this.who = who; } } final static Behavior<Hello> greetingBehavior = Behaviors.receive(Hello.class) .onMessage(Hello.class, (context, message) -> { context.getLog().info("Hello {}!", message.who); return Behavior.same(); }).build(); public static void main(String[] args) throws IOException { ActorSystem<Hello> actorSystem = ActorSystem.create(greetingBehavior, "my-system"); ActorRef<Hello> rootActor = actorSystem; rootActor.tell(new Hello("Johan")); rootActor.tell(new Hello(“Øredev audience")); System.out.println("Press that any-key to terminate"); System.in.read(); actorSystem.terminate(); } }
  • 11. public class Sample1 { static class Hello { public final String who; public Hello(String who) { this.who = who; } } final static Behavior<Hello> greetingBehavior = Behaviors.receive(Hello.class) .onMessage(Hello.class, (context, message) -> { context.getLog().info("Hello {}!", message.who); return Behavior.same(); }).build(); public static void main(String[] args) throws IOException { ActorSystem<Hello> actorSystem = ActorSystem.create(greetingBehavior, "my-system"); ActorRef<Hello> rootActor = actorSystem; rootActor.tell(new Hello("Johan"));
  • 12. public class Sample1 { static class Hello { public final String who; public Hello(String who) { this.who = who; } } final static Behavior<Hello> greetingBehavior = Behaviors.receive(Hello.class) .onMessage(Hello.class, (context, message) -> { context.getLog().info("Hello {}!", message.who); return Behavior.same(); }).build(); public static void main(String[] args) throws IOException { ActorSystem<Hello> actorSystem = ActorSystem.create(greetingBehavior, "my-system"); ActorRef<Hello> rootActor = actorSystem; rootActor.tell(new Hello("Johan"));
  • 13. } } final static Behavior<Hello> greetingBehavior = Behaviors.receive(Hello.class) .onMessage(Hello.class, (context, message) -> { context.getLog().info("Hello {}!", message.who); return Behavior.same(); }).build(); public static void main(String[] args) throws IOException { ActorSystem<Hello> actorSystem = ActorSystem.create(greetingBehavior, "my-system"); ActorRef<Hello> rootActor = actorSystem; rootActor.tell(new Hello("Johan")); rootActor.tell(new Hello(“Øredev audience")); System.out.println("Press that any-key to terminate"); System.in.read(); actorSystem.terminate(); } }
  • 14. } } final static Behavior<Hello> greetingBehavior = Behaviors.receive(Hello.class) .onMessage(Hello.class, (context, message) -> { context.getLog().info("Hello {}!", message.who); return Behavior.same(); }).build(); public static void main(String[] args) throws IOException { ActorSystem<Hello> actorSystem = ActorSystem.create(greetingBehavior, "my-system"); ActorRef<Hello> rootActor = actorSystem; rootActor.tell(new Hello("Johan")); rootActor.tell(new Hello(“Øredev audience")); System.out.println("Press that any-key to terminate"); System.in.read(); actorSystem.terminate(); } }
  • 15. import akka.actor.typed.{ActorRef, ActorSystem, Behavior} import akka.actor.typed.scaladsl.Behaviors import scala.io.StdIn object Sample1 { case class Hello(who: String) val greetingBehavior: Behavior[Hello] = Behaviors.receive { (ctx, hello) => ctx.log.info(s"Hello ${hello.who}!") Behaviors.same } def main(args: Array[String]): Unit = { val system = ActorSystem(greetingBehavior, "my-system") val rootActor: ActorRef[Hello] = system rootActor ! Hello("Johan") rootActor ! Hello(“Øredev audience") println("Press the any-key to terminate") StdIn.readLine() system.terminate() } }
  • 16. Let’s do another one right away The mystery of the changing state 🔎
  • 17. interface Command {} static class ChangeGreeting implements Command { public final String newGreeting; public ChangeGreeting(String newGreeting) { this.newGreeting = newGreeting; } } static class Hello implements Command { public final String who; public Hello(String who) { this.who = who; } } public static Behavior<Command> dynamicGreetingBehavior(String greeting) { return Behaviors.receive(Command.class) .onMessage(Hello.class, (context, message) -> { context.getLog().info(greeting + " " + message.who + "!"); return Behavior.same(); }).onMessage(ChangeGreeting.class, (context, changeGreeting) -> dynamicGreetingBehavior(changeGreeting.newGreeting) ).build(); } public static void main(String[] args) throws IOException { var actorSystem = ActorSystem.create(dynamicGreetingBehavior("Hello"), "my-system"); actorSystem.tell(new Hello("Johan")); actorSystem.tell(new ChangeGreeting("Hej")); actorSystem.tell(new Hello(“Øredev audience")); }
  • 18. interface Command {} static class ChangeGreeting implements Command { public final String newGreeting; public ChangeGreeting(String newGreeting) { this.newGreeting = newGreeting; } } static class Hello implements Command { public final String who; public Hello(String who) { this.who = who; } } public static Behavior<Command> dynamicGreetingBehavior(String greeting) { return Behaviors.receive(Command.class) .onMessage(Hello.class, (context, message) -> { context.getLog().info(greeting + " " + message.who + "!"); return Behavior.same(); }).onMessage(ChangeGreeting.class, (context, changeGreeting) -> dynamicGreetingBehavior(changeGreeting.newGreeting) ).build(); }
  • 19. static class Hello implements Command { public final String who; public Hello(String who) { this.who = who; } } public static Behavior<Command> dynamicGreetingBehavior(String greeting) { return Behaviors.receive(Command.class) .onMessage(Hello.class, (context, message) -> { context.getLog().info(greeting + " " + message.who + "!"); return Behavior.same(); }).onMessage(ChangeGreeting.class, (context, changeGreeting) -> dynamicGreetingBehavior(changeGreeting.newGreeting) ).build(); } public static void main(String[] args) throws IOException { var actorSystem = ActorSystem.create(dynamicGreetingBehavior("Hello"), "my-system"); actorSystem.tell(new Hello("Johan")); actorSystem.tell(new ChangeGreeting("Hej")); actorSystem.tell(new Hello(“Øredev audience")); }
  • 20. public static Behavior<Command> dynamicGreetingBehavior(String greeting) { return Behaviors.receive(Command.class) .onMessage(Hello.class, (context, message) -> { context.getLog().info(greeting + " " + message.who + "!"); return Behavior.same(); }).onMessage(ChangeGreeting.class, (context, changeGreeting) -> dynamicGreetingBehavior(changeGreeting.newGreeting) ).build(); } public static void main(String[] args) throws IOException { var actorSystem = ActorSystem.create(dynamicGreetingBehavior("Hello"), "my-system"); actorSystem.tell(new Hello("Johan")); actorSystem.tell(new ChangeGreeting("Hej")); actorSystem.tell(new Hello(“Øredev audience")); }
  • 21. sealed trait Command case class Hello(who: String) extends Command case class ChangeGreeting(newGreeting: String) extends Command def dynamicGreetingBehavior(greeting: String): Behavior[Command] = Behaviors.receive { (ctx, message) => message match { case Hello(who) => ctx.log.info(s"$greeting ${who}!") Behaviors.same case ChangeGreeting(newGreeting) => dynamicGreetingBehavior(newGreeting) } } def main(args: Array[String]): Unit = { val system = ActorSystem(dynamicGreetingBehavior("Hello"), "my-system") system ! Hello("Johan") system ! ChangeGreeting("Hej") system ! Hello(“Øredev audience") }
  • 22. But I don’t like it (the FP style, that is)
  • 23. static class DynamicGreetingBehavior extends AbstractBehavior<Command> { private final ActorContext<Command> context; private String greeting; public DynamicGreetingBehavior(String initialGreeting, ActorContext<Command> context) { this.context = context; greeting = initialGreeting; } @Override public Receive<Command> createReceive() { return receiveBuilder() .onMessage(Hello.class, this::onHello) .onMessage(ChangeGreeting.class, this::onChangeGreeting) .build(); } private Behavior<Command> onHello(Hello hello) { context.getLog().info(greeting + " " + hello.who + "!"); return Behaviors.same(); } private Behavior<Command> onChangeGreeting(ChangeGreeting changeGreeting) { greeting = changeGreeting.newGreeting; return Behaviors.same(); } }
  • 24. static class DynamicGreetingBehavior extends AbstractBehavior<Command> { private final ActorContext<Command> context; private String greeting; public DynamicGreetingBehavior(String initialGreeting, ActorContext<Command> contex this.context = context; greeting = initialGreeting; } @Override public Receive<Command> createReceive() { return receiveBuilder() .onMessage(Hello.class, this::onHello) .onMessage(ChangeGreeting.class, this::onChangeGreeting) .build(); } private Behavior<Command> onHello(Hello hello) { context.getLog().info(greeting + " " + hello.who + "!"); return Behaviors.same(); }
  • 25. static class DynamicGreetingBehavior extends AbstractBehavior<Command> { private final ActorContext<Command> context; private String greeting; public DynamicGreetingBehavior(String initialGreeting, ActorContext<Command> contex this.context = context; greeting = initialGreeting; } @Override public Receive<Command> createReceive() { return receiveBuilder() .onMessage(Hello.class, this::onHello) .onMessage(ChangeGreeting.class, this::onChangeGreeting) .build(); } private Behavior<Command> onHello(Hello hello) { context.getLog().info(greeting + " " + hello.who + "!"); return Behaviors.same(); }
  • 26. private String greeting; public DynamicGreetingBehavior(String initialGreeting, ActorContext<Command> contex this.context = context; greeting = initialGreeting; } @Override public Receive<Command> createReceive() { return receiveBuilder() .onMessage(Hello.class, this::onHello) .onMessage(ChangeGreeting.class, this::onChangeGreeting) .build(); } private Behavior<Command> onHello(Hello hello) { context.getLog().info(greeting + " " + hello.who + "!"); return Behaviors.same(); } private Behavior<Command> onChangeGreeting(ChangeGreeting changeGreeting) { greeting = changeGreeting.newGreeting; return Behaviors.same(); } }
  • 27. public static void main(String[] args) { ActorSystem<Command> system = ActorSystem.<Command>create( Behaviors.setup((context) -> new DynamicGreetingBehavior("Hello", context)), "my-system" ); system.tell(new Hello("Johan")); system.tell(new ChangeGreeting(“Hej")); system.tell(new Hello(“Øredev audience")); }
  • 28. • Discoverability, how are things related • More compile time type-safety, less runtime debugging
 Types helps productivity! (and results in more reliable systems in production) The need for strong/strict typing “Sending the wrong message to an actor is actually quite uncommon” – Myself
  • 29. Burglar Alarm • enabled/disabled with a pin code • accepts notifications about “activity” • if enabled on activity, sound the alarm “Realistic” Example DIY
  • 30. interface AlarmMessage {} static class EnableAlarm implements AlarmMessage { public final String pinCode; public EnableAlarm(String pinCode) { this.pinCode = pinCode; } } static class DisableAlarm implements AlarmMessage { public final String pinCode; public DisableAlarm(String pinCode) { this.pinCode = pinCode; } } static class ActivityEvent implements AlarmMessage { }
  • 31. public static Behavior<AlarmMessage> enabledAlarm(String pinCode) { return Behaviors.receive(AlarmMessage.class) .onMessage( DisableAlarm.class, // predicate (disable) -> disable.pinCode.equals(pinCode), (context, message) -> { context.getLog().info("Correct pin entered, disabling alarm"); return disabledAlarm(pinCode); } ).onMessage(ActivityEvent.class, (context, activityEvent) -> { context.getLog().warning("EOEOEOEOEOE ALARM ALARM!!!"); return Behaviors.same(); }).build(); }
  • 32. public static Behavior<AlarmMessage> disabledAlarm(String pinCode) { return Behaviors.receive(AlarmMessage.class) .onMessage(EnableAlarm.class, // predicate (enable) -> enable.pinCode.equals(pinCode), (context, message) -> { context.getLog().info("Correct pin entered, enabling alarm"); return enabledAlarm(pinCode); } ).build(); }
  • 33. public static void main(String[] args) { var system = ActorSystem.create(enabledAlarm("0000"), "my-system"); system.tell(new ActivityEvent()); system.tell(new DisableAlarm("1234")); system.tell(new ActivityEvent()); system.tell(new DisableAlarm("0000")); system.tell(new ActivityEvent()); system.tell(new EnableAlarm("0000")); }
  • 34. sealed trait AlarmMessage case class EnableAlarm(pinCode: String) extends AlarmMessage case class DisableAlarm(pinCode: String) extends AlarmMessage case object ActivityEvent extends AlarmMessage def enabledAlarm(pinCode: String): Behavior[AlarmMessage] = Behaviors.receive { (context, message) => message match { case ActivityEvent => context.log.warning("EOEOEOEOEOE ALARM ALARM!!!") Behaviors.same case DisableAlarm(`pinCode`) => context.log.info("Correct pin entered, disabling alarm"); disabledAlarm(pinCode) case _ => Behaviors.unhandled } } def disabledAlarm(pinCode: String): Behavior[AlarmMessage] = Behaviors.receivePartial { case (context, EnableAlarm(`pinCode`)) => context.log.info("Correct pin entered, enabling alarm") enabledAlarm(pinCode) } def main(args: Array[String]): Unit = { val system = ActorSystem.create(enabledAlarm("0000"), "my-system") system.tell(ActivityEvent) system.tell(DisableAlarm("1234")) system.tell(ActivityEvent) system.tell(DisableAlarm("0000")) system.tell(ActivityEvent) system.tell(EnableAlarm("0000")) system.tell(ActivityEvent) }
  • 35. Request-response with other actors • In untyped actors the sender was auto-magically available • In Akka Typed the recipient of response has to be encoded in message (why?)
  • 36. Request-response with other actors Actor<ProtocolA> Actor<ProtocolB> RequestForB ActorRef<ResponseFromB> ResponseFromBProtocolA ?
  • 37. Request-response with other actors Actor<ProtocolA> Actor<ProtocolB> RequestForB ActorRef<ResponseFromB> ResponseFromBProtocolA ResponseFromB -> ProtocolA ?
  • 38. One off with Ask context.ask( ResponseFromB.class, actorB, Timeout.create(Duration.ofSeconds(5)), (ActorRef<ResponseFromB> respondTo) -> new RequestForB(respondTo), (ResponseFromB res, Throwable failure) -> { if (res != null) return new ProtocolAMessage(res); else throw new RuntimeException("Request failed", failure); } );
  • 39. Long live the adapter ActorRef<ResponseFromB> adapter = context.messageAdapter( ResponseFromB.class, (responseFromB) -> new ProtocolAMessage(responseFromB) ); actorB.tell(new RequestForB(adapter));
  • 40. Keeping parts of the protocol to ourselves ActorRef<ProtocolA> actorRef = … ActorRef<SubProtocolA> moreNarrowActorRef = actorRef.narrow(); ProtocolA SubProtocolA SubProtocolA2
  • 41. Actor Model vs Network Interaction already modelled as immutable messages
 Data travels over the network in packages, changes has to be explicitly sent back. At most once
 Data reaches a node on the other side at most once, but can be lost, already part of model! A recipient of a message can reply directly to sender
 Regardless if there were intermediate recipients of the message Messages not limited to request response
 Messages can flow in either direction when two systems are connected.
  • 44. Akka Cluster + Akka Typed ActorSystem ActorSystem ActorSystem
  • 49. Distributed Burglar Alarm • we can have any number of nodes • a sensor on any node can report activity to the alarm Example DYI Distributed
  • 50. static final ServiceKey<ActivityEvent> serviceKey = ServiceKey.create(ActivityEvent.class, "alarm"); interface AlarmMessage extends Serializable {} static class EnableAlarm implements AlarmMessage { public final String pinCode; public EnableAlarm(String pinCode) { this.pinCode = pinCode; } } static class DisableAlarm implements AlarmMessage { public final String pinCode; public DisableAlarm(String pinCode) { this.pinCode = pinCode; } } static class ActivityEvent implements AlarmMessage { }
  • 51. static final ServiceKey<ActivityEvent> serviceKey = ServiceKey.create(ActivityEvent.class, "alarm"); interface AlarmMessage extends Serializable {} static class EnableAlarm implements AlarmMessage { public final String pinCode; public EnableAlarm(String pinCode) { this.pinCode = pinCode; } } static class DisableAlarm implements AlarmMessage { public final String pinCode; public DisableAlarm(String pinCode) { this.pinCode = pinCode; } } static class ActivityEvent implements AlarmMessage { }
  • 52. public static Behavior<AlarmMessage> alarm(String pinCode) { return Behaviors.setup((context) -> { ActorRef<Receptionist.Command> receptionist = context.getSystem().receptionist(); receptionist.tell( Receptionist.register(serviceKey, context.getSelf().narrow())); return enabledAlarm(pinCode); }); }
  • 53. public static class SensorBehavior extends AbstractBehavior<TriggerCommand> { private final ActorContext<TriggerCommand> context; private Set<ActorRef<ActivityEvent>> alarms = Collections.EMPTY_SET; public SensorBehavior(ActorContext<TriggerCommand> context) { this.context = context; // we need to transform the messages from the receptionist protocol // into our own protocol: ActorRef<Receptionist.Listing> adapter = context.messageAdapter( Receptionist.Listing.class, (listing) -> new AlarmActorUpdate(listing.getServiceInstances(serviceKey)) ); ActorRef<Receptionist.Command> receptionist = context.getSystem().receptionist(); receptionist.tell(Receptionist.subscribe(serviceKey, adapter)); } @Override public Behaviors.Receive<TriggerCommand> createReceive() { return receiveBuilder() .onMessage(TriggerSensor.class, this::onTrigger) .onMessage(AlarmActorUpdate.class, this::onAlarmActorUpdate) .build(); } private Behavior<TriggerCommand> onTrigger(TriggerSensor trigger) { final ActivityEvent activityEvent = new ActivityEvent(); if (alarms.isEmpty()) context.getLog().warning("Saw trigger but no alarms known yet"); alarms.forEach((alarm) -> alarm.tell(activityEvent) ); return Behaviors.same(); } private Behavior<TriggerCommand> onAlarmActorUpdate(AlarmActorUpdate update) { context.getLog().info("Got alarm actor list update"); alarms = update.alarms; return Behaviors.same(); } }
  • 54. public static class SensorBehavior extends AbstractBehavior<TriggerCommand> { private final ActorContext<TriggerCommand> context; private Set<ActorRef<ActivityEvent>> alarms = Collections.EMPTY_SET; public SensorBehavior(ActorContext<TriggerCommand> context) { this.context = context; // we need to transform the messages from the receptionist protocol // into our own protocol: ActorRef<Receptionist.Listing> adapter = context.messageAdapter( Receptionist.Listing.class, (listing) -> new AlarmActorUpdate(listing.getServiceInstances(serviceKey)) ); ActorRef<Receptionist.Command> receptionist = context.getSystem().receptionist(); receptionist.tell(Receptionist.subscribe(serviceKey, adapter)); } @Override public Behaviors.Receive<TriggerCommand> createReceive() { return receiveBuilder() .onMessage(TriggerSensor.class, this::onTrigger) .onMessage(AlarmActorUpdate.class, this::onAlarmActorUpdate) .build(); } private Behavior<TriggerCommand> onTrigger(TriggerSensor trigger) { final ActivityEvent activityEvent = new ActivityEvent();
  • 55. ); ActorRef<Receptionist.Command> receptionist = context.getSystem().receptionist(); receptionist.tell(Receptionist.subscribe(serviceKey, adapter)); } @Override public Behaviors.Receive<TriggerCommand> createReceive() { return receiveBuilder() .onMessage(TriggerSensor.class, this::onTrigger) .onMessage(AlarmActorUpdate.class, this::onAlarmActorUpdate) .build(); } private Behavior<TriggerCommand> onTrigger(TriggerSensor trigger) { final ActivityEvent activityEvent = new ActivityEvent(); if (alarms.isEmpty()) context.getLog().warning("Saw trigger but no alarms known yet"); alarms.forEach((alarm) -> alarm.tell(activityEvent) ); return Behaviors.same(); } private Behavior<TriggerCommand> onAlarmActorUpdate(AlarmActorUpdate update) { context.getLog().info("Got alarm actor list update"); alarms = update.alarms; return Behaviors.same(); } }
  • 56. public static void main(String[] args) throws Exception { ActorSystem<AlarmMessage> system1 = ActorSystem.create(alarm("0000"), "my-cluster"); ActorSystem<TriggerCommand> system2 = ActorSystem.create(sensorBehavior(), "my-cluster"); ActorSystem<TriggerCommand> system3 = ActorSystem.create(sensorBehavior(), "my-cluster"); // first join the first node to itself to form a cluster Cluster node1 = Cluster.get(system1); node1.manager().tell(Join.create(node1.selfMember().address())); // then have node 2 and 3 join that cluster Cluster node2 = Cluster.get(system2); node2.manager().tell(Join.create(node1.selfMember().address())); Cluster node3 = Cluster.get(system3); node3.manager().tell(Join.create(node1.selfMember().address())); Scanner in = new Scanner(System.in); while (true) {
  • 57. // then have node 2 and 3 join that cluster Cluster node2 = Cluster.get(system2); node2.manager().tell(Join.create(node1.selfMember().address())); Cluster node3 = Cluster.get(system3); node3.manager().tell(Join.create(node1.selfMember().address())); Scanner in = new Scanner(System.in); while (true) { try { System.out.println("Enter 2 or 3 to trigger activity on that node"); int chosenNode = Integer.parseInt(in.next()); System.out.println("Triggering sensor on node " + chosenNode); if (chosenNode == 2) system2.tell(new TriggerSensor()); else if (chosenNode == 3) system3.tell(new TriggerSensor()); } catch (Exception ex) { // we don't care, loop! } } }
  • 58. Summary • On message - message another actor, change state or behavior • Types gives better guardrails and makes understanding the system easier • We can use the same abstraction for local and distributed
  • 59. GitHub repo with all samples in this talk https://bit.ly/2OKRFxD Akka typed docs doc.akka.io/docs/akka/2.5/typed/index.html More resources blog.akka.io - news and articles discuss.akka.io - forums developer.lightbend.com - samples github.com/akka/akka - sources and getting involved Further reading
  • 60. Questions? GitHub repo with all samples in this talk https://bit.ly/2OKRFxD