From 91db18b564b64a98ade6b574d04c7f2a92b1b30e Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Fri, 27 Sep 2019 11:17:37 +0200 Subject: [PATCH] ActorContext as constructor parameter in AbstractBehavior, #27689 (#27806) * ActorContext as constructor parameter in AbstractBehavior, #27689 * additional test * additional doc clarification * another rebase --- .../typed/javadsl/SyncTestingExampleTest.java | 14 ++--- .../typed/javadsl/ReceiveBuilderTest.java | 24 +------- .../java/jdocs/akka/typed/Aggregator.java | 1 + .../java/jdocs/akka/typed/AggregatorTest.java | 8 +-- .../java/jdocs/akka/typed/BubblingSample.java | 12 ++-- .../jdocs/akka/typed/GracefulStopDocTest.java | 19 +++--- .../akka/typed/InteractionPatternsTest.java | 44 +++++++++----- .../test/java/jdocs/akka/typed/IntroTest.java | 26 ++++----- .../jdocs/akka/typed/LoggingDocExamples.java | 16 ++--- .../java/jdocs/akka/typed/OOIntroTest.java | 29 ++++++---- .../akka/typed/StyleGuideDocExamples.java | 34 ++++++----- .../java/jdocs/akka/typed/TailChopping.java | 1 + .../coexistence/TypedWatchingClassicTest.java | 5 +- .../akka/typed/fromclassic/TypedSample.java | 15 ++--- .../scala/akka/actor/typed/BehaviorSpec.scala | 2 +- .../akka/actor/typed/SupervisionSpec.scala | 58 ++++++++++++++++++- .../scala/akka/actor/typed/WatchSpec.scala | 8 ++- .../typed/scaladsl/ActorLoggingSpec.scala | 2 +- .../akka/actor/typed/scaladsl/StashSpec.scala | 3 +- .../scala/docs/akka/typed/OOIntroSpec.scala | 15 ++++- .../akka/typed/StyleGuideDocExamples.scala | 2 +- .../akka/typed/fromclassic/TypedSample.scala | 2 +- .../scala/akka/actor/typed/ActorSystem.scala | 2 +- .../actor/typed/internal/Supervision.scala | 6 ++ .../adapter/GuardianStartupBehavior.scala | 34 +++++------ .../internal/routing/GroupRouterImpl.scala | 22 +++---- .../internal/routing/PoolRouterImpl.scala | 14 ++--- .../typed/javadsl/AbstractBehavior.scala | 44 +++++++++++--- .../typed/scaladsl/AbstractBehavior.scala | 39 ++++++++++--- .../typed/ShardingCompileOnlyTest.java | 8 +-- .../typed/ShardingReplyCompileOnlyTest.java | 1 + .../typed/javadsl/ReplicatorDocSample.java | 3 +- .../typed/SingletonCompileOnlyTest.java | 3 +- .../project/migration-guide-2.5.x-2.6.x.md | 6 +- .../java/jdocs/actor/typed/BlockingActor.java | 4 +- .../actor/typed/BlockingDispatcherTest.java | 2 +- .../jdocs/actor/typed/DispatcherDocTest.java | 8 ++- .../java/jdocs/actor/typed/PrintActor.java | 6 +- ...eparateDispatcherCompletionStageActor.java | 1 + .../typed/SharedMutableStateDocTest.java | 38 ++++++------ .../ResumableProjectionExample.java | 6 +- .../tutorial_1/ActorHierarchyExperiments.java | 28 ++++----- .../jdocs/typed/tutorial_2/IotSupervisor.java | 8 +-- .../java/jdocs/typed/tutorial_3/Device.java | 7 +-- .../typed/tutorial_3/inprogress2/Device.java | 5 +- .../java/jdocs/typed/tutorial_4/Device.java | 7 +-- .../jdocs/typed/tutorial_4/DeviceGroup.java | 18 +++--- .../jdocs/typed/tutorial_4/DeviceManager.java | 13 ++--- .../java/jdocs/typed/tutorial_5/Device.java | 7 +-- .../jdocs/typed/tutorial_5/DeviceGroup.java | 25 ++++---- .../typed/tutorial_5/DeviceGroupQuery.java | 1 + .../jdocs/typed/tutorial_5/DeviceManager.java | 13 ++--- .../typed/SharedMutableStateDocSpec.scala | 2 +- .../ActorHierarchyExperiments.scala | 16 ++--- .../typed/tutorial_2/IotSupervisor.scala | 2 +- .../test/scala/typed/tutorial_3/Device.scala | 2 +- .../typed/tutorial_3/DeviceInProgress.scala | 2 +- .../test/scala/typed/tutorial_4/Device.scala | 2 +- .../scala/typed/tutorial_4/DeviceGroup.scala | 2 +- .../typed/tutorial_4/DeviceManager.scala | 3 +- .../test/scala/typed/tutorial_5/Device.scala | 2 +- .../scala/typed/tutorial_5/DeviceGroup.scala | 2 +- .../typed/tutorial_5/DeviceGroupQuery.scala | 2 +- .../typed/tutorial_5/DeviceManager.scala | 3 +- .../typed/internal/ReplayingEvents.scala | 2 +- .../persistence/typed/internal/Running.scala | 4 +- 66 files changed, 442 insertions(+), 323 deletions(-) diff --git a/akka-actor-testkit-typed/src/test/java/jdocs/akka/actor/testkit/typed/javadsl/SyncTestingExampleTest.java b/akka-actor-testkit-typed/src/test/java/jdocs/akka/actor/testkit/typed/javadsl/SyncTestingExampleTest.java index f93f770ddf..069ea001da 100644 --- a/akka-actor-testkit-typed/src/test/java/jdocs/akka/actor/testkit/typed/javadsl/SyncTestingExampleTest.java +++ b/akka-actor-testkit-typed/src/test/java/jdocs/akka/actor/testkit/typed/javadsl/SyncTestingExampleTest.java @@ -80,10 +80,8 @@ public class SyncTestingExampleTest extends JUnitSuite { return Behaviors.setup(Hello::new); } - private final ActorContext context; - private Hello(ActorContext context) { - this.context = context; + super(context); } @Override @@ -99,23 +97,23 @@ public class SyncTestingExampleTest extends JUnitSuite { } private Behavior onCreateAChild(CreateAChild message) { - context.spawn(Child.create(), message.childName); + getContext().spawn(Child.create(), message.childName); return Behaviors.same(); } private Behavior onCreateAnonymousChild(CreateAnAnonymousChild message) { - context.spawnAnonymous(Child.create()); + getContext().spawnAnonymous(Child.create()); return Behaviors.same(); } private Behavior onSayHelloToChild(SayHelloToChild message) { - ActorRef child = context.spawn(Child.create(), message.childName); + ActorRef child = getContext().spawn(Child.create(), message.childName); child.tell("hello"); return Behaviors.same(); } private Behavior onSayHelloToAnonymousChild(SayHelloToAnonymousChild message) { - ActorRef child = context.spawnAnonymous(Child.create()); + ActorRef child = getContext().spawnAnonymous(Child.create()); child.tell("hello stranger"); return Behaviors.same(); } @@ -126,7 +124,7 @@ public class SyncTestingExampleTest extends JUnitSuite { } private Behavior onLogAndSayHello(LogAndSayHello message) { - context.getLog().info("Saying hello to {}", message.who.path().name()); + getContext().getLog().info("Saying hello to {}", message.who.path().name()); message.who.tell("hello"); return Behaviors.same(); } diff --git a/akka-actor-typed-tests/src/test/java/akka/actor/typed/javadsl/ReceiveBuilderTest.java b/akka-actor-typed-tests/src/test/java/akka/actor/typed/javadsl/ReceiveBuilderTest.java index 50c67bc5a5..6105038190 100644 --- a/akka-actor-typed-tests/src/test/java/akka/actor/typed/javadsl/ReceiveBuilderTest.java +++ b/akka-actor-typed-tests/src/test/java/akka/actor/typed/javadsl/ReceiveBuilderTest.java @@ -31,7 +31,7 @@ public class ReceiveBuilderTest extends JUnitSuite { Behavior mutable = Behaviors.setup( context -> - new AbstractBehavior() { + new AbstractBehavior(context) { int currentValue = 0; private Behavior receiveIncrease( @@ -56,28 +56,6 @@ public class ReceiveBuilderTest extends JUnitSuite { }); } - private static class MyAbstractBehavior - extends AbstractBehavior { - private int value; - - public MyAbstractBehavior(int initialValue) { - super(); - this.value = initialValue; - } - - @Override - public Receive createReceive() { - assertEquals(42, value); - return newReceiveBuilder().build(); - } - } - - @Test - public void testInitializationOrder() throws Exception { - MyAbstractBehavior mutable = new MyAbstractBehavior(42); - assertEquals(Behaviors.unhandled(), mutable.receive(null, new BehaviorBuilderTest.Increase())); - } - @Test public void caseSelectedInOrderAdded() { final TestProbe probe = testKit.createTestProbe(); diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/Aggregator.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/Aggregator.java index 7132826570..76c7ed1c27 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/Aggregator.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/Aggregator.java @@ -66,6 +66,7 @@ public class Aggregator extends AbstractBehavior replyTo, Function, Aggregate> aggregateReplies, Duration timeout) { + super(context); this.expectedReplies = expectedReplies; this.replyTo = replyTo; this.aggregateReplies = aggregateReplies; diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/AggregatorTest.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/AggregatorTest.java index 8b5e9d32a8..1afa3bc39b 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/AggregatorTest.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/AggregatorTest.java @@ -152,13 +152,11 @@ public class AggregatorTest extends JUnitSuite { return Behaviors.setup(context -> new HotelCustomer(context, hotel1, hotel2)); } - private final ActorContext context; - public HotelCustomer( ActorContext context, ActorRef hotel1, ActorRef hotel2) { - this.context = context; + super(context); Consumer> sendRequests = replyTo -> { @@ -209,8 +207,8 @@ public class AggregatorTest extends JUnitSuite { } private Behavior onAggregatedQuotes(AggregatedQuotes aggregated) { - if (aggregated.quotes.isEmpty()) context.getLog().info("Best Quote N/A"); - else context.getLog().info("Best {}", aggregated.quotes.get(0)); + if (aggregated.quotes.isEmpty()) getContext().getLog().info("Best Quote N/A"); + else getContext().getLog().info("Best {}", aggregated.quotes.get(0)); return this; } } diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/BubblingSample.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/BubblingSample.java index 9ebd011268..82f6cfc408 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/BubblingSample.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/BubblingSample.java @@ -45,7 +45,11 @@ public class BubblingSample { public static class Worker extends AbstractBehavior { public static Behavior create() { - return Behaviors.setup(context -> new Worker()); + return Behaviors.setup(Worker::new); + } + + private Worker(ActorContext context) { + super(context); } @Override @@ -72,11 +76,10 @@ public class BubblingSample { return Behaviors.setup(MiddleManagement::new); } - private final ActorContext context; private final ActorRef child; private MiddleManagement(ActorContext context) { - this.context = context; + super(context); context.getLog().info("Middle management starting up"); // default supervision of child, meaning that it will stop on failure @@ -109,11 +112,10 @@ public class BubblingSample { .onFailure(DeathPactException.class, SupervisorStrategy.restart()); } - private final ActorContext context; private final ActorRef middleManagement; private Boss(ActorContext context) { - this.context = context; + super(context); context.getLog().info("Boss starting up"); // default supervision of child, meaning that it will stop on failure middleManagement = context.spawn(MiddleManagement.create(), "middle-management"); diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/GracefulStopDocTest.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/GracefulStopDocTest.java index 4e100fdeb5..cca1ca159d 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/GracefulStopDocTest.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/GracefulStopDocTest.java @@ -42,10 +42,8 @@ interface GracefulStopDocTest { return Behaviors.setup(MasterControlProgram::new); } - private final ActorContext context; - public MasterControlProgram(ActorContext context) { - this.context = context; + super(context); } @Override @@ -58,21 +56,21 @@ interface GracefulStopDocTest { } private Behavior onSpawnJob(SpawnJob message) { - context.getSystem().log().info("Spawning job {}!", message.name); - context.spawn(Job.create(message.name), message.name); + getContext().getSystem().log().info("Spawning job {}!", message.name); + getContext().spawn(Job.create(message.name), message.name); return this; } private Behavior onGracefulShutdown() { - context.getSystem().log().info("Initiating graceful shutdown..."); + getContext().getSystem().log().info("Initiating graceful shutdown..."); // perform graceful stop, executing cleanup before final system termination // behavior executing cleanup is passed as a parameter to Actor.stopped - return Behaviors.stopped(() -> context.getSystem().log().info("Cleanup!")); + return Behaviors.stopped(() -> getContext().getSystem().log().info("Cleanup!")); } private Behavior onPostStop() { - context.getSystem().log().info("Master Control Program stopped"); + getContext().getSystem().log().info("Master Control Program stopped"); return this; } } @@ -106,11 +104,10 @@ interface GracefulStopDocTest { return Behaviors.setup(context -> new Job(context, name)); } - private final ActorContext context; private final String name; public Job(ActorContext context, String name) { - this.context = context; + super(context); this.name = name; } @@ -120,7 +117,7 @@ interface GracefulStopDocTest { } private Behavior onPostStop() { - context.getSystem().log().info("Worker {} stopped", name); + getContext().getSystem().log().info("Worker {} stopped", name); return this; } } diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/InteractionPatternsTest.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/InteractionPatternsTest.java index e2f84b74e1..96e6aa8154 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/InteractionPatternsTest.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/InteractionPatternsTest.java @@ -170,7 +170,6 @@ public class InteractionPatternsTest extends JUnitSuite { } public static class Translator extends AbstractBehavior { - private final ActorContext context; private final ActorRef backend; private final ActorRef backendResponseAdapter; @@ -178,7 +177,7 @@ public class InteractionPatternsTest extends JUnitSuite { private Map> inProgress = new HashMap<>(); public Translator(ActorContext context, ActorRef backend) { - this.context = context; + super(context); this.backend = backend; this.backendResponseAdapter = context.messageAdapter(Backend.Response.class, WrappedBackendResponse::new); @@ -204,13 +203,13 @@ public class InteractionPatternsTest extends JUnitSuite { Backend.Response response = wrapped.response; if (response instanceof Backend.JobStarted) { Backend.JobStarted rsp = (Backend.JobStarted) response; - context.getLog().info("Started {}", rsp.taskId); + getContext().getLog().info("Started {}", rsp.taskId); } else if (response instanceof Backend.JobProgress) { Backend.JobProgress rsp = (Backend.JobProgress) response; - context.getLog().info("Progress {}", rsp.taskId); + getContext().getLog().info("Progress {}", rsp.taskId); } else if (response instanceof Backend.JobCompleted) { Backend.JobCompleted rsp = (Backend.JobCompleted) response; - context.getLog().info("Completed {}", rsp.taskId); + getContext().getLog().info("Completed {}", rsp.taskId); inProgress.get(rsp.taskId).tell(rsp.result); inProgress.remove(rsp.taskId); } else { @@ -292,13 +291,15 @@ public class InteractionPatternsTest extends JUnitSuite { private Behavior onIdleCommand(Command message) { timers.startSingleTimer(TIMER_KEY, Timeout.INSTANCE, after); - return new Active(message); + return Behaviors.setup(context -> new Active(context, message)); } private class Active extends AbstractBehavior { + private final List buffer = new ArrayList<>(); - Active(Command firstCommand) { + Active(ActorContext context, Command firstCommand) { + super(context); buffer.add(firstCommand); } @@ -332,6 +333,14 @@ public class InteractionPatternsTest extends JUnitSuite { // #actor-ask public class Hal extends AbstractBehavior { + public Behavior create() { + return Behaviors.setup(Hal::new); + } + + private Hal(ActorContext context) { + super(context); + } + public interface Command {} public static final class OpenThePodBayDoorsPlease implements Command { @@ -380,10 +389,8 @@ public class InteractionPatternsTest extends JUnitSuite { return Behaviors.setup(context -> new Dave(context, hal)); } - private final ActorContext context; - private Dave(ActorContext context, ActorRef hal) { - this.context = context; + super(context); // asking someone requires a timeout, if the timeout hits without response // the ask is failed with a TimeoutException @@ -435,7 +442,7 @@ public class InteractionPatternsTest extends JUnitSuite { } private Behavior onAdaptedResponse(AdaptedResponse response) { - context.getLog().info("Got response from HAL: {}", response.message); + getContext().getLog().info("Got response from HAL: {}", response.message); return this; } } @@ -535,7 +542,7 @@ public class InteractionPatternsTest extends JUnitSuite { private Behavior onLeaveHome(LeaveHome message) { context.spawn( - new PrepareToLeaveHome(message.who, message.respondTo, keyCabinet, drawer), + PrepareToLeaveHome.create(message.who, message.respondTo, keyCabinet, drawer), "leaving" + message.who); return Behaviors.same(); } @@ -548,6 +555,15 @@ public class InteractionPatternsTest extends JUnitSuite { // per session actor behavior class PrepareToLeaveHome extends AbstractBehavior { + static Behavior create( + String whoIsLeaving, + ActorRef replyTo, + ActorRef keyCabinet, + ActorRef drawer) { + return Behaviors.setup( + context -> new PrepareToLeaveHome(context, whoIsLeaving, replyTo, keyCabinet, drawer)); + } + private final String whoIsLeaving; private final ActorRef replyTo; private final ActorRef keyCabinet; @@ -555,11 +571,13 @@ public class InteractionPatternsTest extends JUnitSuite { private Optional wallet = Optional.empty(); private Optional keys = Optional.empty(); - PrepareToLeaveHome( + private PrepareToLeaveHome( + ActorContext context, String whoIsLeaving, ActorRef replyTo, ActorRef keyCabinet, ActorRef drawer) { + super(context); this.whoIsLeaving = whoIsLeaving; this.replyTo = replyTo; this.keyCabinet = keyCabinet; diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/IntroTest.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/IntroTest.java index 55f490f175..16035fd772 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/IntroTest.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/IntroTest.java @@ -54,10 +54,8 @@ public interface IntroTest { return Behaviors.setup(HelloWorld::new); } - private final ActorContext context; - private HelloWorld(ActorContext context) { - this.context = context; + super(context); } @Override @@ -66,8 +64,8 @@ public interface IntroTest { } private Behavior onGreet(Greet command) { - context.getLog().info("Hello {}!", command.whom); - command.replyTo.tell(new Greeted(command.whom, context.getSelf())); + getContext().getLog().info("Hello {}!", command.whom); + command.replyTo.tell(new Greeted(command.whom, getContext().getSelf())); return this; } } @@ -80,12 +78,11 @@ public interface IntroTest { return Behaviors.setup(context -> new HelloWorldBot(context, max)); } - private final ActorContext context; private final int max; private int greetingCounter; private HelloWorldBot(ActorContext context, int max) { - this.context = context; + super(context); this.max = max; } @@ -96,11 +93,11 @@ public interface IntroTest { private Behavior onGreeted(HelloWorld.Greeted message) { greetingCounter++; - context.getLog().info("Greeting {} for {}", greetingCounter, message.whom); + getContext().getLog().info("Greeting {} for {}", greetingCounter, message.whom); if (greetingCounter == max) { return Behaviors.stopped(); } else { - message.from.tell(new HelloWorld.Greet(message.whom, context.getSelf())); + message.from.tell(new HelloWorld.Greet(message.whom, getContext().getSelf())); return this; } } @@ -125,11 +122,10 @@ public interface IntroTest { return Behaviors.setup(HelloWorldMain::new); } - private final ActorContext context; private final ActorRef greeter; private HelloWorldMain(ActorContext context) { - this.context = context; + super(context); greeter = context.spawn(HelloWorld.create(), "greeter"); } // #hello-world-main-setup @@ -140,7 +136,8 @@ public interface IntroTest { } private Behavior onStart(Start command) { - ActorRef replyTo = context.spawn(HelloWorldBot.create(3), command.name); + ActorRef replyTo = + getContext().spawn(HelloWorldBot.create(3), command.name); greeter.tell(new HelloWorld.Greet(command.name, replyTo)); return this; } @@ -177,15 +174,14 @@ public interface IntroTest { return Behaviors.setup(HelloWorldMain::new); } - private final ActorContext context; private final ActorRef greeter; private HelloWorldMain(ActorContext context) { - this.context = context; + super(context); final String dispatcherPath = "akka.actor.default-blocking-io-dispatcher"; Props greeterProps = DispatcherSelector.fromConfig(dispatcherPath); - greeter = context.spawn(HelloWorld.create(), "greeter", greeterProps); + greeter = getContext().spawn(HelloWorld.create(), "greeter", greeterProps); } // createReceive ... diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/LoggingDocExamples.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/LoggingDocExamples.java index a449d28d69..d49d190273 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/LoggingDocExamples.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/LoggingDocExamples.java @@ -38,10 +38,8 @@ public interface LoggingDocExamples { return Behaviors.setup(MyLoggingBehavior::new); } - private final ActorContext context; - private MyLoggingBehavior(ActorContext context) { - this.context = context; + super(context); } @Override @@ -50,7 +48,7 @@ public interface LoggingDocExamples { } private Behavior onReceive(String message) { - context.getLog().info("Received message: {}", message); + getContext().getLog().info("Received message: {}", message); return this; } } @@ -68,10 +66,8 @@ public interface LoggingDocExamples { }); } - private final ActorContext context; - private BackendManager(ActorContext context) { - this.context = context; + super(context); } @Override @@ -80,7 +76,7 @@ public interface LoggingDocExamples { } private Behavior onReceive(String message) { - context.getLog().debug("Received message: {}", message); + getContext().getLog().debug("Received message: {}", message); return this; } } @@ -122,6 +118,10 @@ public interface LoggingDocExamples { return Behaviors.empty(); } + public BackendManager2(ActorContext context) { + super(context); + } + @Override public Receive createReceive() { return newReceiveBuilder().build(); diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/OOIntroTest.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/OOIntroTest.java index 6de999c6d2..e19c226130 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/OOIntroTest.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/OOIntroTest.java @@ -108,11 +108,10 @@ public interface OOIntroTest { } public static class ChatRoomBehavior extends AbstractBehavior { - final ActorContext context; final List> sessions = new ArrayList<>(); private ChatRoomBehavior(ActorContext context) { - this.context = context; + super(context); } @Override @@ -129,9 +128,10 @@ public interface OOIntroTest { throws UnsupportedEncodingException { ActorRef client = getSession.replyTo; ActorRef ses = - context.spawn( - new SessionBehavior(context.getSelf(), getSession.screenName, client), - URLEncoder.encode(getSession.screenName, StandardCharsets.UTF_8.name())); + getContext() + .spawn( + SessionBehavior.create(getContext().getSelf(), getSession.screenName, client), + URLEncoder.encode(getSession.screenName, StandardCharsets.UTF_8.name())); // narrow to only expose PostMessage client.tell(new SessionGranted(ses.narrow())); sessions.add(ses); @@ -151,8 +151,17 @@ public interface OOIntroTest { private final String screenName; private final ActorRef client; - SessionBehavior( + public static Behavior create( ActorRef room, String screenName, ActorRef client) { + return Behaviors.setup(context -> new SessionBehavior(context, room, screenName, client)); + } + + private SessionBehavior( + ActorContext context, + ActorRef room, + String screenName, + ActorRef client) { + super(context); this.room = room; this.screenName = screenName; this.client = client; @@ -187,10 +196,8 @@ public interface OOIntroTest { return Behaviors.setup(Gabbler::new); } - private ActorContext context; - private Gabbler(ActorContext context) { - this.context = context; + super(context); } @Override @@ -204,7 +211,7 @@ public interface OOIntroTest { } private Behavior onSessionDenied(ChatRoom.SessionDenied message) { - context.getLog().info("cannot start chat room session: {}", message.reason); + getContext().getLog().info("cannot start chat room session: {}", message.reason); return Behaviors.stopped(); } @@ -214,7 +221,7 @@ public interface OOIntroTest { } private Behavior onMessagePosted(ChatRoom.MessagePosted message) { - context + getContext() .getLog() .info("message has been posted by '{}': {}", message.screenName, message.message); return Behaviors.stopped(); diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/StyleGuideDocExamples.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/StyleGuideDocExamples.java index 8f7500ea59..84001ca736 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/StyleGuideDocExamples.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/StyleGuideDocExamples.java @@ -110,12 +110,10 @@ interface StyleGuideDocExamples { return Behaviors.setup(Counter::new); } - private final ActorContext context; - private int n; private Counter(ActorContext context) { - this.context = context; + super(context); } @Override @@ -130,7 +128,7 @@ interface StyleGuideDocExamples { private Behavior onIncrement() { n++; - context.getLog().debug("Incremented counter to [{}]", n); + getContext().getLog().debug("Incremented counter to [{}]", n); return this; } @@ -426,13 +424,15 @@ interface StyleGuideDocExamples { // factory for the initial `Behavior` public static Behavior create(int countDownFrom, ActorRef notifyWhenZero) { - return Behaviors.setup(context -> new CountDown(countDownFrom, notifyWhenZero)); + return Behaviors.setup(context -> new CountDown(context, countDownFrom, notifyWhenZero)); } private final ActorRef notifyWhenZero; private int remaining; - private CountDown(int countDownFrom, ActorRef notifyWhenZero) { + private CountDown( + ActorContext context, int countDownFrom, ActorRef notifyWhenZero) { + super(context); this.remaining = countDownFrom; this.notifyWhenZero = notifyWhenZero; } @@ -558,12 +558,11 @@ interface StyleGuideDocExamples { } private final String name; - private final ActorContext context; private int count; private Counter(String name, ActorContext context) { + super(context); this.name = name; - this.context = context; } // #on-message-lambda @@ -589,14 +588,16 @@ interface StyleGuideDocExamples { // #on-message-lambda private Behavior onIncrement() { count++; - context.getLog().debug("[{}] Incremented counter to [{}]", name, count); + getContext().getLog().debug("[{}] Incremented counter to [{}]", name, count); return this; } // #on-message-lambda private Behavior onTick() { count++; - context.getLog().debug("[{}] Incremented counter by background tick to [{}]", name, count); + getContext() + .getLog() + .debug("[{}] Incremented counter by background tick to [{}]", name, count); return this; } @@ -616,14 +617,14 @@ interface StyleGuideDocExamples { Increment.class, notUsed -> { count++; - context.getLog().debug("[{}] Incremented counter to [{}]", name, count); + getContext().getLog().debug("[{}] Incremented counter to [{}]", name, count); return this; }) .onMessage( Tick.class, notUsed -> { count++; - context + getContext() .getLog() .debug("[{}] Incremented counter by background tick to [{}]", name, count); return this; @@ -694,12 +695,11 @@ interface StyleGuideDocExamples { } private final String name; - private final ActorContext context; private int count; private Counter(String name, ActorContext context) { + super(context); this.name = name; - this.context = context; } @Override @@ -713,13 +713,15 @@ interface StyleGuideDocExamples { private Behavior onIncrement() { count++; - context.getLog().debug("[{}] Incremented counter to [{}]", name, count); + getContext().getLog().debug("[{}] Incremented counter to [{}]", name, count); return this; } private Behavior onTick() { count++; - context.getLog().debug("[{}] Incremented counter by background tick to [{}]", name, count); + getContext() + .getLog() + .debug("[{}] Incremented counter by background tick to [{}]", name, count); return this; } diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/TailChopping.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/TailChopping.java index 0ad1b4afb1..4813ef7363 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/TailChopping.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/TailChopping.java @@ -77,6 +77,7 @@ public class TailChopping extends AbstractBehavior ActorRef replyTo, Duration finalTimeout, Reply timeoutReply) { + super(context); this.timers = timers; this.sendRequest = sendRequest; this.nextRequestAfter = nextRequestAfter; diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/coexistence/TypedWatchingClassicTest.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/coexistence/TypedWatchingClassicTest.java index 24a963d767..1feeb1ea0d 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/coexistence/TypedWatchingClassicTest.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/coexistence/TypedWatchingClassicTest.java @@ -39,11 +39,10 @@ public class TypedWatchingClassicTest extends JUnitSuite { INSTANCE } - private final akka.actor.typed.javadsl.ActorContext context; private final akka.actor.ActorRef second; private Typed(ActorContext context, akka.actor.ActorRef second) { - this.context = context; + super(context); this.second = second; } @@ -70,7 +69,7 @@ public class TypedWatchingClassicTest extends JUnitSuite { } private Behavior onPong() { - Adapter.stop(context, second); + Adapter.stop(getContext(), second); return this; } } diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/fromclassic/TypedSample.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/fromclassic/TypedSample.java index ee7c8c18c2..90149bf987 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/fromclassic/TypedSample.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/fromclassic/TypedSample.java @@ -46,10 +46,8 @@ interface TypedSample { return Behaviors.setup(HelloWorld::new); } - private final ActorContext context; - private HelloWorld(ActorContext context) { - this.context = context; + super(context); } @Override @@ -58,8 +56,8 @@ interface TypedSample { } private Behavior onGreet(Greet command) { - context.getLog().info("Hello {}!", command.whom); - command.replyTo.tell(new Greeted(command.whom, context.getSelf())); + getContext().getLog().info("Hello {}!", command.whom); + command.replyTo.tell(new Greeted(command.whom, getContext().getSelf())); return this; } } @@ -92,11 +90,10 @@ interface TypedSample { return Behaviors.setup(Parent::new); } - private final ActorContext context; private Map> children = new HashMap<>(); private Parent(ActorContext context) { - this.context = context; + super(context); } @Override @@ -110,8 +107,8 @@ interface TypedSample { private Behavior onDelegateToChild(DelegateToChild command) { ActorRef ref = children.get(command.name); if (ref == null) { - ref = context.spawn(Child.create(), command.name); - context.watchWith(ref, new ChildTerminated(command.name)); + ref = getContext().spawn(Child.create(), command.name); + getContext().watchWith(ref, new ChildTerminated(command.name)); children.put(command.name, ref); } ref.tell(command.message); diff --git a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/BehaviorSpec.scala b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/BehaviorSpec.scala index e0b775cbdd..84feb00bd4 100644 --- a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/BehaviorSpec.scala +++ b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/BehaviorSpec.scala @@ -441,7 +441,7 @@ class MutableScalaBehaviorSpec extends Messages with Become with Stoppable { def behv(monitor: ActorRef[Event]): Behavior[Command] = SBehaviors.setup[Command] { context => - new SAbstractBehavior[Command] { + new SAbstractBehavior[Command](context) { private var state: State = StateA override def onMessage(message: Command): Behavior[Command] = { diff --git a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/SupervisionSpec.scala b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/SupervisionSpec.scala index 03ee41154f..a7181d6ed2 100644 --- a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/SupervisionSpec.scala +++ b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/SupervisionSpec.scala @@ -22,6 +22,7 @@ import akka.actor.typed.SupervisorStrategy.Resume import akka.actor.typed.eventstream.EventStream import akka.actor.typed.scaladsl.Behaviors._ import akka.actor.typed.scaladsl.AbstractBehavior +import akka.actor.typed.scaladsl.ActorContext import akka.actor.typed.scaladsl.Behaviors import org.scalatest.Matchers import org.scalatest.WordSpec @@ -81,7 +82,8 @@ object SupervisionSpec { Behaviors.same } - class FailingConstructor(monitor: ActorRef[Event]) extends AbstractBehavior[Command] { + class FailingConstructor(context: ActorContext[Command], monitor: ActorRef[Event]) + extends AbstractBehavior[Command](context) { monitor ! Started throw new RuntimeException("simulated exc from constructor") with NoStackTrace @@ -263,7 +265,8 @@ class SupervisionSpec extends ScalaTestWithActorTestKit(""" class FailingConstructorTestSetup(failCount: Int) { val failCounter = new AtomicInteger(0) - class FailingConstructor(monitor: ActorRef[Event]) extends AbstractBehavior[Command] { + class FailingConstructor(context: ActorContext[Command], monitor: ActorRef[Event]) + extends AbstractBehavior[Command](context) { monitor ! Started if (failCounter.getAndIncrement() < failCount) { throw TestException("simulated exc from constructor") @@ -1023,7 +1026,7 @@ class SupervisionSpec extends ScalaTestWithActorTestKit(""" "fail when exception from AbstractBehavior constructor" in new FailingConstructorTestSetup(failCount = 1) { val probe = TestProbe[Event]("evt") - val behv = supervise(setup[Command](_ => new FailingConstructor(probe.ref))) + val behv = supervise(setup[Command](ctx => new FailingConstructor(ctx, probe.ref))) .onFailure[Exception](SupervisorStrategy.restart) LoggingEventFilter.error[ActorInitializationException].intercept { @@ -1271,6 +1274,55 @@ class SupervisionSpec extends ScalaTestWithActorTestKit(""" probe.expectMessage(Pong(2)) } + "not allow AbstractBehavior without setup" in { + val contextProbe = createTestProbe[ActorContext[String]] + spawn(Behaviors.setup[String] { context => + contextProbe.ref ! context + Behaviors.empty + }) + + val wrongContext = contextProbe.receiveMessage() + + intercept[IllegalArgumentException] { + Behaviors + .supervise(new AbstractBehavior[String](wrongContext) { + override def onMessage(msg: String): Behavior[String] = Behaviors.same + }) + .onFailure(SupervisorStrategy.restart) + } + + intercept[IllegalArgumentException] { + Behaviors.supervise(new AbstractBehavior[String](null) { + override def onMessage(msg: String): Behavior[String] = Behaviors.same + }) + } + } + + "detect AbstractBehavior with wrong ActorContext" in { + val contextProbe = createTestProbe[ActorContext[String]] + spawn(Behaviors.setup[String] { context => + contextProbe.ref ! context + Behaviors.empty + }) + + val wrongContext = contextProbe.receiveMessage() + + val wrong = spawn(Behaviors.setup[String](_ => + new AbstractBehavior[String](wrongContext) { + override def onMessage(msg: String): Behavior[String] = Behaviors.same + })) + + val probe = createTestProbe() + LoggingEventFilter + .error[IllegalStateException] + .withMessageContains("created with wrong ActorContext") + .withOccurrences(2) // twice because also logged for PostStop signal + .intercept { + wrong ! "boom" + } + probe.expectTerminated(wrong) + } + } val allStrategies = Seq( diff --git a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/WatchSpec.scala b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/WatchSpec.scala index e866d00ac6..83939dea24 100644 --- a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/WatchSpec.scala +++ b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/WatchSpec.scala @@ -27,9 +27,11 @@ object WatchSpec { case (_, Stop) => Behaviors.stopped } - val mutableTerminatorBehavior = new AbstractBehavior[Stop.type] { - override def onMessage(message: Stop.type) = message match { - case Stop => Behaviors.stopped + val mutableTerminatorBehavior = Behaviors.setup[Stop.type] { context => + new AbstractBehavior[Stop.type](context) { + override def onMessage(message: Stop.type) = message match { + case Stop => Behaviors.stopped + } } } diff --git a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/scaladsl/ActorLoggingSpec.scala b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/scaladsl/ActorLoggingSpec.scala index 833f662bed..ae87a1bc4a 100644 --- a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/scaladsl/ActorLoggingSpec.scala +++ b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/scaladsl/ActorLoggingSpec.scala @@ -38,7 +38,7 @@ object WhereTheBehaviorIsDefined { object BehaviorWhereTheLoggerIsUsed { def behavior: Behavior[String] = Behaviors.setup(ctx => new BehaviorWhereTheLoggerIsUsed(ctx)) } -class BehaviorWhereTheLoggerIsUsed(context: ActorContext[String]) extends AbstractBehavior[String] { +class BehaviorWhereTheLoggerIsUsed(context: ActorContext[String]) extends AbstractBehavior[String](context) { context.log.info("Starting up") override def onMessage(msg: String): Behavior[String] = { Behaviors.same diff --git a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/scaladsl/StashSpec.scala b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/scaladsl/StashSpec.scala index b695895f91..298b298ed4 100644 --- a/akka-actor-typed-tests/src/test/scala/akka/actor/typed/scaladsl/StashSpec.scala +++ b/akka-actor-typed-tests/src/test/scala/akka/actor/typed/scaladsl/StashSpec.scala @@ -131,7 +131,8 @@ object AbstractStashSpec { } } - class MutableStash(context: ActorContext[Command], buffer: StashBuffer[Command]) extends AbstractBehavior[Command] { + class MutableStash(context: ActorContext[Command], buffer: StashBuffer[Command]) + extends AbstractBehavior[Command](context) { private var stashing = false private var processed = Vector.empty[String] diff --git a/akka-actor-typed-tests/src/test/scala/docs/akka/typed/OOIntroSpec.scala b/akka-actor-typed-tests/src/test/scala/docs/akka/typed/OOIntroSpec.scala index 9976cba581..ca9673cd05 100644 --- a/akka-actor-typed-tests/src/test/scala/docs/akka/typed/OOIntroSpec.scala +++ b/akka-actor-typed-tests/src/test/scala/docs/akka/typed/OOIntroSpec.scala @@ -48,7 +48,7 @@ object OOIntroSpec { def apply(): Behavior[RoomCommand] = Behaviors.setup(context => new ChatRoomBehavior(context)) - class ChatRoomBehavior(context: ActorContext[RoomCommand]) extends AbstractBehavior[RoomCommand] { + class ChatRoomBehavior(context: ActorContext[RoomCommand]) extends AbstractBehavior[RoomCommand](context) { private var sessions: List[ActorRef[SessionCommand]] = List.empty override def onMessage(message: RoomCommand): Behavior[RoomCommand] = { @@ -56,7 +56,7 @@ object OOIntroSpec { case GetSession(screenName, client) => // create a child actor for further interaction with the client val ses = context.spawn( - new SessionBehavior(context.self, screenName, client), + SessionBehavior(context.self, screenName, client), name = URLEncoder.encode(screenName, StandardCharsets.UTF_8.name)) client ! SessionGranted(ses) sessions = ses :: sessions @@ -69,11 +69,20 @@ object OOIntroSpec { } } + object SessionBehavior { + def apply( + room: ActorRef[PublishSessionMessage], + screenName: String, + client: ActorRef[SessionEvent]): Behavior[SessionCommand] = + Behaviors.setup(ctx => new SessionBehavior(ctx, room, screenName, client)) + } + private class SessionBehavior( + context: ActorContext[SessionCommand], room: ActorRef[PublishSessionMessage], screenName: String, client: ActorRef[SessionEvent]) - extends AbstractBehavior[SessionCommand] { + extends AbstractBehavior[SessionCommand](context) { override def onMessage(msg: SessionCommand): Behavior[SessionCommand] = { msg match { diff --git a/akka-actor-typed-tests/src/test/scala/docs/akka/typed/StyleGuideDocExamples.scala b/akka-actor-typed-tests/src/test/scala/docs/akka/typed/StyleGuideDocExamples.scala index 9fca66bb1e..a21d1eacc2 100644 --- a/akka-actor-typed-tests/src/test/scala/docs/akka/typed/StyleGuideDocExamples.scala +++ b/akka-actor-typed-tests/src/test/scala/docs/akka/typed/StyleGuideDocExamples.scala @@ -77,7 +77,7 @@ object StyleGuideDocExamples { } } - class Counter(context: ActorContext[Counter.Command]) extends AbstractBehavior[Counter.Command] { + class Counter(context: ActorContext[Counter.Command]) extends AbstractBehavior[Counter.Command](context) { import Counter._ private var n = 0 diff --git a/akka-actor-typed-tests/src/test/scala/docs/akka/typed/fromclassic/TypedSample.scala b/akka-actor-typed-tests/src/test/scala/docs/akka/typed/fromclassic/TypedSample.scala index 4b37f6782e..961da8d24c 100644 --- a/akka-actor-typed-tests/src/test/scala/docs/akka/typed/fromclassic/TypedSample.scala +++ b/akka-actor-typed-tests/src/test/scala/docs/akka/typed/fromclassic/TypedSample.scala @@ -24,7 +24,7 @@ object TypedSample { Behaviors.setup(context => new HelloWorld(context)) } - class HelloWorld(context: ActorContext[HelloWorld.Greet]) extends AbstractBehavior[HelloWorld.Greet] { + class HelloWorld(context: ActorContext[HelloWorld.Greet]) extends AbstractBehavior[HelloWorld.Greet](context) { import HelloWorld._ override def onMessage(message: Greet): Behavior[Greet] = { diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/ActorSystem.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/ActorSystem.scala index ec98313ab2..15a2c9f23f 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/ActorSystem.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/ActorSystem.scala @@ -250,7 +250,7 @@ object ActorSystem { appConfig, cl, executionContext, - Some(PropsAdapter[Any](() => new GuardianStartupBehavior(guardianBehavior), guardianProps)), + Some(PropsAdapter[Any](() => GuardianStartupBehavior(guardianBehavior), guardianProps)), setup) system.start() diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/internal/Supervision.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/internal/Supervision.scala index 1feca5dd4a..e088a7279e 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/internal/Supervision.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/internal/Supervision.scala @@ -32,6 +32,12 @@ import org.slf4j.event.Level */ @InternalApi private[akka] object Supervisor { def apply[T, Thr <: Throwable: ClassTag](initialBehavior: Behavior[T], strategy: SupervisorStrategy): Behavior[T] = { + if (initialBehavior.isInstanceOf[scaladsl.AbstractBehavior[_]] || initialBehavior + .isInstanceOf[javadsl.AbstractBehavior[_]]) { + throw new IllegalArgumentException( + "The supervised Behavior must not be a AbstractBehavior instance directly," + + "because a different instance should be created when it is restarted. Wrap in Behaviors.setup.") + } strategy match { case r: RestartOrBackoff => diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/internal/adapter/GuardianStartupBehavior.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/internal/adapter/GuardianStartupBehavior.scala index 8dd7b59317..68b3ebebc4 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/internal/adapter/GuardianStartupBehavior.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/internal/adapter/GuardianStartupBehavior.scala @@ -8,17 +8,9 @@ import akka.actor.typed.Behavior import akka.actor.typed.BehaviorInterceptor import akka.actor.typed.Signal import akka.actor.typed.TypedActorContext -import akka.actor.typed.scaladsl.{ AbstractBehavior, Behaviors, StashOverflowException } +import akka.actor.typed.scaladsl.{ Behaviors, StashOverflowException } import akka.annotation.InternalApi -/** - * INTERNAL API - */ -@InternalApi -private[akka] object GuardianStartupBehavior { - case object Start -} - /** * INTERNAL API * @@ -27,29 +19,29 @@ private[akka] object GuardianStartupBehavior { * system, and we know that the bootstrap is completed and the actor context can be accessed. */ @InternalApi -private[akka] final class GuardianStartupBehavior[T](val guardianBehavior: Behavior[T]) extends AbstractBehavior[Any] { +private[akka] object GuardianStartupBehavior { + case object Start - import GuardianStartupBehavior.Start + private val StashCapacity = 1000 - private var tempStash: List[Any] = Nil + def apply[T](guardianBehavior: Behavior[T]): Behavior[Any] = + waitingForStart(guardianBehavior, Vector.empty) - override def onMessage(msg: Any): Behavior[Any] = - msg match { + private def waitingForStart[T](guardianBehavior: Behavior[T], tempStash: Vector[Any]): Behavior[Any] = { + Behaviors.receiveMessage { case Start => // ctx is not available initially so we cannot use it until here - Behaviors.withStash[Any](1000) { stash => - tempStash.reverse.foreach(stash.stash) - tempStash = null + Behaviors.withStash[Any](StashCapacity) { stash => + tempStash.foreach(stash.stash) stash.unstashAll(Behaviors.intercept(() => new GuardianStopInterceptor)(guardianBehavior.unsafeCast[Any])) } case other => - tempStash = other :: tempStash - if (tempStash.size > 1000) { + if (tempStash.size >= StashCapacity) { throw new StashOverflowException("Guardian Behavior did not receive start and buffer is full.") } - this + waitingForStart(guardianBehavior, tempStash :+ other) } - + } } /** diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/internal/routing/GroupRouterImpl.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/internal/routing/GroupRouterImpl.scala index b39e68e0fe..f5d19a11f6 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/internal/routing/GroupRouterImpl.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/internal/routing/GroupRouterImpl.scala @@ -43,28 +43,30 @@ private final class InitialGroupRouterImpl[T]( ctx: ActorContext[T], serviceKey: ServiceKey[T], routingLogic: RoutingLogic[T]) - extends AbstractBehavior[T] { + extends AbstractBehavior[T](ctx) { // casting trix to avoid having to wrap incoming messages - note that this will cause problems if intercepting // messages to a router - ctx.system.receptionist ! Receptionist.Subscribe(serviceKey, ctx.self.unsafeUpcast[Any].narrow[Receptionist.Listing]) + context.system.receptionist ! Receptionist.Subscribe( + serviceKey, + context.self.unsafeUpcast[Any].narrow[Receptionist.Listing]) - private val stash = StashBuffer[T](ctx, capacity = 10000) + private val stash = StashBuffer[T](context, capacity = 10000) def onMessage(msg: T): Behavior[T] = msg match { case serviceKey.Listing(update) => // we don't need to watch, because receptionist already does that routingLogic.routeesUpdated(update) - val activeGroupRouter = new GroupRouterImpl[T](ctx, serviceKey, routingLogic, update.isEmpty) + val activeGroupRouter = new GroupRouterImpl[T](context, serviceKey, routingLogic, update.isEmpty) stash.unstashAll(activeGroupRouter) case msg: T @unchecked => import akka.actor.typed.scaladsl.adapter._ if (!stash.isFull) stash.stash(msg) else - ctx.system.eventStream ! EventStream.Publish(Dropped( + context.system.eventStream ! EventStream.Publish(Dropped( msg, s"Stash is full in group router for [$serviceKey]", - ctx.self.toClassic)) // don't fail on full stash + context.self.toClassic)) // don't fail on full stash this } } @@ -78,13 +80,13 @@ private[akka] final class GroupRouterImpl[T]( serviceKey: ServiceKey[T], routingLogic: RoutingLogic[T], routeesInitiallyEmpty: Boolean) - extends AbstractBehavior[T] { + extends AbstractBehavior[T](ctx) { private var routeesEmpty = routeesInitiallyEmpty def onMessage(msg: T): Behavior[T] = msg match { case l @ serviceKey.Listing(update) => - ctx.log.debug("Update from receptionist: [{}]", l) + context.log.debug("Update from receptionist: [{}]", l) val routees = if (update.nonEmpty) update else @@ -98,8 +100,8 @@ private[akka] final class GroupRouterImpl[T]( import akka.actor.typed.scaladsl.adapter._ if (!routeesEmpty) routingLogic.selectRoutee() ! msg else - ctx.system.eventStream ! EventStream.Publish( - Dropped(msg, s"No routees in group router for [$serviceKey]", ctx.self.toClassic)) + context.system.eventStream ! EventStream.Publish( + Dropped(msg, s"No routees in group router for [$serviceKey]", context.self.toClassic)) this } } diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/internal/routing/PoolRouterImpl.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/internal/routing/PoolRouterImpl.scala index 94b1d7258a..2f8faad153 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/internal/routing/PoolRouterImpl.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/internal/routing/PoolRouterImpl.scala @@ -42,17 +42,17 @@ private final class PoolRouterImpl[T]( poolSize: Int, behaviorFactory: () => Behavior[T], logic: RoutingLogic[T]) - extends AbstractBehavior[T] { + extends AbstractBehavior[T](ctx) { (1 to poolSize).foreach { _ => - val child = ctx.spawnAnonymous(behaviorFactory()) - ctx.watch(child) + val child = context.spawnAnonymous(behaviorFactory()) + context.watch(child) child } onRouteesChanged() private def onRouteesChanged(): Unit = { - val children = ctx.children.toSet.asInstanceOf[Set[ActorRef[T]]] + val children = context.children.toSet.asInstanceOf[Set[ActorRef[T]]] logic.routeesUpdated(children) } @@ -67,12 +67,12 @@ private final class PoolRouterImpl[T]( // for the `Terminated` we receive for the first child. This means it is not certain that // there will be a log entry per child in those cases (it does not make sense to keep the // pool alive just to get the logging right when there are no routees available) - if (ctx.children.nonEmpty) { - ctx.log.debug("Pool child stopped [{}]", child.path) + if (context.children.nonEmpty) { + context.log.debug("Pool child stopped [{}]", child.path) onRouteesChanged() this } else { - ctx.log.info("Last pool child stopped, stopping pool [{}]", ctx.self.path) + context.log.info("Last pool child stopped, stopping pool [{}]", context.self.path) Behaviors.stopped } } diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/AbstractBehavior.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/AbstractBehavior.scala index 4ee7b6fccc..504457de0e 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/AbstractBehavior.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/javadsl/AbstractBehavior.scala @@ -16,14 +16,29 @@ import akka.util.OptionVal * alternative is provided by the factory methods in [[Behaviors]], for example * [[Behaviors.receiveMessage]]. * - * Instances of this behavior should be created via [[Behaviors.setup]] and if - * the [[ActorContext]] is needed it can be passed as a constructor parameter - * from the factory function. This is important because a new instance + * Instances of this behavior should be created via [[Behaviors.setup]] and + * the [[ActorContext]] should be passed as a constructor parameter + * from the factory function. This is important because a new instance * should be created when restart supervision is used. * + * When switching `Behavior` to another `AbstractBehavior` the original `ActorContext` + * can be used as the `context` parameter instead of wrapping in a new `Behaviors.setup`, + * but it wouldn't be wrong to use `context` from `Behaviors.setup` since that is the same + * `ActorContext` instance. + * + * It must not be created with an `ActorContext` of another actor, such as the parent actor. + * Such mistake will be detected at runtime and throw `IllegalStateException` when the + * first message is received. + * * @see [[Behaviors.setup]] */ -abstract class AbstractBehavior[T] extends ExtensibleBehavior[T] { +abstract class AbstractBehavior[T](context: ActorContext[T]) extends ExtensibleBehavior[T] { + + if (context eq null) + throw new IllegalArgumentException( + "context must not be null. Wrap in Behaviors.setup and " + + "pass the context to the constructor of AbstractBehavior.") + private var _receive: OptionVal[Receive[T]] = OptionVal.None private def receive: Receive[T] = _receive match { case OptionVal.None => @@ -33,13 +48,26 @@ abstract class AbstractBehavior[T] extends ExtensibleBehavior[T] { case OptionVal.Some(r) => r } - @throws(classOf[Exception]) - override final def receive(ctx: TypedActorContext[T], msg: T): Behavior[T] = - receive.receive(ctx, msg) + def getContext: ActorContext[T] = context + + private def checkRightContext(ctx: TypedActorContext[T]): Unit = + if (ctx.asJava ne context) + throw new IllegalStateException( + s"Actor [${ctx.asJava.getSelf}] of AbstractBehavior class " + + s"[${getClass.getName}] was created with wrong ActorContext [${context.asJava.getSelf}]. " + + "Wrap in Behaviors.setup and pass the context to the constructor of AbstractBehavior.") @throws(classOf[Exception]) - override final def receiveSignal(ctx: TypedActorContext[T], msg: Signal): Behavior[T] = + override final def receive(ctx: TypedActorContext[T], msg: T): Behavior[T] = { + checkRightContext(ctx) + receive.receive(ctx, msg) + } + + @throws(classOf[Exception]) + override final def receiveSignal(ctx: TypedActorContext[T], msg: Signal): Behavior[T] = { + checkRightContext(ctx) receive.receiveSignal(ctx, msg) + } /** * Implement this to define how messages and signals are processed. Use the diff --git a/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/AbstractBehavior.scala b/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/AbstractBehavior.scala index a8ad121de3..5902327ebe 100644 --- a/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/AbstractBehavior.scala +++ b/akka-actor-typed/src/main/scala/akka/actor/typed/scaladsl/AbstractBehavior.scala @@ -16,14 +16,28 @@ import akka.actor.typed.{ Behavior, ExtensibleBehavior, Signal, TypedActorContex * alternative is provided by the factory methods in [[Behaviors]], for example * [[Behaviors.receiveMessage]]. * - * Instances of this behavior should be created via [[Behaviors.setup]] and if - * the [[ActorContext]] is needed it can be passed as a constructor parameter + * Instances of this behavior should be created via [[Behaviors.setup]] and + * the [[ActorContext]] should be passed as a constructor parameter * from the factory function. This is important because a new instance * should be created when restart supervision is used. * + * When switching `Behavior` to another `AbstractBehavior` the original `ActorContext` + * can be used as the `context` parameter instead of wrapping in a new `Behaviors.setup`, + * but it wouldn't be wrong to use `context` from `Behaviors.setup` since that is the same + * `ActorContext` instance. + * + * It must not be created with an `ActorContext` of another actor, such as the parent actor. + * Such mistake will be detected at runtime and throw `IllegalStateException` when the + * first message is received. + * * @see [[Behaviors.setup]] */ -abstract class AbstractBehavior[T] extends ExtensibleBehavior[T] { +abstract class AbstractBehavior[T](protected val context: ActorContext[T]) extends ExtensibleBehavior[T] { + + if (context eq null) + throw new IllegalArgumentException( + "context must not be null. Wrap in Behaviors.setup and " + + "pass the context to the constructor of AbstractBehavior.") /** * Implement this method to process an incoming message and return the next behavior. @@ -55,11 +69,22 @@ abstract class AbstractBehavior[T] extends ExtensibleBehavior[T] { @throws(classOf[Exception]) def onSignal: PartialFunction[Signal, Behavior[T]] = PartialFunction.empty - @throws(classOf[Exception]) - override final def receive(ctx: TypedActorContext[T], msg: T): Behavior[T] = - onMessage(msg) + private def checkRightContext(ctx: TypedActorContext[T]): Unit = + if (ctx.asJava ne context) + throw new IllegalStateException( + s"Actor [${ctx.asJava.getSelf}] of AbstractBehavior class " + + s"[${getClass.getName}] was created with wrong ActorContext [${context.asJava.getSelf}]. " + + "Wrap in Behaviors.setup and pass the context to the constructor of AbstractBehavior.") @throws(classOf[Exception]) - override final def receiveSignal(ctx: TypedActorContext[T], msg: Signal): Behavior[T] = + override final def receive(ctx: TypedActorContext[T], msg: T): Behavior[T] = { + checkRightContext(ctx) + onMessage(msg) + } + + @throws(classOf[Exception]) + override final def receiveSignal(ctx: TypedActorContext[T], msg: Signal): Behavior[T] = { + checkRightContext(ctx) onSignal.applyOrElse(msg, { case _ => Behaviors.unhandled }: PartialFunction[Signal, Behavior[T]]) + } } diff --git a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/ShardingCompileOnlyTest.java b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/ShardingCompileOnlyTest.java index 3da4fbc069..4c05c577dc 100644 --- a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/ShardingCompileOnlyTest.java +++ b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/ShardingCompileOnlyTest.java @@ -49,12 +49,11 @@ interface ShardingCompileOnlyTest { return Behaviors.setup(context -> new Counter(context, entityId)); } - private final ActorContext context; private final String entityId; private int value = 0; private Counter(ActorContext context, String entityId) { - this.context = context; + super(context); this.entityId = entityId; } @@ -112,7 +111,6 @@ interface ShardingCompileOnlyTest { }); } - private final ActorContext context; private final ActorRef shard; private final String entityId; private int value = 0; @@ -121,7 +119,7 @@ interface ShardingCompileOnlyTest { ActorContext context, ActorRef shard, String entityId) { - this.context = context; + super(context); this.shard = shard; this.entityId = entityId; } @@ -148,7 +146,7 @@ interface ShardingCompileOnlyTest { private Behavior onIdle() { // after receive timeout - shard.tell(new ClusterSharding.Passivate<>(context.getSelf())); + shard.tell(new ClusterSharding.Passivate<>(getContext().getSelf())); return this; } diff --git a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/ShardingReplyCompileOnlyTest.java b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/ShardingReplyCompileOnlyTest.java index ff8de8a9e0..b2ca487fda 100644 --- a/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/ShardingReplyCompileOnlyTest.java +++ b/akka-cluster-sharding-typed/src/test/java/jdocs/akka/cluster/sharding/typed/ShardingReplyCompileOnlyTest.java @@ -59,6 +59,7 @@ interface ShardingReplyCompileOnlyTest { private int value = 0; private Counter(ActorContext context) { + super(context); this.sharding = ClusterSharding.get(context.getSystem()); } diff --git a/akka-cluster-typed/src/test/java/jdocs/akka/cluster/ddata/typed/javadsl/ReplicatorDocSample.java b/akka-cluster-typed/src/test/java/jdocs/akka/cluster/ddata/typed/javadsl/ReplicatorDocSample.java index 29c3838f9c..ba416cc5b7 100644 --- a/akka-cluster-typed/src/test/java/jdocs/akka/cluster/ddata/typed/javadsl/ReplicatorDocSample.java +++ b/akka-cluster-typed/src/test/java/jdocs/akka/cluster/ddata/typed/javadsl/ReplicatorDocSample.java @@ -81,7 +81,6 @@ interface ReplicatorDocSample { new Counter(ctx, replicatorAdapter, key))); } - private final ActorContext context; // adapter that turns the response messages from the replicator into our own protocol private final ReplicatorMessageAdapter replicatorAdapter; private final SelfUniqueAddress node; @@ -93,8 +92,8 @@ interface ReplicatorDocSample { ActorContext context, ReplicatorMessageAdapter replicatorAdapter, Key key) { + super(context); - this.context = context; this.replicatorAdapter = replicatorAdapter; this.key = key; diff --git a/akka-cluster-typed/src/test/java/jdocs/akka/cluster/typed/SingletonCompileOnlyTest.java b/akka-cluster-typed/src/test/java/jdocs/akka/cluster/typed/SingletonCompileOnlyTest.java index c3e01992e5..1eea0a6cf9 100644 --- a/akka-cluster-typed/src/test/java/jdocs/akka/cluster/typed/SingletonCompileOnlyTest.java +++ b/akka-cluster-typed/src/test/java/jdocs/akka/cluster/typed/SingletonCompileOnlyTest.java @@ -45,11 +45,10 @@ public interface SingletonCompileOnlyTest { return Behaviors.setup(Counter::new); } - private final ActorContext context; private int value = 0; private Counter(ActorContext context) { - this.context = context; + super(context); } @Override diff --git a/akka-docs/src/main/paradox/project/migration-guide-2.5.x-2.6.x.md b/akka-docs/src/main/paradox/project/migration-guide-2.5.x-2.6.x.md index 0d1d94ebbf..b9763af0df 100644 --- a/akka-docs/src/main/paradox/project/migration-guide-2.5.x-2.6.x.md +++ b/akka-docs/src/main/paradox/project/migration-guide-2.5.x-2.6.x.md @@ -542,7 +542,11 @@ made before finalizing the APIs. Compared to Akka 2.5.x the source incompatible * `akka.cluster.sharding.typed.scaladsl.Entity.apply` changed to use two parameter lists because the new `EntityContext.entityTypeKey` required additional type parameter that is inferred better with a secondary parameter list. -* `EventSourcedBehavior.withEnforcedReplies` signature changed. Command is not required to extend `ExpectingReply` anymore. `ExpectingReply` has been removed therefore. +* `EventSourcedBehavior.withEnforcedReplies` signature changed. Command is not required to extend `ExpectingReply` + anymore. `ExpectingReply` has therefore been removed. +* `ActorContext` is now a mandatory constructor parameter in `AbstractBehavior`. Create via `Behaviors.setup. + The reason is to encourage right usage and detect mistakes like not creating a new instance (via `setup`) + when the behavior is supervised and restarted. #### Akka Typed Stream API changes diff --git a/akka-docs/src/test/java/jdocs/actor/typed/BlockingActor.java b/akka-docs/src/test/java/jdocs/actor/typed/BlockingActor.java index f9a5a6eee4..1a72bf7c0d 100644 --- a/akka-docs/src/test/java/jdocs/actor/typed/BlockingActor.java +++ b/akka-docs/src/test/java/jdocs/actor/typed/BlockingActor.java @@ -13,7 +13,9 @@ public class BlockingActor extends AbstractBehavior { return Behaviors.setup(BlockingActor::new); } - private BlockingActor(ActorContext context) {} + private BlockingActor(ActorContext context) { + super(context); + } @Override public Receive createReceive() { diff --git a/akka-docs/src/test/java/jdocs/actor/typed/BlockingDispatcherTest.java b/akka-docs/src/test/java/jdocs/actor/typed/BlockingDispatcherTest.java index 1d84ec9aab..1cb637a860 100644 --- a/akka-docs/src/test/java/jdocs/actor/typed/BlockingDispatcherTest.java +++ b/akka-docs/src/test/java/jdocs/actor/typed/BlockingDispatcherTest.java @@ -14,7 +14,7 @@ public class BlockingDispatcherTest { Behaviors.setup( context -> { ActorRef actor1 = context.spawn(BlockingActor.create(), "BlockingActor"); - ActorRef actor2 = context.spawn(new PrintActor(), "PrintActor"); + ActorRef actor2 = context.spawn(PrintActor.create(), "PrintActor"); for (int i = 0; i < 100; i++) { actor1.tell(i); diff --git a/akka-docs/src/test/java/jdocs/actor/typed/DispatcherDocTest.java b/akka-docs/src/test/java/jdocs/actor/typed/DispatcherDocTest.java index 430e2e7233..d2721a0ba1 100644 --- a/akka-docs/src/test/java/jdocs/actor/typed/DispatcherDocTest.java +++ b/akka-docs/src/test/java/jdocs/actor/typed/DispatcherDocTest.java @@ -21,7 +21,7 @@ public class DispatcherDocTest { // #defining-dispatcher-in-code ActorRef myActor = context.spawn( - new PrintActor(), "PrintActor", DispatcherSelector.fromConfig("my-dispatcher")); + PrintActor.create(), "PrintActor", DispatcherSelector.fromConfig("my-dispatcher")); // #defining-dispatcher-in-code } @@ -29,7 +29,7 @@ public class DispatcherDocTest { // #defining-fixed-pool-size-dispatcher ActorRef myActor = context.spawn( - new PrintActor(), + PrintActor.create(), "PrintActor", DispatcherSelector.fromConfig("blocking-io-dispatcher")); // #defining-fixed-pool-size-dispatcher @@ -39,7 +39,9 @@ public class DispatcherDocTest { // #defining-pinned-dispatcher ActorRef myActor = context.spawn( - new PrintActor(), "PrintActor", DispatcherSelector.fromConfig("my-pinned-dispatcher")); + PrintActor.create(), + "PrintActor", + DispatcherSelector.fromConfig("my-pinned-dispatcher")); // #defining-pinned-dispatcher } diff --git a/akka-docs/src/test/java/jdocs/actor/typed/PrintActor.java b/akka-docs/src/test/java/jdocs/actor/typed/PrintActor.java index 5f87efbcf6..bffb904793 100644 --- a/akka-docs/src/test/java/jdocs/actor/typed/PrintActor.java +++ b/akka-docs/src/test/java/jdocs/actor/typed/PrintActor.java @@ -11,7 +11,11 @@ import akka.actor.typed.javadsl.*; class PrintActor extends AbstractBehavior { public static Behavior create() { - return Behaviors.setup(context -> new PrintActor()); + return Behaviors.setup(PrintActor::new); + } + + private PrintActor(ActorContext context) { + super(context); } @Override diff --git a/akka-docs/src/test/java/jdocs/actor/typed/SeparateDispatcherCompletionStageActor.java b/akka-docs/src/test/java/jdocs/actor/typed/SeparateDispatcherCompletionStageActor.java index 23cf10850c..24ac269839 100644 --- a/akka-docs/src/test/java/jdocs/actor/typed/SeparateDispatcherCompletionStageActor.java +++ b/akka-docs/src/test/java/jdocs/actor/typed/SeparateDispatcherCompletionStageActor.java @@ -19,6 +19,7 @@ class SeparateDispatcherFutureActor extends AbstractBehavior { } private SeparateDispatcherFutureActor(ActorContext context) { + super(context); ec = context .getSystem() diff --git a/akka-docs/src/test/java/jdocs/actor/typed/SharedMutableStateDocTest.java b/akka-docs/src/test/java/jdocs/actor/typed/SharedMutableStateDocTest.java index 86341ec8d1..f45fc59a9b 100644 --- a/akka-docs/src/test/java/jdocs/actor/typed/SharedMutableStateDocTest.java +++ b/akka-docs/src/test/java/jdocs/actor/typed/SharedMutableStateDocTest.java @@ -52,13 +52,11 @@ interface SharedMutableStateDocTest { } } - private final ActorContext context; - private String state = ""; private Set mySet = new HashSet<>(); public MyActor(ActorContext context) { - this.context = context; + super(context); } @Override @@ -96,12 +94,13 @@ interface SharedMutableStateDocTest { // Turn the future result into a message that is sent to // self when future completes CompletableFuture futureResult = expensiveCalculation(); - context.pipeToSelf( - futureResult, - (result, failure) -> { - if (result != null) return new UpdateState(result); - else throw new RuntimeException(failure); - }); + getContext() + .pipeToSelf( + futureResult, + (result, failure) -> { + if (result != null) return new UpdateState(result); + else throw new RuntimeException(failure); + }); // Another example of incorrect approach // mutating actor state from ask future callback @@ -110,7 +109,7 @@ interface SharedMutableStateDocTest { message.otherActor, Query::new, Duration.ofSeconds(3), - context.getSystem().scheduler()); + getContext().getSystem().scheduler()); response.whenComplete( (result, failure) -> { if (result != null) state = "new state: " + result; @@ -118,15 +117,16 @@ interface SharedMutableStateDocTest { // use context.ask instead, turns the completion // into a message sent to self - context.ask( - String.class, - message.otherActor, - Duration.ofSeconds(3), - Query::new, - (result, failure) -> { - if (result != null) return new UpdateState(result); - else throw new RuntimeException(failure); - }); + getContext() + .ask( + String.class, + message.otherActor, + Duration.ofSeconds(3), + Query::new, + (result, failure) -> { + if (result != null) return new UpdateState(result); + else throw new RuntimeException(failure); + }); return this; } diff --git a/akka-docs/src/test/java/jdocs/persistence/ResumableProjectionExample.java b/akka-docs/src/test/java/jdocs/persistence/ResumableProjectionExample.java index c30e49a5d3..7c40f9a160 100644 --- a/akka-docs/src/test/java/jdocs/persistence/ResumableProjectionExample.java +++ b/akka-docs/src/test/java/jdocs/persistence/ResumableProjectionExample.java @@ -9,6 +9,7 @@ import akka.actor.typed.ActorRef; import akka.actor.typed.ActorSystem; import akka.actor.typed.Behavior; import akka.actor.typed.javadsl.AbstractBehavior; +import akka.actor.typed.javadsl.ActorContext; import akka.actor.typed.javadsl.Adapter; import akka.actor.typed.javadsl.Behaviors; import akka.actor.typed.javadsl.Receive; @@ -79,14 +80,15 @@ public interface ResumableProjectionExample { } public static Behavior create(String id, ExampleStore store) { - return Behaviors.setup(context -> new TheOneWhoWritesToQueryJournal(store)); + return Behaviors.setup(context -> new TheOneWhoWritesToQueryJournal(context, store)); } private final ExampleStore store; private ComplexState state = new ComplexState(); - private TheOneWhoWritesToQueryJournal(ExampleStore store) { + private TheOneWhoWritesToQueryJournal(ActorContext context, ExampleStore store) { + super(context); this.store = store; } diff --git a/akka-docs/src/test/java/jdocs/typed/tutorial_1/ActorHierarchyExperiments.java b/akka-docs/src/test/java/jdocs/typed/tutorial_1/ActorHierarchyExperiments.java index 1a6a3478ee..051ff5658d 100644 --- a/akka-docs/src/test/java/jdocs/typed/tutorial_1/ActorHierarchyExperiments.java +++ b/akka-docs/src/test/java/jdocs/typed/tutorial_1/ActorHierarchyExperiments.java @@ -28,10 +28,8 @@ class PrintMyActorRefActor extends AbstractBehavior { return Behaviors.setup(PrintMyActorRefActor::new); } - private final ActorContext context; - private PrintMyActorRefActor(ActorContext context) { - this.context = context; + super(context); } @Override @@ -40,7 +38,7 @@ class PrintMyActorRefActor extends AbstractBehavior { } private Behavior printIt() { - ActorRef secondRef = context.spawn(Behaviors.empty(), "second-actor"); + ActorRef secondRef = getContext().spawn(Behaviors.empty(), "second-actor"); System.out.println("Second: " + secondRef); return this; } @@ -51,10 +49,11 @@ class PrintMyActorRefActor extends AbstractBehavior { class StartStopActor1 extends AbstractBehavior { static Behavior create() { - return Behaviors.setup(context -> new StartStopActor1()); + return Behaviors.setup(StartStopActor1::new); } - private StartStopActor1() { + private StartStopActor1(ActorContext context) { + super(context); System.out.println("first started"); } @@ -75,10 +74,11 @@ class StartStopActor1 extends AbstractBehavior { class StartStopActor2 extends AbstractBehavior { static Behavior create() { - return Behaviors.setup(context -> new StartStopActor2()); + return Behaviors.setup(StartStopActor2::new); } - private StartStopActor2() { + private StartStopActor2(ActorContext context) { + super(context); System.out.println("second started"); } @@ -104,6 +104,7 @@ class SupervisingActor extends AbstractBehavior { private final ActorRef child; private SupervisingActor(ActorContext context) { + super(context); child = context.spawn( Behaviors.supervise(SupervisedActor.create()).onFailure(SupervisorStrategy.restart()), @@ -124,10 +125,11 @@ class SupervisingActor extends AbstractBehavior { class SupervisedActor extends AbstractBehavior { static Behavior create() { - return Behaviors.setup(context -> new SupervisedActor()); + return Behaviors.setup(SupervisedActor::new); } - private SupervisedActor() { + private SupervisedActor(ActorContext context) { + super(context); System.out.println("supervised actor started"); } @@ -165,10 +167,8 @@ class Main extends AbstractBehavior { return Behaviors.setup(Main::new); } - private final ActorContext context; - private Main(ActorContext context) { - this.context = context; + super(context); } @Override @@ -177,7 +177,7 @@ class Main extends AbstractBehavior { } private Behavior start() { - ActorRef firstRef = context.spawn(PrintMyActorRefActor.create(), "first-actor"); + ActorRef firstRef = getContext().spawn(PrintMyActorRefActor.create(), "first-actor"); System.out.println("First: " + firstRef); firstRef.tell("printit"); diff --git a/akka-docs/src/test/java/jdocs/typed/tutorial_2/IotSupervisor.java b/akka-docs/src/test/java/jdocs/typed/tutorial_2/IotSupervisor.java index c2f1f992d9..0f38d983d1 100644 --- a/akka-docs/src/test/java/jdocs/typed/tutorial_2/IotSupervisor.java +++ b/akka-docs/src/test/java/jdocs/typed/tutorial_2/IotSupervisor.java @@ -18,10 +18,8 @@ public class IotSupervisor extends AbstractBehavior { return Behaviors.setup(IotSupervisor::new); } - private final ActorContext context; - - public IotSupervisor(ActorContext context) { - this.context = context; + private IotSupervisor(ActorContext context) { + super(context); context.getLog().info("IoT Application started"); } @@ -32,7 +30,7 @@ public class IotSupervisor extends AbstractBehavior { } private IotSupervisor onPostStop() { - context.getLog().info("IoT Application stopped"); + getContext().getLog().info("IoT Application stopped"); return this; } } diff --git a/akka-docs/src/test/java/jdocs/typed/tutorial_3/Device.java b/akka-docs/src/test/java/jdocs/typed/tutorial_3/Device.java index 7b372ee6c2..1b73c6967b 100644 --- a/akka-docs/src/test/java/jdocs/typed/tutorial_3/Device.java +++ b/akka-docs/src/test/java/jdocs/typed/tutorial_3/Device.java @@ -66,14 +66,13 @@ public class Device extends AbstractBehavior { return Behaviors.setup(context -> new Device(context, groupId, deviceId)); } - private final ActorContext context; private final String groupId; private final String deviceId; private Optional lastTemperatureReading = Optional.empty(); private Device(ActorContext context, String groupId, String deviceId) { - this.context = context; + super(context); this.groupId = groupId; this.deviceId = deviceId; @@ -90,7 +89,7 @@ public class Device extends AbstractBehavior { } private Behavior onRecordTemperature(RecordTemperature r) { - context.getLog().info("Recorded temperature reading {} with {}", r.value, r.requestId); + getContext().getLog().info("Recorded temperature reading {} with {}", r.value, r.requestId); lastTemperatureReading = Optional.of(r.value); r.replyTo.tell(new TemperatureRecorded(r.requestId)); return this; @@ -102,7 +101,7 @@ public class Device extends AbstractBehavior { } private Behavior onPostStop() { - context.getLog().info("Device actor {}-{} stopped", groupId, deviceId); + getContext().getLog().info("Device actor {}-{} stopped", groupId, deviceId); return Behaviors.stopped(); } } diff --git a/akka-docs/src/test/java/jdocs/typed/tutorial_3/inprogress2/Device.java b/akka-docs/src/test/java/jdocs/typed/tutorial_3/inprogress2/Device.java index ffac718347..0ceed0b187 100644 --- a/akka-docs/src/test/java/jdocs/typed/tutorial_3/inprogress2/Device.java +++ b/akka-docs/src/test/java/jdocs/typed/tutorial_3/inprogress2/Device.java @@ -45,14 +45,13 @@ public class Device extends AbstractBehavior { return Behaviors.setup(context -> new Device(context, groupId, deviceId)); } - private final ActorContext context; private final String groupId; private final String deviceId; private Optional lastTemperatureReading = Optional.empty(); private Device(ActorContext context, String groupId, String deviceId) { - this.context = context; + super(context); this.groupId = groupId; this.deviceId = deviceId; @@ -73,7 +72,7 @@ public class Device extends AbstractBehavior { } private Device onPostStop() { - context.getLog().info("Device actor {}-{} stopped", groupId, deviceId); + getContext().getLog().info("Device actor {}-{} stopped", groupId, deviceId); return this; } // #read-protocol-2 diff --git a/akka-docs/src/test/java/jdocs/typed/tutorial_4/Device.java b/akka-docs/src/test/java/jdocs/typed/tutorial_4/Device.java index 59abd8bc6b..55971e7b13 100644 --- a/akka-docs/src/test/java/jdocs/typed/tutorial_4/Device.java +++ b/akka-docs/src/test/java/jdocs/typed/tutorial_4/Device.java @@ -70,14 +70,13 @@ public class Device extends AbstractBehavior { return Behaviors.setup(context -> new Device(context, groupId, deviceId)); } - private final ActorContext context; private final String groupId; private final String deviceId; private Optional lastTemperatureReading = Optional.empty(); private Device(ActorContext context, String groupId, String deviceId) { - this.context = context; + super(context); this.groupId = groupId; this.deviceId = deviceId; @@ -95,7 +94,7 @@ public class Device extends AbstractBehavior { } private Behavior onRecordTemperature(RecordTemperature r) { - context.getLog().info("Recorded temperature reading {} with {}", r.value, r.requestId); + getContext().getLog().info("Recorded temperature reading {} with {}", r.value, r.requestId); lastTemperatureReading = Optional.of(r.value); r.replyTo.tell(new TemperatureRecorded(r.requestId)); return this; @@ -107,7 +106,7 @@ public class Device extends AbstractBehavior { } private Behavior onPostStop() { - context.getLog().info("Device actor {}-{} stopped", groupId, deviceId); + getContext().getLog().info("Device actor {}-{} stopped", groupId, deviceId); return Behaviors.stopped(); } } diff --git a/akka-docs/src/test/java/jdocs/typed/tutorial_4/DeviceGroup.java b/akka-docs/src/test/java/jdocs/typed/tutorial_4/DeviceGroup.java index db2ceed759..a213260a52 100644 --- a/akka-docs/src/test/java/jdocs/typed/tutorial_4/DeviceGroup.java +++ b/akka-docs/src/test/java/jdocs/typed/tutorial_4/DeviceGroup.java @@ -40,12 +40,11 @@ public class DeviceGroup extends AbstractBehavior { return Behaviors.setup(context -> new DeviceGroup(context, groupId)); } - private final ActorContext context; private final String groupId; private final Map> deviceIdToActor = new HashMap<>(); private DeviceGroup(ActorContext context, String groupId) { - this.context = context; + super(context); this.groupId = groupId; context.getLog().info("DeviceGroup {} started", groupId); } @@ -56,18 +55,19 @@ public class DeviceGroup extends AbstractBehavior { if (deviceActor != null) { trackMsg.replyTo.tell(new DeviceManager.DeviceRegistered(deviceActor)); } else { - context.getLog().info("Creating device actor for {}", trackMsg.deviceId); + getContext().getLog().info("Creating device actor for {}", trackMsg.deviceId); deviceActor = - context.spawn(Device.create(groupId, trackMsg.deviceId), "device-" + trackMsg.deviceId); + getContext() + .spawn(Device.create(groupId, trackMsg.deviceId), "device-" + trackMsg.deviceId); // #device-group-register - context.watchWith( - deviceActor, new DeviceTerminated(deviceActor, groupId, trackMsg.deviceId)); + getContext() + .watchWith(deviceActor, new DeviceTerminated(deviceActor, groupId, trackMsg.deviceId)); // #device-group-register deviceIdToActor.put(trackMsg.deviceId, deviceActor); trackMsg.replyTo.tell(new DeviceManager.DeviceRegistered(deviceActor)); } } else { - context + getContext() .getLog() .warn( "Ignoring TrackDevice request for {}. This actor is responsible for {}.", @@ -87,7 +87,7 @@ public class DeviceGroup extends AbstractBehavior { // #device-group-remove private DeviceGroup onTerminated(DeviceTerminated t) { - context.getLog().info("Device actor for {} has been terminated", t.deviceId); + getContext().getLog().info("Device actor for {} has been terminated", t.deviceId); deviceIdToActor.remove(t.deviceId); return this; } @@ -111,7 +111,7 @@ public class DeviceGroup extends AbstractBehavior { } private DeviceGroup onPostStop() { - context.getLog().info("DeviceGroup {} stopped", groupId); + getContext().getLog().info("DeviceGroup {} stopped", groupId); return this; } } diff --git a/akka-docs/src/test/java/jdocs/typed/tutorial_4/DeviceManager.java b/akka-docs/src/test/java/jdocs/typed/tutorial_4/DeviceManager.java index d85dc27b50..0899191e21 100644 --- a/akka-docs/src/test/java/jdocs/typed/tutorial_4/DeviceManager.java +++ b/akka-docs/src/test/java/jdocs/typed/tutorial_4/DeviceManager.java @@ -82,11 +82,10 @@ public class DeviceManager extends AbstractBehavior { return Behaviors.setup(DeviceManager::new); } - private final ActorContext context; private final Map> groupIdToActor = new HashMap<>(); private DeviceManager(ActorContext context) { - this.context = context; + super(context); context.getLog().info("DeviceManager started"); } @@ -96,10 +95,10 @@ public class DeviceManager extends AbstractBehavior { if (ref != null) { ref.tell(trackMsg); } else { - context.getLog().info("Creating device group actor for {}", groupId); + getContext().getLog().info("Creating device group actor for {}", groupId); ActorRef groupActor = - context.spawn(DeviceGroup.create(groupId), "group-" + groupId); - context.watchWith(groupActor, new DeviceGroupTerminated(groupId)); + getContext().spawn(DeviceGroup.create(groupId), "group-" + groupId); + getContext().watchWith(groupActor, new DeviceGroupTerminated(groupId)); groupActor.tell(trackMsg); groupIdToActor.put(groupId, groupActor); } @@ -117,7 +116,7 @@ public class DeviceManager extends AbstractBehavior { } private DeviceManager onTerminated(DeviceGroupTerminated t) { - context.getLog().info("Device group actor for {} has been terminated", t.groupId); + getContext().getLog().info("Device group actor for {} has been terminated", t.groupId); groupIdToActor.remove(t.groupId); return this; } @@ -132,7 +131,7 @@ public class DeviceManager extends AbstractBehavior { } private DeviceManager onPostStop() { - context.getLog().info("DeviceManager stopped"); + getContext().getLog().info("DeviceManager stopped"); return this; } // #device-registration-msgs diff --git a/akka-docs/src/test/java/jdocs/typed/tutorial_5/Device.java b/akka-docs/src/test/java/jdocs/typed/tutorial_5/Device.java index dcd385403e..975af55d48 100644 --- a/akka-docs/src/test/java/jdocs/typed/tutorial_5/Device.java +++ b/akka-docs/src/test/java/jdocs/typed/tutorial_5/Device.java @@ -68,14 +68,13 @@ public class Device extends AbstractBehavior { return Behaviors.setup(context -> new Device(context, groupId, deviceId)); } - private final ActorContext context; private final String groupId; private final String deviceId; private Optional lastTemperatureReading = Optional.empty(); private Device(ActorContext context, String groupId, String deviceId) { - this.context = context; + super(context); this.groupId = groupId; this.deviceId = deviceId; @@ -93,7 +92,7 @@ public class Device extends AbstractBehavior { } private Behavior onRecordTemperature(RecordTemperature r) { - context.getLog().info("Recorded temperature reading {} with {}", r.value, r.requestId); + getContext().getLog().info("Recorded temperature reading {} with {}", r.value, r.requestId); lastTemperatureReading = Optional.of(r.value); r.replyTo.tell(new TemperatureRecorded(r.requestId)); return this; @@ -105,7 +104,7 @@ public class Device extends AbstractBehavior { } private Behavior onPostStop() { - context.getLog().info("Device actor {}-{} stopped", groupId, deviceId); + getContext().getLog().info("Device actor {}-{} stopped", groupId, deviceId); return Behaviors.stopped(); } } diff --git a/akka-docs/src/test/java/jdocs/typed/tutorial_5/DeviceGroup.java b/akka-docs/src/test/java/jdocs/typed/tutorial_5/DeviceGroup.java index ae1be3dfa3..5d68622f7a 100644 --- a/akka-docs/src/test/java/jdocs/typed/tutorial_5/DeviceGroup.java +++ b/akka-docs/src/test/java/jdocs/typed/tutorial_5/DeviceGroup.java @@ -37,12 +37,11 @@ public class DeviceGroup extends AbstractBehavior { return Behaviors.setup(context -> new DeviceGroup(context, groupId)); } - private final ActorContext context; private final String groupId; private final Map> deviceIdToActor = new HashMap<>(); private DeviceGroup(ActorContext context, String groupId) { - this.context = context; + super(context); this.groupId = groupId; context.getLog().info("DeviceGroup {} started", groupId); } @@ -54,16 +53,17 @@ public class DeviceGroup extends AbstractBehavior { if (deviceActor != null) { trackMsg.replyTo.tell(new DeviceManager.DeviceRegistered(deviceActor)); } else { - context.getLog().info("Creating device actor for {}", trackMsg.deviceId); + getContext().getLog().info("Creating device actor for {}", trackMsg.deviceId); deviceActor = - context.spawn(Device.create(groupId, trackMsg.deviceId), "device-" + trackMsg.deviceId); - context.watchWith( - deviceActor, new DeviceTerminated(deviceActor, groupId, trackMsg.deviceId)); + getContext() + .spawn(Device.create(groupId, trackMsg.deviceId), "device-" + trackMsg.deviceId); + getContext() + .watchWith(deviceActor, new DeviceTerminated(deviceActor, groupId, trackMsg.deviceId)); deviceIdToActor.put(trackMsg.deviceId, deviceActor); trackMsg.replyTo.tell(new DeviceManager.DeviceRegistered(deviceActor)); } } else { - context + getContext() .getLog() .warn( "Ignoring TrackDevice request for {}. This actor is responsible for {}.", @@ -79,13 +79,13 @@ public class DeviceGroup extends AbstractBehavior { } private DeviceGroup onTerminated(DeviceTerminated t) { - context.getLog().info("Device actor for {} has been terminated", t.deviceId); + getContext().getLog().info("Device actor for {} has been terminated", t.deviceId); deviceIdToActor.remove(t.deviceId); return this; } private DeviceGroup onPostStop() { - context.getLog().info("DeviceGroup {} stopped", groupId); + getContext().getLog().info("DeviceGroup {} stopped", groupId); return this; } @@ -101,9 +101,10 @@ public class DeviceGroup extends AbstractBehavior { // applications! Map> deviceIdToActorCopy = new HashMap<>(this.deviceIdToActor); - context.spawnAnonymous( - DeviceGroupQuery.create( - deviceIdToActorCopy, r.requestId, r.replyTo, Duration.ofSeconds(3))); + getContext() + .spawnAnonymous( + DeviceGroupQuery.create( + deviceIdToActorCopy, r.requestId, r.replyTo, Duration.ofSeconds(3))); return this; } diff --git a/akka-docs/src/test/java/jdocs/typed/tutorial_5/DeviceGroupQuery.java b/akka-docs/src/test/java/jdocs/typed/tutorial_5/DeviceGroupQuery.java index 48552da852..53d1b48bdf 100644 --- a/akka-docs/src/test/java/jdocs/typed/tutorial_5/DeviceGroupQuery.java +++ b/akka-docs/src/test/java/jdocs/typed/tutorial_5/DeviceGroupQuery.java @@ -74,6 +74,7 @@ public class DeviceGroupQuery extends AbstractBehavior Duration timeout, ActorContext context, TimerScheduler timers) { + super(context); this.requestId = requestId; this.requester = requester; diff --git a/akka-docs/src/test/java/jdocs/typed/tutorial_5/DeviceManager.java b/akka-docs/src/test/java/jdocs/typed/tutorial_5/DeviceManager.java index b6713024d7..ba568f91d2 100644 --- a/akka-docs/src/test/java/jdocs/typed/tutorial_5/DeviceManager.java +++ b/akka-docs/src/test/java/jdocs/typed/tutorial_5/DeviceManager.java @@ -144,7 +144,6 @@ public class DeviceManager extends AbstractBehavior { } } - private final ActorContext context; private final Map> groupIdToActor = new HashMap<>(); public static Behavior create() { @@ -152,7 +151,7 @@ public class DeviceManager extends AbstractBehavior { } private DeviceManager(ActorContext context) { - this.context = context; + super(context); context.getLog().info("DeviceManager started"); } @@ -162,10 +161,10 @@ public class DeviceManager extends AbstractBehavior { if (ref != null) { ref.tell(trackMsg); } else { - context.getLog().info("Creating device group actor for {}", groupId); + getContext().getLog().info("Creating device group actor for {}", groupId); ActorRef groupActor = - context.spawn(DeviceGroup.create(groupId), "group-" + groupId); - context.watchWith(groupActor, new DeviceGroupTerminated(groupId)); + getContext().spawn(DeviceGroup.create(groupId), "group-" + groupId); + getContext().watchWith(groupActor, new DeviceGroupTerminated(groupId)); groupActor.tell(trackMsg); groupIdToActor.put(groupId, groupActor); } @@ -193,7 +192,7 @@ public class DeviceManager extends AbstractBehavior { } private DeviceManager onTerminated(DeviceGroupTerminated t) { - context.getLog().info("Device group actor for {} has been terminated", t.groupId); + getContext().getLog().info("Device group actor for {} has been terminated", t.groupId); groupIdToActor.remove(t.groupId); return this; } @@ -209,7 +208,7 @@ public class DeviceManager extends AbstractBehavior { } private DeviceManager onPostStop() { - context.getLog().info("DeviceManager stopped"); + getContext().getLog().info("DeviceManager stopped"); return this; } } diff --git a/akka-docs/src/test/scala/docs/actor/typed/SharedMutableStateDocSpec.scala b/akka-docs/src/test/scala/docs/actor/typed/SharedMutableStateDocSpec.scala index 7c5dd7c548..009561f7bb 100644 --- a/akka-docs/src/test/scala/docs/actor/typed/SharedMutableStateDocSpec.scala +++ b/akka-docs/src/test/scala/docs/actor/typed/SharedMutableStateDocSpec.scala @@ -29,7 +29,7 @@ class SharedMutableStateDocSpec { } } //#mutable-state - class MyActor(context: ActorContext[MyActor.Command]) extends AbstractBehavior[MyActor.Command] { + class MyActor(context: ActorContext[MyActor.Command]) extends AbstractBehavior[MyActor.Command](context) { import MyActor._ var state = "" diff --git a/akka-docs/src/test/scala/typed/tutorial_1/ActorHierarchyExperiments.scala b/akka-docs/src/test/scala/typed/tutorial_1/ActorHierarchyExperiments.scala index d3c9036b14..16224e00da 100644 --- a/akka-docs/src/test/scala/typed/tutorial_1/ActorHierarchyExperiments.scala +++ b/akka-docs/src/test/scala/typed/tutorial_1/ActorHierarchyExperiments.scala @@ -23,7 +23,7 @@ object PrintMyActorRefActor { Behaviors.setup(context => new PrintMyActorRefActor(context)) } -class PrintMyActorRefActor(context: ActorContext[String]) extends AbstractBehavior[String] { +class PrintMyActorRefActor(context: ActorContext[String]) extends AbstractBehavior[String](context) { override def onMessage(msg: String): Behavior[String] = msg match { @@ -41,7 +41,7 @@ object StartStopActor1 { Behaviors.setup(context => new StartStopActor1(context)) } -class StartStopActor1(context: ActorContext[String]) extends AbstractBehavior[String] { +class StartStopActor1(context: ActorContext[String]) extends AbstractBehavior[String](context) { println("first started") context.spawn(StartStopActor2(), "second") @@ -60,10 +60,10 @@ class StartStopActor1(context: ActorContext[String]) extends AbstractBehavior[St object StartStopActor2 { def apply(): Behavior[String] = - Behaviors.setup(_ => new StartStopActor2) + Behaviors.setup(new StartStopActor2(_)) } -class StartStopActor2 extends AbstractBehavior[String] { +class StartStopActor2(context: ActorContext[String]) extends AbstractBehavior[String](context) { println("second started") override def onMessage(msg: String): Behavior[String] = { @@ -86,7 +86,7 @@ object SupervisingActor { Behaviors.setup(context => new SupervisingActor(context)) } -class SupervisingActor(context: ActorContext[String]) extends AbstractBehavior[String] { +class SupervisingActor(context: ActorContext[String]) extends AbstractBehavior[String](context) { private val child = context.spawn( Behaviors.supervise(SupervisedActor()).onFailure(SupervisorStrategy.restart), name = "supervised-actor") @@ -101,10 +101,10 @@ class SupervisingActor(context: ActorContext[String]) extends AbstractBehavior[S object SupervisedActor { def apply(): Behavior[String] = - Behaviors.setup(_ => new SupervisedActor) + Behaviors.setup(context => new SupervisedActor(context)) } -class SupervisedActor extends AbstractBehavior[String] { +class SupervisedActor(context: ActorContext[String]) extends AbstractBehavior[String](context) { println("supervised actor started") override def onMessage(msg: String): Behavior[String] = @@ -134,7 +134,7 @@ object Main { } -class Main(context: ActorContext[String]) extends AbstractBehavior[String] { +class Main(context: ActorContext[String]) extends AbstractBehavior[String](context) { override def onMessage(msg: String): Behavior[String] = msg match { case "start" => diff --git a/akka-docs/src/test/scala/typed/tutorial_2/IotSupervisor.scala b/akka-docs/src/test/scala/typed/tutorial_2/IotSupervisor.scala index 0506149f7f..a65dcc82b8 100644 --- a/akka-docs/src/test/scala/typed/tutorial_2/IotSupervisor.scala +++ b/akka-docs/src/test/scala/typed/tutorial_2/IotSupervisor.scala @@ -17,7 +17,7 @@ object IotSupervisor { Behaviors.setup[Nothing](context => new IotSupervisor(context)) } -class IotSupervisor(context: ActorContext[Nothing]) extends AbstractBehavior[Nothing] { +class IotSupervisor(context: ActorContext[Nothing]) extends AbstractBehavior[Nothing](context) { context.log.info("IoT Application started") override def onMessage(msg: Nothing): Behavior[Nothing] = { diff --git a/akka-docs/src/test/scala/typed/tutorial_3/Device.scala b/akka-docs/src/test/scala/typed/tutorial_3/Device.scala index 6a0b25c2dd..ee04e7eac1 100644 --- a/akka-docs/src/test/scala/typed/tutorial_3/Device.scala +++ b/akka-docs/src/test/scala/typed/tutorial_3/Device.scala @@ -31,7 +31,7 @@ object Device { } class Device(context: ActorContext[Device.Command], groupId: String, deviceId: String) - extends AbstractBehavior[Device.Command] { + extends AbstractBehavior[Device.Command](context) { import Device._ var lastTemperatureReading: Option[Double] = None diff --git a/akka-docs/src/test/scala/typed/tutorial_3/DeviceInProgress.scala b/akka-docs/src/test/scala/typed/tutorial_3/DeviceInProgress.scala index 629d753de3..d75c7fae0f 100644 --- a/akka-docs/src/test/scala/typed/tutorial_3/DeviceInProgress.scala +++ b/akka-docs/src/test/scala/typed/tutorial_3/DeviceInProgress.scala @@ -43,7 +43,7 @@ object DeviceInProgress2 { } class Device(context: ActorContext[Device.Command], groupId: String, deviceId: String) - extends AbstractBehavior[Device.Command] { + extends AbstractBehavior[Device.Command](context) { import Device._ var lastTemperatureReading: Option[Double] = None diff --git a/akka-docs/src/test/scala/typed/tutorial_4/Device.scala b/akka-docs/src/test/scala/typed/tutorial_4/Device.scala index 197a68090c..29f748f036 100644 --- a/akka-docs/src/test/scala/typed/tutorial_4/Device.scala +++ b/akka-docs/src/test/scala/typed/tutorial_4/Device.scala @@ -33,7 +33,7 @@ object Device { } class Device(context: ActorContext[Device.Command], groupId: String, deviceId: String) - extends AbstractBehavior[Device.Command] { + extends AbstractBehavior[Device.Command](context) { import Device._ var lastTemperatureReading: Option[Double] = None diff --git a/akka-docs/src/test/scala/typed/tutorial_4/DeviceGroup.scala b/akka-docs/src/test/scala/typed/tutorial_4/DeviceGroup.scala index 4ab9ed8141..7e625219cf 100644 --- a/akka-docs/src/test/scala/typed/tutorial_4/DeviceGroup.scala +++ b/akka-docs/src/test/scala/typed/tutorial_4/DeviceGroup.scala @@ -30,7 +30,7 @@ object DeviceGroup { //#device-group-remove class DeviceGroup(context: ActorContext[DeviceGroup.Command], groupId: String) - extends AbstractBehavior[DeviceGroup.Command] { + extends AbstractBehavior[DeviceGroup.Command](context) { import DeviceGroup._ import DeviceManager.{ DeviceRegistered, ReplyDeviceList, RequestDeviceList, RequestTrackDevice } diff --git a/akka-docs/src/test/scala/typed/tutorial_4/DeviceManager.scala b/akka-docs/src/test/scala/typed/tutorial_4/DeviceManager.scala index c9f5b5705a..feb0300d0e 100644 --- a/akka-docs/src/test/scala/typed/tutorial_4/DeviceManager.scala +++ b/akka-docs/src/test/scala/typed/tutorial_4/DeviceManager.scala @@ -41,7 +41,8 @@ object DeviceManager { //#device-manager-msgs } -class DeviceManager(context: ActorContext[DeviceManager.Command]) extends AbstractBehavior[DeviceManager.Command] { +class DeviceManager(context: ActorContext[DeviceManager.Command]) + extends AbstractBehavior[DeviceManager.Command](context) { import DeviceManager._ var groupIdToActor = Map.empty[String, ActorRef[DeviceGroup.Command]] diff --git a/akka-docs/src/test/scala/typed/tutorial_5/Device.scala b/akka-docs/src/test/scala/typed/tutorial_5/Device.scala index 52a690f3bc..a4e6bb6922 100644 --- a/akka-docs/src/test/scala/typed/tutorial_5/Device.scala +++ b/akka-docs/src/test/scala/typed/tutorial_5/Device.scala @@ -31,7 +31,7 @@ object Device { } class Device(context: ActorContext[Device.Command], groupId: String, deviceId: String) - extends AbstractBehavior[Device.Command] { + extends AbstractBehavior[Device.Command](context) { import Device._ var lastTemperatureReading: Option[Double] = None diff --git a/akka-docs/src/test/scala/typed/tutorial_5/DeviceGroup.scala b/akka-docs/src/test/scala/typed/tutorial_5/DeviceGroup.scala index e226eea063..b72dcddb11 100644 --- a/akka-docs/src/test/scala/typed/tutorial_5/DeviceGroup.scala +++ b/akka-docs/src/test/scala/typed/tutorial_5/DeviceGroup.scala @@ -27,7 +27,7 @@ object DeviceGroup { //#query-added class DeviceGroup(context: ActorContext[DeviceGroup.Command], groupId: String) - extends AbstractBehavior[DeviceGroup.Command] { + extends AbstractBehavior[DeviceGroup.Command](context) { import DeviceGroup._ import DeviceManager.{ DeviceRegistered, diff --git a/akka-docs/src/test/scala/typed/tutorial_5/DeviceGroupQuery.scala b/akka-docs/src/test/scala/typed/tutorial_5/DeviceGroupQuery.scala index d0521f7ac7..b65b854d9a 100644 --- a/akka-docs/src/test/scala/typed/tutorial_5/DeviceGroupQuery.scala +++ b/akka-docs/src/test/scala/typed/tutorial_5/DeviceGroupQuery.scala @@ -45,7 +45,7 @@ class DeviceGroupQuery( timeout: FiniteDuration, context: ActorContext[DeviceGroupQuery.Command], timers: TimerScheduler[DeviceGroupQuery.Command]) - extends AbstractBehavior[DeviceGroupQuery.Command] { + extends AbstractBehavior[DeviceGroupQuery.Command](context) { import DeviceGroupQuery._ import DeviceManager.DeviceNotAvailable diff --git a/akka-docs/src/test/scala/typed/tutorial_5/DeviceManager.scala b/akka-docs/src/test/scala/typed/tutorial_5/DeviceManager.scala index 3cbd2e2c9c..289632760c 100644 --- a/akka-docs/src/test/scala/typed/tutorial_5/DeviceManager.scala +++ b/akka-docs/src/test/scala/typed/tutorial_5/DeviceManager.scala @@ -53,7 +53,8 @@ object DeviceManager { //#query-protocol } -class DeviceManager(context: ActorContext[DeviceManager.Command]) extends AbstractBehavior[DeviceManager.Command] { +class DeviceManager(context: ActorContext[DeviceManager.Command]) + extends AbstractBehavior[DeviceManager.Command](context) { import DeviceManager._ var groupIdToActor = Map.empty[String, ActorRef[DeviceGroup.Command]] diff --git a/akka-persistence-typed/src/main/scala/akka/persistence/typed/internal/ReplayingEvents.scala b/akka-persistence-typed/src/main/scala/akka/persistence/typed/internal/ReplayingEvents.scala index d91afde722..bb301306d4 100644 --- a/akka-persistence-typed/src/main/scala/akka/persistence/typed/internal/ReplayingEvents.scala +++ b/akka-persistence-typed/src/main/scala/akka/persistence/typed/internal/ReplayingEvents.scala @@ -65,7 +65,7 @@ private[akka] object ReplayingEvents { private[akka] final class ReplayingEvents[C, E, S]( override val setup: BehaviorSetup[C, E, S], var state: ReplayingState[S]) - extends AbstractBehavior[InternalProtocol] + extends AbstractBehavior[InternalProtocol](setup.context) with JournalInteractions[C, E, S] with SnapshotInteractions[C, E, S] with StashManagement[C, E, S] diff --git a/akka-persistence-typed/src/main/scala/akka/persistence/typed/internal/Running.scala b/akka-persistence-typed/src/main/scala/akka/persistence/typed/internal/Running.scala index 8c44b551ed..3aa6f78552 100644 --- a/akka-persistence-typed/src/main/scala/akka/persistence/typed/internal/Running.scala +++ b/akka-persistence-typed/src/main/scala/akka/persistence/typed/internal/Running.scala @@ -96,7 +96,7 @@ private[akka] object Running { import BehaviorSetup._ final class HandlingCommands(state: RunningState[S]) - extends AbstractBehavior[InternalProtocol] + extends AbstractBehavior[InternalProtocol](setup.context) with WithSeqNrAccessible { def onMessage(msg: InternalProtocol): Behavior[InternalProtocol] = msg match { @@ -226,7 +226,7 @@ private[akka] object Running { shouldSnapshotAfterPersist: SnapshotAfterPersist, var sideEffects: immutable.Seq[SideEffect[S]], persistStartTime: Long = System.nanoTime()) - extends AbstractBehavior[InternalProtocol] + extends AbstractBehavior[InternalProtocol](setup.context) with WithSeqNrAccessible { private var eventCounter = 0