Merge remote-tracking branch 'origin/wip-simplify-configuring-new-router-in-props-jboner'

Signed-off-by: Jonas Bonér <jonas@jonasboner.com>
This commit is contained in:
Jonas Bonér 2011-12-15 10:06:04 +01:00
commit b4f1978b37
8 changed files with 117 additions and 55 deletions

View file

@ -63,7 +63,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)
}
@ -91,7 +91,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)
}
@ -119,7 +119,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) {
@ -157,7 +157,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")
@ -172,7 +172,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)
}
@ -195,7 +195,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")
@ -209,7 +209,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)
}
@ -232,7 +232,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"
@ -263,7 +263,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"
@ -277,7 +277,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)
}
@ -300,7 +300,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")
@ -314,7 +314,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,16 @@ 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].withFaultHandler(OneForOneStrategy {
* case e: IllegalStateException Resume
* })
@ -103,19 +118,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 +160,42 @@ 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)
}

View file

@ -5,7 +5,5 @@
package akka
package object routing {
type Route = PartialFunction[(akka.actor.ActorRef, Any), Iterable[Destination]]
}
}

View file

@ -4,24 +4,21 @@ package akka.docs.actor;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
//#imports
//#import-future
import akka.dispatch.Future;
import akka.dispatch.Await;
import akka.util.Duration;
import akka.util.Timeout;
//#import-future
//#import-actors
import static akka.actor.Actors.*;
//#import-actors
//#import-procedure
import akka.japi.Procedure;
//#import-procedure
import akka.actor.Props;
@ -38,6 +35,25 @@ import static org.junit.Assert.*;
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() {
//#system-actorOf
@ -78,8 +94,9 @@ public class UntypedActorDocTestBase {
ActorSystem system = ActorSystem.create("MySystem");
//#creating-props
MessageDispatcher dispatcher = system.dispatcherFactory().lookup("my-dispatcher");
ActorRef myActor = system.actorOf(new Props().withCreator(MyUntypedActor.class).withDispatcher(dispatcher),
"myactor");
ActorRef myActor = system.actorOf(
new Props().withCreator(MyUntypedActor.class).withDispatcher(dispatcher),
"myactor");
//#creating-props
myActor.tell("test");
system.shutdown();

View file

@ -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
----------------------------------------
@ -76,26 +93,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.
Creating Actors with Props
--------------------------
``Props`` is a configuration object to specify additional things for the actor to
be created, such as the ``MessageDispatcher``.
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java#creating-props
This way of creating the Actor is also great for integrating with Dependency Injection
(DI) frameworks like Guice or Spring.
UntypedActor API

View file

@ -95,11 +95,19 @@ Here is an example:
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#creating-constructor
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/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 a ``Props`` instance into the ``actorOf`` factory method.
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#creating-props

View file

@ -15,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
@ -187,6 +188,23 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
system.stop(myActor)
}
"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,8 +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(nrOfWorkers)), "pi")
//#create-router
//#master-receive