diff --git a/akka-actor-tests/src/test/java/akka/actor/ActorCreationTest.java b/akka-actor-tests/src/test/java/akka/actor/ActorCreationTest.java index 82bcb7d422..05040afb0e 100644 --- a/akka-actor-tests/src/test/java/akka/actor/ActorCreationTest.java +++ b/akka-actor-tests/src/test/java/akka/actor/ActorCreationTest.java @@ -22,7 +22,7 @@ public class ActorCreationTest { }); assert false; } catch(IllegalArgumentException e) { - assertEquals("cannot use non-static local Creator to create actors; make it static or top-level", e.getMessage()); + assertEquals("cannot use non-static local Creator to create actors; make it static (e.g. local to a static method) or top-level", e.getMessage()); } } diff --git a/akka-actor-tests/src/test/java/akka/actor/JavaAPI.java b/akka-actor-tests/src/test/java/akka/actor/JavaAPI.java index d834dea1ca..640c16cf01 100644 --- a/akka-actor-tests/src/test/java/akka/actor/JavaAPI.java +++ b/akka-actor-tests/src/test/java/akka/actor/JavaAPI.java @@ -48,14 +48,18 @@ public class JavaAPI { ActorRef ref = system.actorOf(Props.create(JavaAPITestActor.class)); assertNotNull(ref); } - - @Test - public void mustBeAbleToCreateActorRefFromFactory() { - ActorRef ref = system.actorOf(Props.empty().withCreator(new Creator() { + + public static Props mkProps() { + return Props.create(new Creator() { public Actor create() { return new JavaAPITestActor(); } - })); + }); + } + + @Test + public void mustBeAbleToCreateActorRefFromFactory() { + ActorRef ref = system.actorOf(mkProps()); assertNotNull(ref); } diff --git a/akka-actor-tests/src/test/scala/akka/actor/SupervisorHierarchySpec.scala b/akka-actor-tests/src/test/scala/akka/actor/SupervisorHierarchySpec.scala index 56a58ebe04..6c483969b0 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/SupervisorHierarchySpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/SupervisorHierarchySpec.scala @@ -159,7 +159,7 @@ object SupervisorHierarchySpec { val propsTemplate = Props.empty.withDispatcher("hierarchy") (1 to kids).map { (id) ⇒ val kidSize = if (rest > 0) { rest -= 1; sizes + 1 } else sizes - val props = propsTemplate.withCreator(new Hierarchy(kidSize, breadth, listener, myLevel + 1, random)) + val props = Props(new Hierarchy(kidSize, breadth, listener, myLevel + 1, random)).withDeploy(propsTemplate.deploy) (context.watch(context.actorOf(props, id.toString)).path, kidSize) }(collection.breakOut) } else Map() diff --git a/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala b/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala index 065585b3b4..2e01b5702c 100644 --- a/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala @@ -272,11 +272,6 @@ class VerifySerializabilitySpec extends AkkaSpec(SerializationTests.verifySerial val b = system.actorOf(Props(new FooActor)) system stop b - val c = system.actorOf(Props.empty.withCreator(new UntypedActorFactory { - def create() = new FooUntypedActor - })) - system stop c - intercept[IllegalArgumentException] { val d = system.actorOf(Props(new NonSerializableActor(system))) } diff --git a/akka-actor/src/main/scala/akka/actor/ActorCell.scala b/akka-actor/src/main/scala/akka/actor/ActorCell.scala index e3a4838b4c..7c1a96c1d3 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorCell.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorCell.scala @@ -310,7 +310,7 @@ private[akka] object ActorCell { final val emptyActorRefSet: Set[ActorRef] = immutable.HashSet.empty - final val terminatedProps: Props = Props(() ⇒ throw new IllegalActorStateException("This Actor has been terminated")) + final val terminatedProps: Props = Props((throw new IllegalActorStateException("This Actor has been terminated")): Actor) final val undefinedUid = 0 diff --git a/akka-actor/src/main/scala/akka/actor/Props.scala b/akka-actor/src/main/scala/akka/actor/Props.scala index f73e141d9f..b7ccd00849 100644 --- a/akka-actor/src/main/scala/akka/actor/Props.scala +++ b/akka-actor/src/main/scala/akka/actor/Props.scala @@ -51,7 +51,7 @@ object Props { /** * The default Props instance, uses the settings from the Props object starting with default*. */ - final val default = new Props() + final val default = Props(defaultDeploy, classOf[CreatorFunctionConsumer], List(defaultCreator)) /** * INTERNAL API @@ -87,36 +87,6 @@ object Props { 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 - * using the supplied thunk. - */ - @deprecated("give class and arguments instead", "2.2") - def apply(creator: Creator[_ <: Actor]): Props = default.withCreator(creator.create) - - /** - * The deprecated legacy constructor. - */ - @deprecated("use Props.withDispatcher and friends", "2.2") - def apply( - creator: () ⇒ Actor = Props.defaultCreator, - dispatcher: String = Deploy.NoDispatcherGiven, - routerConfig: RouterConfig = Props.defaultRoutedProps, - deploy: Deploy = Props.defaultDeploy): Props = { - - val d1 = if (dispatcher != Deploy.NoDispatcherGiven) deploy.copy(dispatcher = dispatcher) else deploy - val d2 = if (routerConfig != Props.defaultRoutedProps) d1.copy(routerConfig = routerConfig) else d1 - val p = Props(classOf[CreatorFunctionConsumer], creator) - if (d2 != Props.defaultDeploy) p.withDeploy(d2) else p - } - - /** - * The deprecated legacy extractor. - */ - @deprecated("use three-argument version", "2.2") - def unapply(p: Props)(dummy: Int = 0): Option[(() ⇒ Actor, String, RouterConfig, Deploy)] = - Some((p.creator, p.dispatcher, p.routerConfig, p.deploy)) - /** * Scala API: create a Props given a class and its constructor arguments. */ @@ -133,7 +103,7 @@ object Props { */ def create[T <: Actor](creator: Creator[T]): Props = { if ((creator.getClass.getEnclosingClass ne null) && (creator.getClass.getModifiers & Modifier.STATIC) == 0) - throw new IllegalArgumentException("cannot use non-static local Creator to create actors; make it static or top-level") + throw new IllegalArgumentException("cannot use non-static local Creator to create actors; make it static (e.g. local to a static method) or top-level") val ac = classOf[Actor] val actorClass = Reflect.findMarker(creator.getClass, classOf[Creator[_]]) match { case t: ParameterizedType ⇒ @@ -199,37 +169,6 @@ final case class Props(deploy: Deploy, clazz: Class[_], args: immutable.Seq[Any] // validate producer constructor signature; throws IllegalArgumentException if invalid producer - /** - * No-args constructor that sets all the default values. - * - * @deprecated use `Props.create(clazz, args ...)` instead - */ - @deprecated("use Props.create()", "2.2") - def this() = this(Props.defaultDeploy, classOf[CreatorFunctionConsumer], List(Props.defaultCreator)) - - /** - * Java API: create Props from an [[UntypedActorFactory]] - * - * @deprecated use `Props.create(clazz, args ...)` instead; this method has been - * deprecated because it encourages creating Props which contain - * non-serializable inner classes, making them also - * non-serializable - */ - @deprecated("use Props.create()", "2.2") - def this(factory: UntypedActorFactory) = this(Props.defaultDeploy, classOf[UntypedActorFactoryConsumer], List(factory)) - - /** - * Java API: create Props from a given [[java.lang.Class]] - * - * @deprecated use Props.create(clazz) instead; deprecated since it duplicates - * another API - */ - @deprecated("use Props.create()", "2.2") - def this(actorClass: Class[_ <: Actor]) = this(Props.defaultDeploy, actorClass, List.empty) - - @deprecated("There is no use-case for this method anymore", "2.2") - def creator: () ⇒ Actor = newActor - /** * Convenience method for extracting the dispatcher information from the * contained [[Deploy]] instance. @@ -254,36 +193,6 @@ final case class Props(deploy: Deploy, clazz: Class[_], args: immutable.Seq[Any] */ def routerConfig: RouterConfig = deploy.routerConfig - /** - * Scala API: Returns a new Props with the specified creator set. - * - * The creator must not return the same instance multiple times. - */ - @deprecated("use Props(...).withDeploy(other.deploy)", "2.2") - def withCreator(c: ⇒ Actor): Props = copy(clazz = classOf[CreatorFunctionConsumer], args = (() ⇒ c) :: Nil) - - /** - * Java API: Returns a new Props with the specified creator set. - * - * The creator must not return the same instance multiple times. - * - * @deprecated use `Props.create(clazz, args ...)` instead; this method has been - * deprecated because it encourages creating Props which contain - * non-serializable inner classes, making them also - * non-serializable - */ - @deprecated("use Props.create(clazz, args ...).withDeploy(other.deploy) instead", "2.2") - def withCreator(c: Creator[Actor]): Props = copy(clazz = classOf[CreatorConsumer], args = classOf[Actor] :: c :: Nil) - - /** - * Returns a new Props with the specified creator set. - * - * @deprecated use Props.create(clazz) instead; deprecated since it duplicates - * another API - */ - @deprecated("use Props.create(clazz, args).withDeploy(other.deploy)", "2.2") - def withCreator(c: Class[_ <: Actor]): Props = copy(clazz = c, args = Nil) - /** * Returns a new Props with the specified dispatcher set. */ diff --git a/akka-actor/src/main/scala/akka/actor/TypedActor.scala b/akka-actor/src/main/scala/akka/actor/TypedActor.scala index ce1c7dbc5a..1f36a4dfce 100644 --- a/akka-actor/src/main/scala/akka/actor/TypedActor.scala +++ b/akka-actor/src/main/scala/akka/actor/TypedActor.scala @@ -75,7 +75,7 @@ trait TypedActorFactory { val proxyVar = new AtomVar[R] //Chicken'n'egg-resolver val c = props.creator //Cache this to avoid closing over the Props val i = props.interfaces //Cache this to avoid closing over the Props - val ap = props.actorProps.withCreator(new TypedActor.TypedActor[R, T](proxyVar, c(), i)) + val ap = Props(new TypedActor.TypedActor[R, T](proxyVar, c(), i)).withDeploy(props.actorProps.deploy) typedActor.createActorRefProxy(props, proxyVar, actorFactory.actorOf(ap)) } @@ -86,7 +86,7 @@ trait TypedActorFactory { val proxyVar = new AtomVar[R] //Chicken'n'egg-resolver val c = props.creator //Cache this to avoid closing over the Props val i = props.interfaces //Cache this to avoid closing over the Props - val ap = props.actorProps.withCreator(new akka.actor.TypedActor.TypedActor[R, T](proxyVar, c(), i)) + val ap = Props(new akka.actor.TypedActor.TypedActor[R, T](proxyVar, c(), i)).withDeploy(props.actorProps.deploy) typedActor.createActorRefProxy(props, proxyVar, actorFactory.actorOf(ap, name)) } @@ -619,7 +619,7 @@ case class TypedProps[T <: AnyRef] protected[TypedProps] ( def actorProps(): Props = if (dispatcher == Props.default.dispatcher) Props.default.withDeploy(deploy) - else Props(dispatcher = dispatcher).withDeploy(deploy) + else Props.default.withDispatcher(dispatcher).withDeploy(deploy) } /** diff --git a/akka-actor/src/main/scala/akka/actor/dungeon/Dispatch.scala b/akka-actor/src/main/scala/akka/actor/dungeon/Dispatch.scala index 2d1604de65..6ab3ec4879 100644 --- a/akka-actor/src/main/scala/akka/actor/dungeon/Dispatch.scala +++ b/akka-actor/src/main/scala/akka/actor/dungeon/Dispatch.scala @@ -58,8 +58,11 @@ private[akka] trait Dispatch { this: ActorCell ⇒ case _: ProducesMessageQueue[_] if system.mailboxes.hasRequiredType(actorClass) ⇒ val req = system.mailboxes.getRequiredType(actorClass) if (req isInstance mbox.messageQueue) Create(None) - else Create(Some(ActorInitializationException(self, - s"Actor [$self] requires mailbox type [$req] got [${mbox.messageQueue.getClass.getName}]"))) + else { + val gotType = if (mbox.messageQueue == null) "null" else mbox.messageQueue.getClass.getName + Create(Some(ActorInitializationException(self, + s"Actor [$self] requires mailbox type [$req] got [$gotType]"))) + } case _ ⇒ Create(None) } diff --git a/akka-docs/rst/java/code/docs/actor/UntypedActorDocTest.java b/akka-docs/rst/java/code/docs/actor/UntypedActorDocTest.java index 1f478ee009..bc5f8d9e7b 100644 --- a/akka-docs/rst/java/code/docs/actor/UntypedActorDocTest.java +++ b/akka-docs/rst/java/code/docs/actor/UntypedActorDocTest.java @@ -11,14 +11,17 @@ import static akka.pattern.Patterns.pipe; import static akka.pattern.Patterns.gracefulStop; //#import-gracefulStop + import java.util.ArrayList; import java.util.Iterator; import java.util.concurrent.TimeUnit; import akka.testkit.AkkaJUnitActorSystemResource; + import org.junit.ClassRule; import org.junit.Test; + //#import-gracefulStop import scala.concurrent.Await; //#import-ask @@ -119,43 +122,6 @@ public class UntypedActorDocTest { } //#parametric-creator - @SuppressWarnings("deprecation") - @Test - public void createPropsDeprecated() { - //#creating-props-deprecated - // DEPRECATED: encourages to close over enclosing class - final Props props1 = new Props(new UntypedActorFactory() { - private static final long serialVersionUID = 1L; - @Override - public UntypedActor create() throws Exception { - return new MyUntypedActor(); - } - }); - - // DEPRECATED: encourages to close over enclosing class - final Props props2 = new Props().withCreator(new UntypedActorFactory() { - private static final long serialVersionUID = 1L; - @Override - public UntypedActor create() throws Exception { - return new MyUntypedActor(); - } - }); - - // these are DEPRECATED due to duplicate functionality with Props.create() - final Props props3 = new Props(MyUntypedActor.class); - final Props props4 = new Props().withCreator(MyUntypedActor.class); - //#creating-props-deprecated - new JavaTestKit(system) { - { - for (Props props : new Props[] { props1, props2, props3, props4 }) { - final ActorRef a = system.actorOf(props); - a.tell("hello", getRef()); - expectMsgEquals("hello"); - } - } - }; - } - @Test public void systemActorOf() { //#system-actorOf @@ -538,8 +504,15 @@ public class UntypedActorDocTest { * @return a Props for creating this actor, which can then be further configured * (e.g. calling `.withDispatcher()` on it) */ - public static Props props(int magicNumber) { - return Props.create(DemoActor.class, magicNumber); + public static Props props(final int magicNumber) { + return Props.create(new Creator() { + private static final long serialVersionUID = 1L; + + @Override + public DemoActor create() throws Exception { + return new DemoActor(magicNumber); + } + }); } final int magicNumber; diff --git a/akka-docs/rst/java/untyped-actors.rst b/akka-docs/rst/java/untyped-actors.rst index 6b978b8fca..4a28a1f3e6 100644 --- a/akka-docs/rst/java/untyped-actors.rst +++ b/akka-docs/rst/java/untyped-actors.rst @@ -65,52 +65,22 @@ example of a parametric factory could be: .. includecode:: code/docs/actor/UntypedActorDocTest.java#parametric-creator -Deprecated Variants -^^^^^^^^^^^^^^^^^^^ +.. note:: -Up to Akka 2.1 there were also the following possibilities (which are retained -for a migration period): - -.. includecode:: code/docs/actor/UntypedActorDocTest.java#import-untypedActor -.. includecode:: code/docs/actor/UntypedActorDocTest.java#creating-props-deprecated - -The last two are deprecated because their functionality is available in full -through :meth:`Props.create()`. - -The first two are deprecated because the resulting :class:`UntypedActorFactory` -is typically a local class which means that it implicitly carries a reference -to the enclosing class. This can easily make the resulting :class:`Props` -non-serializable, e.g. when the enclosing class is an :class:`Actor`. Akka -advocates location transparency, meaning that an application written with -actors should just work when it is deployed over multiple network nodes, and -non-serializable actor factories would break this principle. In case indirect -actor creation is needed—for example when using dependency injection—there is -the possibility to use an :class:`IndirectActorProducer` as described below. - -There were two use-cases for these methods: passing constructor arguments to -the actor—which is solved by the newly introduced :meth:`Props.create()` method -above—and creating actors “on the spot” as anonymous classes. The latter should -be solved by making these actors named inner classes instead (if they are not -``static`` then the enclosing instance’s ``this`` reference needs to be passed -as the first argument). - -.. warning:: - - Declaring one actor within another is very dangerous and breaks actor - encapsulation unless the nested actor is a static inner class. Never pass an - actor’s ``this`` reference into :class:`Props`! + In order for mailbox requirements—like using a deque-based mailbox for actors + using the stash—to be picked up, the actor type needs to be known before + creating it, which is what the :class:`Creator` type argument allows. + Therefore make sure to use the specific type for your actors wherever + possible. Recommended Practices ^^^^^^^^^^^^^^^^^^^^^ It is a good idea to provide static factory methods on the :class:`UntypedActor` which help keeping the creation of suitable -:class:`Props` as close to the actor definition as possible, thus containing -the gap in type-safety introduced by reflective instantiation within a single -class instead of spreading it out across a whole code-base. This helps -especially when refactoring the actor’s constructor signature at a later point, -where compiler checks will allow this modification to be done with greater -confidence than without. +:class:`Props` as close to the actor definition as possible. This also allows +usage of the :class:`Creator`-based methods which statically verify that the +used constructor actually exists instead relying only on a runtime check. .. includecode:: code/docs/actor/UntypedActorDocTest.java#props-factory diff --git a/akka-docs/rst/project/migration-guide-2.2.x-2.3.x.rst b/akka-docs/rst/project/migration-guide-2.2.x-2.3.x.rst index 6419e27675..611310bcc6 100644 --- a/akka-docs/rst/project/migration-guide-2.2.x-2.3.x.rst +++ b/akka-docs/rst/project/migration-guide-2.2.x-2.3.x.rst @@ -171,6 +171,7 @@ The following, previously deprecated, features have been removed: * `event-handlers renamed to loggers `_ * `API changes to FSM and TestFSMRef `_ * DefaultScheduler superseded by LightArrayRevolverScheduler + * all previously deprecated construction and deconstruction methods for Props publishCurrentClusterState is Deprecated ======================================== diff --git a/akka-docs/rst/scala/actors.rst b/akka-docs/rst/scala/actors.rst index ba6159fa65..882180c07f 100644 --- a/akka-docs/rst/scala/actors.rst +++ b/akka-docs/rst/scala/actors.rst @@ -71,43 +71,37 @@ dispatcher to use, see more below). Here are some examples of how to create a .. includecode:: code/docs/actor/ActorDocSpec.scala#creating-props -The last line shows how to pass constructor arguments to the :class:`Actor` -being created. The presence of a matching constructor is verified during -construction of the :class:`Props` object, resulting in an +The second variant shows how to pass constructor arguments to the +:class:`Actor` being created, but it should only be used outside of actors as +explained below. + +The last line shows a possibility to pass constructor arguments regardless of +the context it is being used in. The presence of a matching constructor is +verified during construction of the :class:`Props` object, resulting in an :class:`IllegalArgumentEception` if no or multiple matching constructors are found. -Deprecated Variants -^^^^^^^^^^^^^^^^^^^ - -Up to Akka 2.1 there were also the following possibilities (which are retained -for a migration period): +Dangerous Variants +^^^^^^^^^^^^^^^^^^ .. includecode:: code/docs/actor/ActorDocSpec.scala#creating-props-deprecated -The first one is deprecated because the case class structure changed between -Akka 2.1 and 2.2. - -The two variants in the middle are deprecated because :class:`Props` are -primarily concerned with actor creation and thus the “creator” part should be -explicitly set when creating an instance. In case you want to deploy one actor -in the same was as another, simply use -``Props(...).withDeploy(otherProps.deploy)``. - -The last one is not technically deprecated, but it is not recommended because -it encourages to close over the enclosing scope, resulting in non-serializable +This method is not recommended to be used within another actor because it +encourages to close over the enclosing scope, resulting in non-serializable :class:`Props` and possibly race conditions (breaking the actor encapsulation). We will provide a macro-based solution in a future release which allows similar syntax without the headaches, at which point this variant will be properly -deprecated. +deprecated. On the other hand using this variant in a :class:`Props` factory in +the actor’s companion object as documented under “Recommended Practices” below +is completely fine. There were two use-cases for these methods: passing constructor arguments to the actor—which is solved by the newly introduced -:meth:`Props.apply(clazz, args)` method above—and creating actors “on the spot” -as anonymous classes. The latter should be solved by making these actors named -inner classes instead (if they are not declared within a top-level ``object`` -then the enclosing instance’s ``this`` reference needs to be passed as the -first argument). +:meth:`Props.apply(clazz, args)` method above or the recommended practice +below—and creating actors “on the spot” as anonymous classes. The latter should +be solved by making these actors named classes instead (if they are not +declared within a top-level ``object`` then the enclosing instance’s ``this`` +reference needs to be passed as the first argument). .. warning:: @@ -119,12 +113,10 @@ Recommended Practices It is a good idea to provide factory methods on the companion object of each :class:`Actor` which help keeping the creation of suitable :class:`Props` as -close to the actor definition as possible, thus containing the gap in -type-safety introduced by reflective instantiation within a single class -instead of spreading it out across a whole code-base. This helps especially -when refactoring the actor’s constructor signature at a later point, where -compiler checks will allow this modification to be done with greater confidence -than without. +close to the actor definition as possible. This also avoids the pitfalls +associated with using the ``Props.apply(...)`` method which takes a by-name +argument, since within a companion object the given code block will not retain +a reference to its enclosing scope: .. includecode:: code/docs/actor/ActorDocSpec.scala#props-factory diff --git a/akka-docs/rst/scala/code/docs/actor/ActorDocSpec.scala b/akka-docs/rst/scala/code/docs/actor/ActorDocSpec.scala index 4f5d86ef52..286f171e2e 100644 --- a/akka-docs/rst/scala/code/docs/actor/ActorDocSpec.scala +++ b/akka-docs/rst/scala/code/docs/actor/ActorDocSpec.scala @@ -59,7 +59,7 @@ class DemoActorWrapper extends Actor { * @return a Props for creating this actor, which can then be further configured * (e.g. calling `.withDispatcher()` on it) */ - def props(magicNumber: Int): Props = Props(classOf[DemoActor], magicNumber) + def props(magicNumber: Int): Props = Props(new DemoActor(magicNumber)) } class DemoActor(magicNumber: Int) extends Actor { @@ -68,9 +68,16 @@ class DemoActorWrapper extends Actor { } } - // ... - - context.actorOf(DemoActor.props(42), "demo") + class SomeOtherActor extends Actor { + // Props(new DemoActor(42)) would not be safe + context.actorOf(DemoActor.props(42), "demo") + // ... + //#props-factory + def receive = { + case msg => + } + //#props-factory + } //#props-factory def receive = Actor.emptyBehavior @@ -239,22 +246,13 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) { import akka.actor.Props val props1 = Props[MyActor] + val props2 = Props(new ActorWithArgs("arg")) // careful, see below val props3 = Props(classOf[ActorWithArgs], "arg") //#creating-props //#creating-props-deprecated - // DEPRECATED: old case class signature - val props4 = Props( - creator = { () => new MyActor }, - dispatcher = "my-dispatcher") - - // DEPRECATED due to duplicate functionality with Props.apply() - val props5 = props1.withCreator(new MyActor) - - // DEPRECATED due to duplicate functionality with Props.apply() - val props6 = props1.withCreator(classOf[MyActor]) - - // NOT RECOMMENDED: encourages to close over enclosing class + // NOT RECOMMENDED within another actor: + // encourages to close over enclosing class val props7 = Props(new MyActor) //#creating-props-deprecated } @@ -305,7 +303,10 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) { "helloBean") //#creating-indirectly } - val actorRef = a.actorRef + val actorRef = { + import scala.language.reflectiveCalls + a.actorRef + } val message = 42 implicit val self = testActor diff --git a/akka-remote/src/test/scala/akka/remote/serialization/DaemonMsgCreateSerializerSpec.scala b/akka-remote/src/test/scala/akka/remote/serialization/DaemonMsgCreateSerializerSpec.scala index ff82ae948b..7beb77b239 100644 --- a/akka-remote/src/test/scala/akka/remote/serialization/DaemonMsgCreateSerializerSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/serialization/DaemonMsgCreateSerializerSpec.scala @@ -48,7 +48,7 @@ class DaemonMsgCreateSerializerSpec extends AkkaSpec { "serialize and de-serialize DaemonMsgCreate with function creator" in { verifySerialization { DaemonMsgCreate( - props = Props.empty.withCreator(new MyActor), + props = Props(new MyActor), deploy = Deploy(), path = "foo", supervisor = supervisor) diff --git a/akka-testkit/src/main/scala/akka/testkit/CallingThreadDispatcher.scala b/akka-testkit/src/main/scala/akka/testkit/CallingThreadDispatcher.scala index 78607fcf16..ebbb663c26 100644 --- a/akka-testkit/src/main/scala/akka/testkit/CallingThreadDispatcher.scala +++ b/akka-testkit/src/main/scala/akka/testkit/CallingThreadDispatcher.scala @@ -320,6 +320,12 @@ class CallingThreadMailbox(_receiver: akka.actor.Cell, val mailboxType: MailboxT } } + /** + * This is only a marker to be put in the messageQueue’s stead to make error + * messages pertaining to violated mailbox type requirements less cryptic. + */ + override val messageQueue: MessageQueue = q.get + override def enqueue(receiver: ActorRef, msg: Envelope): Unit = q.get.enqueue(receiver, msg) override def dequeue(): Envelope = throw new UnsupportedOperationException("CallingThreadMailbox cannot dequeue normally") override def hasMessages: Boolean = q.get.hasMessages diff --git a/akka-testkit/src/main/scala/akka/testkit/TestActorRef.scala b/akka-testkit/src/main/scala/akka/testkit/TestActorRef.scala index 627d09d9a8..dee7437dcb 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.empty.withCreator(factory), randomName) + def apply[T <: Actor: ClassTag](factory: ⇒ T)(implicit system: ActorSystem): TestActorRef[T] = apply[T](Props(factory), randomName) - def apply[T <: Actor](factory: ⇒ T, name: String)(implicit system: ActorSystem): TestActorRef[T] = apply[T](Props.empty.withCreator(factory), name) + def apply[T <: Actor: ClassTag](factory: ⇒ T, name: String)(implicit system: ActorSystem): TestActorRef[T] = apply[T](Props(factory), name) def apply[T <: Actor](props: Props)(implicit system: ActorSystem): TestActorRef[T] = apply[T](props, randomName) diff --git a/akka-testkit/src/main/scala/akka/testkit/TestFSMRef.scala b/akka-testkit/src/main/scala/akka/testkit/TestFSMRef.scala index ee795ff302..2bda99c5e9 100644 --- a/akka-testkit/src/main/scala/akka/testkit/TestFSMRef.scala +++ b/akka-testkit/src/main/scala/akka/testkit/TestFSMRef.scala @@ -10,6 +10,7 @@ import akka.dispatch.DispatcherPrerequisites import scala.concurrent.duration.FiniteDuration import akka.dispatch.MessageDispatcher import akka.dispatch.MailboxType +import scala.reflect.ClassTag /** * This is a specialised form of the TestActorRef with support for querying and @@ -89,13 +90,13 @@ class TestFSMRef[S, D, T <: Actor]( object TestFSMRef { - def apply[S, D, T <: Actor](factory: ⇒ T)(implicit ev: T <:< FSM[S, D], system: ActorSystem): TestFSMRef[S, D, T] = { + def apply[S, D, T <: Actor: ClassTag](factory: ⇒ T)(implicit ev: T <:< FSM[S, D], system: ActorSystem): TestFSMRef[S, D, T] = { val impl = system.asInstanceOf[ActorSystemImpl] //TODO ticket #1559 - new TestFSMRef(impl, Props(creator = () ⇒ factory), impl.guardian.asInstanceOf[InternalActorRef], TestActorRef.randomName) + new TestFSMRef(impl, Props(factory), impl.guardian.asInstanceOf[InternalActorRef], TestActorRef.randomName) } - def apply[S, D, T <: Actor](factory: ⇒ T, name: String)(implicit ev: T <:< FSM[S, D], system: ActorSystem): TestFSMRef[S, D, T] = { + def apply[S, D, T <: Actor: ClassTag](factory: ⇒ T, name: String)(implicit ev: T <:< FSM[S, D], system: ActorSystem): TestFSMRef[S, D, T] = { val impl = system.asInstanceOf[ActorSystemImpl] //TODO ticket #1559 - new TestFSMRef(impl, Props(creator = () ⇒ factory), impl.guardian.asInstanceOf[InternalActorRef], name) + new TestFSMRef(impl, Props(factory), impl.guardian.asInstanceOf[InternalActorRef], name) } }