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:
Jonas Bonér 2011-12-14 14:05:44 +01:00
parent 66e7155ef1
commit 80600abc33
10 changed files with 178 additions and 83 deletions

View file

@ -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

View file

@ -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; <code>ActorSystem.actorOf</code> and <code>ActorContext.actorOf</code>.
*/
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,11 +119,13 @@ 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,
case class Props(
creator: () Actor = Props.defaultCreator,
@transient dispatcher: MessageDispatcher = Props.defaultDispatcher,
timeout: Timeout = Props.defaultTimeout,
faultHandler: FaultHandlingStrategy = Props.defaultFaultHandler,
@ -115,7 +133,6 @@ case class Props(creator: () ⇒ Actor = Props.defaultCreator,
/**
* 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)
}
}

View file

@ -8,4 +8,9 @@ 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]
}

View file

@ -0,0 +1,5 @@
package akka.docs.actor
import org.scalatest.junit.JUnitSuite
class UntypedActorDocTest extends UntypedActorDocTestBase with JUnitSuite

View file

@ -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() {

View file

@ -1,5 +0,0 @@
package akka.docs.actor
import org.scalatest.junit.JUnitSuite
class UntypedActorTest extends UntypedActorTestBase with JUnitSuite

View file

@ -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
@ -85,17 +85,26 @@ 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.
@ -250,7 +259,7 @@ To complete the future with an exception you need send a Failure message to the
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.
@ -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
@ -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,7 +411,7 @@ 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
@ -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

View file

@ -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

View file

@ -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

View file

@ -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