From afb7fabc600a6effd1a264bcc8322f9d233c4362 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 8 Oct 2019 10:09:19 +0100 Subject: [PATCH] Akka 2.6.0-M8, drop runtime DI support for class-based behaviors --- .../java/play/libs/akka/AkkaGuiceSupport.java | 33 +------------- .../libs/concurrent/AkkaGuiceSupport.scala | 27 +----------- .../working/commonGuide/akka/AkkaTyped.md | 12 ++--- .../akka/typed/AkkaTypedDocTest.java | 9 +++- .../javaguide/akka/typed/AppComponents.java | 9 +++- .../code/javaguide/akka/typed/AppModule.java | 44 +++++++++++++++++-- .../javaguide/akka/typed/ConfiguredActor.java | 7 +-- .../code/javaguide/akka/typed/HelloActor.java | 5 +++ .../akka/typed/AkkaTypedDocSpec.scala | 7 +-- .../akka/typed/fp/ConfiguredActor.scala | 1 - .../scalaguide/akka/typed/fp/HelloActor.scala | 1 - .../scalaguide/akka/typed/oo/AppModule.scala | 19 +++++++- .../akka/typed/oo/ConfiguredActor.scala | 8 +++- .../scalaguide/akka/typed/oo/HelloActor.scala | 4 +- project/Dependencies.scala | 2 +- 15 files changed, 103 insertions(+), 85 deletions(-) diff --git a/core/play-guice/src/main/java/play/libs/akka/AkkaGuiceSupport.java b/core/play-guice/src/main/java/play/libs/akka/AkkaGuiceSupport.java index 262316d7157..229d298ffd0 100644 --- a/core/play-guice/src/main/java/play/libs/akka/AkkaGuiceSupport.java +++ b/core/play-guice/src/main/java/play/libs/akka/AkkaGuiceSupport.java @@ -4,21 +4,14 @@ package play.libs.akka; -import scala.reflect.ClassTag; - import akka.actor.Actor; import akka.actor.ActorRef; import akka.actor.Props; -import akka.actor.typed.Behavior; -import akka.annotation.ApiMayChange; import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.name.Names; import com.google.inject.util.Providers; -import play.api.libs.concurrent.TypedActorRefProvider; import play.libs.Akka; -import static play.api.libs.concurrent.TypedAkka.*; - import java.util.function.Function; /** @@ -36,7 +29,7 @@ * } * * - * Then to use the above actor in your application, add a qualified injected dependency, like so: + *

Then to use the above actor in your application, add a qualified injected dependency, like so: * *

  * public class MyController extends Controller {
@@ -104,28 +97,4 @@ default  void bindActorFactory(Class actorClass, Class fa
     BinderAccessor.binder(this)
         .install(new FactoryModuleBuilder().implement(Actor.class, actorClass).build(factoryClass));
   }
-
-  /**
-   * Bind a typed actor.
-   *
-   * 

For the given message type {@code T} binds {@code Behavior[T]} to the given {@link Behavior} - * subclass and {@code ActorRef[T]} to an instance of {@link TypedActorRefProvider} with the given - * actor name, so that it can be injected into other components. - * - *

Note that, while the name is used when spawning the actor in the {@code ActorSystem}, it is - * NOT used as a name qualifier for the binding. This is so that you don't need to use - * {@link javax.inject.Named Named} to qualify all injections of typed actors. Use the underlying - * API to create multiple, name-annotated bindings. - * - * @param behaviorClass The {@code Behavior} subclass for the typed actor. - * @param name The name of the typed actor. - * @param The type of the messages the typed actor can handle. - */ - @ApiMayChange - default void bindTypedActor(Class> behaviorClass, String name) { - Class cls = messageTypeOf(behaviorClass); - TypedActorRefProvider provider = new TypedActorRefProvider<>(name, ClassTag.apply(cls)); - BinderAccessor.binder(this).bind(behaviorOf(cls)).to(behaviorClass).asEagerSingleton(); - BinderAccessor.binder(this).bind(actorRefOf(cls)).toProvider(provider).asEagerSingleton(); - } } diff --git a/core/play-guice/src/main/scala/play/api/libs/concurrent/AkkaGuiceSupport.scala b/core/play-guice/src/main/scala/play/api/libs/concurrent/AkkaGuiceSupport.scala index cb3e83a5baf..3027f82127c 100644 --- a/core/play-guice/src/main/scala/play/api/libs/concurrent/AkkaGuiceSupport.scala +++ b/core/play-guice/src/main/scala/play/api/libs/concurrent/AkkaGuiceSupport.scala @@ -141,7 +141,8 @@ trait AkkaGuiceSupport { * * Binds `Behavior[T]` and `ActorRef[T]` for the given message type `T` to the given [[Behavior]] * value and actor name, so that it can be injected into other components. Use this variant of - * `bindTypedActor` when your actor's behavior doesn't depend on anything in dependency scope. + * `bindTypedActor` when using the "functional programming" style of defining your actor's + * behavior and it doesn't depend on anything in dependency scope. * * $unnamed * @@ -180,30 +181,6 @@ trait AkkaGuiceSupport { bindTypedActorRef[T](name) } - /** - * Bind a typed actor. - * - * Binds `Behavior[T]` and `ActorRef[T]` for the given message type `T` to the given [[Behavior]] - * subclass and actor name, so that it can be injected into other components. Use this variant of - * `bindTypedActor` when using the "object-oriented" style of defining your actor's behavior and - * (optionally) it needs to be injected with dependencies in dependency scope (such as - * [[play.api.Configuration Configuration]]. - * - * The [[Behavior]] class passed will typically be an application-specific, named subclass of - * Akka's scaladsl [[akka.actor.typed.scaladsl.AbstractBehavior AbstractBehavior]]. - * - * $unnamed - * - * @param behaviorClass The `Behavior` subclass for the typed actor. - * @param name The name of the typed actor. - * @tparam T The type of the messages the typed actor can handle. - */ - @ApiMayChange - final def bindTypedActor[T: ClassTag](behaviorClass: Class[_ <: Behavior[T]], name: String): Unit = { - accessBinder.bind(behaviorOf[T]).to(behaviorClass).asEagerSingleton() - bindTypedActorRef[T](name) - } - private[concurrent] final def bindTypedActorRef[T: ClassTag](name: String): Unit = { accessBinder.bind(actorRefOf[T]).toProvider(new TypedActorRefProvider[T](name)).asEagerSingleton() } diff --git a/documentation/manual/working/commonGuide/akka/AkkaTyped.md b/documentation/manual/working/commonGuide/akka/AkkaTyped.md index ccef16e9453..6aef1da714b 100644 --- a/documentation/manual/working/commonGuide/akka/AkkaTyped.md +++ b/documentation/manual/working/commonGuide/akka/AkkaTyped.md @@ -3,12 +3,12 @@ ## Akka Actor Typed styles -Akka's [Typed Actor API][] has two styles: +Akka's [Actor Typed API][] has two styles: -1. a ["functional programming" style][fp-style], based on defining actor `Behavior` as values, and -2. a ["object-oriented" style][oo-style], based on defining the `Behavior` as a subclass +1. a ["functional programming" style][fp-style], based on defining an actor `Behavior`s with values, and +2. a ["object-oriented" style][oo-style], based on defining an actor `Behavior`s with subclasses. -[Typed Actor API]: https://doc.akka.io/docs/akka/2.6/typed/actors.html +[Actor Typed API]: https://doc.akka.io/docs/akka/2.6/typed/actors.html [fp-style]: https://doc.akka.io/docs/akka/2.6/typed/actors.html#functional-style [oo-style]: https://doc.akka.io/docs/akka/2.6/typed/actors.html#object-oriented-style @@ -36,7 +36,7 @@ Java ## 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: +Using compile-time dependency injection for Akka Actor Typed requires creating the actor `Behavior` value and using it to spawn the actor: Scala : @[compile-time-di](code/scalaguide/akka/typed/fp/AppComponents.scala) @@ -56,7 +56,7 @@ Scala Java : @[main](code/javaguide/akka/typed/Main.java) -You can define a Guice `Module` defined like so: +You can define a Guice `Module` like so: Scala FP : @[fp-app-module](code/scalaguide/akka/typed/fp/AppModule.scala) diff --git a/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/AkkaTypedDocTest.java b/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/AkkaTypedDocTest.java index 795d4e94406..62a7ce22628 100644 --- a/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/AkkaTypedDocTest.java +++ b/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/AkkaTypedDocTest.java @@ -7,6 +7,7 @@ import akka.actor.ActorSystem; import akka.actor.typed.ActorRef; import akka.actor.typed.javadsl.Adapter; +import akka.actor.typed.javadsl.Behaviors; import com.google.inject.AbstractModule; import com.google.inject.TypeLiteral; import com.google.inject.name.Names; @@ -76,7 +77,8 @@ private void bindHelloActor(String name) { @Override public ActorRef get() { - return Adapter.spawn(actorSystem, new HelloActor(), name); + return Adapter.spawn( + actorSystem, Behaviors.setup(context -> new HelloActor(context)), name); } }) .asEagerSingleton(); @@ -92,7 +94,10 @@ private void bindConfiguredActor(String name) { @Override public ActorRef get() { - return Adapter.spawn(actorSystem, new ConfiguredActor(config), name); + return Adapter.spawn( + actorSystem, + Behaviors.setup(context -> new ConfiguredActor(context, config)), + name); } }) .asEagerSingleton(); diff --git a/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/AppComponents.java b/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/AppComponents.java index 239277c4179..2dc752353f7 100644 --- a/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/AppComponents.java +++ b/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/AppComponents.java @@ -7,6 +7,7 @@ // #compile-time-di import akka.actor.typed.ActorRef; import akka.actor.typed.javadsl.Adapter; +import akka.actor.typed.javadsl.Behaviors; import play.ApplicationLoader; import play.BuiltInComponentsFromContext; import play.mvc.EssentialFilter; @@ -23,9 +24,13 @@ public final class AppComponents extends BuiltInComponentsFromContext { public AppComponents(ApplicationLoader.Context context) { super(context); - helloActor = Adapter.spawn(actorSystem(), new HelloActor(), "hello-actor"); + helloActor = + Adapter.spawn(actorSystem(), Behaviors.setup(ctx -> new HelloActor(ctx)), "hello-actor"); configuredActor = - Adapter.spawn(actorSystem(), new ConfiguredActor(config()), "configured-actor"); + Adapter.spawn( + actorSystem(), + Behaviors.setup(ctx -> new ConfiguredActor(ctx, config())), + "configured-actor"); main = new Main(helloActor, configuredActor); } diff --git a/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/AppModule.java b/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/AppModule.java index d8f3bab3f38..602dcca0293 100644 --- a/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/AppModule.java +++ b/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/AppModule.java @@ -5,15 +5,51 @@ package javaguide.akka.typed; // #oo-app-module +import akka.actor.ActorSystem; +import akka.actor.typed.ActorRef; +import akka.actor.typed.javadsl.Adapter; +import akka.actor.typed.javadsl.Behaviors; import com.google.inject.AbstractModule; -import play.libs.akka.AkkaGuiceSupport; +import com.google.inject.Provider; +import com.google.inject.TypeLiteral; +import com.typesafe.config.Config; +import javax.inject.Inject; +import play.api.Configuration; +import play.api.libs.concurrent.AkkaGuiceSupport; -public class AppModule extends AbstractModule implements AkkaGuiceSupport { +public class AppModule extends AbstractModule { @Override protected void configure() { - bindTypedActor(HelloActor.class, "hello-actor"); - bindTypedActor(ConfiguredActor.class, "configured-actor"); + bind(new TypeLiteral>() {}) + .toProvider( + new Provider>() { + @Inject ActorSystem actorSystem; + + @Override + public ActorRef get() { + return Adapter.spawn( + actorSystem, + Behaviors.setup(context -> new HelloActor(context)), + "hello-actor"); + } + }) + .asEagerSingleton(); + bind(new TypeLiteral>() {}) + .toProvider( + new Provider>() { + @Inject ActorSystem actorSystem; + @Inject Config config; + + @Override + public ActorRef get() { + return Adapter.spawn( + actorSystem, + Behaviors.setup(context -> new ConfiguredActor(context, config)), + "configured-actor"); + } + }) + .asEagerSingleton(); } } // #oo-app-module diff --git a/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/ConfiguredActor.java b/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/ConfiguredActor.java index 6b12853b90a..4cc3dd21342 100644 --- a/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/ConfiguredActor.java +++ b/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/ConfiguredActor.java @@ -8,8 +8,9 @@ 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.ActorContext; import akka.actor.typed.javadsl.Adapter; +import akka.actor.typed.javadsl.Receive; import com.typesafe.config.Config; import javax.inject.Inject; @@ -26,8 +27,8 @@ public GetConfig(ActorRef replyTo) { private final String config; - @Inject - public ConfiguredActor(Config configuration) { + public ConfiguredActor(ActorContext context, Config configuration) { + super(context); config = configuration.getString("my.config"); } diff --git a/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/HelloActor.java b/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/HelloActor.java index a2a7ace47a2..0cb62bc15ec 100644 --- a/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/HelloActor.java +++ b/documentation/manual/working/commonGuide/akka/code/javaguide/akka/typed/HelloActor.java @@ -8,6 +8,7 @@ import akka.actor.typed.ActorRef; import akka.actor.typed.Behavior; import akka.actor.typed.javadsl.AbstractBehavior; +import akka.actor.typed.javadsl.ActorContext; import akka.actor.typed.javadsl.Receive; public final class HelloActor extends AbstractBehavior { @@ -22,6 +23,10 @@ public SayHello(String name, ActorRef replyTo) { } } + public HelloActor(ActorContext context) { + super(context); + } + @Override public Receive createReceive() { return newReceiveBuilder().onMessage(SayHello.class, this::onHello).build(); diff --git a/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/AkkaTypedDocSpec.scala b/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/AkkaTypedDocSpec.scala index d2ec3d3af67..357717c7591 100644 --- a/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/AkkaTypedDocSpec.scala +++ b/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/AkkaTypedDocSpec.scala @@ -4,13 +4,14 @@ package scalaguide.akka.typed -import akka.actor.ActorSystem import javax.inject.Inject import javax.inject.Named import javax.inject.Provider import javax.inject.Singleton +import akka.actor.ActorSystem import akka.actor.typed.ActorRef import akka.actor.typed.scaladsl.adapter._ +import akka.actor.typed.scaladsl.Behaviors import com.google.inject.name.Names import com.google.inject.AbstractModule import com.google.inject.TypeLiteral @@ -122,7 +123,7 @@ object AkkaTypedDocSpec { .toProvider(new Provider[ActorRef[HelloActor.SayHello]] { @Inject var actorSystem: ActorSystem = _ - def get() = actorSystem.spawn(new HelloActor, name) + def get() = actorSystem.spawn(Behaviors.setup(new HelloActor(_)), name) }) .asEagerSingleton() } @@ -133,7 +134,7 @@ object AkkaTypedDocSpec { @Inject var actorSystem: ActorSystem = _ @Inject var configuration: Configuration = _ - def get() = actorSystem.spawn(new ConfiguredActor(configuration), name) + def get() = actorSystem.spawn(Behaviors.setup(new ConfiguredActor(_, configuration)), name) }) .asEagerSingleton() } diff --git a/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/fp/ConfiguredActor.scala b/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/fp/ConfiguredActor.scala index 439594dde3f..a0fcfe28650 100644 --- a/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/fp/ConfiguredActor.scala +++ b/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/fp/ConfiguredActor.scala @@ -7,7 +7,6 @@ package scalaguide.akka.typed.fp // #fp-configured-actor 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 diff --git a/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/fp/HelloActor.scala b/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/fp/HelloActor.scala index 51248841497..417b9d66f6a 100644 --- a/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/fp/HelloActor.scala +++ b/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/fp/HelloActor.scala @@ -7,7 +7,6 @@ package scalaguide.akka.typed.fp // #fp-hello-actor 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]) diff --git a/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/oo/AppModule.scala b/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/oo/AppModule.scala index b5cbcf27ac0..3983de5051c 100644 --- a/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/oo/AppModule.scala +++ b/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/oo/AppModule.scala @@ -5,13 +5,28 @@ package scalaguide.akka.typed.oo // #oo-app-module +import akka.actor.ActorSystem +import akka.actor.typed.scaladsl.adapter._ +import akka.actor.typed.scaladsl.Behaviors +import akka.actor.typed.ActorRef import com.google.inject.AbstractModule +import com.google.inject.Provider +import com.google.inject.TypeLiteral +import javax.inject.Inject +import play.api.Configuration 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") + bindTypedActor(Behaviors.setup(context => new HelloActor(context)), "hello-actor") + bind(new TypeLiteral[ActorRef[ConfiguredActor.GetConfig]]() {}) + .toProvider(new Provider[ActorRef[ConfiguredActor.GetConfig]] { + @Inject var actorSystem: ActorSystem = _ + @Inject var configuration: Configuration = _ + + def get() = actorSystem.spawn(Behaviors.setup(context => new ConfiguredActor(context, configuration)), "configured-actor") + }) + .asEagerSingleton() } } // #oo-app-module diff --git a/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/oo/ConfiguredActor.scala b/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/oo/ConfiguredActor.scala index b39db96f1a9..0ccde83d7ec 100644 --- a/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/oo/ConfiguredActor.scala +++ b/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/oo/ConfiguredActor.scala @@ -6,7 +6,9 @@ package scalaguide.akka.typed.oo // #oo-configured-actor import akka.actor.typed.ActorRef +import akka.actor.typed.Behavior import akka.actor.typed.scaladsl.AbstractBehavior +import akka.actor.typed.scaladsl.ActorContext import javax.inject.Inject import play.api.Configuration @@ -14,8 +16,10 @@ object ConfiguredActor { final case class GetConfig(replyTo: ActorRef[String]) } -final class ConfiguredActor @Inject()(configuration: Configuration) - extends AbstractBehavior[ConfiguredActor.GetConfig] { +final class ConfiguredActor( + context: ActorContext[ConfiguredActor.GetConfig], + configuration: Configuration, +) extends AbstractBehavior(context) { import ConfiguredActor._ val config = configuration.get[String]("my.config") def onMessage(msg: GetConfig) = { diff --git a/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/oo/HelloActor.scala b/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/oo/HelloActor.scala index 1dc21abc7d3..f008e9b0550 100644 --- a/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/oo/HelloActor.scala +++ b/documentation/manual/working/commonGuide/akka/code/scalaguide/akka/typed/oo/HelloActor.scala @@ -6,13 +6,15 @@ package scalaguide.akka.typed.oo // #oo-hello-actor import akka.actor.typed.ActorRef +import akka.actor.typed.Behavior import akka.actor.typed.scaladsl.AbstractBehavior +import akka.actor.typed.scaladsl.ActorContext object HelloActor { final case class SayHello(name: String, replyTo: ActorRef[String]) } -final class HelloActor extends AbstractBehavior[HelloActor.SayHello] { +final class HelloActor(context: ActorContext[HelloActor.SayHello]) extends AbstractBehavior(context) { import HelloActor._ def onMessage(msg: SayHello) = { msg.replyTo ! s"Hello, ${msg.name}" diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 422d0dfe897..a9954c87579 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -8,7 +8,7 @@ import buildinfo.BuildInfo object Dependencies { - val akkaVersion: String = sys.props.getOrElse("akka.version", "2.6.0-M7") + val akkaVersion: String = sys.props.getOrElse("akka.version", "2.6.0-M8") val akkaHttpVersion = "10.1.10" val sslConfig = "com.typesafe" %% "ssl-config-core" % "0.4.0"