From 33ebf24c0fec622869a5306312c3bac3ac889f68 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Wed, 28 Aug 2013 17:13:20 +0200 Subject: [PATCH] =act #3565 Add ClassTag in Props.apply(creator) * Remove deprecated apply without ClassTag --- .../scala/akka/actor/ActorMailboxSpec.scala | 8 ++++++ .../scala/akka/actor/ActorWithStashSpec.scala | 25 ++++++++----------- .../src/main/scala/akka/actor/Props.scala | 21 +++++++++++----- .../scala/akka/testkit/TestActorRef.scala | 4 +-- 4 files changed, 35 insertions(+), 23 deletions(-) diff --git a/akka-actor-tests/src/test/scala/akka/actor/ActorMailboxSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/ActorMailboxSpec.scala index 18d10ad3a6..10ee2bd043 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/ActorMailboxSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/ActorMailboxSpec.scala @@ -128,6 +128,8 @@ object ActorMailboxSpec { class StashQueueReportingActor extends QueueReportingActor with Stash + class StashQueueReportingActorWithParams(i: Int, s: String) extends StashQueueReportingActor + val UnboundedMailboxTypes = Seq(classOf[UnboundedMessageQueueSemantics]) val BoundedMailboxTypes = Seq(classOf[BoundedMessageQueueSemantics]) val UnboundedDeqMailboxTypes = Seq( @@ -174,6 +176,12 @@ class ActorMailboxSpec(conf: Config) extends AkkaSpec(conf) with DefaultTimeout "get an unbounded deque message queue when it's only mixed with Stash" in { checkMailboxQueue(Props[StashQueueReportingActor], "default-override-from-stash", UnboundedDeqMailboxTypes) + checkMailboxQueue(Props(new StashQueueReportingActor), + "default-override-from-stash2", UnboundedDeqMailboxTypes) + checkMailboxQueue(Props(classOf[StashQueueReportingActorWithParams], 17, "hello"), + "default-override-from-stash3", UnboundedDeqMailboxTypes) + checkMailboxQueue(Props(new StashQueueReportingActorWithParams(17, "hello")), + "default-override-from-stash4", UnboundedDeqMailboxTypes) } "get a bounded message queue when it's configured as mailbox" in { diff --git a/akka-actor-tests/src/test/scala/akka/actor/ActorWithStashSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/ActorWithStashSpec.scala index c904950d79..4071d7969a 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/ActorWithStashSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/ActorWithStashSpec.scala @@ -17,7 +17,8 @@ import org.scalatest.junit.JUnitSuiteLike object ActorWithStashSpec { - class StashingActor(implicit sys: ActorSystem) extends Actor with Stash { + class StashingActor extends Actor with Stash { + import context.system def greeted: Receive = { case "bye" ⇒ state.s = "bye" @@ -34,7 +35,7 @@ object ActorWithStashSpec { } } - class StashingTwiceActor(implicit sys: ActorSystem) extends Actor with Stash { + class StashingTwiceActor extends Actor with Stash { def receive = { case "hello" ⇒ try { @@ -48,7 +49,8 @@ object ActorWithStashSpec { } } - class ActorWithProtocol(implicit sys: ActorSystem) extends Actor with Stash { + class ActorWithProtocol extends Actor with Stash { + import context.system def receive = { case "open" ⇒ unstashAll() @@ -73,9 +75,6 @@ object ActorWithStashSpec { val testConf = """ akka.actor.serialize-messages = off - my-dispatcher { - mailbox-type = "akka.dispatch.UnboundedDequeBasedMailbox" - } """ } @@ -86,20 +85,16 @@ class JavaActorWithStashSpec extends StashJavaAPI with JUnitSuiteLike class ActorWithStashSpec extends AkkaSpec(ActorWithStashSpec.testConf) with DefaultTimeout with BeforeAndAfterEach { import ActorWithStashSpec._ - implicit val sys = system - override def atStartup { system.eventStream.publish(Mute(EventFilter[Exception]("Crashing..."))) } override def beforeEach() = state.finished.reset - def myProps(creator: ⇒ Actor): Props = Props(creator).withDispatcher("my-dispatcher") - "An Actor with Stash" must { "stash messages" in { - val stasher = system.actorOf(myProps(new StashingActor)) + val stasher = system.actorOf(Props(new StashingActor)) stasher ! "bye" stasher ! "hello" state.finished.await @@ -107,7 +102,7 @@ class ActorWithStashSpec extends AkkaSpec(ActorWithStashSpec.testConf) with Defa } "support protocols" in { - val protoActor = system.actorOf(myProps(new ActorWithProtocol)) + val protoActor = system.actorOf(Props[ActorWithProtocol]) protoActor ! "open" protoActor ! "write" protoActor ! "open" @@ -120,20 +115,20 @@ class ActorWithStashSpec extends AkkaSpec(ActorWithStashSpec.testConf) with Defa "throw an IllegalStateException if the same messages is stashed twice" in { state.expectedException = new TestLatch - val stasher = system.actorOf(myProps(new StashingTwiceActor)) + val stasher = system.actorOf(Props[StashingTwiceActor]) stasher ! "hello" stasher ! "hello" Await.ready(state.expectedException, 10 seconds) } "process stashed messages after restart" in { - val boss = system.actorOf(myProps(new Supervisor( + val boss = system.actorOf(Props(new Supervisor( OneForOneStrategy(maxNrOfRetries = 2, withinTimeRange = 1 second)(List(classOf[Throwable]))))) val restartLatch = new TestLatch val hasMsgLatch = new TestLatch - val slaveProps = myProps(new Actor with Stash { + val slaveProps = Props(new Actor with Stash { def receive = { case "crash" ⇒ throw new Exception("Crashing...") diff --git a/akka-actor/src/main/scala/akka/actor/Props.scala b/akka-actor/src/main/scala/akka/actor/Props.scala index bf2cd57f77..88eb860980 100644 --- a/akka-actor/src/main/scala/akka/actor/Props.scala +++ b/akka-actor/src/main/scala/akka/actor/Props.scala @@ -63,20 +63,29 @@ object Props { } /** - * Returns a Props that has default values except for "creator" which will be a function that creates an instance + * Scala API: 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: ClassTag](): Props = apply(defaultDeploy, implicitly[ClassTag[T]].runtimeClass, Vector.empty) /** - * Returns a Props that has default values except for "creator" which will be a function that creates an instance + * Scala API: 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. + * CAVEAT: Required mailbox type cannot be detected when using anonymous mixin composition + * when creating the instance. For example, the following will not detect the need for + * `DequeBasedMessageQueueSemantics` as defined in `Stash`: + * {{{ + * 'Props(new Actor with Stash { ... }) + * }}} + * Instead you must create a named class that mixin the trait, + * e.g. `class MyActor extends Actor with Stash`. */ - def apply(creator: ⇒ Actor): Props = default.withCreator(creator) + def apply[T <: Actor: ClassTag](creator: ⇒ T): Props = + mkProps(implicitly[ClassTag[T]].runtimeClass, () ⇒ creator) + + private def mkProps(classOfActor: Class[_], ctor: () ⇒ Actor): Props = + Props(classOf[TypedCreatorFunctionConsumer], classOfActor, ctor) /** * Returns a Props that has default values except for "creator" which will be a function that creates an instance diff --git a/akka-testkit/src/main/scala/akka/testkit/TestActorRef.scala b/akka-testkit/src/main/scala/akka/testkit/TestActorRef.scala index a9f8371981..627d09d9a8 100644 --- a/akka-testkit/src/main/scala/akka/testkit/TestActorRef.scala +++ b/akka-testkit/src/main/scala/akka/testkit/TestActorRef.scala @@ -127,9 +127,9 @@ object TestActorRef { "$" + akka.util.Helpers.base64(l) } - def apply[T <: Actor](factory: ⇒ T)(implicit system: ActorSystem): TestActorRef[T] = apply[T](Props(factory), randomName) + def apply[T <: Actor](factory: ⇒ T)(implicit system: ActorSystem): TestActorRef[T] = apply[T](Props.empty.withCreator(factory), randomName) - def apply[T <: Actor](factory: ⇒ T, name: String)(implicit system: ActorSystem): TestActorRef[T] = apply[T](Props(factory), name) + def apply[T <: Actor](factory: ⇒ T, name: String)(implicit system: ActorSystem): TestActorRef[T] = apply[T](Props.empty.withCreator(factory), name) def apply[T <: Actor](props: Props)(implicit system: ActorSystem): TestActorRef[T] = apply[T](props, randomName)