From 80600abc3373aa35bce85d321d699f7072f3726e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bone=CC=81r?= Date: Wed, 14 Dec 2011 14:05:44 +0100 Subject: [PATCH 1/5] Added 'withRouter[TYPE]' to 'Props'. Added docs (Scala and Java) and (code for the docs) for 'Props'. Renamed UntypedActorTestBase to UntypedActorDocTestBase. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Bonér --- .../test/scala/akka/routing/RoutingSpec.scala | 24 ++--- .../src/main/scala/akka/actor/Props.scala | 62 +++++++++--- .../src/main/scala/akka/routing/package.scala | 7 +- .../akka/docs/actor/UntypedActorDocTest.scala | 5 + ...Base.java => UntypedActorDocTestBase.java} | 23 ++++- .../akka/docs/actor/UntypedActorTest.scala | 5 - akka-docs/java/untyped-actors.rst | 99 ++++++++++--------- akka-docs/scala/actors.rst | 14 ++- akka-docs/scala/code/ActorDocSpec.scala | 20 ++++ .../src/main/scala/Pi.scala | 2 +- 10 files changed, 178 insertions(+), 83 deletions(-) create mode 100644 akka-docs/java/code/akka/docs/actor/UntypedActorDocTest.scala rename akka-docs/java/code/akka/docs/actor/{UntypedActorTestBase.java => UntypedActorDocTestBase.java} (90%) delete mode 100644 akka-docs/java/code/akka/docs/actor/UntypedActorTest.scala diff --git a/akka-actor-tests/src/test/scala/akka/routing/RoutingSpec.scala b/akka-actor-tests/src/test/scala/akka/routing/RoutingSpec.scala index e6e0f1c898..e4e0e01541 100644 --- a/akka-actor-tests/src/test/scala/akka/routing/RoutingSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/routing/RoutingSpec.scala @@ -62,7 +62,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender { "no router" must { "be started when constructed" in { - val routedActor = system.actorOf(Props(new TestActor).withRouter(NoRouter)) + val routedActor = system.actorOf(Props[TestActor].withRouter(NoRouter)) routedActor.isTerminated must be(false) } @@ -90,7 +90,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender { "round robin router" must { "be started when constructed" in { - val routedActor = system.actorOf(Props(new TestActor).withRouter(RoundRobinRouter(nrOfInstances = 1))) + val routedActor = system.actorOf(Props[TestActor].withRouter(RoundRobinRouter(nrOfInstances = 1))) routedActor.isTerminated must be(false) } @@ -118,7 +118,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender { actors = actors :+ actor } - val routedActor = system.actorOf(Props(new TestActor).withRouter(RoundRobinRouter(targets = actors))) + val routedActor = system.actorOf(Props[TestActor].withRouter(RoundRobinRouter(targets = actors))) //send messages to the actor. for (i ← 0 until iterationCount) { @@ -156,7 +156,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender { } })) - val routedActor = system.actorOf(Props(new TestActor).withRouter(RoundRobinRouter(targets = List(actor1, actor2)))) + val routedActor = system.actorOf(Props[TestActor].withRouter(RoundRobinRouter(targets = List(actor1, actor2)))) routedActor ! Broadcast(1) routedActor ! Broadcast("end") @@ -171,7 +171,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender { "random router" must { "be started when constructed" in { - val routedActor = system.actorOf(Props(new TestActor).withRouter(RandomRouter(nrOfInstances = 1))) + val routedActor = system.actorOf(Props[TestActor].withRouter(RandomRouter(nrOfInstances = 1))) routedActor.isTerminated must be(false) } @@ -194,7 +194,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender { } })) - val routedActor = system.actorOf(Props(new TestActor).withRouter(RandomRouter(targets = List(actor1, actor2)))) + val routedActor = system.actorOf(Props[TestActor].withRouter(RandomRouter(targets = List(actor1, actor2)))) routedActor ! Broadcast(1) routedActor ! Broadcast("end") @@ -208,7 +208,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender { "broadcast router" must { "be started when constructed" in { - val routedActor = system.actorOf(Props(new TestActor).withRouter(BroadcastRouter(nrOfInstances = 1))) + val routedActor = system.actorOf(Props[TestActor].withRouter(BroadcastRouter(nrOfInstances = 1))) routedActor.isTerminated must be(false) } @@ -231,7 +231,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender { } })) - val routedActor = system.actorOf(Props(new TestActor).withRouter(BroadcastRouter(targets = List(actor1, actor2)))) + val routedActor = system.actorOf(Props[TestActor].withRouter(BroadcastRouter(targets = List(actor1, actor2)))) routedActor ! 1 routedActor ! "end" @@ -262,7 +262,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender { } })) - val routedActor = system.actorOf(Props(new TestActor).withRouter(BroadcastRouter(targets = List(actor1, actor2)))) + val routedActor = system.actorOf(Props[TestActor].withRouter(BroadcastRouter(targets = List(actor1, actor2)))) routedActor ? 1 routedActor ! "end" @@ -276,7 +276,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender { "Scatter-gather router" must { "be started when constructed" in { - val routedActor = system.actorOf(Props(new TestActor).withRouter(ScatterGatherFirstCompletedRouter(targets = List(newActor(0))))) + val routedActor = system.actorOf(Props[TestActor].withRouter(ScatterGatherFirstCompletedRouter(targets = List(newActor(0))))) routedActor.isTerminated must be(false) } @@ -299,7 +299,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender { } })) - val routedActor = system.actorOf(Props(new TestActor).withRouter(ScatterGatherFirstCompletedRouter(targets = List(actor1, actor2)))) + val routedActor = system.actorOf(Props[TestActor].withRouter(ScatterGatherFirstCompletedRouter(targets = List(actor1, actor2)))) routedActor ! Broadcast(1) routedActor ! Broadcast("end") @@ -313,7 +313,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender { val shutdownLatch = new TestLatch(1) val actor1 = newActor(1, Some(shutdownLatch)) val actor2 = newActor(22, Some(shutdownLatch)) - val routedActor = system.actorOf(Props(new TestActor).withRouter(ScatterGatherFirstCompletedRouter(targets = List(actor1, actor2)))) + val routedActor = system.actorOf(Props[TestActor].withRouter(ScatterGatherFirstCompletedRouter(targets = List(actor1, actor2)))) routedActor ! Broadcast(Stop(Some(1))) shutdownLatch.await diff --git a/akka-actor/src/main/scala/akka/actor/Props.scala b/akka-actor/src/main/scala/akka/actor/Props.scala index 9824803aea..29d1374dbc 100644 --- a/akka-actor/src/main/scala/akka/actor/Props.scala +++ b/akka-actor/src/main/scala/akka/actor/Props.scala @@ -8,11 +8,13 @@ import akka.dispatch._ import akka.japi.Creator import akka.util._ import collection.immutable.Stack -import akka.routing.{ NoRouter, RouterConfig } +import akka.routing._ /** * Factory for Props instances. + * * Props is a ActorRef configuration object, that is thread safe and fully sharable. + * * Used when creating new actors through; ActorSystem.actorOf and ActorContext.actorOf. */ object Props { @@ -47,6 +49,8 @@ object Props { /** * Returns a Props that has default values except for "creator" which will be a function that creates an instance * of the supplied type using the default constructor. + * + * Scala API. */ def apply[T <: Actor: ClassManifest]: Props = default.withCreator(implicitly[ClassManifest[T]].erasure.asInstanceOf[Class[_ <: Actor]].newInstance) @@ -61,6 +65,8 @@ object Props { /** * Returns a Props that has default values except for "creator" which will be a function that creates an instance * using the supplied thunk. + * + * Scala API. */ def apply(creator: ⇒ Actor): Props = default.withCreator(creator) @@ -87,7 +93,17 @@ object Props { * {{{ * val props = Props[MyActor] * val props = Props(new MyActor) + * val props = Props { + * creator = .., + * dispatcher = .., + * timeout = .., + * faultHandler = .., + * routerConfig = .. + * } + * val props = Props().withCreator(new MyActor) * val props = Props[MyActor].withTimeout(timeout) + * val props = Props[MyActor].withRouter[RoundRobinRouter] + * val props = Props[MyActor].withRouter(new RoundRobinRouter(..)) * val props = Props[MyActor].withFaultHandler(OneForOneStrategy { * case e: IllegalStateException ⇒ Resume * }) @@ -103,19 +119,20 @@ object Props { * } * }); * Props props = new Props().withCreator(new UntypedActorFactory() { ... }); - * Props props = new Props().withTimeout(timeout); - * Props props = new Props().withFaultHandler(new OneForOneStrategy(...)); + * Props props = new Props(MyActor.class).withTimeout(timeout); + * Props props = new Props(MyActor.class).withFaultHandler(new OneForOneStrategy(...)); + * Props props = new Props(MyActor.class).withRouter(new RoundRobinRouter(..)); * }}} */ -case class Props(creator: () ⇒ Actor = Props.defaultCreator, - @transient dispatcher: MessageDispatcher = Props.defaultDispatcher, - timeout: Timeout = Props.defaultTimeout, - faultHandler: FaultHandlingStrategy = Props.defaultFaultHandler, - routerConfig: RouterConfig = Props.defaultRoutedProps) { +case class Props( + creator: () ⇒ Actor = Props.defaultCreator, + @transient dispatcher: MessageDispatcher = Props.defaultDispatcher, + timeout: Timeout = Props.defaultTimeout, + faultHandler: FaultHandlingStrategy = Props.defaultFaultHandler, + routerConfig: RouterConfig = Props.defaultRoutedProps) { /** * No-args constructor that sets all the default values. - * Java API. */ def this() = this( creator = Props.defaultCreator, @@ -144,43 +161,58 @@ case class Props(creator: () ⇒ Actor = Props.defaultCreator, /** * Returns a new Props with the specified creator set. + * * Scala API. */ def withCreator(c: ⇒ Actor) = copy(creator = () ⇒ c) /** * Returns a new Props with the specified creator set. + * * Java API. */ def withCreator(c: Creator[Actor]) = copy(creator = () ⇒ c.create) /** * Returns a new Props with the specified creator set. + * * Java API. */ def withCreator(c: Class[_ <: Actor]) = copy(creator = () ⇒ c.newInstance) /** * Returns a new Props with the specified dispatcher set. - * Java API. */ def withDispatcher(d: MessageDispatcher) = copy(dispatcher = d) /** - * Returns a new Props with the specified timeout set - * Java API. + * Returns a new Props with the specified timeout set. */ def withTimeout(t: Timeout) = copy(timeout = t) /** * Returns a new Props with the specified faulthandler set. - * Java API. */ def withFaultHandler(f: FaultHandlingStrategy) = copy(faultHandler = f) /** - * Returns a new Props with the specified router config set - * Java API + * Returns a new Props with the specified router config set. */ def withRouter(r: RouterConfig) = copy(routerConfig = r) + + /** + * Returns a new Props with the specified router config set. + * + * Scala API. + */ + def withRouter[T <: RouterConfig: ClassManifest] = { + val routerConfig = implicitly[ClassManifest[T]].erasure.asInstanceOf[Class[_ <: RouterConfig]] match { + case RoundRobinRouterClass ⇒ RoundRobinRouter() + case RandomRouterClass ⇒ RandomRouter() + case BroadcastRouterClass ⇒ BroadcastRouter() + case ScatterGatherRouterClass ⇒ ScatterGatherFirstCompletedRouter() + case unknown ⇒ throw new akka.config.ConfigurationException("Router not supported [" + unknown.getName + "]") + } + copy(routerConfig = routerConfig) + } } diff --git a/akka-actor/src/main/scala/akka/routing/package.scala b/akka-actor/src/main/scala/akka/routing/package.scala index 1f2e343a33..579484493c 100644 --- a/akka-actor/src/main/scala/akka/routing/package.scala +++ b/akka-actor/src/main/scala/akka/routing/package.scala @@ -8,4 +8,9 @@ package object routing { type Route = PartialFunction[(akka.actor.ActorRef, Any), Iterable[Destination]] -} \ No newline at end of file + // To allow pattern matching on the class types + val RoundRobinRouterClass = classOf[RoundRobinRouter] + val RandomRouterClass = classOf[RandomRouter] + val BroadcastRouterClass = classOf[BroadcastRouter] + val ScatterGatherRouterClass = classOf[ScatterGatherFirstCompletedRouter] +} diff --git a/akka-docs/java/code/akka/docs/actor/UntypedActorDocTest.scala b/akka-docs/java/code/akka/docs/actor/UntypedActorDocTest.scala new file mode 100644 index 0000000000..76b3b990fa --- /dev/null +++ b/akka-docs/java/code/akka/docs/actor/UntypedActorDocTest.scala @@ -0,0 +1,5 @@ +package akka.docs.actor + +import org.scalatest.junit.JUnitSuite + +class UntypedActorDocTest extends UntypedActorDocTestBase with JUnitSuite diff --git a/akka-docs/java/code/akka/docs/actor/UntypedActorTestBase.java b/akka-docs/java/code/akka/docs/actor/UntypedActorDocTestBase.java similarity index 90% rename from akka-docs/java/code/akka/docs/actor/UntypedActorTestBase.java rename to akka-docs/java/code/akka/docs/actor/UntypedActorDocTestBase.java index c2a877d962..fd1eb2f630 100644 --- a/akka-docs/java/code/akka/docs/actor/UntypedActorTestBase.java +++ b/akka-docs/java/code/akka/docs/actor/UntypedActorDocTestBase.java @@ -1,5 +1,7 @@ package akka.docs.actor; +import akka.actor.Timeout; + //#imports import akka.actor.ActorRef; import akka.actor.ActorSystem; @@ -33,7 +35,26 @@ import scala.Option; import static org.junit.Assert.*; -public class UntypedActorTestBase { +public class UntypedActorDocTestBase { + + @Test + public void createProps() { + //#creating-props-config + Props props1 = new Props(); + Props props2 = new Props(MyUntypedActor.class); + Props props3 = new Props(new UntypedActorFactory() { + public UntypedActor create() { + return new MyUntypedActor(); + } + }); + Props props4 = props1.withCreator(new UntypedActorFactory() { + public UntypedActor create() { + return new MyUntypedActor(); + } + }); + Props props5 = props4.withTimeout(new Timeout(1000)); + //#creating-props-config + } @Test public void systemActorOf() { diff --git a/akka-docs/java/code/akka/docs/actor/UntypedActorTest.scala b/akka-docs/java/code/akka/docs/actor/UntypedActorTest.scala deleted file mode 100644 index 1747f30f92..0000000000 --- a/akka-docs/java/code/akka/docs/actor/UntypedActorTest.scala +++ /dev/null @@ -1,5 +0,0 @@ -package akka.docs.actor - -import org.scalatest.junit.JUnitSuite - -class UntypedActorTest extends UntypedActorTestBase with JUnitSuite diff --git a/akka-docs/java/untyped-actors.rst b/akka-docs/java/untyped-actors.rst index 4324aadf19..7ed3100fab 100644 --- a/akka-docs/java/untyped-actors.rst +++ b/akka-docs/java/untyped-actors.rst @@ -42,7 +42,7 @@ Here is an example: Creating Actors with default constructor ---------------------------------------- -.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java +.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java :include: imports,system-actorOf The call to :meth:`actorOf` returns an instance of ``ActorRef``. This is a handle to @@ -62,7 +62,7 @@ a top level actor, that is supervised by the system (internal guardian actor). .. includecode:: code/akka/docs/actor/FirstUntypedActor.java#context-actorOf Actors are automatically started asynchronously when created. -When you create the ``UntypedActor`` then it will automatically call the ``preStart`` +When you create the ``UntypedActor`` then it will automatically call the ``preStart`` callback method on the ``UntypedActor`` class. This is an excellent place to add initialization code for the actor. @@ -76,26 +76,35 @@ add initialization code for the actor. Creating Actors with non-default constructor -------------------------------------------- -If your UntypedActor has a constructor that takes parameters then you can't create it using 'actorOf(clazz)'. -Instead you can use a variant of ``actorOf`` that takes an instance of an 'UntypedActorFactory' -in which you can create the Actor in any way you like. If you use this method then you to make sure that -no one can get a reference to the actor instance. If they can get a reference it then they can -touch state directly in bypass the whole actor dispatching mechanism and create race conditions +If your UntypedActor has a constructor that takes parameters then you can't create it using 'actorOf(clazz)'. +Instead you can use a variant of ``actorOf`` that takes an instance of an 'UntypedActorFactory' +in which you can create the Actor in any way you like. If you use this method then you to make sure that +no one can get a reference to the actor instance. If they can get a reference it then they can +touch state directly in bypass the whole actor dispatching mechanism and create race conditions which can lead to corrupt data. Here is an example: -.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java#creating-constructor +.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#creating-constructor This way of creating the Actor is also great for integrating with Dependency Injection (DI) frameworks like Guice or Spring. + +Props +----- + +``Props`` is a configuration object to specify configuration options for the creation +of actors. Here are some examples on how to create a ``Props`` instance. + +.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#creating-props-config + + Creating Actors with Props -------------------------- -``Props`` is a configuration object to specify additional things for the actor to -be created, such as the ``MessageDispatcher``. +Actors are created by passing in the ``Props`` object into the ``actorOf`` factory method. -.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java#creating-props +.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#creating-props UntypedActor API @@ -119,7 +128,7 @@ In addition, it offers: The remaining visible methods are user-overridable life-cycle hooks which are described in the following: -.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java#lifecycle-callbacks +.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#lifecycle-callbacks The implementations shown above are the defaults provided by the :class:`UntypedActor` class. @@ -162,7 +171,7 @@ processing a message. This restart involves the hooks mentioned above: An actor restart replaces only the actual actor object; the contents of the mailbox and the hotswap stack are unaffected by the restart, so processing of -messages will resume after the :meth:`postRestart` hook returns. The message +messages will resume after the :meth:`postRestart` hook returns. The message that triggered the exception will not be received again. Any message sent to an actor while it is being restarted will be queued to its mailbox as usual. @@ -172,9 +181,9 @@ Stop Hook After stopping an actor, its :meth:`postStop` hook is called, which may be used e.g. for deregistering this actor from other services. This hook is guaranteed -to run after message queuing has been disabled for this actor, i.e. messages -sent to a stopped actor will be redirected to the :obj:`deadLetters` of the -:obj:`ActorSystem`. +to run after message queuing has been disabled for this actor, i.e. messages +sent to a stopped actor will be redirected to the :obj:`deadLetters` of the +:obj:`ActorSystem`. Identifying Actors @@ -188,7 +197,7 @@ Messages and immutability **IMPORTANT**: Messages can be any kind of object but have to be immutable. Akka can’t enforce immutability (yet) so this has to be by -convention. +convention. Here is an example of an immutable message: @@ -207,8 +216,8 @@ Messages are sent to an Actor through one of the following methods. Message ordering is guaranteed on a per-sender basis. -In all these methods you have the option of passing along your own ``ActorRef``. -Make it a practice of doing so because it will allow the receiver actors to be able to respond +In all these methods you have the option of passing along your own ``ActorRef``. +Make it a practice of doing so because it will allow the receiver actors to be able to respond to your message, since the sender reference is sent along with the message. Tell: Fire-forget @@ -229,7 +238,7 @@ to reply to the original sender, by using ``getSender().tell(replyMsg)``. actor.tell("Hello", getSelf()); -If invoked without the sender parameter the sender will be +If invoked without the sender parameter the sender will be :obj:`deadLetters` actor reference in the target actor. Ask: Send-And-Receive-Future @@ -244,13 +253,13 @@ will immediately return a :class:`Future`: Future future = actorRef.ask("Hello", timeoutMillis); The receiving actor should reply to this message, which will complete the -future with the reply message as value; ``getSender.tell(result)``. +future with the reply message as value; ``getSender.tell(result)``. -To complete the future with an exception you need send a Failure message to the sender. -This is not done automatically when an actor throws an exception while processing a -message. +To complete the future with an exception you need send a Failure message to the sender. +This is not done automatically when an actor throws an exception while processing a +message. -.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java#reply-exception +.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#reply-exception If the actor does not complete the future, it will expire after the timeout period, specified as parameter to the ``ask`` method. @@ -258,16 +267,16 @@ specified as parameter to the ``ask`` method. See :ref:`futures-java` for more information on how to await or query a future. -The ``onComplete``, ``onResult``, or ``onTimeout`` methods of the ``Future`` can be -used to register a callback to get a notification when the Future completes. +The ``onComplete``, ``onResult``, or ``onTimeout`` methods of the ``Future`` can be +used to register a callback to get a notification when the Future completes. Gives you a way to avoid blocking. .. warning:: When using future callbacks, inside actors you need to carefully avoid closing over - the containing actor’s reference, i.e. do not call methods or access mutable state - on the enclosing actor from within the callback. This would break the actor - encapsulation and may introduce synchronization bugs and race conditions because + the containing actor’s reference, i.e. do not call methods or access mutable state + on the enclosing actor from within the callback. This would break the actor + encapsulation and may introduce synchronization bugs and race conditions because the callback will be scheduled concurrently to the enclosing actor. Unfortunately there is not yet a way to detect these illegal accesses at compile time. See also: :ref:`jmm-shared-state` @@ -278,7 +287,7 @@ even if that entails waiting for it (but keep in mind that waiting inside an actor is prone to dead-locks, e.g. if obtaining the result depends on processing another message on this actor). -.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java +.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java :include: import-future,using-ask Forward message @@ -297,7 +306,7 @@ You need to pass along your context variable as well. Receive messages ================ -When an actor receives a message it is passed into the ``onReceive`` method, this is +When an actor receives a message it is passed into the ``onReceive`` method, this is an abstract method on the ``UntypedActor`` base class that needs to be defined. Here is an example: @@ -340,17 +349,17 @@ message. Stopping actors =============== -Actors are stopped by invoking the ``stop`` method of the ``ActorRef``. +Actors are stopped by invoking the ``stop`` method of the ``ActorRef``. The actual termination of the actor is performed asynchronously, i.e. -``stop`` may return before the actor is stopped. +``stop`` may return before the actor is stopped. .. code-block:: java actor.stop(); -Processing of the current message, if any, will continue before the actor is stopped, +Processing of the current message, if any, will continue before the actor is stopped, but additional messages in the mailbox will not be processed. By default these -messages are sent to the :obj:`deadLetters` of the :obj:`ActorSystem`, but that +messages are sent to the :obj:`deadLetters` of the :obj:`ActorSystem`, but that depends on the mailbox implementation. When stop is called then a call to the ``def postStop`` callback method will @@ -365,7 +374,7 @@ take place. The ``Actor`` can use this callback to implement shutdown behavior. All Actors are stopped when the ``ActorSystem`` is stopped. Supervised actors are stopped when the supervisor is stopped, i.e. children are stopped -when parent is stopped. +when parent is stopped. PoisonPill @@ -381,7 +390,7 @@ If the ``PoisonPill`` was sent with ``ask``, the ``Future`` will be completed wi Use it like this: -.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java +.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java :include: import-actors,poison-pill .. _UntypedActor.HotSwap: @@ -402,10 +411,10 @@ The hotswapped code is kept in a Stack which can be pushed and popped. To hotswap the Actor using ``getContext().become``: -.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java +.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java :include: import-procedure,hot-swap-actor -The ``become`` method is useful for many different things, such as to implement +The ``become`` method is useful for many different things, such as to implement a Finite State Machine (FSM). Here is another little cute example of ``become`` and ``unbecome`` in action: @@ -432,7 +441,7 @@ through regular supervisor semantics. Use it like this: -.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java +.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java :include: import-actors,kill Actors and exceptions @@ -462,9 +471,9 @@ messages on that mailbox, will be there as well. What happens to the actor ------------------------- -If an exception is thrown, the actor instance is discarded and a new instance is +If an exception is thrown, the actor instance is discarded and a new instance is created. This new instance will now be used in the actor references to this actor -(so this is done invisible to the developer). Note that this means that current -state of the failing actor instance is lost if you don't store and restore it in -``preRestart`` and ``postRestart`` callbacks. +(so this is done invisible to the developer). Note that this means that current +state of the failing actor instance is lost if you don't store and restore it in +``preRestart`` and ``postRestart`` callbacks. diff --git a/akka-docs/scala/actors.rst b/akka-docs/scala/actors.rst index 618d2618c9..7f06dbcc9d 100644 --- a/akka-docs/scala/actors.rst +++ b/akka-docs/scala/actors.rst @@ -54,7 +54,7 @@ Creating Actors with default constructor ---------------------------------------- .. includecode:: code/ActorDocSpec.scala -:include: imports2,system-actorOf + :include: imports2,system-actorOf The call to :meth:`actorOf` returns an instance of ``ActorRef``. This is a handle to the ``Actor`` instance which you can use to interact with the ``Actor``. The @@ -95,11 +95,19 @@ Here is an example: .. includecode:: code/ActorDocSpec.scala#creating-constructor +Props +----- + +``Props`` is a configuration object to specify configuration options for the creation +of actors. Here are some examples on how to create a ``Props`` instance. + +.. includecode:: code/ActorDocSpec.scala#creating-props-config + + Creating Actors with Props -------------------------- -``Props`` is a configuration object to specify additional things for the actor to -be created, such as the ``MessageDispatcher``. +Actors are created by passing in the ``Props`` object into the ``actorOf`` factory method. .. includecode:: code/ActorDocSpec.scala#creating-props diff --git a/akka-docs/scala/code/ActorDocSpec.scala b/akka-docs/scala/code/ActorDocSpec.scala index 5592572443..81f25af8b3 100644 --- a/akka-docs/scala/code/ActorDocSpec.scala +++ b/akka-docs/scala/code/ActorDocSpec.scala @@ -1,5 +1,7 @@ package akka.docs.actor +import akka.actor.Timeout + //#imports1 import akka.actor.Actor import akka.actor.Props @@ -13,6 +15,7 @@ import akka.actor.ActorSystem import org.scalatest.{ BeforeAndAfterAll, WordSpec } import org.scalatest.matchers.MustMatchers import akka.testkit._ +import akka.util._ import akka.util.duration._ //#my-actor @@ -185,6 +188,23 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) { myActor.stop() } + "creating a Props config" in { + val dispatcher = system.dispatcherFactory.lookup("my-dispatcher") + //#creating-props-config + import akka.actor.Props + val props1 = Props() + val props2 = Props[MyActor] + val props3 = Props(new MyActor) + val props4 = Props( + creator = { () ⇒ new MyActor }, + dispatcher = dispatcher, + timeout = Timeout(100)) + val props5 = props1.withCreator(new MyActor) + val props6 = props5.withDispatcher(dispatcher) + val props7 = props6.withTimeout(Timeout(100)) + //#creating-props-config + } + "creating actor with Props" in { //#creating-props import akka.actor.Props diff --git a/akka-tutorials/akka-tutorial-first/src/main/scala/Pi.scala b/akka-tutorials/akka-tutorial-first/src/main/scala/Pi.scala index 0a6c0ed04e..4d19f47db4 100644 --- a/akka-tutorials/akka-tutorial-first/src/main/scala/Pi.scala +++ b/akka-tutorials/akka-tutorial-first/src/main/scala/Pi.scala @@ -50,7 +50,7 @@ object Pi extends App { var start: Long = _ //#create-router - val router = context.actorOf(Props(new Worker).withRouter(RoundRobinRouter(nrOfInstances = nrOfWorkers)), "pi") + val router = context.actorOf(Props[Worker].withRouter(RoundRobinRouter(nrOfInstances = nrOfWorkers)), "pi") //#create-router //#master-receive From 8289ac2a291278765f1cd40ad6f59296526c6916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bone=CC=81r?= Date: Wed, 14 Dec 2011 15:10:42 +0100 Subject: [PATCH 2/5] Minor doc changes to Props docs --- akka-docs/java/untyped-actors.rst | 4 ++-- akka-docs/scala/actors.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/akka-docs/java/untyped-actors.rst b/akka-docs/java/untyped-actors.rst index 7ed3100fab..ab82599450 100644 --- a/akka-docs/java/untyped-actors.rst +++ b/akka-docs/java/untyped-actors.rst @@ -93,7 +93,7 @@ This way of creating the Actor is also great for integrating with Dependency Inj Props ----- -``Props`` is a configuration object to specify configuration options for the creation +``Props`` is a configuration class to specify options for the creation of actors. Here are some examples on how to create a ``Props`` instance. .. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#creating-props-config @@ -102,7 +102,7 @@ of actors. Here are some examples on how to create a ``Props`` instance. Creating Actors with Props -------------------------- -Actors are created by passing in the ``Props`` object into the ``actorOf`` factory method. +Actors are created by passing in a ``Props`` instance into the ``actorOf`` factory method. .. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#creating-props diff --git a/akka-docs/scala/actors.rst b/akka-docs/scala/actors.rst index 7f06dbcc9d..92bdfe244c 100644 --- a/akka-docs/scala/actors.rst +++ b/akka-docs/scala/actors.rst @@ -98,7 +98,7 @@ Here is an example: Props ----- -``Props`` is a configuration object to specify configuration options for the creation +``Props`` is a configuration class to specify options for the creation of actors. Here are some examples on how to create a ``Props`` instance. .. includecode:: code/ActorDocSpec.scala#creating-props-config @@ -107,7 +107,7 @@ of actors. Here are some examples on how to create a ``Props`` instance. Creating Actors with Props -------------------------- -Actors are created by passing in the ``Props`` object into the ``actorOf`` factory method. +Actors are created by passing in a ``Props`` instance into the ``actorOf`` factory method. .. includecode:: code/ActorDocSpec.scala#creating-props From f2e36f060d99e1339f60bd91ec1b65912f9b8150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bone=CC=81r?= Date: Wed, 14 Dec 2011 15:20:17 +0100 Subject: [PATCH 3/5] Fix minor issue in the untyped actor docs --- akka-docs/java/untyped-actors.rst | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/akka-docs/java/untyped-actors.rst b/akka-docs/java/untyped-actors.rst index ab82599450..eddcadc9dc 100644 --- a/akka-docs/java/untyped-actors.rst +++ b/akka-docs/java/untyped-actors.rst @@ -76,18 +76,16 @@ add initialization code for the actor. Creating Actors with non-default constructor -------------------------------------------- -If your UntypedActor has a constructor that takes parameters then you can't create it using 'actorOf(clazz)'. -Instead you can use a variant of ``actorOf`` that takes an instance of an 'UntypedActorFactory' -in which you can create the Actor in any way you like. If you use this method then you to make sure that -no one can get a reference to the actor instance. If they can get a reference it then they can -touch state directly in bypass the whole actor dispatching mechanism and create race conditions -which can lead to corrupt data. +If your UntypedActor has a constructor that takes parameters then you can't create it using +'actorOf(new Props(clazz))'. Then you can instead pass in 'new Props(new UntypedActorFactory() {..})' +in which you can create the Actor in any way you like. Here is an example: .. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#creating-constructor -This way of creating the Actor is also great for integrating with Dependency Injection (DI) frameworks like Guice or Spring. +This way of creating the Actor is also great for integrating with Dependency Injection +(DI) frameworks like Guice or Spring. Props From 7f93f560489f1047a67893a8fc48cf7b4f34a10f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bone=CC=81r?= Date: Wed, 14 Dec 2011 15:22:04 +0100 Subject: [PATCH 4/5] Rearranged ordering of sections in untyped actor docs --- akka-docs/java/untyped-actors.rst | 34 +++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/akka-docs/java/untyped-actors.rst b/akka-docs/java/untyped-actors.rst index eddcadc9dc..f6af777acd 100644 --- a/akka-docs/java/untyped-actors.rst +++ b/akka-docs/java/untyped-actors.rst @@ -39,6 +39,23 @@ Here is an example: .. includecode:: code/akka/docs/actor/MyUntypedActor.java#my-untyped-actor +Props +----- + +``Props`` is a configuration class to specify options for the creation +of actors. Here are some examples on how to create a ``Props`` instance. + +.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#creating-props-config + + +Creating Actors with Props +-------------------------- + +Actors are created by passing in a ``Props`` instance into the ``actorOf`` factory method. + +.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#creating-props + + Creating Actors with default constructor ---------------------------------------- @@ -88,23 +105,6 @@ This way of creating the Actor is also great for integrating with Dependency Inj (DI) frameworks like Guice or Spring. -Props ------ - -``Props`` is a configuration class to specify options for the creation -of actors. Here are some examples on how to create a ``Props`` instance. - -.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#creating-props-config - - -Creating Actors with Props --------------------------- - -Actors are created by passing in a ``Props`` instance into the ``actorOf`` factory method. - -.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#creating-props - - UntypedActor API ================ From 2fd43bc4b1eb4ee83910adb3824138c650569294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bone=CC=81r?= Date: Wed, 14 Dec 2011 16:31:26 +0100 Subject: [PATCH 5/5] Removed withRouter[TYPE] method and cleaned up some docs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Bonér --- .../src/main/scala/akka/actor/Props.scala | 23 +++---------------- .../src/main/scala/akka/routing/package.scala | 7 ------ .../src/main/scala/Pi.scala | 2 +- 3 files changed, 4 insertions(+), 28 deletions(-) diff --git a/akka-actor/src/main/scala/akka/actor/Props.scala b/akka-actor/src/main/scala/akka/actor/Props.scala index 29d1374dbc..e96a5b37c9 100644 --- a/akka-actor/src/main/scala/akka/actor/Props.scala +++ b/akka-actor/src/main/scala/akka/actor/Props.scala @@ -93,17 +93,16 @@ object Props { * {{{ * val props = Props[MyActor] * val props = Props(new MyActor) - * val props = Props { + * val props = Props( * creator = .., * dispatcher = .., * timeout = .., * faultHandler = .., * routerConfig = .. - * } + * ) * val props = Props().withCreator(new MyActor) * val props = Props[MyActor].withTimeout(timeout) - * val props = Props[MyActor].withRouter[RoundRobinRouter] - * val props = Props[MyActor].withRouter(new RoundRobinRouter(..)) + * val props = Props[MyActor].withRouter(RoundRobinRouter(..)) * val props = Props[MyActor].withFaultHandler(OneForOneStrategy { * case e: IllegalStateException ⇒ Resume * }) @@ -199,20 +198,4 @@ case class Props( * Returns a new Props with the specified router config set. */ def withRouter(r: RouterConfig) = copy(routerConfig = r) - - /** - * Returns a new Props with the specified router config set. - * - * Scala API. - */ - def withRouter[T <: RouterConfig: ClassManifest] = { - val routerConfig = implicitly[ClassManifest[T]].erasure.asInstanceOf[Class[_ <: RouterConfig]] match { - case RoundRobinRouterClass ⇒ RoundRobinRouter() - case RandomRouterClass ⇒ RandomRouter() - case BroadcastRouterClass ⇒ BroadcastRouter() - case ScatterGatherRouterClass ⇒ ScatterGatherFirstCompletedRouter() - case unknown ⇒ throw new akka.config.ConfigurationException("Router not supported [" + unknown.getName + "]") - } - copy(routerConfig = routerConfig) - } } diff --git a/akka-actor/src/main/scala/akka/routing/package.scala b/akka-actor/src/main/scala/akka/routing/package.scala index 579484493c..44662856b1 100644 --- a/akka-actor/src/main/scala/akka/routing/package.scala +++ b/akka-actor/src/main/scala/akka/routing/package.scala @@ -5,12 +5,5 @@ package akka package object routing { - type Route = PartialFunction[(akka.actor.ActorRef, Any), Iterable[Destination]] - - // To allow pattern matching on the class types - val RoundRobinRouterClass = classOf[RoundRobinRouter] - val RandomRouterClass = classOf[RandomRouter] - val BroadcastRouterClass = classOf[BroadcastRouter] - val ScatterGatherRouterClass = classOf[ScatterGatherFirstCompletedRouter] } diff --git a/akka-tutorials/akka-tutorial-first/src/main/scala/Pi.scala b/akka-tutorials/akka-tutorial-first/src/main/scala/Pi.scala index 4d19f47db4..b46ed3f1f8 100644 --- a/akka-tutorials/akka-tutorial-first/src/main/scala/Pi.scala +++ b/akka-tutorials/akka-tutorial-first/src/main/scala/Pi.scala @@ -50,7 +50,7 @@ object Pi extends App { var start: Long = _ //#create-router - val router = context.actorOf(Props[Worker].withRouter(RoundRobinRouter(nrOfInstances = nrOfWorkers)), "pi") + val router = context.actorOf(Props[Worker].withRouter(RoundRobinRouter(nrOfWorkers)), "pi") //#create-router //#master-receive