Added 'withRouter[TYPE]' to 'Props'.
Added docs (Scala and Java) and (code for the docs) for 'Props'. Renamed UntypedActorTestBase to UntypedActorDocTestBase. Signed-off-by: Jonas Bonér <jonas@jonasboner.com>
This commit is contained in:
parent
66e7155ef1
commit
80600abc33
10 changed files with 178 additions and 83 deletions
|
|
@ -62,7 +62,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
|
||||||
|
|
||||||
"no router" must {
|
"no router" must {
|
||||||
"be started when constructed" in {
|
"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)
|
routedActor.isTerminated must be(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,7 +90,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
|
||||||
|
|
||||||
"round robin router" must {
|
"round robin router" must {
|
||||||
"be started when constructed" in {
|
"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)
|
routedActor.isTerminated must be(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,7 +118,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
|
||||||
actors = actors :+ actor
|
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.
|
//send messages to the actor.
|
||||||
for (i ← 0 until iterationCount) {
|
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(1)
|
||||||
routedActor ! Broadcast("end")
|
routedActor ! Broadcast("end")
|
||||||
|
|
@ -171,7 +171,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
|
||||||
"random router" must {
|
"random router" must {
|
||||||
|
|
||||||
"be started when constructed" in {
|
"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)
|
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(1)
|
||||||
routedActor ! Broadcast("end")
|
routedActor ! Broadcast("end")
|
||||||
|
|
@ -208,7 +208,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
|
||||||
|
|
||||||
"broadcast router" must {
|
"broadcast router" must {
|
||||||
"be started when constructed" in {
|
"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)
|
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 ! 1
|
||||||
routedActor ! "end"
|
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 ? 1
|
||||||
routedActor ! "end"
|
routedActor ! "end"
|
||||||
|
|
||||||
|
|
@ -276,7 +276,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
|
||||||
"Scatter-gather router" must {
|
"Scatter-gather router" must {
|
||||||
|
|
||||||
"be started when constructed" in {
|
"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)
|
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(1)
|
||||||
routedActor ! Broadcast("end")
|
routedActor ! Broadcast("end")
|
||||||
|
|
||||||
|
|
@ -313,7 +313,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
|
||||||
val shutdownLatch = new TestLatch(1)
|
val shutdownLatch = new TestLatch(1)
|
||||||
val actor1 = newActor(1, Some(shutdownLatch))
|
val actor1 = newActor(1, Some(shutdownLatch))
|
||||||
val actor2 = newActor(22, 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)))
|
routedActor ! Broadcast(Stop(Some(1)))
|
||||||
shutdownLatch.await
|
shutdownLatch.await
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,13 @@ import akka.dispatch._
|
||||||
import akka.japi.Creator
|
import akka.japi.Creator
|
||||||
import akka.util._
|
import akka.util._
|
||||||
import collection.immutable.Stack
|
import collection.immutable.Stack
|
||||||
import akka.routing.{ NoRouter, RouterConfig }
|
import akka.routing._
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory for Props instances.
|
* Factory for Props instances.
|
||||||
|
*
|
||||||
* Props is a ActorRef configuration object, that is thread safe and fully sharable.
|
* Props is a ActorRef configuration object, that is thread safe and fully sharable.
|
||||||
|
*
|
||||||
* Used when creating new actors through; <code>ActorSystem.actorOf</code> and <code>ActorContext.actorOf</code>.
|
* Used when creating new actors through; <code>ActorSystem.actorOf</code> and <code>ActorContext.actorOf</code>.
|
||||||
*/
|
*/
|
||||||
object Props {
|
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
|
* 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.
|
* of the supplied type using the default constructor.
|
||||||
|
*
|
||||||
|
* Scala API.
|
||||||
*/
|
*/
|
||||||
def apply[T <: Actor: ClassManifest]: Props =
|
def apply[T <: Actor: ClassManifest]: Props =
|
||||||
default.withCreator(implicitly[ClassManifest[T]].erasure.asInstanceOf[Class[_ <: Actor]].newInstance)
|
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
|
* Returns a Props that has default values except for "creator" which will be a function that creates an instance
|
||||||
* using the supplied thunk.
|
* using the supplied thunk.
|
||||||
|
*
|
||||||
|
* Scala API.
|
||||||
*/
|
*/
|
||||||
def apply(creator: ⇒ Actor): Props =
|
def apply(creator: ⇒ Actor): Props =
|
||||||
default.withCreator(creator)
|
default.withCreator(creator)
|
||||||
|
|
@ -87,7 +93,17 @@ object Props {
|
||||||
* {{{
|
* {{{
|
||||||
* val props = Props[MyActor]
|
* val props = Props[MyActor]
|
||||||
* val props = Props(new 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].withTimeout(timeout)
|
||||||
|
* val props = Props[MyActor].withRouter[RoundRobinRouter]
|
||||||
|
* val props = Props[MyActor].withRouter(new RoundRobinRouter(..))
|
||||||
* val props = Props[MyActor].withFaultHandler(OneForOneStrategy {
|
* val props = Props[MyActor].withFaultHandler(OneForOneStrategy {
|
||||||
* case e: IllegalStateException ⇒ Resume
|
* case e: IllegalStateException ⇒ Resume
|
||||||
* })
|
* })
|
||||||
|
|
@ -103,19 +119,20 @@ object Props {
|
||||||
* }
|
* }
|
||||||
* });
|
* });
|
||||||
* Props props = new Props().withCreator(new UntypedActorFactory() { ... });
|
* Props props = new Props().withCreator(new UntypedActorFactory() { ... });
|
||||||
* Props props = new Props().withTimeout(timeout);
|
* Props props = new Props(MyActor.class).withTimeout(timeout);
|
||||||
* Props props = new Props().withFaultHandler(new OneForOneStrategy(...));
|
* 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,
|
case class Props(
|
||||||
@transient dispatcher: MessageDispatcher = Props.defaultDispatcher,
|
creator: () ⇒ Actor = Props.defaultCreator,
|
||||||
timeout: Timeout = Props.defaultTimeout,
|
@transient dispatcher: MessageDispatcher = Props.defaultDispatcher,
|
||||||
faultHandler: FaultHandlingStrategy = Props.defaultFaultHandler,
|
timeout: Timeout = Props.defaultTimeout,
|
||||||
routerConfig: RouterConfig = Props.defaultRoutedProps) {
|
faultHandler: FaultHandlingStrategy = Props.defaultFaultHandler,
|
||||||
|
routerConfig: RouterConfig = Props.defaultRoutedProps) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No-args constructor that sets all the default values.
|
* No-args constructor that sets all the default values.
|
||||||
* Java API.
|
|
||||||
*/
|
*/
|
||||||
def this() = this(
|
def this() = this(
|
||||||
creator = Props.defaultCreator,
|
creator = Props.defaultCreator,
|
||||||
|
|
@ -144,43 +161,58 @@ case class Props(creator: () ⇒ Actor = Props.defaultCreator,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new Props with the specified creator set.
|
* Returns a new Props with the specified creator set.
|
||||||
|
*
|
||||||
* Scala API.
|
* Scala API.
|
||||||
*/
|
*/
|
||||||
def withCreator(c: ⇒ Actor) = copy(creator = () ⇒ c)
|
def withCreator(c: ⇒ Actor) = copy(creator = () ⇒ c)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new Props with the specified creator set.
|
* Returns a new Props with the specified creator set.
|
||||||
|
*
|
||||||
* Java API.
|
* Java API.
|
||||||
*/
|
*/
|
||||||
def withCreator(c: Creator[Actor]) = copy(creator = () ⇒ c.create)
|
def withCreator(c: Creator[Actor]) = copy(creator = () ⇒ c.create)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new Props with the specified creator set.
|
* Returns a new Props with the specified creator set.
|
||||||
|
*
|
||||||
* Java API.
|
* Java API.
|
||||||
*/
|
*/
|
||||||
def withCreator(c: Class[_ <: Actor]) = copy(creator = () ⇒ c.newInstance)
|
def withCreator(c: Class[_ <: Actor]) = copy(creator = () ⇒ c.newInstance)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new Props with the specified dispatcher set.
|
* Returns a new Props with the specified dispatcher set.
|
||||||
* Java API.
|
|
||||||
*/
|
*/
|
||||||
def withDispatcher(d: MessageDispatcher) = copy(dispatcher = d)
|
def withDispatcher(d: MessageDispatcher) = copy(dispatcher = d)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new Props with the specified timeout set
|
* Returns a new Props with the specified timeout set.
|
||||||
* Java API.
|
|
||||||
*/
|
*/
|
||||||
def withTimeout(t: Timeout) = copy(timeout = t)
|
def withTimeout(t: Timeout) = copy(timeout = t)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new Props with the specified faulthandler set.
|
* Returns a new Props with the specified faulthandler set.
|
||||||
* Java API.
|
|
||||||
*/
|
*/
|
||||||
def withFaultHandler(f: FaultHandlingStrategy) = copy(faultHandler = f)
|
def withFaultHandler(f: FaultHandlingStrategy) = copy(faultHandler = f)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new Props with the specified router config set
|
* Returns a new Props with the specified router config set.
|
||||||
* Java API
|
|
||||||
*/
|
*/
|
||||||
def withRouter(r: RouterConfig) = copy(routerConfig = r)
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,4 +8,9 @@ package object routing {
|
||||||
|
|
||||||
type Route = PartialFunction[(akka.actor.ActorRef, Any), Iterable[Destination]]
|
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]
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package akka.docs.actor
|
||||||
|
|
||||||
|
import org.scalatest.junit.JUnitSuite
|
||||||
|
|
||||||
|
class UntypedActorDocTest extends UntypedActorDocTestBase with JUnitSuite
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package akka.docs.actor;
|
package akka.docs.actor;
|
||||||
|
|
||||||
|
import akka.actor.Timeout;
|
||||||
|
|
||||||
//#imports
|
//#imports
|
||||||
import akka.actor.ActorRef;
|
import akka.actor.ActorRef;
|
||||||
import akka.actor.ActorSystem;
|
import akka.actor.ActorSystem;
|
||||||
|
|
@ -33,7 +35,26 @@ import scala.Option;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
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
|
@Test
|
||||||
public void systemActorOf() {
|
public void systemActorOf() {
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
package akka.docs.actor
|
|
||||||
|
|
||||||
import org.scalatest.junit.JUnitSuite
|
|
||||||
|
|
||||||
class UntypedActorTest extends UntypedActorTestBase with JUnitSuite
|
|
||||||
|
|
@ -42,7 +42,7 @@ Here is an example:
|
||||||
Creating Actors with default constructor
|
Creating Actors with default constructor
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java
|
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java
|
||||||
:include: imports,system-actorOf
|
:include: imports,system-actorOf
|
||||||
|
|
||||||
The call to :meth:`actorOf` returns an instance of ``ActorRef``. This is a handle to
|
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
|
.. includecode:: code/akka/docs/actor/FirstUntypedActor.java#context-actorOf
|
||||||
|
|
||||||
Actors are automatically started asynchronously when created.
|
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
|
callback method on the ``UntypedActor`` class. This is an excellent place to
|
||||||
add initialization code for the actor.
|
add initialization code for the actor.
|
||||||
|
|
||||||
|
|
@ -76,26 +76,35 @@ add initialization code for the actor.
|
||||||
Creating Actors with non-default constructor
|
Creating Actors with non-default constructor
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
If your UntypedActor has a constructor that takes parameters then you can't create it using 'actorOf(clazz)'.
|
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'
|
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
|
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
|
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
|
touch state directly in bypass the whole actor dispatching mechanism and create race conditions
|
||||||
which can lead to corrupt data.
|
which can lead to corrupt data.
|
||||||
|
|
||||||
Here is an example:
|
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.
|
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
|
Creating Actors with Props
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
``Props`` is a configuration object to specify additional things for the actor to
|
Actors are created by passing in the ``Props`` object into the ``actorOf`` factory method.
|
||||||
be created, such as the ``MessageDispatcher``.
|
|
||||||
|
|
||||||
.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java#creating-props
|
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#creating-props
|
||||||
|
|
||||||
|
|
||||||
UntypedActor API
|
UntypedActor API
|
||||||
|
|
@ -119,7 +128,7 @@ In addition, it offers:
|
||||||
The remaining visible methods are user-overridable life-cycle hooks which are
|
The remaining visible methods are user-overridable life-cycle hooks which are
|
||||||
described in the following:
|
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`
|
The implementations shown above are the defaults provided by the :class:`UntypedActor`
|
||||||
class.
|
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
|
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
|
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
|
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
|
sent to an actor while it is being restarted will be queued to its mailbox as
|
||||||
usual.
|
usual.
|
||||||
|
|
@ -172,9 +181,9 @@ Stop Hook
|
||||||
|
|
||||||
After stopping an actor, its :meth:`postStop` hook is called, which may be used
|
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
|
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
|
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
|
sent to a stopped actor will be redirected to the :obj:`deadLetters` of the
|
||||||
:obj:`ActorSystem`.
|
:obj:`ActorSystem`.
|
||||||
|
|
||||||
|
|
||||||
Identifying Actors
|
Identifying Actors
|
||||||
|
|
@ -188,7 +197,7 @@ Messages and immutability
|
||||||
|
|
||||||
**IMPORTANT**: Messages can be any kind of object but have to be
|
**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
|
immutable. Akka can’t enforce immutability (yet) so this has to be by
|
||||||
convention.
|
convention.
|
||||||
|
|
||||||
Here is an example of an immutable message:
|
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.
|
Message ordering is guaranteed on a per-sender basis.
|
||||||
|
|
||||||
In all these methods you have the option of passing along your own ``ActorRef``.
|
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
|
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.
|
to your message, since the sender reference is sent along with the message.
|
||||||
|
|
||||||
Tell: Fire-forget
|
Tell: Fire-forget
|
||||||
|
|
@ -229,7 +238,7 @@ to reply to the original sender, by using ``getSender().tell(replyMsg)``.
|
||||||
|
|
||||||
actor.tell("Hello", getSelf());
|
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.
|
:obj:`deadLetters` actor reference in the target actor.
|
||||||
|
|
||||||
Ask: Send-And-Receive-Future
|
Ask: Send-And-Receive-Future
|
||||||
|
|
@ -244,13 +253,13 @@ will immediately return a :class:`Future`:
|
||||||
Future future = actorRef.ask("Hello", timeoutMillis);
|
Future future = actorRef.ask("Hello", timeoutMillis);
|
||||||
|
|
||||||
The receiving actor should reply to this message, which will complete the
|
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.
|
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
|
This is not done automatically when an actor throws an exception while processing a
|
||||||
message.
|
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,
|
If the actor does not complete the future, it will expire after the timeout period,
|
||||||
specified as parameter to the ``ask`` method.
|
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
|
See :ref:`futures-java` for more information on how to await or query a
|
||||||
future.
|
future.
|
||||||
|
|
||||||
The ``onComplete``, ``onResult``, or ``onTimeout`` methods of the ``Future`` can be
|
The ``onComplete``, ``onResult``, or ``onTimeout`` methods of the ``Future`` can be
|
||||||
used to register a callback to get a notification when the Future completes.
|
used to register a callback to get a notification when the Future completes.
|
||||||
Gives you a way to avoid blocking.
|
Gives you a way to avoid blocking.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
When using future callbacks, inside actors you need to carefully avoid closing over
|
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
|
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
|
on the enclosing actor from within the callback. This would break the actor
|
||||||
encapsulation and may introduce synchronization bugs and race conditions because
|
encapsulation and may introduce synchronization bugs and race conditions because
|
||||||
the callback will be scheduled concurrently to the enclosing actor. Unfortunately
|
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:
|
there is not yet a way to detect these illegal accesses at compile time. See also:
|
||||||
:ref:`jmm-shared-state`
|
: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
|
actor is prone to dead-locks, e.g. if obtaining the result depends on
|
||||||
processing another message on this actor).
|
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
|
:include: import-future,using-ask
|
||||||
|
|
||||||
Forward message
|
Forward message
|
||||||
|
|
@ -297,7 +306,7 @@ You need to pass along your context variable as well.
|
||||||
Receive messages
|
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.
|
an abstract method on the ``UntypedActor`` base class that needs to be defined.
|
||||||
|
|
||||||
Here is an example:
|
Here is an example:
|
||||||
|
|
@ -340,17 +349,17 @@ message.
|
||||||
Stopping actors
|
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.
|
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
|
.. code-block:: java
|
||||||
|
|
||||||
actor.stop();
|
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
|
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.
|
depends on the mailbox implementation.
|
||||||
|
|
||||||
When stop is called then a call to the ``def postStop`` callback method will
|
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.
|
All Actors are stopped when the ``ActorSystem`` is stopped.
|
||||||
Supervised actors are stopped when the supervisor is stopped, i.e. children are stopped
|
Supervised actors are stopped when the supervisor is stopped, i.e. children are stopped
|
||||||
when parent is stopped.
|
when parent is stopped.
|
||||||
|
|
||||||
|
|
||||||
PoisonPill
|
PoisonPill
|
||||||
|
|
@ -381,7 +390,7 @@ If the ``PoisonPill`` was sent with ``ask``, the ``Future`` will be completed wi
|
||||||
|
|
||||||
Use it like this:
|
Use it like this:
|
||||||
|
|
||||||
.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java
|
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java
|
||||||
:include: import-actors,poison-pill
|
:include: import-actors,poison-pill
|
||||||
|
|
||||||
.. _UntypedActor.HotSwap:
|
.. _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``:
|
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
|
: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).
|
a Finite State Machine (FSM).
|
||||||
|
|
||||||
Here is another little cute example of ``become`` and ``unbecome`` in action:
|
Here is another little cute example of ``become`` and ``unbecome`` in action:
|
||||||
|
|
@ -432,7 +441,7 @@ through regular supervisor semantics.
|
||||||
|
|
||||||
Use it like this:
|
Use it like this:
|
||||||
|
|
||||||
.. includecode:: code/akka/docs/actor/UntypedActorTestBase.java
|
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java
|
||||||
:include: import-actors,kill
|
:include: import-actors,kill
|
||||||
|
|
||||||
Actors and exceptions
|
Actors and exceptions
|
||||||
|
|
@ -462,9 +471,9 @@ messages on that mailbox, will be there as well.
|
||||||
What happens to the actor
|
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
|
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
|
(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
|
state of the failing actor instance is lost if you don't store and restore it in
|
||||||
``preRestart`` and ``postRestart`` callbacks.
|
``preRestart`` and ``postRestart`` callbacks.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ Creating Actors with default constructor
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
.. includecode:: code/ActorDocSpec.scala
|
.. 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 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
|
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
|
.. 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
|
Creating Actors with Props
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
``Props`` is a configuration object to specify additional things for the actor to
|
Actors are created by passing in the ``Props`` object into the ``actorOf`` factory method.
|
||||||
be created, such as the ``MessageDispatcher``.
|
|
||||||
|
|
||||||
.. includecode:: code/ActorDocSpec.scala#creating-props
|
.. includecode:: code/ActorDocSpec.scala#creating-props
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package akka.docs.actor
|
package akka.docs.actor
|
||||||
|
|
||||||
|
import akka.actor.Timeout
|
||||||
|
|
||||||
//#imports1
|
//#imports1
|
||||||
import akka.actor.Actor
|
import akka.actor.Actor
|
||||||
import akka.actor.Props
|
import akka.actor.Props
|
||||||
|
|
@ -13,6 +15,7 @@ import akka.actor.ActorSystem
|
||||||
import org.scalatest.{ BeforeAndAfterAll, WordSpec }
|
import org.scalatest.{ BeforeAndAfterAll, WordSpec }
|
||||||
import org.scalatest.matchers.MustMatchers
|
import org.scalatest.matchers.MustMatchers
|
||||||
import akka.testkit._
|
import akka.testkit._
|
||||||
|
import akka.util._
|
||||||
import akka.util.duration._
|
import akka.util.duration._
|
||||||
|
|
||||||
//#my-actor
|
//#my-actor
|
||||||
|
|
@ -185,6 +188,23 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
|
||||||
myActor.stop()
|
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 actor with Props" in {
|
||||||
//#creating-props
|
//#creating-props
|
||||||
import akka.actor.Props
|
import akka.actor.Props
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ object Pi extends App {
|
||||||
var start: Long = _
|
var start: Long = _
|
||||||
|
|
||||||
//#create-router
|
//#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
|
//#create-router
|
||||||
|
|
||||||
//#master-receive
|
//#master-receive
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue