You are viewing the documentation for the 2.8.0-M4 development release. The latest stable release series is 3.0.x.
§Integrating with Akka Typed
§Akka Actor Typed styles
Akka’s Typed Actor API has two styles:
- a “functional programming” style, based on defining actor
Behavior
as values, and - a “object-oriented” style, based on defining the
Behavior
as a subclass
Here’s an example of a simple actor that says hello back:
- Scala FP
-
import akka.actor.typed.ActorRef import akka.actor.typed.Behavior import akka.actor.typed.scaladsl.Behaviors object HelloActor { final case class SayHello(name: String, replyTo: ActorRef[String]) def apply(): Behavior[SayHello] = { Behaviors.receiveMessage[SayHello] { case SayHello(name, replyTo) => replyTo ! s"Hello, $name" Behaviors.same } } }
- Scala OO
-
import akka.actor.typed.ActorRef import akka.actor.typed.scaladsl.AbstractBehavior object HelloActor { final case class SayHello(name: String, replyTo: ActorRef[String]) } final class HelloActor extends AbstractBehavior[HelloActor.SayHello] { import HelloActor._ def onMessage(msg: SayHello) = { msg.replyTo ! s"Hello, ${msg.name}" this } }
- Java
-
import akka.actor.typed.ActorRef; import akka.actor.typed.Behavior; import akka.actor.typed.javadsl.AbstractBehavior; import akka.actor.typed.javadsl.Receive; public final class HelloActor extends AbstractBehavior<HelloActor.SayHello> { public static final class SayHello { public final String name; public final ActorRef<String> replyTo; public SayHello(String name, ActorRef<String> replyTo) { this.name = name; this.replyTo = replyTo; } } @Override public Receive<SayHello> createReceive() { return newReceiveBuilder().onMessage(SayHello.class, this::onHello).build(); } private Behavior<SayHello> onHello(SayHello message) { message.replyTo.tell("Hello, " + message.name); return this; } }
Here’s an example of an actor that depends on Play’s Configuration
in order to return configuration values:
- Scala FP
-
import akka.actor.typed.ActorRef import akka.actor.typed.Behavior import akka.actor.typed.scaladsl.Behaviors import com.google.inject.Provides import play.api.Configuration import play.api.libs.concurrent.ActorModule object ConfiguredActor extends ActorModule { type Message = GetConfig final case class GetConfig(replyTo: ActorRef[String]) @Provides def apply(configuration: Configuration): Behavior[GetConfig] = { Behaviors.setup { _ => val config = configuration.get[String]("my.config") Behaviors.receiveMessage[GetConfig] { case GetConfig(replyTo) => replyTo ! config Behaviors.same } } } }
- Scala OO
-
import akka.actor.typed.ActorRef import akka.actor.typed.scaladsl.AbstractBehavior import javax.inject.Inject import play.api.Configuration object ConfiguredActor { final case class GetConfig(replyTo: ActorRef[String]) } final class ConfiguredActor @Inject()(configuration: Configuration) extends AbstractBehavior[ConfiguredActor.GetConfig] { import ConfiguredActor._ val config = configuration.get[String]("my.config") def onMessage(msg: GetConfig) = { msg.replyTo ! config this } }
- Java
-
import akka.actor.typed.ActorRef; import akka.actor.typed.Behavior; import akka.actor.typed.javadsl.AbstractBehavior; import akka.actor.typed.javadsl.Receive; import akka.actor.typed.javadsl.Adapter; import com.typesafe.config.Config; import javax.inject.Inject; public final class ConfiguredActor extends AbstractBehavior<ConfiguredActor.GetConfig> { public static final class GetConfig { public final ActorRef<String> replyTo; public GetConfig(ActorRef<String> replyTo) { this.replyTo = replyTo; } } private final String config; @Inject public ConfiguredActor(Config configuration) { config = configuration.getString("my.config"); } @Override public Receive<GetConfig> createReceive() { return newReceiveBuilder().onMessage(GetConfig.class, this::onGetConfig).build(); } private Behavior<GetConfig> onGetConfig(GetConfig message) { message.replyTo.tell(config); return this; } }
§Compile-time dependency injection
Using compile-time dependency injection for Akka Typed requires creating the actor Behavior
value and using it to spawn the actor:
- Scala
-
import akka.actor.typed.scaladsl.adapter._ import play.api._ import play.api.routing.Router final class AppComponents(context: ApplicationLoader.Context) extends BuiltInComponentsFromContext(context) with NoHttpFiltersComponents { val router = Router.empty val helloActor = actorSystem.spawn(HelloActor(), "hello-actor") val configuredActor = actorSystem.spawn(ConfiguredActor(configuration), "configured-actor") val main = new Main(helloActor, configuredActor) }
- Java
-
import akka.actor.typed.ActorRef; import akka.actor.typed.javadsl.Adapter; import play.ApplicationLoader; import play.BuiltInComponentsFromContext; import play.mvc.EssentialFilter; import play.routing.Router; import java.util.Collections; import java.util.List; public final class AppComponents extends BuiltInComponentsFromContext { public final ActorRef<HelloActor.SayHello> helloActor; public final ActorRef<ConfiguredActor.GetConfig> configuredActor; public final Main main; public AppComponents(ApplicationLoader.Context context) { super(context); helloActor = Adapter.spawn(actorSystem(), new HelloActor(), "hello-actor"); configuredActor = Adapter.spawn(actorSystem(), new ConfiguredActor(config()), "configured-actor"); main = new Main(helloActor, configuredActor); } @Override public Router router() { return Router.empty(); } @Override public List<EssentialFilter> httpFilters() { return Collections.emptyList(); } }
§Runtime dependency injection
For runtime dependency injection use the “typed” methods in AkkaGuiceSupport
.
Given a component in your application or system that needs injecting, like this one:
- Scala
-
import javax.inject.Inject import javax.inject.Singleton import akka.actor.typed.ActorRef @Singleton final class Main @Inject()( val helloActor: ActorRef[HelloActor.SayHello], val configuredActor: ActorRef[ConfiguredActor.GetConfig], )
- Java
-
import akka.actor.typed.ActorRef; import javax.inject.Inject; import javax.inject.Singleton; @Singleton public final class Main { public final ActorRef<HelloActor.SayHello> helloActor; public final ActorRef<ConfiguredActor.GetConfig> configuredActor; @Inject public Main( ActorRef<HelloActor.SayHello> helloActor, ActorRef<ConfiguredActor.GetConfig> configuredActor) { this.helloActor = helloActor; this.configuredActor = configuredActor; } }
You can define a Guice Module
defined like so:
- Scala FP
-
import com.google.inject.AbstractModule import play.api.libs.concurrent.AkkaGuiceSupport object AppModule extends AbstractModule with AkkaGuiceSupport { override def configure() = { bindTypedActor(HelloActor(), "hello-actor") // uses apply bindTypedActor(ConfiguredActor, "configured-actor") // uses object } }
- Scala OO
-
import com.google.inject.AbstractModule import play.api.libs.concurrent.AkkaGuiceSupport object AppModule extends AbstractModule with AkkaGuiceSupport { override def configure() = { bindTypedActor(classOf[HelloActor], "hello-actor") bindTypedActor(classOf[ConfiguredActor], "configured-actor") } }
- Java
-
import com.google.inject.AbstractModule; import play.libs.akka.AkkaGuiceSupport; public class AppModule extends AbstractModule implements AkkaGuiceSupport { @Override protected void configure() { bindTypedActor(HelloActor.class, "hello-actor"); bindTypedActor(ConfiguredActor.class, "configured-actor"); } }
Next: Contributing to Play