diff --git a/akka-actor-tests/src/test/scala/akka/actor/dispatch/ActorModelSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/dispatch/ActorModelSpec.scala
index 0afed9cb14..5d4a812e52 100644
--- a/akka-actor-tests/src/test/scala/akka/actor/dispatch/ActorModelSpec.scala
+++ b/akka-actor-tests/src/test/scala/akka/actor/dispatch/ActorModelSpec.scala
@@ -408,34 +408,38 @@ abstract class ActorModelSpec(config: String) extends AkkaSpec(config) with Defa
}
"continue to process messages when a thread gets interrupted and throws an exception" in {
- filterEvents(EventFilter[InterruptedException](), EventFilter[akka.event.Logging.LoggerException]()) {
- implicit val dispatcher = interceptedDispatcher()
- val a = newTestActor(dispatcher.id)
- val f1 = a ? Reply("foo")
- val f2 = a ? Reply("bar")
- val f3 = a ? Interrupt
- Thread.interrupted() // CallingThreadDispatcher may necessitate this
- val f4 = a ? Reply("foo2")
- val f5 = a ? Interrupt
- Thread.interrupted() // CallingThreadDispatcher may necessitate this
- val f6 = a ? Reply("bar2")
+ filterEvents(
+ EventFilter[InterruptedException](),
+ EventFilter[ActorInterruptedException](),
+ EventFilter[akka.event.Logging.LoggerException]()) {
+ implicit val dispatcher = interceptedDispatcher()
+ val a = newTestActor(dispatcher.id)
+ val f1 = a ? Reply("foo")
+ val f2 = a ? Reply("bar")
+ val f3 = a ? Interrupt
+ Thread.interrupted() // CallingThreadDispatcher may necessitate this
+ val f4 = a ? Reply("foo2")
+ val f5 = a ? Interrupt
+ Thread.interrupted() // CallingThreadDispatcher may necessitate this
+ val f6 = a ? Reply("bar2")
- val c = system.scheduler.scheduleOnce(2.seconds) {
- import collection.JavaConverters._
- Thread.getAllStackTraces().asScala foreach {
- case (thread, stack) ⇒
- println(s"$thread:")
- stack foreach (s ⇒ println(s"\t$s"))
+ val c = system.scheduler.scheduleOnce(2.seconds) {
+ import collection.JavaConverters._
+ Thread.getAllStackTraces().asScala foreach {
+ case (thread, stack) ⇒
+ println(s"$thread:")
+ stack foreach (s ⇒ println(s"\t$s"))
+ }
}
+ assert(Await.result(f1, remaining) === "foo")
+ assert(Await.result(f2, remaining) === "bar")
+ assert(Await.result(f4, remaining) === "foo2")
+ assert(intercept[ActorInterruptedException](Await.result(f3, remaining)).getCause.getMessage === "Ping!")
+ assert(Await.result(f6, remaining) === "bar2")
+ assert(intercept[ActorInterruptedException](Await.result(f5, remaining)).getCause.getMessage === "Ping!")
+ c.cancel()
+ Thread.sleep(300) // give the EventFilters a chance of catching all messages
}
- assert(Await.result(f1, remaining) === "foo")
- assert(Await.result(f2, remaining) === "bar")
- assert(Await.result(f4, remaining) === "foo2")
- assert(intercept[ActorInterruptedException](Await.result(f3, remaining)).getCause.getMessage === "Ping!")
- assert(Await.result(f6, remaining) === "bar2")
- assert(intercept[ActorInterruptedException](Await.result(f5, remaining)).getCause.getMessage === "Ping!")
- c.cancel()
- }
}
"continue to process messages without failure when a thread gets interrupted and doesn't throw an exception" in {
diff --git a/akka-actor/src/main/scala/akka/actor/Actor.scala b/akka-actor/src/main/scala/akka/actor/Actor.scala
index 01ae610a65..473ec814bb 100644
--- a/akka-actor/src/main/scala/akka/actor/Actor.scala
+++ b/akka-actor/src/main/scala/akka/actor/Actor.scala
@@ -338,8 +338,11 @@ object Actor {
/**
* Type alias representing a Receive-expression for Akka Actors.
*/
+ //#receive
type Receive = PartialFunction[Any, Unit]
+ //#receive
+
/**
* emptyBehavior is a Receive-expression that matches no messages at all, ever.
*/
@@ -463,7 +466,9 @@ trait Actor {
* This defines the initial actor behavior, it must return a partial function
* with the actor logic.
*/
- def receive: Receive
+ //#receive
+ def receive: Actor.Receive
+ //#receive
/**
* User overridable definition the strategy to use for supervising
@@ -478,8 +483,11 @@ trait Actor {
* Actors are automatically started asynchronously when created.
* Empty default implementation.
*/
- @throws(classOf[Exception])
- def preStart() {}
+ @throws(classOf[Exception]) // when changing this you MUST also change UntypedActorDocTestBase
+ //#lifecycle-hooks
+ def preStart(): Unit = ()
+
+ //#lifecycle-hooks
/**
* User overridable callback.
@@ -487,8 +495,11 @@ trait Actor {
* Is called asynchronously after 'actor.stop()' is invoked.
* Empty default implementation.
*/
- @throws(classOf[Exception])
- def postStop() {}
+ @throws(classOf[Exception]) // when changing this you MUST also change UntypedActorDocTestBase
+ //#lifecycle-hooks
+ def postStop(): Unit = ()
+
+ //#lifecycle-hooks
/**
* User overridable callback: '''By default it disposes of all children and then calls `postStop()`.'''
@@ -498,8 +509,9 @@ trait Actor {
* Is called on a crashed Actor right BEFORE it is restarted to allow clean
* up of resources before Actor is terminated.
*/
- @throws(classOf[Exception])
- def preRestart(reason: Throwable, message: Option[Any]) {
+ @throws(classOf[Exception]) // when changing this you MUST also change UntypedActorDocTestBase
+ //#lifecycle-hooks
+ def preRestart(reason: Throwable, message: Option[Any]): Unit = {
context.children foreach { child ⇒
context.unwatch(child)
context.stop(child)
@@ -507,14 +519,20 @@ trait Actor {
postStop()
}
+ //#lifecycle-hooks
+
/**
* User overridable callback: By default it calls `preStart()`.
* @param reason the Throwable that caused the restart to happen
*
* Is called right AFTER restart on the newly created Actor to allow reinitialization after an Actor crash.
*/
- @throws(classOf[Exception])
- def postRestart(reason: Throwable) { preStart() }
+ @throws(classOf[Exception]) // when changing this you MUST also change UntypedActorDocTestBase
+ //#lifecycle-hooks
+ def postRestart(reason: Throwable): Unit = {
+ preStart()
+ }
+ //#lifecycle-hooks
/**
* User overridable callback.
diff --git a/akka-actor/src/main/scala/akka/actor/ActorCell.scala b/akka-actor/src/main/scala/akka/actor/ActorCell.scala
index 242897ad30..61aa820d2d 100644
--- a/akka-actor/src/main/scala/akka/actor/ActorCell.scala
+++ b/akka-actor/src/main/scala/akka/actor/ActorCell.scala
@@ -31,18 +31,12 @@ import scala.util.control.NonFatal
* context.actorOf(props)
*
* // Scala
- * context.actorOf(Props[MyActor]("name")
- * context.actorOf(Props[MyActor]
- * context.actorOf(Props(new MyActor(...))
+ * context.actorOf(Props[MyActor])
+ * context.actorOf(Props(classOf[MyActor], arg1, arg2), "name")
*
* // Java
- * context.actorOf(classOf[MyActor]);
- * context.actorOf(Props(new Creator() {
- * public MyActor create() { ... }
- * });
- * context.actorOf(Props(new Creator() {
- * public MyActor create() { ... }
- * }, "name");
+ * getContext().actorOf(Props.create(MyActor.class));
+ * getContext().actorOf(Props.create(MyActor.class, arg1, arg2), "name");
* }}}
*
* Where no name is given explicitly, one will be automatically generated.
@@ -534,7 +528,7 @@ private[akka] class ActorCell(
contextStack.set(this :: contextStack.get)
try {
behaviorStack = emptyBehaviorStack
- val instance = props.creator.apply()
+ val instance = props.newActor()
if (instance eq null)
throw ActorInitializationException(self, "Actor instance passed to actorOf can't be 'null'")
diff --git a/akka-actor/src/main/scala/akka/actor/ActorRef.scala b/akka-actor/src/main/scala/akka/actor/ActorRef.scala
index 08a7e84421..3c48b3a861 100644
--- a/akka-actor/src/main/scala/akka/actor/ActorRef.scala
+++ b/akka-actor/src/main/scala/akka/actor/ActorRef.scala
@@ -46,7 +46,7 @@ import akka.event.LoggingAdapter
*
* public class ExampleActor Extends UntypedActor {
* // this child will be destroyed and re-created upon restart by default
- * final ActorRef other = getContext().actorOf(new Props(OtherActor.class), "childName");
+ * final ActorRef other = getContext().actorOf(Props.create(OtherActor.class), "childName");
*
* @Override
* public void onReceive(Object o) {
diff --git a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala
index 18a3077e22..ef8ff80175 100644
--- a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala
+++ b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala
@@ -362,6 +362,73 @@ private[akka] object SystemGuardian {
case object TerminationHookDone
}
+private[akka] object LocalActorRefProvider {
+
+ /*
+ * Root and user guardian
+ */
+ private class Guardian(override val supervisorStrategy: SupervisorStrategy) extends Actor {
+
+ def receive = {
+ case Terminated(_) ⇒ context.stop(self)
+ case StopChild(child) ⇒ context.stop(child)
+ case m ⇒ context.system.deadLetters forward DeadLetter(m, sender, self)
+ }
+
+ // guardian MUST NOT lose its children during restart
+ override def preRestart(cause: Throwable, msg: Option[Any]) {}
+ }
+
+ /**
+ * System guardian
+ */
+ private class SystemGuardian(override val supervisorStrategy: SupervisorStrategy, val guardian: ActorRef) extends Actor {
+ import SystemGuardian._
+
+ var terminationHooks = Set.empty[ActorRef]
+
+ def receive = {
+ case Terminated(`guardian`) ⇒
+ // time for the systemGuardian to stop, but first notify all the
+ // termination hooks, they will reply with TerminationHookDone
+ // and when all are done the systemGuardian is stopped
+ context.become(terminating)
+ terminationHooks foreach { _ ! TerminationHook }
+ stopWhenAllTerminationHooksDone()
+ case Terminated(a) ⇒
+ // a registered, and watched termination hook terminated before
+ // termination process of guardian has started
+ terminationHooks -= a
+ case StopChild(child) ⇒ context.stop(child)
+ case RegisterTerminationHook if sender != context.system.deadLetters ⇒
+ terminationHooks += sender
+ context watch sender
+ case m ⇒ context.system.deadLetters forward DeadLetter(m, sender, self)
+ }
+
+ def terminating: Receive = {
+ case Terminated(a) ⇒ stopWhenAllTerminationHooksDone(a)
+ case TerminationHookDone ⇒ stopWhenAllTerminationHooksDone(sender)
+ case m ⇒ context.system.deadLetters forward DeadLetter(m, sender, self)
+ }
+
+ def stopWhenAllTerminationHooksDone(remove: ActorRef): Unit = {
+ terminationHooks -= remove
+ stopWhenAllTerminationHooksDone()
+ }
+
+ def stopWhenAllTerminationHooksDone(): Unit =
+ if (terminationHooks.isEmpty) {
+ context.system.eventStream.stopDefaultLoggers(context.system)
+ context.stop(self)
+ }
+
+ // guardian MUST NOT lose its children during restart
+ override def preRestart(cause: Throwable, msg: Option[Any]) {}
+ }
+
+}
+
/**
* Local ActorRef provider.
*
@@ -428,82 +495,22 @@ private[akka] class LocalActorRefProvider private[akka] (
override def !(message: Any)(implicit sender: ActorRef = Actor.noSender): Unit = stopped.ifOff(message match {
case null ⇒ throw new InvalidMessageException("Message is null")
case NullMessage ⇒ // do nothing
- case _ ⇒ log.error(this + " received unexpected message [" + message + "]")
+ case _ ⇒ log.error(s"$this received unexpected message [$message]")
})
override def sendSystemMessage(message: SystemMessage): Unit = stopped ifOff {
message match {
- case Failed(child, ex, _) ⇒ { causeOfTermination = Some(ex); child.asInstanceOf[InternalActorRef].stop() }
- case _: Supervise ⇒ // TODO register child in some map to keep track of it and enable shutdown after all dead
+ case Failed(child, ex, _) ⇒
+ log.error(ex, s"guardian $child failed, shutting down!")
+ causeOfTermination = Some(ex)
+ child.asInstanceOf[InternalActorRef].stop()
+ case Supervise(_, _) ⇒ // TODO register child in some map to keep track of it and enable shutdown after all dead
case _: DeathWatchNotification ⇒ stop()
- case _ ⇒ log.error(this + " received unexpected system message [" + message + "]")
+ case _ ⇒ log.error(s"$this received unexpected system message [$message]")
}
}
}
- /*
- * Root and user guardian
- */
- private class Guardian(override val supervisorStrategy: SupervisorStrategy) extends Actor {
-
- def receive = {
- case Terminated(_) ⇒ context.stop(self)
- case StopChild(child) ⇒ context.stop(child)
- case m ⇒ deadLetters forward DeadLetter(m, sender, self)
- }
-
- // guardian MUST NOT lose its children during restart
- override def preRestart(cause: Throwable, msg: Option[Any]) {}
- }
-
- /**
- * System guardian
- */
- private class SystemGuardian(override val supervisorStrategy: SupervisorStrategy) extends Actor {
- import SystemGuardian._
-
- var terminationHooks = Set.empty[ActorRef]
-
- def receive = {
- case Terminated(`guardian`) ⇒
- // time for the systemGuardian to stop, but first notify all the
- // termination hooks, they will reply with TerminationHookDone
- // and when all are done the systemGuardian is stopped
- context.become(terminating)
- terminationHooks foreach { _ ! TerminationHook }
- stopWhenAllTerminationHooksDone()
- case Terminated(a) ⇒
- // a registered, and watched termination hook terminated before
- // termination process of guardian has started
- terminationHooks -= a
- case StopChild(child) ⇒ context.stop(child)
- case RegisterTerminationHook if sender != context.system.deadLetters ⇒
- terminationHooks += sender
- context watch sender
- case m ⇒ deadLetters forward DeadLetter(m, sender, self)
- }
-
- def terminating: Receive = {
- case Terminated(a) ⇒ stopWhenAllTerminationHooksDone(a)
- case TerminationHookDone ⇒ stopWhenAllTerminationHooksDone(sender)
- case m ⇒ deadLetters forward DeadLetter(m, sender, self)
- }
-
- def stopWhenAllTerminationHooksDone(remove: ActorRef): Unit = {
- terminationHooks -= remove
- stopWhenAllTerminationHooksDone()
- }
-
- def stopWhenAllTerminationHooksDone(): Unit =
- if (terminationHooks.isEmpty) {
- eventStream.stopDefaultLoggers(system)
- context.stop(self)
- }
-
- // guardian MUST NOT lose its children during restart
- override def preRestart(cause: Throwable, msg: Option[Any]) {}
- }
-
/*
* The problem is that ActorRefs need a reference to the ActorSystem to
* provide their service. Hence they cannot be created while the
@@ -552,7 +559,11 @@ private[akka] class LocalActorRefProvider private[akka] (
protected def systemGuardianStrategy: SupervisorStrategy = SupervisorStrategy.defaultStrategy
override lazy val rootGuardian: LocalActorRef =
- new LocalActorRef(system, Props(new Guardian(rootGuardianStrategy)), theOneWhoWalksTheBubblesOfSpaceTime, rootPath) {
+ new LocalActorRef(
+ system,
+ Props(classOf[LocalActorRefProvider.Guardian], rootGuardianStrategy),
+ theOneWhoWalksTheBubblesOfSpaceTime,
+ rootPath) {
override def getParent: InternalActorRef = this
override def getSingleChild(name: String): InternalActorRef = name match {
case "temp" ⇒ tempContainer
@@ -568,7 +579,8 @@ private[akka] class LocalActorRefProvider private[akka] (
override lazy val guardian: LocalActorRef = {
val cell = rootGuardian.underlying
cell.reserveChild("user")
- val ref = new LocalActorRef(system, Props(new Guardian(guardianStrategy)), rootGuardian, rootPath / "user")
+ val ref = new LocalActorRef(system, Props(classOf[LocalActorRefProvider.Guardian], guardianStrategy),
+ rootGuardian, rootPath / "user")
cell.initChild(ref)
ref.start()
ref
@@ -577,7 +589,9 @@ private[akka] class LocalActorRefProvider private[akka] (
override lazy val systemGuardian: LocalActorRef = {
val cell = rootGuardian.underlying
cell.reserveChild("system")
- val ref = new LocalActorRef(system, Props(new SystemGuardian(systemGuardianStrategy)), rootGuardian, rootPath / "system")
+ val ref = new LocalActorRef(
+ system, Props(classOf[LocalActorRefProvider.SystemGuardian], systemGuardianStrategy, guardian),
+ rootGuardian, rootPath / "system")
cell.initChild(ref)
ref.start()
ref
@@ -669,7 +683,7 @@ private[akka] class LocalActorRefProvider private[akka] (
def actorOf(system: ActorSystemImpl, props: Props, supervisor: InternalActorRef, path: ActorPath,
systemService: Boolean, deploy: Option[Deploy], lookupDeploy: Boolean, async: Boolean): InternalActorRef = {
- props.routerConfig match {
+ props.deploy.routerConfig match {
case NoRouter ⇒
if (settings.DebugRouterMisconfiguration) {
deployer.lookup(path) foreach { d ⇒
diff --git a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala
index 85d9f93310..8b9e1bb76e 100644
--- a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala
+++ b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala
@@ -217,17 +217,11 @@ object ActorSystem {
*
* // Scala
* system.actorOf(Props[MyActor], "name")
- * system.actorOf(Props[MyActor])
- * system.actorOf(Props(new MyActor(...)))
+ * system.actorOf(Props(classOf[MyActor], arg1, arg2), "name")
*
* // Java
- * system.actorOf(MyActor.class);
- * system.actorOf(Props(new Creator() {
- * public MyActor create() { ... }
- * });
- * system.actorOf(Props(new Creator() {
- * public MyActor create() { ... }
- * }, "name");
+ * system.actorOf(Props.create(MyActor.class), "name");
+ * system.actorOf(Props.create(MyActor.class, arg1, arg2), "name");
* }}}
*
* Where no name is given explicitly, one will be automatically generated.
diff --git a/akka-actor/src/main/scala/akka/actor/Deployer.scala b/akka-actor/src/main/scala/akka/actor/Deployer.scala
index a9a93c4a88..c3d728fc25 100644
--- a/akka-actor/src/main/scala/akka/actor/Deployer.scala
+++ b/akka-actor/src/main/scala/akka/actor/Deployer.scala
@@ -29,7 +29,7 @@ object Deploy {
* not needed when just doing deploy-as-you-go:
*
* {{{
- * context.actorOf(someProps, "someName", Deploy(scope = RemoteScope("someOtherNodeName")))
+ * val remoteProps = someProps.withDeploy(Deploy(scope = RemoteScope("someOtherNodeName")))
* }}}
*/
@SerialVersionUID(1L)
@@ -62,7 +62,12 @@ final case class Deploy(
*/
def withFallback(other: Deploy): Deploy = {
val disp = if (dispatcher == Deploy.NoDispatcherGiven) other.dispatcher else dispatcher
- Deploy(path, config.withFallback(other.config), routerConfig.withFallback(other.routerConfig), scope.withFallback(other.scope), disp)
+ Deploy(
+ path,
+ config.withFallback(other.config),
+ routerConfig.withFallback(other.routerConfig),
+ scope.withFallback(other.scope),
+ disp)
}
}
diff --git a/akka-actor/src/main/scala/akka/actor/FaultHandling.scala b/akka-actor/src/main/scala/akka/actor/FaultHandling.scala
index 93dc032440..a6e3febbff 100644
--- a/akka-actor/src/main/scala/akka/actor/FaultHandling.scala
+++ b/akka-actor/src/main/scala/akka/actor/FaultHandling.scala
@@ -115,7 +115,8 @@ object SupervisorStrategy extends SupervisorStrategyLowPriorityImplicits {
/**
* Escalates the failure to the supervisor of the supervisor,
- * by rethrowing the cause of the failure.
+ * by rethrowing the cause of the failure, i.e. the supervisor fails with
+ * the same exception as the child.
*/
case object Escalate extends Directive
@@ -132,14 +133,13 @@ object SupervisorStrategy extends SupervisorStrategyLowPriorityImplicits {
/**
* Java API: Returning this directive stops the Actor
- * Java API
*/
def stop = Stop
/**
* Java API: Returning this directive escalates the failure to the supervisor of the supervisor,
- * by rethrowing the cause of the failure.
- * Java API
+ * by rethrowing the cause of the failure, i.e. the supervisor fails with
+ * the same exception as the child.
*/
def escalate = Escalate
diff --git a/akka-actor/src/main/scala/akka/actor/Props.scala b/akka-actor/src/main/scala/akka/actor/Props.scala
index 07181c4f99..90aacdb7ff 100644
--- a/akka-actor/src/main/scala/akka/actor/Props.scala
+++ b/akka-actor/src/main/scala/akka/actor/Props.scala
@@ -9,13 +9,16 @@ import akka.japi.Creator
import scala.reflect.ClassTag
import akka.routing._
import akka.util.Reflect
+import scala.annotation.varargs
+import Deploy.NoDispatcherGiven
+import scala.collection.immutable
/**
* Factory for Props instances.
*
* Props is a ActorRef configuration object, that is immutable, so it is thread safe and fully sharable.
*
- * Used when creating new actors through; ActorSystem.actorOf and ActorContext.actorOf.
+ * Used when creating new actors through ActorSystem.actorOf and ActorContext.actorOf.
*/
object Props {
@@ -34,30 +37,32 @@ object Props {
*/
final val defaultDeploy = Deploy()
- /**
- * A Props instance whose creator will create an actor that doesn't respond to any message
- */
- final val empty = new Props(() ⇒ new Actor { def receive = Actor.emptyBehavior })
-
/**
* The default Props instance, uses the settings from the Props object starting with default*.
*/
final val default = new Props()
+ /**
+ * A Props instance whose creator will create an actor that doesn't respond to any message
+ */
+ final val empty = Props[EmptyActor]
+
+ /**
+ * INTERNAL API
+ *
+ * (Not because it is so immensely complicated, only because we might remove it if no longer needed internally)
+ */
+ private[akka] class EmptyActor extends Actor {
+ def receive = Actor.emptyBehavior
+ }
+
/**
* 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 =
- default.withCreator(implicitly[ClassTag[T]].runtimeClass.asInstanceOf[Class[_ <: Actor]])
-
- /**
- * Returns a Props that has default values except for "creator" which will be a function that creates an instance
- * of the supplied class using the default constructor.
- */
- def apply(actorClass: Class[_ <: Actor]): Props = default.withCreator(actorClass)
+ def apply[T <: Actor: ClassTag](): Props = apply(implicitly[ClassTag[T]].runtimeClass)
/**
* Returns a Props that has default values except for "creator" which will be a function that creates an instance
@@ -65,116 +70,242 @@ object Props {
*
* Scala API.
*/
+ @deprecated("give class and arguments instead", "2.2")
def apply(creator: ⇒ Actor): Props = default.withCreator(creator)
/**
* 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("give class and arguments instead", "2.2")
+ def apply(
+ creator: () ⇒ Actor = Props.defaultCreator,
+ dispatcher: String = Dispatchers.DefaultDispatcherId,
+ routerConfig: RouterConfig = Props.defaultRoutedProps,
+ deploy: Deploy = Props.defaultDeploy): Props = {
+
+ val d1 = if (dispatcher != Dispatchers.DefaultDispatcherId) 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
+ }
+
+ /**
+ * Scala API: create a Props given a class and its constructor arguments.
+ */
+ def apply(clazz: Class[_], args: Any*): Props = apply(defaultDeploy, clazz, args.toVector)
+
+ /**
+ * Java API: create a Props given a class and its constructor arguments.
+ */
+ @varargs
+ def create(clazz: Class[_], args: AnyRef*): Props = apply(defaultDeploy, clazz, args.toVector)
}
/**
- * Props is a ActorRef configuration object, that is immutable, so it is thread safe and fully sharable.
- * Used when creating new actors through; ActorSystem.actorOf and ActorContext.actorOf.
- *
- * In case of providing code which creates the actual Actor instance, that must not return the same instance multiple times.
+ * Props is a configuration object using in creating an [[Actor]]; it is
+ * immutable, so it is thread-safe and fully shareable.
*
* Examples on Scala API:
* {{{
+ * val props = Props.empty
* val props = Props[MyActor]
- * val props = Props(new MyActor)
- * val props = Props(
- * creator = ..,
- * dispatcher = ..,
- * routerConfig = ..
- * )
- * val props = Props().withCreator(new MyActor)
- * val props = Props[MyActor].withRouter(RoundRobinRouter(..))
+ * val props = Props(classOf[MyActor], arg1, arg2)
+ *
+ * val otherProps = props.withDispatcher("dispatcher-id")
+ * val otherProps = props.withDeploy()
* }}}
*
* Examples on Java API:
* {{{
- * Props props = new Props();
- * Props props = new Props(MyActor.class);
- * Props props = new Props(new UntypedActorFactory() {
- * public UntypedActor create() {
- * return new MyActor();
- * }
- * });
- * Props props = new Props().withCreator(new UntypedActorFactory() { ... });
- * Props props = new Props(MyActor.class).withRouter(new RoundRobinRouter(..));
+ * final Props props = Props.empty();
+ * final Props props = Props.create(MyActor.class, arg1, arg2);
+ *
+ * final Props otherProps = props.withDispatcher("dispatcher-id");
+ * final Props otherProps = props.withDeploy();
* }}}
*/
-@SerialVersionUID(1L)
-case class Props(
- creator: () ⇒ Actor = Props.defaultCreator,
- dispatcher: String = Dispatchers.DefaultDispatcherId,
- routerConfig: RouterConfig = Props.defaultRoutedProps,
- deploy: Deploy = Props.defaultDeploy) {
+@SerialVersionUID(2L)
+case class Props(deploy: Deploy, clazz: Class[_], args: immutable.Seq[Any]) {
+
+ // validate constructor signature; throws IllegalArgumentException if invalid
+ Reflect.findConstructor(clazz, args)
/**
* No-args constructor that sets all the default values.
+ *
+ * @deprecated use `Props.create(clazz, args ...)` instead
*/
- def this() = this(
- creator = Props.defaultCreator,
- dispatcher = Dispatchers.DefaultDispatcherId)
+ @deprecated("use Props.create()", "2.2")
+ def this() = this(Props.defaultDeploy, classOf[CreatorFunctionConsumer], Vector(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
*/
- def this(factory: UntypedActorFactory) = this(
- creator = () ⇒ factory.create(),
- dispatcher = Dispatchers.DefaultDispatcherId)
+ @deprecated("use constructor which takes the actor class directly", "2.2")
+ def this(factory: UntypedActorFactory) = this(Props.defaultDeploy, classOf[UntypedActorFactoryConsumer], Vector(factory))
/**
* Java API: create Props from a given [[Class]]
+ *
+ * @deprecated use Props.create(clazz) instead; deprecated since it duplicates
+ * another API
*/
- def this(actorClass: Class[_ <: Actor]) = this(
- creator = FromClassCreator(actorClass),
- dispatcher = Dispatchers.DefaultDispatcherId,
- routerConfig = Props.defaultRoutedProps)
+ @deprecated("use Props.create()", "2.2")
+ def this(actorClass: Class[_ <: Actor]) = this(Props.defaultDeploy, actorClass, Vector.empty)
+
+ @deprecated("use newActor()", "2.2")
+ def creator: () ⇒ Actor = newActor
+
+ /**
+ * Convenience method for extracting the dispatcher information from the
+ * contained [[Deploy]] instance.
+ */
+ def dispatcher: String = deploy.dispatcher match {
+ case NoDispatcherGiven ⇒ Dispatchers.DefaultDispatcherId
+ case x ⇒ x
+ }
+
+ /**
+ * Convenience method for extracting the router configuration from the
+ * contained [[Deploy]] instance.
+ */
+ 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.
*/
- def withCreator(c: ⇒ Actor): Props = copy(creator = () ⇒ c)
+ @deprecated("move actor into named class and use withCreator(clazz)", "2.2")
+ def withCreator(c: ⇒ Actor): Props = copy(clazz = classOf[CreatorFunctionConsumer], args = Vector(() ⇒ c))
/**
* 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
*/
- def withCreator(c: Creator[Actor]): Props = copy(creator = () ⇒ c.create)
+ @deprecated("use Props.create(clazz, args ...) instead", "2.2")
+ def withCreator(c: Creator[Actor]): Props = copy(clazz = classOf[CreatorConsumer], args = Vector(c))
/**
- * Java API: Returns a new Props with the specified creator set.
+ * Returns a new Props with the specified creator set.
+ *
+ * @deprecated use Props.create(clazz) instead; deprecated since it duplicates
+ * another API
*/
- def withCreator(c: Class[_ <: Actor]): Props = copy(creator = FromClassCreator(c))
+ @deprecated("use Props(clazz, args).withDeploy(other.deploy)", "2.2")
+ def withCreator(c: Class[_ <: Actor]): Props = copy(clazz = c, args = Vector.empty)
/**
* Returns a new Props with the specified dispatcher set.
*/
- def withDispatcher(d: String): Props = copy(dispatcher = d)
+ def withDispatcher(d: String): Props = copy(deploy = deploy.copy(dispatcher = d))
/**
* Returns a new Props with the specified router config set.
*/
- def withRouter(r: RouterConfig): Props = copy(routerConfig = r)
+ def withRouter(r: RouterConfig): Props = copy(deploy = deploy.copy(routerConfig = r))
/**
* Returns a new Props with the specified deployment configuration.
*/
- def withDeploy(d: Deploy): Props = copy(deploy = d)
+ def withDeploy(d: Deploy): Props = copy(deploy = d withFallback deploy)
+ /**
+ * Create a new actor instance. This method is only useful when called during
+ * actor creation by the ActorSystem, i.e. for user-level code it can only be
+ * used within the implementation of [[IndirectActorProducer#produce]].
+ */
+ def newActor(): Actor = {
+ Reflect.instantiate(clazz, args) match {
+ case a: Actor ⇒ a
+ case i: IndirectActorProducer ⇒ i.produce()
+ case _ ⇒ throw new IllegalArgumentException(s"unknown actor creator [$clazz]")
+ }
+ }
+
+ /**
+ * Obtain an upper-bound approximation of the actor class which is going to
+ * be created by these Props. In other words, the [[#newActor]] method will
+ * produce an instance of this class or a subclass thereof. This is used by
+ * the actor system to select special dispatchers or mailboxes in case
+ * dependencies are encoded in the actor type.
+ */
+ def actorClass(): Class[_ <: Actor] = {
+ if (classOf[IndirectActorProducer].isAssignableFrom(clazz)) {
+ Reflect.instantiate(clazz, args).asInstanceOf[IndirectActorProducer].actorClass
+ } else if (classOf[Actor].isAssignableFrom(clazz)) {
+ clazz.asInstanceOf[Class[_ <: Actor]]
+ } else {
+ throw new IllegalArgumentException("unknown actor creator [$clazz]")
+ }
+ }
}
/**
- * Used when creating an Actor from a class. Special Function0 to be
- * able to optimize serialization.
+ * This interface defines a class of actor creation strategies deviating from
+ * the usual default of just reflectively instantiating the [[Actor]]
+ * subclass. It can be used to allow a dependency injection framework to
+ * determine the actual actor class and how it shall be instantiated.
*/
-private[akka] case class FromClassCreator(clazz: Class[_ <: Actor]) extends Function0[Actor] {
- def apply(): Actor = Reflect.instantiate(clazz)
+trait IndirectActorProducer {
+
+ /**
+ * This factory method must produce a fresh actor instance upon each
+ * invocation. It is not permitted to return the same instance more than
+ * once.
+ */
+ def produce(): Actor
+
+ /**
+ * This method is used by [[Props]] to determine the type of actor which will
+ * be created. This means that an instance of this `IndirectActorProducer`
+ * will be created in order to call this method during any call to
+ * [[Props#actorClass]]; it should be noted that such calls may
+ * performed during actor set-up before the actual actor’s instantiation, and
+ * that the instance created for calling `actorClass` is not necessarily reused
+ * later to produce the actor.
+ */
+ def actorClass: Class[_ <: Actor]
+}
+
+/**
+ * INTERNAL API
+ */
+private[akka] class UntypedActorFactoryConsumer(factory: UntypedActorFactory) extends IndirectActorProducer {
+ override def actorClass = classOf[Actor]
+ override def produce() = factory.create()
+}
+
+/**
+ * INTERNAL API
+ */
+private[akka] class CreatorFunctionConsumer(creator: () ⇒ Actor) extends IndirectActorProducer {
+ override def actorClass = classOf[Actor]
+ override def produce() = creator()
+}
+
+/**
+ * INTERNAL API
+ */
+private[akka] class CreatorConsumer(creator: Creator[Actor]) extends IndirectActorProducer {
+ override def actorClass = classOf[Actor]
+ override def produce() = creator.create()
}
diff --git a/akka-actor/src/main/scala/akka/actor/UntypedActor.scala b/akka-actor/src/main/scala/akka/actor/UntypedActor.scala
index 741d74feda..23fed1d819 100644
--- a/akka-actor/src/main/scala/akka/actor/UntypedActor.scala
+++ b/akka-actor/src/main/scala/akka/actor/UntypedActor.scala
@@ -71,11 +71,11 @@ import akka.japi.{ Creator }
*
* } else if (msg.equals("ErrorKernelWithDirectReply")) {
* // Send work to one-off child which will reply directly to original sender
- * getContext().actorOf(new Props(Worker.class)).tell("DoSomeDangerousWork", getSender());
+ * getContext().actorOf(Props.create(Worker.class)).tell("DoSomeDangerousWork", getSender());
*
* } else if (msg.equals("ErrorKernelWithReplyHere")) {
* // Send work to one-off child and collect the answer, reply handled further down
- * getContext().actorOf(new Props(Worker.class)).tell("DoWorkAndReplyToMe");
+ * getContext().actorOf(Props.create(Worker.class)).tell("DoWorkAndReplyToMe", getSelf());
*
* } else throw new IllegalArgumentException("Unknown message: " + message);
*
@@ -166,4 +166,5 @@ abstract class UntypedActor extends Actor {
/**
* Factory closure for an UntypedActor, to be used with 'Actors.actorOf(factory)'.
*/
+@deprecated("use Props.create(clazz, args) instead", "2.2")
trait UntypedActorFactory extends Creator[Actor] with Serializable
diff --git a/akka-actor/src/main/scala/akka/actor/dungeon/Children.scala b/akka-actor/src/main/scala/akka/actor/dungeon/Children.scala
index c419f1a14f..2281243b92 100644
--- a/akka-actor/src/main/scala/akka/actor/dungeon/Children.scala
+++ b/akka-actor/src/main/scala/akka/actor/dungeon/Children.scala
@@ -168,9 +168,11 @@ private[akka] trait Children { this: ActorCell ⇒
}
private def makeChild(cell: ActorCell, props: Props, name: String, async: Boolean, systemService: Boolean): ActorRef = {
- if (cell.system.settings.SerializeAllCreators && !props.creator.isInstanceOf[NoSerializationVerificationNeeded]) {
+ if (cell.system.settings.SerializeAllCreators) {
val ser = SerializationExtension(cell.system)
- ser.deserialize(ser.serialize(props.creator).get, props.creator.getClass).get
+ props.args forall (arg ⇒
+ arg.isInstanceOf[NoSerializationVerificationNeeded] ||
+ ser.deserialize(ser.serialize(arg.asInstanceOf[AnyRef]).get, arg.getClass).get != null)
}
/*
* in case we are currently terminating, fail external attachChild requests
diff --git a/akka-actor/src/main/scala/akka/routing/Routing.scala b/akka-actor/src/main/scala/akka/routing/Routing.scala
index 69f41fcbbf..9dc2088a0e 100644
--- a/akka-actor/src/main/scala/akka/routing/Routing.scala
+++ b/akka-actor/src/main/scala/akka/routing/Routing.scala
@@ -39,11 +39,20 @@ private[akka] class RoutedActorRef(_system: ActorSystemImpl, _props: Props, _sup
}
+private[akka] object RoutedActorCell {
+ class RouterCreator(routerConfig: RouterConfig) extends IndirectActorProducer {
+ override def actorClass = classOf[Router]
+ override def produce() = routerConfig.createActor()
+ }
+}
+
private[akka] class RoutedActorCell(_system: ActorSystemImpl, _ref: InternalActorRef, _props: Props, _supervisor: InternalActorRef)
extends ActorCell(
_system,
_ref,
- _props.copy(creator = () ⇒ _props.routerConfig.createActor(), dispatcher = _props.routerConfig.routerDispatcher),
+ _props.copy(
+ deploy = _props.deploy.copy(dispatcher = _props.routerConfig.routerDispatcher),
+ classOf[RoutedActorCell.RouterCreator], Vector(_props.routerConfig)),
_supervisor) {
private[akka] val routerConfig = _props.routerConfig
@@ -59,7 +68,7 @@ private[akka] class RoutedActorCell(_system: ActorSystemImpl, _ref: InternalActo
def routeeProvider = _routeeProvider
val route = {
- val routeeProps = _props.copy(routerConfig = NoRouter)
+ val routeeProps = _props.withRouter(NoRouter)
_routeeProvider = routerConfig.createRouteeProvider(this, routeeProps)
val r = routerConfig.createRoute(routeeProvider)
// initial resize, before message send
diff --git a/akka-actor/src/main/scala/akka/util/Reflect.scala b/akka-actor/src/main/scala/akka/util/Reflect.scala
index 5761fe5dd3..b3f67381ab 100644
--- a/akka-actor/src/main/scala/akka/util/Reflect.scala
+++ b/akka-actor/src/main/scala/akka/util/Reflect.scala
@@ -3,6 +3,8 @@
*/
package akka.util
import scala.util.control.NonFatal
+import java.lang.reflect.Constructor
+import scala.collection.immutable
/**
* Collection of internal reflection utilities which may or may not be
@@ -43,6 +45,42 @@ private[akka] object Reflect {
ctor.newInstance()
}
+ /**
+ * INTERNAL API
+ * Calls findConstructor and invokes it with the given arguments.
+ */
+ private[akka] def instantiate[T](clazz: Class[T], args: immutable.Seq[Any]): T = {
+ val constructor = findConstructor(clazz, args)
+ constructor.setAccessible(true)
+ try constructor.newInstance(args.asInstanceOf[Seq[AnyRef]]: _*)
+ catch {
+ case e: IllegalArgumentException ⇒
+ val argString = args map (_.getClass) mkString ("[", ", ", "]")
+ throw new IllegalArgumentException(s"constructor $constructor is incompatible with arguments $argString", e)
+ }
+ }
+
+ /**
+ * INTERNAL API
+ * Implements a primitive form of overload resolution a.k.a. finding the
+ * right constructor.
+ */
+ private[akka] def findConstructor[T](clazz: Class[T], args: immutable.Seq[Any]): Constructor[T] = {
+ def error(msg: String): Nothing = {
+ val argClasses = args map (_.getClass) mkString ", "
+ throw new IllegalArgumentException(s"$msg found on $clazz for arguments [$argClasses]")
+ }
+ val candidates =
+ clazz.getDeclaredConstructors filter (c ⇒
+ c.getParameterTypes.length == args.length &&
+ (c.getParameterTypes zip args forall {
+ case (found, required) ⇒ found.isInstance(required) || BoxedType(found).isInstance(required)
+ }))
+ if (candidates.size == 1) candidates.head.asInstanceOf[Constructor[T]]
+ else if (candidates.size > 1) error("multiple matching constructors")
+ else error("no matching constructor")
+ }
+
/**
* INTERNAL API
* @param clazz the class which to instantiate an instance of
diff --git a/akka-camel/src/test/scala/akka/camel/ConcurrentActivationTest.scala b/akka-camel/src/test/scala/akka/camel/ConcurrentActivationTest.scala
index 7d014f8a8c..9bf577a893 100644
--- a/akka-camel/src/test/scala/akka/camel/ConcurrentActivationTest.scala
+++ b/akka-camel/src/test/scala/akka/camel/ConcurrentActivationTest.scala
@@ -99,7 +99,7 @@ class ConsumerBroadcast(promise: Promise[(Future[List[List[ActorRef]]], Future[L
}
promise.success(Future.sequence(allActivationFutures) -> Future.sequence(allDeactivationFutures))
- broadcaster = Some(context.actorOf(Props[Registrar] withRouter (BroadcastRouter(routees)), "registrarRouter"))
+ broadcaster = Some(context.actorOf(Props.empty withRouter (BroadcastRouter(routees)), "registrarRouter"))
case reg: Any ⇒
broadcaster.foreach(_.forward(reg))
}
diff --git a/akka-contrib/src/main/scala/akka/contrib/pattern/ReliableProxy.scala b/akka-contrib/src/main/scala/akka/contrib/pattern/ReliableProxy.scala
index f34b73d589..f958ac0a80 100644
--- a/akka-contrib/src/main/scala/akka/contrib/pattern/ReliableProxy.scala
+++ b/akka-contrib/src/main/scala/akka/contrib/pattern/ReliableProxy.scala
@@ -74,16 +74,17 @@ import ReliableProxy._
* situations or other VM errors).
*
* You can create a reliable connection like this:
+ *
+ * In Scala:
+ *
* {{{
- * val proxy = context.actorOf(Props(new ReliableProxy(target)))
+ * val proxy = context.actorOf(Props(classOf[ReliableProxy], target))
* }}}
- * or in Java:
+ *
+ * In Java:
+ *
* {{{
- * final ActorRef proxy = getContext().actorOf(new Props(new UntypedActorFactory() {
- * public Actor create() {
- * return new ReliableProxy(target);
- * }
- * }));
+ * final ActorRef proxy = getContext().actorOf(Props.create(ReliableProxy.class target));
* }}}
*
* '''''Please note:''''' the tunnel is uni-directional, and original sender
diff --git a/akka-contrib/src/main/scala/akka/contrib/throttle/TimerBasedThrottler.scala b/akka-contrib/src/main/scala/akka/contrib/throttle/TimerBasedThrottler.scala
index 01003aff3d..709c1ee8cd 100644
--- a/akka-contrib/src/main/scala/akka/contrib/throttle/TimerBasedThrottler.scala
+++ b/akka-contrib/src/main/scala/akka/contrib/throttle/TimerBasedThrottler.scala
@@ -160,13 +160,17 @@ object TimerBasedThrottler {
* sending out further messages:
* {{{
* // A simple actor that prints whatever it receives
- * val printer = system.actorOf(Props(new Actor {
+ * class Printer extends Actor {
* def receive = {
* case x => println(x)
* }
- * }))
+ * }
+ *
+ * val printer = system.actorOf(Props[Printer], "printer")
+ *
* // The throttler for this example, setting the rate
- * val throttler = system.actorOf(Props(new TimerBasedThrottler(3 msgsPer (1.second))))
+ * val throttler = system.actorOf(Props(classOf[TimerBasedThrottler], 3 msgsPer 1.second))
+ *
* // Set the target
* throttler ! SetTarget(Some(printer))
* // These three messages will be sent to the printer immediately
diff --git a/akka-docs/rst/general/supervision.rst b/akka-docs/rst/general/supervision.rst
index 88097a5b88..3c65ae44d8 100644
--- a/akka-docs/rst/general/supervision.rst
+++ b/akka-docs/rst/general/supervision.rst
@@ -23,7 +23,7 @@ a choice of the following four options:
#. Resume the subordinate, keeping its accumulated internal state
#. Restart the subordinate, clearing out its accumulated internal state
#. Terminate the subordinate permanently
-#. Escalate the failure
+#. Escalate the failure, thereby failing itself
It is important to always view an actor as part of a supervision hierarchy,
which explains the existence of the fourth choice (as a supervisor also is
diff --git a/akka-docs/rst/java/code/docs/actor/FSMDocTestBase.java b/akka-docs/rst/java/code/docs/actor/FSMDocTestBase.java
index 91bd5af888..467e012010 100644
--- a/akka-docs/rst/java/code/docs/actor/FSMDocTestBase.java
+++ b/akka-docs/rst/java/code/docs/actor/FSMDocTestBase.java
@@ -186,7 +186,7 @@ public class FSMDocTestBase {
@org.junit.Test
public void mustBunch() {
- final ActorRef buncher = system.actorOf(new Props(MyFSM.class));
+ final ActorRef buncher = system.actorOf(Props.create(MyFSM.class));
final TestProbe probe = new TestProbe(system);
buncher.tell(new SetTarget(probe.ref()), null);
buncher.tell(new Queue(1), null);
diff --git a/akka-docs/rst/java/code/docs/actor/FaultHandlingTestBase.java b/akka-docs/rst/java/code/docs/actor/FaultHandlingTestBase.java
index 5de6a2eb31..b2ae8df06c 100644
--- a/akka-docs/rst/java/code/docs/actor/FaultHandlingTestBase.java
+++ b/akka-docs/rst/java/code/docs/actor/FaultHandlingTestBase.java
@@ -30,7 +30,6 @@ import static java.util.concurrent.TimeUnit.SECONDS;
import static akka.japi.Util.immutableSeq;
import akka.japi.Function;
import scala.Option;
-import scala.collection.JavaConverters;
import scala.collection.immutable.Seq;
import org.junit.Test;
@@ -171,10 +170,10 @@ public class FaultHandlingTestBase {
system.eventStream().publish(new TestEvent.Mute(ignoreExceptions));
//#create
- Props superprops = new Props(Supervisor.class);
+ Props superprops = Props.create(Supervisor.class);
ActorRef supervisor = system.actorOf(superprops, "supervisor");
ActorRef child = (ActorRef) Await.result(ask(supervisor,
- new Props(Child.class), 5000), timeout);
+ Props.create(Child.class), 5000), timeout);
//#create
//#resume
@@ -198,7 +197,7 @@ public class FaultHandlingTestBase {
//#escalate-kill
child = (ActorRef) Await.result(ask(supervisor,
- new Props(Child.class), 5000), timeout);
+ Props.create(Child.class), 5000), timeout);
probe.watch(child);
assert Await.result(ask(child, "get", 5000), timeout).equals(0);
child.tell(new Exception(), null);
@@ -206,10 +205,10 @@ public class FaultHandlingTestBase {
//#escalate-kill
//#escalate-restart
- superprops = new Props(Supervisor2.class);
+ superprops = Props.create(Supervisor2.class);
supervisor = system.actorOf(superprops);
child = (ActorRef) Await.result(ask(supervisor,
- new Props(Child.class), 5000), timeout);
+ Props.create(Child.class), 5000), timeout);
child.tell(23, null);
assert Await.result(ask(child, "get", 5000), timeout).equals(23);
child.tell(new Exception(), null);
@@ -219,6 +218,7 @@ public class FaultHandlingTestBase {
}
//#testkit
+ @SuppressWarnings("unchecked")
public Seq seq(A... args) {
return immutableSeq(args);
}
diff --git a/akka-docs/rst/java/code/docs/actor/FirstUntypedActor.java b/akka-docs/rst/java/code/docs/actor/FirstUntypedActor.java
index 3512449aaf..eefe49c5c9 100644
--- a/akka-docs/rst/java/code/docs/actor/FirstUntypedActor.java
+++ b/akka-docs/rst/java/code/docs/actor/FirstUntypedActor.java
@@ -10,7 +10,7 @@ import akka.actor.UntypedActor;
//#context-actorOf
public class FirstUntypedActor extends UntypedActor {
- ActorRef myActor = getContext().actorOf(new Props(MyActor.class), "myactor");
+ ActorRef myActor = getContext().actorOf(Props.create(MyActor.class), "myactor");
//#context-actorOf
diff --git a/akka-docs/rst/java/code/docs/actor/InitializationDocSpecJava.java b/akka-docs/rst/java/code/docs/actor/InitializationDocSpecJava.java
index fd9f7d3575..864a2b7848 100644
--- a/akka-docs/rst/java/code/docs/actor/InitializationDocSpecJava.java
+++ b/akka-docs/rst/java/code/docs/actor/InitializationDocSpecJava.java
@@ -78,7 +78,7 @@ public class InitializationDocSpecJava {
public void testIt() {
new JavaTestKit(system) {{
- ActorRef testactor = system.actorOf(new Props(MessageInitExample.class), "testactor");
+ ActorRef testactor = system.actorOf(Props.create(MessageInitExample.class), "testactor");
String probe = "U OK?";
testactor.tell(probe, getRef());
diff --git a/akka-docs/rst/java/code/docs/actor/MyReceivedTimeoutUntypedActor.java b/akka-docs/rst/java/code/docs/actor/MyReceiveTimeoutUntypedActor.java
similarity index 58%
rename from akka-docs/rst/java/code/docs/actor/MyReceivedTimeoutUntypedActor.java
rename to akka-docs/rst/java/code/docs/actor/MyReceiveTimeoutUntypedActor.java
index 1fcbe72036..a6e6db4daa 100644
--- a/akka-docs/rst/java/code/docs/actor/MyReceivedTimeoutUntypedActor.java
+++ b/akka-docs/rst/java/code/docs/actor/MyReceiveTimeoutUntypedActor.java
@@ -4,13 +4,16 @@
package docs.actor;
//#receive-timeout
+import akka.actor.ActorRef;
import akka.actor.ReceiveTimeout;
import akka.actor.UntypedActor;
import scala.concurrent.duration.Duration;
-public class MyReceivedTimeoutUntypedActor extends UntypedActor {
+public class MyReceiveTimeoutUntypedActor extends UntypedActor {
+
+ ActorRef target = getContext().system().deadLetters();
- public MyReceivedTimeoutUntypedActor() {
+ public MyReceiveTimeoutUntypedActor() {
// To set an initial delay
getContext().setReceiveTimeout(Duration.create("30 seconds"));
}
@@ -18,12 +21,13 @@ public class MyReceivedTimeoutUntypedActor extends UntypedActor {
public void onReceive(Object message) {
if (message.equals("Hello")) {
// To set in a response to a message
- getContext().setReceiveTimeout(Duration.create("10 seconds"));
- getSender().tell("Hello world", getSelf());
- } else if (message == ReceiveTimeout.getInstance()) {
+ getContext().setReceiveTimeout(Duration.create("1 second"));
+ target = getSender();
+ target.tell("Hello world", getSelf());
+ } else if (message instanceof ReceiveTimeout) {
// To turn it off
getContext().setReceiveTimeout(Duration.Undefined());
- throw new RuntimeException("received timeout");
+ target.tell("timeout", getSelf());
} else {
unhandled(message);
}
diff --git a/akka-docs/rst/java/code/docs/actor/MyUntypedActor.java b/akka-docs/rst/java/code/docs/actor/MyUntypedActor.java
index 0388913b9e..fc8f7ce68a 100644
--- a/akka-docs/rst/java/code/docs/actor/MyUntypedActor.java
+++ b/akka-docs/rst/java/code/docs/actor/MyUntypedActor.java
@@ -12,9 +12,10 @@ public class MyUntypedActor extends UntypedActor {
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
public void onReceive(Object message) throws Exception {
- if (message instanceof String)
+ if (message instanceof String) {
log.info("Received String message: {}", message);
- else
+ getSender().tell(message, getSelf());
+ } else
unhandled(message);
}
}
diff --git a/akka-docs/rst/java/code/docs/actor/SchedulerDocTestBase.java b/akka-docs/rst/java/code/docs/actor/SchedulerDocTestBase.java
index cfbdec80b0..ac2e8c5f87 100644
--- a/akka-docs/rst/java/code/docs/actor/SchedulerDocTestBase.java
+++ b/akka-docs/rst/java/code/docs/actor/SchedulerDocTestBase.java
@@ -10,9 +10,7 @@ import java.util.concurrent.TimeUnit;
//#imports1
//#imports2
-import akka.actor.Actor;
import akka.actor.UntypedActor;
-import akka.actor.UntypedActorFactory;
import akka.actor.Cancellable;
//#imports2
@@ -32,7 +30,7 @@ public class SchedulerDocTestBase {
@Before
public void setUp() {
system = ActorSystem.create("MySystem", AkkaSpec.testConf());
- testActor = system.actorOf(new Props(MyUntypedActor.class));
+ testActor = system.actorOf(Props.create(MyUntypedActor.class));
}
@After
@@ -61,20 +59,18 @@ public class SchedulerDocTestBase {
@Test
public void scheduleRecurringTask() {
//#schedule-recurring
- ActorRef tickActor = system.actorOf(new Props().withCreator(
- new UntypedActorFactory() {
- public UntypedActor create() {
- return new UntypedActor() {
- public void onReceive(Object message) {
- if (message.equals("Tick")) {
- // Do someting
- } else {
- unhandled(message);
- }
- }
- };
+ class Ticker extends UntypedActor {
+ @Override
+ public void onReceive(Object message) {
+ if (message.equals("Tick")) {
+ // Do someting
+ } else {
+ unhandled(message);
}
- }));
+ }
+ }
+
+ ActorRef tickActor = system.actorOf(Props.create(Ticker.class, this));
//This will schedule to send the Tick-message
//to the tickActor after 0ms repeating every 50ms
diff --git a/akka-docs/rst/java/code/docs/actor/UntypedActorDocTestBase.java b/akka-docs/rst/java/code/docs/actor/UntypedActorDocTestBase.java
index 3e4c1da006..f58f1b82cf 100644
--- a/akka-docs/rst/java/code/docs/actor/UntypedActorDocTestBase.java
+++ b/akka-docs/rst/java/code/docs/actor/UntypedActorDocTestBase.java
@@ -3,74 +3,82 @@
*/
package docs.actor;
-//#imports
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.actor.Props;
-//#imports
-
-//#import-future
-import scala.concurrent.Future;
-import akka.dispatch.Futures;
-import akka.dispatch.Mapper;
-import scala.concurrent.Await;
-import scala.concurrent.duration.Duration;
-import akka.testkit.AkkaSpec;
-import akka.util.Timeout;
-//#import-future
-
-//#import-actors
-import akka.actor.PoisonPill;
-import akka.actor.Kill;
-//#import-actors
-
-//#import-procedure
-import akka.japi.Procedure;
-//#import-procedure
-
-//#import-watch
-import akka.actor.Terminated;
-//#import-watch
-
-//#import-identify
-import akka.actor.ActorSelection;
-import akka.actor.Identify;
-import akka.actor.ActorIdentity;
-//#import-identify
-
-//#import-gracefulStop
-import static akka.pattern.Patterns.gracefulStop;
-import scala.concurrent.Future;
-import scala.concurrent.Await;
-import scala.concurrent.duration.Duration;
-import akka.pattern.AskTimeoutException;
-//#import-gracefulStop
-
-//#import-askPipe
+//#import-ask
import static akka.pattern.Patterns.ask;
import static akka.pattern.Patterns.pipe;
-import scala.concurrent.Future;
-import akka.dispatch.Futures;
-import scala.concurrent.duration.Duration;
-import akka.util.Timeout;
-import java.util.concurrent.TimeUnit;
-import java.util.ArrayList;
-//#import-askPipe
+//#import-ask
+//#import-gracefulStop
+import static akka.pattern.Patterns.gracefulStop;
+//#import-gracefulStop
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+//#import-gracefulStop
+import scala.concurrent.Await;
+//#import-ask
+import scala.concurrent.Future;
+import scala.concurrent.duration.Duration;
+//#import-ask
+//#import-gracefulStop
+//#import-indirect
+import akka.actor.Actor;
+//#import-indirect
+//#import-identify
+import akka.actor.ActorIdentity;
+//#import-identify
+import akka.actor.ActorKilledException;
+//#import-identify
+import akka.actor.ActorSelection;
+//#import-identify
+//#import-actorRef
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+//#import-actorRef
+//#import-identify
+import akka.actor.Identify;
+//#import-identify
+//#import-indirect
+import akka.actor.IndirectActorProducer;
+//#import-indirect
+import akka.actor.OneForOneStrategy;
+//#import-props
+import akka.actor.Props;
+//#import-props
+import akka.actor.SupervisorStrategy;
+import akka.actor.SupervisorStrategy.Directive;
+//#import-terminated
+import akka.actor.Terminated;
+//#import-terminated
+//#import-untypedActor
+import akka.actor.UntypedActor;
+import akka.actor.UntypedActorFactory;
+//#import-untypedActor
//#import-stash
import akka.actor.UntypedActorWithStash;
//#import-stash
-
-import akka.actor.UntypedActor;
-import akka.actor.UntypedActorFactory;
-
-import org.junit.Test;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import scala.Option;
-import java.lang.Object;
-import java.util.Iterator;
+//#import-ask
+import akka.dispatch.Futures;
+import akka.dispatch.Mapper;
+//#import-ask
+import akka.japi.Function;
+//#import-procedure
+import akka.japi.Procedure;
+//#import-procedure
+//#import-gracefulStop
+import akka.pattern.AskTimeoutException;
+//#import-gracefulStop
import akka.pattern.Patterns;
+import akka.testkit.AkkaSpec;
+import akka.testkit.JavaTestKit;
+//#import-ask
+import akka.util.Timeout;
+//#import-ask
public class UntypedActorDocTestBase {
@@ -87,71 +95,148 @@ public class UntypedActorDocTestBase {
system = null;
}
+ @SuppressWarnings("unused")
@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 props1 = Props.create(MyUntypedActor.class);
+ Props props2 = Props.create(MyActor.class, "...");
//#creating-props-config
}
+ @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
- ActorSystem system = ActorSystem.create("MySystem");
- ActorRef myActor = system.actorOf(new Props(MyUntypedActor.class), "myactor");
+ // ActorSystem is a heavy object: create only one per application
+ final ActorSystem system = ActorSystem.create("MySystem");
+ final ActorRef myActor = system.actorOf(Props.create(MyUntypedActor.class), "myactor");
//#system-actorOf
- myActor.tell("test", null);
- system.shutdown();
+ try {
+ new JavaTestKit(system) {
+ {
+ myActor.tell("hello", getRef());
+ expectMsgEquals("hello");
+ }
+ };
+ } finally {
+ system.shutdown();
+ }
}
@Test
public void contextActorOf() {
- //#context-actorOf
- ActorRef myActor = system.actorOf(new Props(MyUntypedActor.class), "myactor2");
- //#context-actorOf
- myActor.tell("test", null);
- }
-
- @Test
- public void constructorActorOf() {
- //#creating-constructor
- // allows passing in arguments to the MyActor constructor
- ActorRef myActor = system.actorOf(new Props(new UntypedActorFactory() {
- public UntypedActor create() {
- return new MyActor("...");
+ new JavaTestKit(system) {
+ {
+ //#context-actorOf
+ class A extends UntypedActor {
+ final ActorRef child =
+ getContext().actorOf(Props.create(MyUntypedActor.class), "myChild");
+ //#plus-some-behavior
+ @Override
+ public void onReceive(Object msg) {
+ getSender().tell(child, getSelf());
+ }
+ //#plus-some-behavior
+ }
+ //#context-actorOf
+ final ActorRef top = system.actorOf(Props.create(A.class, this));
+ top.tell("hello", getRef());
+ final ActorRef child = expectMsgClass(ActorRef.class);
+ child.tell("hello", getRef());
+ expectMsgEquals("hello");
}
- }), "myactor3");
- //#creating-constructor
- myActor.tell("test", null);
+ };
+ }
+
+ // this is just to make the test below a tiny fraction nicer
+ private ActorSystem getContext() {
+ return system;
}
+ static
+ //#creating-indirectly
+ class DependencyInjector implements IndirectActorProducer {
+ final Object applicationContext;
+ final String beanName;
+
+ public DependencyInjector(Object applicationContext, String beanName) {
+ this.applicationContext = applicationContext;
+ this.beanName = beanName;
+ }
+
+ @Override
+ public Class extends Actor> actorClass() {
+ return MyActor.class;
+ }
+
+ @Override
+ public MyActor produce() {
+ MyActor result;
+ //#obtain-fresh-Actor-instance-from-DI-framework
+ result = new MyActor((String) applicationContext);
+ //#obtain-fresh-Actor-instance-from-DI-framework
+ return result;
+ }
+ }
+ //#creating-indirectly
+
@Test
- public void propsActorOf() {
- //#creating-props
- ActorRef myActor = system.actorOf(
- new Props(MyUntypedActor.class).withDispatcher("my-dispatcher"), "myactor4");
- //#creating-props
- myActor.tell("test", null);
+ public void indirectActorOf() {
+ final String applicationContext = "...";
+ //#creating-indirectly
+
+ final ActorRef myActor = getContext().actorOf(
+ Props.create(DependencyInjector.class, applicationContext, "MyActor"), "myactor3");
+ //#creating-indirectly
+ new JavaTestKit(system) {
+ {
+ myActor.tell("hello", getRef());
+ expectMsgEquals("...");
+ }
+ };
}
+ @SuppressWarnings("unused")
@Test
public void usingAsk() throws Exception {
- ActorRef myActor = system.actorOf(new Props(new UntypedActorFactory() {
- public UntypedActor create() {
- return new MyAskActor();
- }
- }), "myactor5");
+ ActorRef myActor = system.actorOf(Props.create(MyAskActor.class, this), "myactor5");
//#using-ask
Future future = Patterns.ask(myActor, "Hello", 1000);
@@ -161,55 +246,181 @@ public class UntypedActorDocTestBase {
@Test
public void receiveTimeout() {
- ActorRef myActor = system.actorOf(new Props(MyReceivedTimeoutUntypedActor.class));
- myActor.tell("Hello", null);
+ final ActorRef myActor = system.actorOf(Props.create(MyReceiveTimeoutUntypedActor.class));
+ new JavaTestKit(system) {
+ {
+ new Within(Duration.create(1, TimeUnit.SECONDS), Duration.create(1500,
+ TimeUnit.MILLISECONDS)) {
+ @Override
+ protected void run() {
+ myActor.tell("Hello", getRef());
+ expectMsgEquals("Hello world");
+ expectMsgEquals("timeout");
+ }
+ };
+ }
+ };
}
@Test
public void usePoisonPill() {
- ActorRef myActor = system.actorOf(new Props(MyUntypedActor.class));
- //#poison-pill
- myActor.tell(PoisonPill.getInstance(), null);
- //#poison-pill
+ final ActorRef myActor = system.actorOf(Props.create(MyUntypedActor.class));
+ new JavaTestKit(system) {
+ {
+ final ActorRef sender = getRef();
+ //#poison-pill
+ myActor.tell(akka.actor.PoisonPill.getInstance(), sender);
+ //#poison-pill
+ watch(myActor);
+ expectTerminated(myActor);
+ }
+ };
}
@Test
public void useKill() {
- ActorRef victim = system.actorOf(new Props(MyUntypedActor.class));
- //#kill
- victim.tell(Kill.getInstance(), null);
- //#kill
+ new JavaTestKit(system) {
+ {
+ class Master extends UntypedActor {
+ private SupervisorStrategy strategy = new OneForOneStrategy(-1,
+ Duration.Undefined(), new Function() {
+ @Override
+ public Directive apply(Throwable thr) {
+ if (thr instanceof ActorKilledException) {
+ target.tell("killed", getSelf());
+ getContext().stop(getSelf());
+ return SupervisorStrategy.stop();
+ }
+ return SupervisorStrategy.escalate();
+ }
+ });
+ final ActorRef target;
+ ActorRef child;
+
+ //#preStart
+ @Override
+ public void preStart() {
+ child = getContext().actorOf(Props.empty());
+ }
+ //#preStart
+
+ @SuppressWarnings("unused")
+ public Master(ActorRef target) {
+ this.target = target;
+
+ /*
+ * Only compilation of `forward` is verified here.
+ */
+ final Object result = "";
+ //#forward
+ target.forward(result, getContext());
+ //#forward
+ }
+
+ @Override
+ public SupervisorStrategy supervisorStrategy() {
+ return strategy;
+ }
+
+ //#reply
+ @Override
+ public void onReceive(Object msg) {
+ Object result =
+ //#calculate-result
+ child;
+ //#calculate-result
+
+ // do not forget the second argument!
+ getSender().tell(result, getSelf());
+ }
+ //#reply
+
+ //#postStop
+ @Override
+ public void postStop() {
+ //#clean-up-resources-here
+ final String message = "stopped";
+ //#tell
+ // don’t forget to think about who is the sender (2nd argument)
+ target.tell(message, getSelf());
+ //#tell
+ //#clean-up-resources-here
+ }
+ //#postStop
+ }
+ final ActorRef master = system.actorOf(Props.create(Master.class, this, getRef()));
+ expectMsgEquals("");
+ master.tell("", getRef());
+ final ActorRef victim = expectMsgClass(ActorRef.class);
+ //#kill
+ victim.tell(akka.actor.Kill.getInstance(), null);
+ //#kill
+ expectMsgEquals("killed");
+ expectMsgEquals("stopped");
+ assert getLastSender().equals(master);
+ }
+ };
}
@Test
public void useBecome() {
- ActorRef myActor = system.actorOf(new Props(new UntypedActorFactory() {
- public UntypedActor create() {
- return new HotSwapActor();
+ new JavaTestKit(system) {
+ {
+ ActorRef myActor = system.actorOf(Props.create(HotSwapActor.class));
+ myActor.tell("foo", getRef());
+ myActor.tell("bar", getRef());
+ expectMsgEquals("I am already happy :-)");
+ myActor.tell("bar", getRef());
+ expectMsgEquals("I am already happy :-)");
}
- }));
- myActor.tell("foo", null);
- myActor.tell("bar", null);
- myActor.tell("bar", null);
+ };
}
@Test
public void useWatch() throws Exception {
- ActorRef myActor = system.actorOf(new Props(WatchActor.class));
+ ActorRef myActor = system.actorOf(Props.create(WatchActor.class));
Future future = Patterns.ask(myActor, "kill", 1000);
assert Await.result(future, Duration.create("1 second")).equals("finished");
}
+
+ // compilation test only
+ public void compileSelections() {
+ //#selection-local
+ // will look up this absolute path
+ getContext().actorSelection("/user/serviceA/actor");
+ // will look up sibling beneath same supervisor
+ getContext().actorSelection("../joe");
+ //#selection-local
+
+ //#selection-wildcard
+ // will look all children to serviceB with names starting with worker
+ getContext().actorSelection("/user/serviceB/worker*");
+ // will look up all siblings beneath same supervisor
+ getContext().actorSelection("../*");
+ //#selection-wildcard
+
+ //#selection-remote
+ getContext().actorSelection("akka.tcp://app@otherhost:1234/user/serviceB");
+ //#selection-remote
+ }
@Test
public void useIdentify() throws Exception {
- ActorRef a = system.actorOf(new Props(MyUntypedActor.class), "another");
- ActorRef b = system.actorOf(new Props(Follower.class));
- system.stop(a);
+ new JavaTestKit(system) {
+ {
+ ActorRef a = system.actorOf(Props.create(MyUntypedActor.class), "another");
+ ActorRef b = system.actorOf(Props.create(Follower.class, getRef()));
+ expectMsgEquals(a);
+ system.stop(a);
+ watch(b);
+ expectTerminated(b);
+ }
+ };
}
@Test
public void usePatternsGracefulStop() throws Exception {
- ActorRef actorRef = system.actorOf(new Props(MyUntypedActor.class));
+ ActorRef actorRef = system.actorOf(Props.create(MyUntypedActor.class));
//#gracefulStop
try {
Future stopped =
@@ -223,68 +434,143 @@ public class UntypedActorDocTestBase {
}
class Result {
- final int x;
+ final String x;
final String s;
- public Result(int x, String s) {
+ public Result(String x, String s) {
this.x = x;
this.s = s;
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((s == null) ? 0 : s.hashCode());
+ result = prime * result + ((x == null) ? 0 : x.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Result other = (Result) obj;
+ if (s == null) {
+ if (other.s != null)
+ return false;
+ } else if (!s.equals(other.s))
+ return false;
+ if (x == null) {
+ if (other.x != null)
+ return false;
+ } else if (!x.equals(other.x))
+ return false;
+ return true;
+ }
}
@Test
public void usePatternsAskPipe() {
- ActorRef actorA = system.actorOf(new Props(MyUntypedActor.class));
- ActorRef actorB = system.actorOf(new Props(MyUntypedActor.class));
- ActorRef actorC = system.actorOf(new Props(MyUntypedActor.class));
- //#ask-pipe
- final Timeout t = new Timeout(Duration.create(5, TimeUnit.SECONDS));
+ new JavaTestKit(system) {
+ {
+ ActorRef actorA = system.actorOf(Props.create(MyUntypedActor.class));
+ ActorRef actorB = system.actorOf(Props.create(MyUntypedActor.class));
+ ActorRef actorC = getRef();
- final ArrayList> futures = new ArrayList>();
- futures.add(ask(actorA, "request", 1000)); // using 1000ms timeout
- futures.add(ask(actorB, "another request", t)); // using timeout from above
+ //#ask-pipe
+ final Timeout t = new Timeout(Duration.create(5, TimeUnit.SECONDS));
- final Future> aggregate =
- Futures.sequence(futures, system.dispatcher());
+ final ArrayList> futures = new ArrayList>();
+ futures.add(ask(actorA, "request", 1000)); // using 1000ms timeout
+ futures.add(ask(actorB, "another request", t)); // using timeout from
+ // above
- final Future transformed = aggregate.map(
- new Mapper, Result>() {
- public Result apply(Iterable coll) {
- final Iterator it = coll.iterator();
- final String s = (String) it.next();
- final int x = (Integer) it.next();
- return new Result(x, s);
- }
- }, system.dispatcher());
+ final Future> aggregate = Futures.sequence(futures,
+ system.dispatcher());
- pipe(transformed, system.dispatcher()).to(actorC);
- //#ask-pipe
+ final Future transformed = aggregate.map(
+ new Mapper, Result>() {
+ public Result apply(Iterable coll) {
+ final Iterator it = coll.iterator();
+ final String x = (String) it.next();
+ final String s = (String) it.next();
+ return new Result(x, s);
+ }
+ }, system.dispatcher());
+
+ pipe(transformed, system.dispatcher()).to(actorC);
+ //#ask-pipe
+
+ expectMsgEquals(new Result("request", "another request"));
+ }
+ };
+ }
+
+ //#props-factory
+ public static class DemoActor extends UntypedActor {
+
+ /**
+ * Create Props for an actor of this type.
+ * @param name The name to be passed to this actor’s constructor.
+ * @return a Props for creating this actor, which can then be further configured
+ * (e.g. calling `.withDispatcher()` on it)
+ */
+ public static Props mkProps(String name) {
+ return Props.create(DemoActor.class, name);
+ }
+
+ final String name;
+
+ public DemoActor(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void onReceive(Object msg) {
+ // some behavior here
+ }
+
+ }
+
+ //#props-factory
+ {
+ if (system != null)
+ //#props-factory
+ system.actorOf(DemoActor.mkProps("hello"));
+ //#props-factory
}
public static class MyActor extends UntypedActor {
+ final String s;
+
public MyActor(String s) {
+ this.s = s;
}
- public void onReceive(Object message) throws Exception {
- try {
- operation();
- } catch (Exception e) {
- getSender().tell(new akka.actor.Status.Failure(e), getSelf());
- throw e;
- }
- }
-
- private void operation() {
+ public void onReceive(Object message) {
+ getSender().tell(s, getSelf());
}
+ /*
+ * This section must be kept in sync with the actual Actor trait.
+ *
+ * BOYSCOUT RULE: whenever you read this, verify that!
+ */
//#lifecycle-callbacks
public void preStart() {
}
- public void preRestart(Throwable reason, Option message) {
- for (ActorRef each : getContext().getChildren())
+ public void preRestart(Throwable reason, scala.Option message) {
+ for (ActorRef each : getContext().getChildren()) {
+ getContext().unwatch(each);
getContext().stop(each);
+ }
postStop();
}
@@ -297,7 +583,7 @@ public class UntypedActorDocTestBase {
//#lifecycle-callbacks
}
- public static class MyAskActor extends UntypedActor {
+ public class MyAskActor extends UntypedActor {
public void onReceive(Object message) throws Exception {
//#reply-exception
@@ -409,13 +695,20 @@ public class UntypedActorDocTestBase {
static
//#identify
public class Follower extends UntypedActor {
- String identifyId = "1";
+ final String identifyId = "1";
{
ActorSelection selection =
getContext().actorSelection("/user/another");
selection.tell(new Identify(identifyId), getSelf());
}
ActorRef another;
+
+ //#test-omitted
+ final ActorRef probe;
+ public Follower(ActorRef probe) {
+ this.probe = probe;
+ }
+ //#test-omitted
@Override
public void onReceive(Object message) {
@@ -428,6 +721,9 @@ public class UntypedActorDocTestBase {
else {
another = ref;
getContext().watch(another);
+ //#test-omitted
+ probe.tell(ref, getSelf());
+ //#test-omitted
}
}
} else if (message instanceof Terminated) {
diff --git a/akka-docs/rst/java/code/docs/actor/UntypedActorSwapper.java b/akka-docs/rst/java/code/docs/actor/UntypedActorSwapper.java
index a741c02da7..f7c376fd48 100644
--- a/akka-docs/rst/java/code/docs/actor/UntypedActorSwapper.java
+++ b/akka-docs/rst/java/code/docs/actor/UntypedActorSwapper.java
@@ -43,7 +43,7 @@ public class UntypedActorSwapper {
public static void main(String... args) {
ActorSystem system = ActorSystem.create("MySystem");
- ActorRef swap = system.actorOf(new Props(Swapper.class));
+ ActorRef swap = system.actorOf(Props.create(Swapper.class));
swap.tell(SWAP, null); // logs Hi
swap.tell(SWAP, null); // logs Ho
swap.tell(SWAP, null); // logs Hi
diff --git a/akka-docs/rst/java/code/docs/actor/japi/FaultHandlingDocSample.java b/akka-docs/rst/java/code/docs/actor/japi/FaultHandlingDocSample.java
index 6aea672023..707e389b92 100644
--- a/akka-docs/rst/java/code/docs/actor/japi/FaultHandlingDocSample.java
+++ b/akka-docs/rst/java/code/docs/actor/japi/FaultHandlingDocSample.java
@@ -47,8 +47,8 @@ public class FaultHandlingDocSample {
"akka.actor.debug.lifecycle = on");
ActorSystem system = ActorSystem.create("FaultToleranceSample", config);
- ActorRef worker = system.actorOf(new Props(Worker.class), "worker");
- ActorRef listener = system.actorOf(new Props(Listener.class), "listener");
+ ActorRef worker = system.actorOf(Props.create(Worker.class), "worker");
+ ActorRef listener = system.actorOf(Props.create(Listener.class), "listener");
// start the work and listen on progress
// note that the listener is used as sender of the tell,
// i.e. it will receive replies from the worker
@@ -121,7 +121,7 @@ public class FaultHandlingDocSample {
// about progress
ActorRef progressListener;
final ActorRef counterService = getContext().actorOf(
- new Props(CounterService.class), "counter");
+ Props.create(CounterService.class), "counter");
final int totalCount = 51;
// Stop the CounterService child if it throws ServiceUnavailable
@@ -202,6 +202,7 @@ public class FaultHandlingDocSample {
}
public static class ServiceUnavailable extends RuntimeException {
+ private static final long serialVersionUID = 1L;
public ServiceUnavailable(String msg) {
super(msg);
}
@@ -271,7 +272,7 @@ public class FaultHandlingDocSample {
*/
void initStorage() {
storage = getContext().watch(getContext().actorOf(
- new Props(Storage.class), "storage"));
+ Props.create(Storage.class), "storage"));
// Tell the counter, if any, to use the new storage
if (counter != null)
counter.tell(new UseStorage(storage), getSelf());
@@ -286,12 +287,7 @@ public class FaultHandlingDocSample {
counter == null) {
// Reply from Storage of the initial value, now we can create the Counter
final long value = ((Entry) msg).value;
- counter = getContext().actorOf(new Props().withCreator(
- new UntypedActorFactory() {
- public Actor create() {
- return new Counter(key, value);
- }
- }));
+ counter = getContext().actorOf(Props.create(Counter.class, key, value));
// Tell the counter to use current storage
counter.tell(new UseStorage(storage), getSelf());
// and send the buffered backlog to the counter
@@ -435,6 +431,7 @@ public class FaultHandlingDocSample {
}
public static class StorageException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
public StorageException(String msg) {
super(msg);
}
diff --git a/akka-docs/rst/java/code/docs/actor/mailbox/DurableMailboxDocTestBase.java b/akka-docs/rst/java/code/docs/actor/mailbox/DurableMailboxDocTestBase.java
index 5a0266c1a9..3d00624b3a 100644
--- a/akka-docs/rst/java/code/docs/actor/mailbox/DurableMailboxDocTestBase.java
+++ b/akka-docs/rst/java/code/docs/actor/mailbox/DurableMailboxDocTestBase.java
@@ -36,7 +36,7 @@ public class DurableMailboxDocTestBase {
@Test
public void configDefinedDispatcher() {
//#dispatcher-config-use
- ActorRef myActor = system.actorOf(new Props(MyUntypedActor.class).
+ ActorRef myActor = system.actorOf(Props.create(MyUntypedActor.class).
withDispatcher("my-dispatcher"), "myactor");
//#dispatcher-config-use
myActor.tell("test", null);
diff --git a/akka-docs/rst/java/code/docs/camel/ActivationTestBase.java b/akka-docs/rst/java/code/docs/camel/ActivationTestBase.java
index 10e369baeb..7a827d86da 100644
--- a/akka-docs/rst/java/code/docs/camel/ActivationTestBase.java
+++ b/akka-docs/rst/java/code/docs/camel/ActivationTestBase.java
@@ -9,7 +9,6 @@ package docs.camel;
import akka.util.Timeout;
import scala.concurrent.Future;
import scala.concurrent.duration.Duration;
- import scala.concurrent.duration.FiniteDuration;
import static java.util.concurrent.TimeUnit.SECONDS;
//#CamelActivation
@@ -17,13 +16,14 @@ import org.junit.Test;
public class ActivationTestBase {
+ @SuppressWarnings("unused")
@Test
public void testActivation() {
//#CamelActivation
// ..
ActorSystem system = ActorSystem.create("some-system");
- Props props = new Props(MyConsumer.class);
+ Props props = Props.create(MyConsumer.class);
ActorRef producer = system.actorOf(props,"myproducer");
Camel camel = CamelExtension.get(system);
// get a future reference to the activation of the endpoint of the Consumer Actor
diff --git a/akka-docs/rst/java/code/docs/camel/CustomRouteTestBase.java b/akka-docs/rst/java/code/docs/camel/CustomRouteTestBase.java
index 8e6b3dc1bf..8393ac4c9e 100644
--- a/akka-docs/rst/java/code/docs/camel/CustomRouteTestBase.java
+++ b/akka-docs/rst/java/code/docs/camel/CustomRouteTestBase.java
@@ -11,7 +11,7 @@ public class CustomRouteTestBase {
//#CustomRoute
ActorSystem system = ActorSystem.create("some-system");
Camel camel = CamelExtension.get(system);
- ActorRef responder = system.actorOf(new Props(Responder.class), "TestResponder");
+ ActorRef responder = system.actorOf(Props.create(Responder.class), "TestResponder");
camel.context().addRoutes(new CustomRouteBuilder(responder));
//#CustomRoute
system.stop(responder);
diff --git a/akka-docs/rst/java/code/docs/camel/OnRouteResponseTestBase.java b/akka-docs/rst/java/code/docs/camel/OnRouteResponseTestBase.java
index 54248c8cfd..832d2c0bba 100644
--- a/akka-docs/rst/java/code/docs/camel/OnRouteResponseTestBase.java
+++ b/akka-docs/rst/java/code/docs/camel/OnRouteResponseTestBase.java
@@ -7,14 +7,10 @@ public class OnRouteResponseTestBase {
public void onRouteResponse(){
//#RouteResponse
ActorSystem system = ActorSystem.create("some-system");
- Props receiverProps = new Props(ResponseReceiver.class);
+ Props receiverProps = Props.create(ResponseReceiver.class);
final ActorRef receiver = system.actorOf(receiverProps,"responseReceiver");
- UntypedActorFactory factory = new UntypedActorFactory() {
- public Actor create() {
- return new Forwarder("http://localhost:8080/news/akka", receiver);
- }
- };
- ActorRef forwardResponse = system.actorOf(new Props(factory));
+ ActorRef forwardResponse = system.actorOf(Props.create(
+ Forwarder.class, "http://localhost:8080/news/akka", receiver));
// the Forwarder sends out a request to the web page and forwards the response to
// the ResponseReceiver
forwardResponse.tell("some request", null);
diff --git a/akka-docs/rst/java/code/docs/camel/ProducerTestBase.java b/akka-docs/rst/java/code/docs/camel/ProducerTestBase.java
index 22b490c609..503f470d72 100644
--- a/akka-docs/rst/java/code/docs/camel/ProducerTestBase.java
+++ b/akka-docs/rst/java/code/docs/camel/ProducerTestBase.java
@@ -14,17 +14,18 @@ public class ProducerTestBase {
public void tellJmsProducer() {
//#TellProducer
ActorSystem system = ActorSystem.create("some-system");
- Props props = new Props(Orders.class);
+ Props props = Props.create(Orders.class);
ActorRef producer = system.actorOf(props, "jmsproducer");
producer.tell("", null);
//#TellProducer
system.shutdown();
}
+ @SuppressWarnings("unused")
public void askProducer() {
//#AskProducer
ActorSystem system = ActorSystem.create("some-system");
- Props props = new Props(FirstProducer.class);
+ Props props = Props.create(FirstProducer.class);
ActorRef producer = system.actorOf(props,"myproducer");
Future future = Patterns.ask(producer, "some request", 1000);
//#AskProducer
@@ -35,7 +36,7 @@ public class ProducerTestBase {
public void correlate(){
//#Correlate
ActorSystem system = ActorSystem.create("some-system");
- Props props = new Props(Orders.class);
+ Props props = Props.create(Orders.class);
ActorRef producer = system.actorOf(props,"jmsproducer");
Map headers = new HashMap();
headers.put(CamelMessage.MessageExchangeId(),"123");
diff --git a/akka-docs/rst/java/code/docs/camel/sample/http/HttpSample.java b/akka-docs/rst/java/code/docs/camel/sample/http/HttpSample.java
index ce5b72d03d..2143c33158 100644
--- a/akka-docs/rst/java/code/docs/camel/sample/http/HttpSample.java
+++ b/akka-docs/rst/java/code/docs/camel/sample/http/HttpSample.java
@@ -9,19 +9,15 @@ public class HttpSample {
// run the example in the MicroKernel. Just add the three lines below
// to your boot class.
ActorSystem system = ActorSystem.create("some-system");
- final ActorRef httpTransformer = system.actorOf(new Props(HttpTransformer.class));
+
+ final ActorRef httpTransformer = system.actorOf(
+ Props.create(HttpTransformer.class));
- final ActorRef httpProducer = system.actorOf(new Props(new UntypedActorFactory(){
- public Actor create() {
- return new HttpProducer(httpTransformer);
- }
- }));
-
- ActorRef httpConsumer = system.actorOf(new Props(new UntypedActorFactory(){
- public Actor create() {
- return new HttpConsumer(httpProducer);
- }
- }));
+ final ActorRef httpProducer = system.actorOf(
+ Props.create(HttpProducer.class, httpTransformer));
+
+ final ActorRef httpConsumer = system.actorOf(
+ Props.create(HttpConsumer.class, httpProducer));
//#HttpExample
}
}
diff --git a/akka-docs/rst/java/code/docs/camel/sample/quartz/QuartzSample.java b/akka-docs/rst/java/code/docs/camel/sample/quartz/QuartzSample.java
index 479aed1200..59875e77a6 100644
--- a/akka-docs/rst/java/code/docs/camel/sample/quartz/QuartzSample.java
+++ b/akka-docs/rst/java/code/docs/camel/sample/quartz/QuartzSample.java
@@ -6,7 +6,7 @@ import akka.actor.Props;
public class QuartzSample {
public static void main(String[] args) {
ActorSystem system = ActorSystem.create("my-quartz-system");
- system.actorOf(new Props(MyQuartzActor.class));
+ system.actorOf(Props.create(MyQuartzActor.class));
}
}
//#QuartzExample
\ No newline at end of file
diff --git a/akka-docs/rst/java/code/docs/camel/sample/route/CustomRouteSample.java b/akka-docs/rst/java/code/docs/camel/sample/route/CustomRouteSample.java
index 1743a79862..f4a3760542 100644
--- a/akka-docs/rst/java/code/docs/camel/sample/route/CustomRouteSample.java
+++ b/akka-docs/rst/java/code/docs/camel/sample/route/CustomRouteSample.java
@@ -4,25 +4,16 @@ import akka.actor.*;
import akka.camel.CamelExtension;
public class CustomRouteSample {
+ @SuppressWarnings("unused")
public static void main(String[] args) {
try {
//#CustomRouteExample
// the below lines can be added to a Boot class, so that you can run the
// example from a MicroKernel
ActorSystem system = ActorSystem.create("some-system");
- final ActorRef producer = system.actorOf(new Props(Producer1.class));
- final ActorRef mediator = system.actorOf(new Props(new UntypedActorFactory() {
- public Actor create() {
- return new Transformer(producer);
-
- }
- }));
- ActorRef consumer = system.actorOf(new Props(new UntypedActorFactory() {
- public Actor create() {
- return new Consumer3(mediator);
-
- }
- }));
+ final ActorRef producer = system.actorOf(Props.create(Producer1.class));
+ final ActorRef mediator = system.actorOf(Props.create(Transformer.class, producer));
+ final ActorRef consumer = system.actorOf(Props.create(Consumer3.class, mediator));
CamelExtension.get(system).context().addRoutes(new CustomRouteBuilder());
//#CustomRouteExample
} catch (Exception e) {
diff --git a/akka-docs/rst/java/code/docs/dispatcher/DispatcherDocTestBase.java b/akka-docs/rst/java/code/docs/dispatcher/DispatcherDocTestBase.java
index d24d2da445..0741bcaece 100644
--- a/akka-docs/rst/java/code/docs/dispatcher/DispatcherDocTestBase.java
+++ b/akka-docs/rst/java/code/docs/dispatcher/DispatcherDocTestBase.java
@@ -58,32 +58,36 @@ public class DispatcherDocTestBase {
system = null;
}
+ @SuppressWarnings("unused")
@Test
public void defineDispatcherInConfig() {
//#defining-dispatcher-in-config
ActorRef myActor =
- system.actorOf(new Props(MyUntypedActor.class),
+ system.actorOf(Props.create(MyUntypedActor.class),
"myactor");
//#defining-dispatcher-in-config
}
+ @SuppressWarnings("unused")
@Test
public void defineDispatcherInCode() {
//#defining-dispatcher-in-code
ActorRef myActor =
- system.actorOf(new Props(MyUntypedActor.class).withDispatcher("my-dispatcher"),
+ system.actorOf(Props.create(MyUntypedActor.class).withDispatcher("my-dispatcher"),
"myactor3");
//#defining-dispatcher-in-code
}
+ @SuppressWarnings("unused")
@Test
public void definePinnedDispatcher() {
//#defining-pinned-dispatcher
- ActorRef myActor = system.actorOf(new Props(MyUntypedActor.class)
+ ActorRef myActor = system.actorOf(Props.create(MyUntypedActor.class)
.withDispatcher("my-pinned-dispatcher"));
//#defining-pinned-dispatcher
}
+ @SuppressWarnings("unused")
public void compileLookup() {
//#lookup
// this is scala.concurrent.ExecutionContext
@@ -97,33 +101,24 @@ public class DispatcherDocTestBase {
JavaTestKit probe = new JavaTestKit(system);
//#prio-dispatcher
- // We create a new Actor that just prints out what it processes
- ActorRef myActor = system.actorOf(
- new Props().withCreator(new UntypedActorFactory() {
- public UntypedActor create() {
- return new UntypedActor() {
- LoggingAdapter log =
- Logging.getLogger(getContext().system(), this);
- {
- for(Object msg : new Object[] {
- "lowpriority",
- "lowpriority",
- "highpriority",
- "pigdog",
- "pigdog2",
- "pigdog3",
- "highpriority",
- PoisonPill.getInstance() }) {
- getSelf().tell(msg, getSelf());
- }
- }
+ class Demo extends UntypedActor {
+ LoggingAdapter log = Logging.getLogger(getContext().system(), this);
+ {
+ for (Object msg : new Object[] { "lowpriority", "lowpriority",
+ "highpriority", "pigdog", "pigdog2", "pigdog3", "highpriority",
+ PoisonPill.getInstance() }) {
+ getSelf().tell(msg, getSelf());
+ }
+ }
- public void onReceive(Object message) {
- log.info(message.toString());
- }
- };
- }
- }).withDispatcher("prio-dispatcher"));
+ public void onReceive(Object message) {
+ log.info(message.toString());
+ }
+ }
+
+ // We create a new Actor that just prints out what it processes
+ ActorRef myActor = system.actorOf(Props.create(Demo.class, this)
+ .withDispatcher("prio-dispatcher"));
/*
Logs:
diff --git a/akka-docs/rst/java/code/docs/event/LoggingDocTestBase.java b/akka-docs/rst/java/code/docs/event/LoggingDocTestBase.java
index fc0a2f2588..efebb4a291 100644
--- a/akka-docs/rst/java/code/docs/event/LoggingDocTestBase.java
+++ b/akka-docs/rst/java/code/docs/event/LoggingDocTestBase.java
@@ -22,7 +22,6 @@ import org.junit.Test;
import scala.Option;
-import akka.actor.UntypedActorFactory;
//#imports-deadletter
import akka.actor.Props;
import akka.actor.ActorRef;
@@ -36,11 +35,7 @@ public class LoggingDocTestBase {
@Test
public void useLoggingActor() {
ActorSystem system = ActorSystem.create("MySystem");
- ActorRef myActor = system.actorOf(new Props(new UntypedActorFactory() {
- public UntypedActor create() {
- return new MyActor();
- }
- }));
+ ActorRef myActor = system.actorOf(Props.create(MyActor.class, this));
myActor.tell("test", null);
system.shutdown();
}
@@ -49,7 +44,7 @@ public class LoggingDocTestBase {
public void subscribeToDeadLetters() {
//#deadletters
final ActorSystem system = ActorSystem.create("DeadLetters");
- final ActorRef actor = system.actorOf(new Props(DeadLetterActor.class));
+ final ActorRef actor = system.actorOf(Props.create(DeadLetterActor.class));
system.eventStream().subscribe(actor, DeadLetter.class);
//#deadletters
system.shutdown();
diff --git a/akka-docs/rst/java/code/docs/future/FutureDocTestBase.java b/akka-docs/rst/java/code/docs/future/FutureDocTestBase.java
index 15ae81bda8..849504e62f 100644
--- a/akka-docs/rst/java/code/docs/future/FutureDocTestBase.java
+++ b/akka-docs/rst/java/code/docs/future/FutureDocTestBase.java
@@ -110,7 +110,7 @@ public class FutureDocTestBase {
@Test
public void useBlockingFromActor() throws Exception {
- ActorRef actor = system.actorOf(new Props(MyActor.class));
+ ActorRef actor = system.actorOf(Props.create(MyActor.class));
String msg = "hello";
//#ask-blocking
Timeout timeout = new Timeout(Duration.create(5, "seconds"));
diff --git a/akka-docs/rst/java/code/docs/io/japi/PipelineTest.java b/akka-docs/rst/java/code/docs/io/japi/PipelineTest.java
index cd1c0744f7..2f40ef7ff7 100644
--- a/akka-docs/rst/java/code/docs/io/japi/PipelineTest.java
+++ b/akka-docs/rst/java/code/docs/io/japi/PipelineTest.java
@@ -13,12 +13,10 @@ import org.junit.Test;
import scala.concurrent.duration.Duration;
-import akka.actor.Actor;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.PoisonPill;
import akka.actor.Props;
-import akka.actor.UntypedActorFactory;
import akka.io.AbstractPipelineContext;
import akka.io.PipelineFactory;
import akka.io.PipelineInjector;
@@ -117,25 +115,23 @@ public class PipelineTest {
public void testTick() {
new JavaTestKit(system) {
{
- final ActorRef proc = system.actorOf(new Props(
- new UntypedActorFactory() {
- private static final long serialVersionUID = 1L;
+ class P extends Processor {
+ public P(ActorRef cmds, ActorRef evts) throws Exception {
+ super(cmds, evts);
+ }
- @Override
- public Actor create() throws Exception {
- return new Processor(getRef(), getRef()) {
-
- @Override
- public void onReceive(Object obj) throws Exception {
- if (obj.equals("fail!")) {
- throw new RuntimeException("FAIL!");
- }
- super.onReceive(obj);
- }
-
- };
- }
- }), "processor");
+ @Override
+ public void onReceive(Object obj) throws Exception {
+ if (obj.equals("fail!")) {
+ throw new RuntimeException("FAIL!");
+ }
+ super.onReceive(obj);
+ }
+
+ }
+
+ final ActorRef proc = system.actorOf(Props.create(
+ P.class, this, getRef(), getRef()), "processor");
expectMsgClass(TickGenerator.Tick.class);
proc.tell(msg, null);
final ByteString encoded = expectMsgClass(ByteString.class);
diff --git a/akka-docs/rst/java/code/docs/jrouting/ConsistentHashingRouterDocTestBase.java b/akka-docs/rst/java/code/docs/jrouting/ConsistentHashingRouterDocTestBase.java
index 9a1ed88ba6..901ba33b6e 100644
--- a/akka-docs/rst/java/code/docs/jrouting/ConsistentHashingRouterDocTestBase.java
+++ b/akka-docs/rst/java/code/docs/jrouting/ConsistentHashingRouterDocTestBase.java
@@ -66,6 +66,7 @@ public class ConsistentHashingRouterDocTestBase {
static
//#cache-actor
public final class Evict implements Serializable {
+ private static final long serialVersionUID = 1L;
public final String key;
public Evict(String key) {
this.key = key;
@@ -76,6 +77,7 @@ public class ConsistentHashingRouterDocTestBase {
static
//#cache-actor
public final class Get implements Serializable, ConsistentHashable {
+ private static final long serialVersionUID = 1L;
public final String key;
public Get(String key) {
this.key = key;
@@ -89,6 +91,7 @@ public class ConsistentHashingRouterDocTestBase {
static
//#cache-actor
public final class Entry implements Serializable {
+ private static final long serialVersionUID = 1L;
public final String key;
public final String value;
public Entry(String key, String value) {
@@ -122,7 +125,7 @@ public class ConsistentHashingRouterDocTestBase {
}
};
- ActorRef cache = system.actorOf(new Props(Cache.class).withRouter(
+ ActorRef cache = system.actorOf(Props.create(Cache.class).withRouter(
new ConsistentHashingRouter(10).withHashMapper(hashMapper)),
"cache");
diff --git a/akka-docs/rst/java/code/docs/jrouting/CustomRouterDocTestBase.java b/akka-docs/rst/java/code/docs/jrouting/CustomRouterDocTestBase.java
index 61fa23292f..593ea1ed4f 100644
--- a/akka-docs/rst/java/code/docs/jrouting/CustomRouterDocTestBase.java
+++ b/akka-docs/rst/java/code/docs/jrouting/CustomRouterDocTestBase.java
@@ -57,7 +57,7 @@ public class CustomRouterDocTestBase {
@Test
public void demonstrateDispatchers() {
//#dispatchers
- final ActorRef router = system.actorOf(new Props(MyActor.class)
+ final ActorRef router = system.actorOf(Props.create(MyActor.class)
// “head” router will run on "head" dispatcher
.withRouter(new RoundRobinRouter(5).withDispatcher("head"))
// MyActor “workers” will run on "workers" dispatcher
@@ -71,7 +71,7 @@ public class CustomRouterDocTestBase {
final SupervisorStrategy strategy =
new OneForOneStrategy(5, Duration.create("1 minute"),
Collections.>singletonList(Exception.class));
- final ActorRef router = system.actorOf(new Props(MyActor.class)
+ final ActorRef router = system.actorOf(Props.create(MyActor.class)
.withRouter(new RoundRobinRouter(5).withSupervisorStrategy(strategy)));
//#supervision
}
@@ -80,7 +80,7 @@ public class CustomRouterDocTestBase {
@Test
public void countVotesAsIntendedNotAsInFlorida() throws Exception {
ActorRef routedActor = system.actorOf(
- new Props().withRouter(new VoteCountRouter()));
+ Props.empty().withRouter(new VoteCountRouter()));
routedActor.tell(DemocratVote, null);
routedActor.tell(DemocratVote, null);
routedActor.tell(RepublicanVote, null);
@@ -167,9 +167,9 @@ public class CustomRouterDocTestBase {
@Override
public CustomRoute createCustomRoute(RouteeProvider routeeProvider) {
final ActorRef democratActor =
- routeeProvider.context().actorOf(new Props(DemocratActor.class), "d");
+ routeeProvider.context().actorOf(Props.create(DemocratActor.class), "d");
final ActorRef republicanActor =
- routeeProvider.context().actorOf(new Props(RepublicanActor.class), "r");
+ routeeProvider.context().actorOf(Props.create(RepublicanActor.class), "r");
List routees =
Arrays.asList(new ActorRef[] { democratActor, republicanActor });
diff --git a/akka-docs/rst/java/code/docs/jrouting/ParentActor.java b/akka-docs/rst/java/code/docs/jrouting/ParentActor.java
index e2684d7c55..82482a4147 100644
--- a/akka-docs/rst/java/code/docs/jrouting/ParentActor.java
+++ b/akka-docs/rst/java/code/docs/jrouting/ParentActor.java
@@ -22,7 +22,7 @@ public class ParentActor extends UntypedActor {
if (msg.equals("rrr")) {
//#roundRobinRouter
ActorRef roundRobinRouter = getContext().actorOf(
- new Props(PrintlnActor.class).withRouter(new RoundRobinRouter(5)),
+ Props.create(PrintlnActor.class).withRouter(new RoundRobinRouter(5)),
"router");
for (int i = 1; i <= 10; i++) {
roundRobinRouter.tell(i, getSelf());
@@ -31,7 +31,7 @@ public class ParentActor extends UntypedActor {
} else if (msg.equals("rr")) {
//#randomRouter
ActorRef randomRouter = getContext().actorOf(
- new Props(PrintlnActor.class).withRouter(new RandomRouter(5)),
+ Props.create(PrintlnActor.class).withRouter(new RandomRouter(5)),
"router");
for (int i = 1; i <= 10; i++) {
randomRouter.tell(i, getSelf());
@@ -40,7 +40,7 @@ public class ParentActor extends UntypedActor {
} else if (msg.equals("smr")) {
//#smallestMailboxRouter
ActorRef smallestMailboxRouter = getContext().actorOf(
- new Props(PrintlnActor.class).withRouter(new SmallestMailboxRouter(5)),
+ Props.create(PrintlnActor.class).withRouter(new SmallestMailboxRouter(5)),
"router");
for (int i = 1; i <= 10; i++) {
smallestMailboxRouter.tell(i, getSelf());
@@ -49,13 +49,13 @@ public class ParentActor extends UntypedActor {
} else if (msg.equals("br")) {
//#broadcastRouter
ActorRef broadcastRouter = getContext().actorOf(
- new Props(PrintlnActor.class).withRouter(new BroadcastRouter(5)), "router");
+ Props.create(PrintlnActor.class).withRouter(new BroadcastRouter(5)), "router");
broadcastRouter.tell("this is a broadcast message", getSelf());
//#broadcastRouter
} else if (msg.equals("sgfcr")) {
//#scatterGatherFirstCompletedRouter
ActorRef scatterGatherFirstCompletedRouter = getContext().actorOf(
- new Props(FibonacciActor.class).withRouter(
+ Props.create(FibonacciActor.class).withRouter(
new ScatterGatherFirstCompletedRouter(5, Duration.create(2, "seconds"))),
"router");
Timeout timeout = new Timeout(Duration.create(5, "seconds"));
diff --git a/akka-docs/rst/java/code/docs/jrouting/RouterViaConfigExample.java b/akka-docs/rst/java/code/docs/jrouting/RouterViaConfigExample.java
index ee4ba7ff7e..ba3b2e1124 100644
--- a/akka-docs/rst/java/code/docs/jrouting/RouterViaConfigExample.java
+++ b/akka-docs/rst/java/code/docs/jrouting/RouterViaConfigExample.java
@@ -44,7 +44,7 @@ public class RouterViaConfigExample {
ActorSystem system = ActorSystem.create("Example", config);
//#configurableRouting
ActorRef router = system.actorOf(
- new Props(ExampleActor.class).withRouter(new FromConfig()), "myrouter1");
+ Props.create(ExampleActor.class).withRouter(new FromConfig()), "myrouter1");
//#configurableRouting
for (int i = 1; i <= 10; i++) {
router.tell(new ExampleActor.Message(i), null);
@@ -52,7 +52,7 @@ public class RouterViaConfigExample {
//#configurableRoutingWithResizer
ActorRef router2 = system.actorOf(
- new Props(ExampleActor.class).withRouter(new FromConfig()), "myrouter2");
+ Props.create(ExampleActor.class).withRouter(new FromConfig()), "myrouter2");
//#configurableRoutingWithResizer
for (int i = 1; i <= 10; i++) {
router2.tell(new ExampleActor.Message(i), null);
diff --git a/akka-docs/rst/java/code/docs/jrouting/RouterViaProgramDocTestBase.java b/akka-docs/rst/java/code/docs/jrouting/RouterViaProgramDocTestBase.java
index db7f1f024a..ac522d9726 100644
--- a/akka-docs/rst/java/code/docs/jrouting/RouterViaProgramDocTestBase.java
+++ b/akka-docs/rst/java/code/docs/jrouting/RouterViaProgramDocTestBase.java
@@ -3,21 +3,23 @@
*/
package docs.jrouting;
-import akka.actor.*;
-import akka.remote.routing.RemoteRouterConfig;
+import java.util.Arrays;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.actor.Kill;
+import akka.actor.PoisonPill;
+import akka.actor.Props;
+import akka.actor.Terminated;
import akka.routing.Broadcast;
import akka.routing.RoundRobinRouter;
import akka.testkit.JavaTestKit;
import docs.jrouting.RouterViaProgramExample.ExampleActor;
import docs.routing.RouterViaProgramDocSpec.Echo;
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
public class RouterViaProgramDocTestBase {
@@ -45,17 +47,18 @@ public class RouterViaProgramDocTestBase {
}
}
+ @SuppressWarnings("unused")
@Test
public void demonstrateRouteesFromPaths() {
new JavaTestKit(system) {{
//#programmaticRoutingRouteePaths
- ActorRef actor1 = system.actorOf(new Props(ExampleActor.class), "actor1");
- ActorRef actor2 = system.actorOf(new Props(ExampleActor.class), "actor2");
- ActorRef actor3 = system.actorOf(new Props(ExampleActor.class), "actor3");
+ ActorRef actor1 = system.actorOf(Props.create(ExampleActor.class), "actor1");
+ ActorRef actor2 = system.actorOf(Props.create(ExampleActor.class), "actor2");
+ ActorRef actor3 = system.actorOf(Props.create(ExampleActor.class), "actor3");
Iterable routees = Arrays.asList(
new String[] { "/user/actor1", "/user/actor2", "/user/actor3" });
ActorRef router = system.actorOf(
- new Props().withRouter(new RoundRobinRouter(routees)));
+ Props.empty().withRouter(new RoundRobinRouter(routees)));
//#programmaticRoutingRouteePaths
for (int i = 1; i <= 6; i++) {
router.tell(new ExampleActor.Message(i), null);
@@ -66,7 +69,7 @@ public class RouterViaProgramDocTestBase {
@Test
public void demonstrateBroadcast() {
new JavaTestKitWithSelf(system) {{
- ActorRef router = system.actorOf(new Props(Echo.class).withRouter(new RoundRobinRouter(5)));
+ ActorRef router = system.actorOf(Props.create(Echo.class).withRouter(new RoundRobinRouter(5)));
//#broadcastDavyJonesWarning
router.tell(new Broadcast("Watch out for Davy Jones' locker"), getSelf());
//#broadcastDavyJonesWarning
@@ -77,7 +80,7 @@ public class RouterViaProgramDocTestBase {
@Test
public void demonstratePoisonPill() {
new JavaTestKitWithSelf(system) {{
- ActorRef router = system.actorOf(new Props(Echo.class).withRouter(new RoundRobinRouter(5)));
+ ActorRef router = system.actorOf(Props.create(Echo.class).withRouter(new RoundRobinRouter(5)));
watch(router);
//#poisonPill
router.tell(PoisonPill.getInstance(), getSelf());
@@ -89,7 +92,7 @@ public class RouterViaProgramDocTestBase {
@Test
public void demonstrateBroadcastOfPoisonPill() {
new JavaTestKitWithSelf(system) {{
- ActorRef router = system.actorOf(new Props(Echo.class).withRouter(new RoundRobinRouter(5)));
+ ActorRef router = system.actorOf(Props.create(Echo.class).withRouter(new RoundRobinRouter(5)));
watch(router);
//#broadcastPoisonPill
router.tell(new Broadcast(PoisonPill.getInstance()), getSelf());
@@ -101,7 +104,7 @@ public class RouterViaProgramDocTestBase {
@Test
public void demonstrateKill() {
new JavaTestKitWithSelf(system) {{
- ActorRef router = system.actorOf(new Props(Echo.class).withRouter(new RoundRobinRouter(5)));
+ ActorRef router = system.actorOf(Props.create(Echo.class).withRouter(new RoundRobinRouter(5)));
watch(router);
//#kill
router.tell(Kill.getInstance(), getSelf());
@@ -113,7 +116,7 @@ public class RouterViaProgramDocTestBase {
@Test
public void demonstrateBroadcastOfKill() {
new JavaTestKitWithSelf(system) {{
- ActorRef router = system.actorOf(new Props(Echo.class).withRouter(new RoundRobinRouter(5)));
+ ActorRef router = system.actorOf(Props.create(Echo.class).withRouter(new RoundRobinRouter(5)));
watch(router);
//#broadcastKill
router.tell(new Broadcast(Kill.getInstance()), getSelf());
diff --git a/akka-docs/rst/java/code/docs/jrouting/RouterViaProgramExample.java b/akka-docs/rst/java/code/docs/jrouting/RouterViaProgramExample.java
index 4d6dd1e485..86e7688112 100644
--- a/akka-docs/rst/java/code/docs/jrouting/RouterViaProgramExample.java
+++ b/akka-docs/rst/java/code/docs/jrouting/RouterViaProgramExample.java
@@ -41,25 +41,26 @@ public class RouterViaProgramExample {
}
}
+ @SuppressWarnings("unused")
public static void main(String... args) {
ActorSystem system = ActorSystem.create("RPE");
//#programmaticRoutingNrOfInstances
int nrOfInstances = 5;
ActorRef router1 = system.actorOf(
- new Props(ExampleActor.class).withRouter(new RoundRobinRouter(nrOfInstances)));
+ Props.create(ExampleActor.class).withRouter(new RoundRobinRouter(nrOfInstances)));
//#programmaticRoutingNrOfInstances
for (int i = 1; i <= 6; i++) {
router1.tell(new ExampleActor.Message(i), null);
}
//#programmaticRoutingRoutees
- ActorRef actor1 = system.actorOf(new Props(ExampleActor.class));
- ActorRef actor2 = system.actorOf(new Props(ExampleActor.class));
- ActorRef actor3 = system.actorOf(new Props(ExampleActor.class));
+ ActorRef actor1 = system.actorOf(Props.create(ExampleActor.class));
+ ActorRef actor2 = system.actorOf(Props.create(ExampleActor.class));
+ ActorRef actor3 = system.actorOf(Props.create(ExampleActor.class));
Iterable routees = Arrays.asList(
new ActorRef[] { actor1, actor2, actor3 });
ActorRef router2 = system.actorOf(
- new Props().withRouter(RoundRobinRouter.create(routees)));
+ Props.empty().withRouter(RoundRobinRouter.create(routees)));
//#programmaticRoutingRoutees
for (int i = 1; i <= 6; i++) {
router2.tell(new ExampleActor.Message(i), null);
@@ -70,7 +71,7 @@ public class RouterViaProgramExample {
int upperBound = 15;
DefaultResizer resizer = new DefaultResizer(lowerBound, upperBound);
ActorRef router3 = system.actorOf(
- new Props(ExampleActor.class).withRouter(new RoundRobinRouter(resizer)));
+ Props.create(ExampleActor.class).withRouter(new RoundRobinRouter(resizer)));
//#programmaticRoutingWithResizer
for (int i = 1; i <= 6; i++) {
router3.tell(new ExampleActor.Message(i), null);
@@ -80,11 +81,12 @@ public class RouterViaProgramExample {
Address addr1 = new Address("akka", "remotesys", "otherhost", 1234);
Address addr2 = AddressFromURIString.parse("akka://othersys@anotherhost:1234");
Address[] addresses = new Address[] { addr1, addr2 };
- ActorRef routerRemote = system.actorOf(new Props(ExampleActor.class)
+ ActorRef routerRemote = system.actorOf(Props.create(ExampleActor.class)
.withRouter(new RemoteRouterConfig(new RoundRobinRouter(5), addresses)));
//#remoteRoutees
}
+ @SuppressWarnings("unused")
private class CompileCheckJavaDocsForRouting extends UntypedActor {
@Override
diff --git a/akka-docs/rst/java/code/docs/pattern/SchedulerPatternTest.java b/akka-docs/rst/java/code/docs/pattern/SchedulerPatternTest.java
index 88ac60f644..4d48f89b0c 100644
--- a/akka-docs/rst/java/code/docs/pattern/SchedulerPatternTest.java
+++ b/akka-docs/rst/java/code/docs/pattern/SchedulerPatternTest.java
@@ -121,13 +121,7 @@ public class SchedulerPatternTest {
public void scheduleInConstructor() {
new TestSchedule(system) {{
final JavaTestKit probe = new JavaTestKit(system);
-
- final Props props = new Props(new UntypedActorFactory() {
- public UntypedActor create() {
- return new ScheduleInConstructor(probe.getRef());
- }
- });
-
+ final Props props = Props.create(ScheduleInConstructor.class, probe.getRef());
testSchedule(probe, props, duration("3000 millis"), duration("2000 millis"));
}};
}
@@ -135,16 +129,9 @@ public class SchedulerPatternTest {
@Test
@Ignore // no way to tag this as timing sensitive
public void scheduleInReceive() {
-
new TestSchedule(system) {{
final JavaTestKit probe = new JavaTestKit(system);
-
- final Props props = new Props(new UntypedActorFactory() {
- public UntypedActor create() {
- return new ScheduleInReceive(probe.getRef());
- }
- });
-
+ final Props props = Props.create(ScheduleInReceive.class, probe.getRef());
testSchedule(probe, props, duration("3000 millis"), duration("2500 millis"));
}};
}
diff --git a/akka-docs/rst/java/code/docs/pattern/SupervisedAsk.java b/akka-docs/rst/java/code/docs/pattern/SupervisedAsk.java
index 1c8d92166c..f87d43b2ff 100644
--- a/akka-docs/rst/java/code/docs/pattern/SupervisedAsk.java
+++ b/akka-docs/rst/java/code/docs/pattern/SupervisedAsk.java
@@ -45,7 +45,7 @@ public class SupervisedAsk {
public void onReceive(Object message) throws Exception {
if (message instanceof AskParam) {
ActorRef supervisor = getContext().actorOf(
- Props.apply(AskSupervisor.class));
+ Props.create(AskSupervisor.class));
supervisor.forward(message, getContext());
} else {
unhandled(message);
@@ -104,6 +104,6 @@ public class SupervisedAsk {
synchronized public static ActorRef createSupervisorCreator(
ActorRefFactory factory) {
- return factory.actorOf(Props.apply(AskSupervisorCreator.class));
+ return factory.actorOf(Props.create(AskSupervisorCreator.class));
}
}
\ No newline at end of file
diff --git a/akka-docs/rst/java/code/docs/pattern/SupervisedAskSpec.java b/akka-docs/rst/java/code/docs/pattern/SupervisedAskSpec.java
index 4486f56e98..4316f2e876 100644
--- a/akka-docs/rst/java/code/docs/pattern/SupervisedAskSpec.java
+++ b/akka-docs/rst/java/code/docs/pattern/SupervisedAskSpec.java
@@ -18,7 +18,7 @@ public class SupervisedAskSpec {
ActorRef supervisorCreator = SupervisedAsk
.createSupervisorCreator(actorSystem);
Future finished = SupervisedAsk.askOf(supervisorCreator,
- Props.apply(someActor), message, timeout);
+ Props.create(someActor), message, timeout);
return Await.result(finished, timeout.duration());
} catch (Exception e) {
// exception propagated by supervision
diff --git a/akka-docs/rst/java/code/docs/remoting/RemoteDeploymentDocTestBase.java b/akka-docs/rst/java/code/docs/remoting/RemoteDeploymentDocTestBase.java
index ab7411118b..b4ca288753 100644
--- a/akka-docs/rst/java/code/docs/remoting/RemoteDeploymentDocTestBase.java
+++ b/akka-docs/rst/java/code/docs/remoting/RemoteDeploymentDocTestBase.java
@@ -48,7 +48,7 @@ public class RemoteDeploymentDocTestBase {
addr = AddressFromURIString.parse("akka.tcp://sys@host:1234"); // the same
//#make-address
//#deploy
- ActorRef ref = system.actorOf(new Props(SampleActor.class).withDeploy(
+ ActorRef ref = system.actorOf(Props.create(SampleActor.class).withDeploy(
new Deploy(new RemoteScope(addr))));
//#deploy
assert ref.path().address().equals(addr);
@@ -58,7 +58,7 @@ public class RemoteDeploymentDocTestBase {
public void demonstrateSampleActor() {
//#sample-actor
- ActorRef actor = system.actorOf(new Props(SampleActor.class), "sampleActor");
+ ActorRef actor = system.actorOf(Props.create(SampleActor.class), "sampleActor");
actor.tell("Pretty slick", null);
//#sample-actor
}
diff --git a/akka-docs/rst/java/code/docs/testkit/TestKitDocTest.java b/akka-docs/rst/java/code/docs/testkit/TestKitDocTest.java
index c2ca01b9ce..69a20e83f9 100644
--- a/akka-docs/rst/java/code/docs/testkit/TestKitDocTest.java
+++ b/akka-docs/rst/java/code/docs/testkit/TestKitDocTest.java
@@ -20,7 +20,6 @@ import akka.actor.PoisonPill;
import akka.actor.Props;
import akka.actor.Terminated;
import akka.actor.UntypedActor;
-import akka.actor.UntypedActorFactory;
import scala.concurrent.Await;
import scala.concurrent.Future;
import akka.testkit.CallingThreadDispatcher;
@@ -63,7 +62,7 @@ public class TestKitDocTest {
//#test-actor-ref
@Test
public void demonstrateTestActorRef() {
- final Props props = new Props(MyActor.class);
+ final Props props = Props.create(MyActor.class);
final TestActorRef ref = TestActorRef.create(system, props, "testA");
final MyActor actor = ref.underlyingActor();
assertTrue(actor.testMe());
@@ -73,7 +72,7 @@ public class TestKitDocTest {
@Test
public void demonstrateAsk() throws Exception {
//#test-behavior
- final Props props = new Props(MyActor.class);
+ final Props props = Props.create(MyActor.class);
final TestActorRef ref = TestActorRef.create(system, props, "testB");
final Future future = akka.pattern.Patterns.ask(ref, "say42", 3000);
assertTrue(future.isCompleted());
@@ -84,7 +83,7 @@ public class TestKitDocTest {
@Test
public void demonstrateExceptions() {
//#test-expecting-exceptions
- final Props props = new Props(MyActor.class);
+ final Props props = Props.create(MyActor.class);
final TestActorRef ref = TestActorRef.create(system, props, "myActor");
try {
ref.receive(new Exception("expected"));
@@ -208,7 +207,7 @@ public class TestKitDocTest {
}
@Test
- @SuppressWarnings("unchecked") // due to generic varargs
+ @SuppressWarnings({ "unchecked", "unused" }) // due to generic varargs
public void demonstrateExpect() {
new JavaTestKit(system) {{
getRef().tell("hello", null);
@@ -273,28 +272,24 @@ public class TestKitDocTest {
@Test
public void demonstrateProbe() {
//#test-probe
- // simple actor which just forwards messages
- class Forwarder extends UntypedActor {
- final ActorRef target;
- public Forwarder(ActorRef target) {
- this.target = target;
- }
- public void onReceive(Object msg) {
- target.forward(msg, getContext());
- }
- }
-
new JavaTestKit(system) {{
+ // simple actor which just forwards messages
+ class Forwarder extends UntypedActor {
+ final ActorRef target;
+ @SuppressWarnings("unused")
+ public Forwarder(ActorRef target) {
+ this.target = target;
+ }
+ public void onReceive(Object msg) {
+ target.forward(msg, getContext());
+ }
+ }
+
// create a test probe
final JavaTestKit probe = new JavaTestKit(system);
// create a forwarder, injecting the probe’s testActor
- final Props props = new Props(new UntypedActorFactory() {
- private static final long serialVersionUID = 8927158735963950216L;
- public UntypedActor create() {
- return new Forwarder(probe.getRef());
- }
- });
+ final Props props = Props.create(Forwarder.class, this, probe.getRef());
final ActorRef forwarder = system.actorOf(props, "forwarder");
// verify correct forwarding
@@ -327,7 +322,7 @@ public class TestKitDocTest {
@Test
public void demonstrateWatch() {
- final ActorRef target = system.actorOf(new Props(MyActor.class));
+ final ActorRef target = system.actorOf(Props.create(MyActor.class));
//#test-probe-watch
new JavaTestKit(system) {{
final JavaTestKit probe = new JavaTestKit(system);
@@ -411,7 +406,7 @@ public class TestKitDocTest {
public void demonstrateCTD() {
//#calling-thread-dispatcher
system.actorOf(
- new Props(MyActor.class)
+ Props.create(MyActor.class)
.withDispatcher(CallingThreadDispatcher.Id()));
//#calling-thread-dispatcher
}
diff --git a/akka-docs/rst/java/code/docs/testkit/TestKitSampleTest.java b/akka-docs/rst/java/code/docs/testkit/TestKitSampleTest.java
index fd6351339c..7070640d63 100644
--- a/akka-docs/rst/java/code/docs/testkit/TestKitSampleTest.java
+++ b/akka-docs/rst/java/code/docs/testkit/TestKitSampleTest.java
@@ -53,7 +53,7 @@ public class TestKitSampleTest {
* if you want to receive actor replies or use Within(), etc.
*/
new JavaTestKit(system) {{
- final Props props = new Props(SomeActor.class);
+ final Props props = Props.create(SomeActor.class);
final ActorRef subject = system.actorOf(props);
// can also use JavaTestKit “from the outside”
diff --git a/akka-docs/rst/java/code/docs/transactor/TransactorDocTest.java b/akka-docs/rst/java/code/docs/transactor/TransactorDocTest.java
index bb129cf577..265b09750e 100644
--- a/akka-docs/rst/java/code/docs/transactor/TransactorDocTest.java
+++ b/akka-docs/rst/java/code/docs/transactor/TransactorDocTest.java
@@ -23,8 +23,8 @@ public class TransactorDocTest {
//#coordinated-example
ActorSystem system = ActorSystem.create("CoordinatedExample");
- ActorRef counter1 = system.actorOf(new Props(CoordinatedCounter.class));
- ActorRef counter2 = system.actorOf(new Props(CoordinatedCounter.class));
+ ActorRef counter1 = system.actorOf(Props.create(CoordinatedCounter.class));
+ ActorRef counter2 = system.actorOf(Props.create(CoordinatedCounter.class));
Timeout timeout = new Timeout(5, SECONDS);
@@ -47,7 +47,7 @@ public class TransactorDocTest {
//#create-coordinated
ActorSystem system = ActorSystem.create("CoordinatedApi");
- ActorRef actor = system.actorOf(new Props(Coordinator.class));
+ ActorRef actor = system.actorOf(Props.create(Coordinator.class));
//#send-coordinated
actor.tell(new Coordinated(new Message(), timeout), null);
@@ -65,7 +65,7 @@ public class TransactorDocTest {
@Test
public void counterTransactor() throws Exception {
ActorSystem system = ActorSystem.create("CounterTransactor");
- ActorRef counter = system.actorOf(new Props(Counter.class));
+ ActorRef counter = system.actorOf(Props.create(Counter.class));
Timeout timeout = new Timeout(5, SECONDS);
Coordinated coordinated = new Coordinated(timeout);
@@ -81,8 +81,8 @@ public class TransactorDocTest {
@Test
public void friendlyCounterTransactor() throws Exception {
ActorSystem system = ActorSystem.create("FriendlyCounterTransactor");
- ActorRef friend = system.actorOf(new Props(Counter.class));
- ActorRef friendlyCounter = system.actorOf(new Props(FriendlyCounter.class));
+ ActorRef friend = system.actorOf(Props.create(Counter.class));
+ ActorRef friendlyCounter = system.actorOf(Props.create(FriendlyCounter.class));
Timeout timeout = new Timeout(5, SECONDS);
Coordinated coordinated = new Coordinated(timeout);
diff --git a/akka-docs/rst/java/code/docs/zeromq/ZeromqDocTestBase.java b/akka-docs/rst/java/code/docs/zeromq/ZeromqDocTestBase.java
index 8f1eb0d38f..51afb9d119 100644
--- a/akka-docs/rst/java/code/docs/zeromq/ZeromqDocTestBase.java
+++ b/akka-docs/rst/java/code/docs/zeromq/ZeromqDocTestBase.java
@@ -68,6 +68,7 @@ public class ZeromqDocTestBase {
system.shutdown();
}
+ @SuppressWarnings("unused")
@Test
public void demonstrateCreateSocket() {
Assume.assumeTrue(checkZeroMQInstallation());
@@ -78,7 +79,7 @@ public class ZeromqDocTestBase {
//#pub-socket
//#sub-socket
- ActorRef listener = system.actorOf(new Props(ListenerActor.class));
+ ActorRef listener = system.actorOf(Props.create(ListenerActor.class));
ActorRef subSocket = ZeroMQExtension.get(system).newSubSocket(
new Connect("tcp://127.0.0.1:1233"),
new Listener(listener), Subscribe.all());
@@ -115,17 +116,17 @@ public class ZeromqDocTestBase {
//#health2
- system.actorOf(new Props(HealthProbe.class), "health");
+ system.actorOf(Props.create(HealthProbe.class), "health");
//#health2
//#logger2
- system.actorOf(new Props(Logger.class), "logger");
+ system.actorOf(Props.create(Logger.class), "logger");
//#logger2
//#alerter2
- system.actorOf(new Props(HeapAlerter.class), "alerter");
+ system.actorOf(Props.create(HeapAlerter.class), "alerter");
//#alerter2
// Let it run for a while to see some output.
@@ -159,6 +160,7 @@ public class ZeromqDocTestBase {
static
//#health
public class Heap implements Serializable {
+ private static final long serialVersionUID = 1L;
public final long timestamp;
public final long used;
public final long max;
@@ -174,6 +176,7 @@ public class ZeromqDocTestBase {
static
//#health
public class Load implements Serializable {
+ private static final long serialVersionUID = 1L;
public final long timestamp;
public final double loadAverage;
diff --git a/akka-docs/rst/java/untyped-actors.rst b/akka-docs/rst/java/untyped-actors.rst
index 2dea93805f..b3940efbe1 100644
--- a/akka-docs/rst/java/untyped-actors.rst
+++ b/akka-docs/rst/java/untyped-actors.rst
@@ -32,7 +32,7 @@ Creating Actors
Defining an Actor class
-----------------------
-Actor in Java are implemented by extending the ``UntypedActor`` class and implementing the
+Actors in Java are implemented by extending the ``UntypedActor`` class and implementing the
:meth:`onReceive` method. This method takes the message as a parameter.
Here is an example:
@@ -42,84 +42,132 @@ Here is an example:
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.
+:class:`Props` is a configuration class to specify options for the creation
+of actors, think of it as an immutable and thus freely shareable recipe for
+creating an actor including associated deployment information (e.g. which
+dispatcher to use, see more below). Here are some examples of how to create a
+:class:`Props` instance.
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#import-props
.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#creating-props-config
+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
+: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):
+
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#import-untypedActor
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.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`!
+
+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.
+
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#props-factory
Creating Actors with Props
--------------------------
-Actors are created by passing in a ``Props`` instance into the ``actorOf`` factory method.
+Actors are created by passing a :class:`Props` instance into the
+:meth:`actorOf` factory method which is available on :class:`ActorSystem` and
+:class:`ActorContext`.
-.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#creating-props
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#import-actorRef
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#system-actorOf
+Using the :class:`ActorSystem` will create top-level actors, supervised by the
+actor system’s provided guardian actor, while using an actor’s context will
+create a child actor.
-Creating Actors with default constructor
-----------------------------------------
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#context-actorOf
+ :exclude: plus-some-behavior
-.. includecode:: code/docs/actor/UntypedActorDocTestBase.java
- :include: imports
+It is recommended to create a hierarchy of children, grand-children and so on
+such that it fits the logical failure-handling structure of the application,
+see :ref:`actor-systems`.
-.. includecode:: code/docs/actor/UntypedActorDocTestBase.java
- :include: system-actorOf
+The call to :meth:`actorOf` returns an instance of :class:`ActorRef`. This is a
+handle to the actor instance and the only way to interact with it. The
+:class:`ActorRef` is immutable and has a one to one relationship with the Actor
+it represents. The :class:`ActorRef` is also serializable and network-aware.
+This means that you can serialize it, send it over the wire and use it on a
+remote host and it will still be representing the same Actor on the original
+node, across the network.
-The call to :meth:`actorOf` returns an instance of ``ActorRef``. This is a handle to
-the ``UntypedActor`` instance which you can use to interact with the ``UntypedActor``. The
-``ActorRef`` is immutable and has a one to one relationship with the Actor it
-represents. The ``ActorRef`` is also serializable and network-aware. This means
-that you can serialize it, send it over the wire and use it on a remote host and
-it will still be representing the same Actor on the original node, across the
-network.
-
-In the above example the actor was created from the system. It is also possible
-to create actors from other actors with the actor ``context``. The difference is
-how the supervisor hierarchy is arranged. When using the context the current actor
-will be supervisor of the created child actor. When using the system it will be
-a top level actor, that is supervised by the system (internal guardian actor).
-
-.. includecode:: code/docs/actor/FirstUntypedActor.java#context-actorOf
-
-The name parameter is optional, but you should preferably name your actors, since
-that is used in log messages and for identifying actors. The name must not be empty
-or start with ``$``, but it may contain URL encoded characters (eg. ``%20`` for a blank space).
-If the given name is already in use by another child to the
-same parent actor an `InvalidActorNameException` is thrown.
+The name parameter is optional, but you should preferably name your actors,
+since that is used in log messages and for identifying actors. The name must
+not be empty or start with ``$``, but it may contain URL encoded characters
+(eg. ``%20`` for a blank space). If the given name is already in use by
+another child to the same parent an `InvalidActorNameException` is thrown.
Actors are automatically started asynchronously when created.
-When you create the ``UntypedActor`` then it will automatically call the ``preStart``
-callback method on the ``UntypedActor`` class. This is an excellent place to
-add initialization code for the actor.
-.. code-block:: java
+.. _actor-create-factory:
- @Override
- public void preStart() {
- ... // initialization code
- }
+Creating Actors with Factory Methods
+------------------------------------
-Creating Actors with non-default constructor
---------------------------------------------
+If your UntypedActor has a constructor that takes parameters then those need to
+be part of the :class:`Props` as well, as described `above `_. But there
+are cases when a factory method must be used, for example when the actual
+constructor arguments are determined by a dependency injection framework.
-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/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.
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#import-indirect
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java
+ :include: creating-indirectly
+ :exclude: obtain-fresh-Actor-instance-from-DI-framework
.. warning::
- You might be tempted at times to offer an ``UntypedActor`` factory which
- always returns the same instance, e.g. by using a static field. This is not
- supported, as it goes against the meaning of an actor restart, which is
+ You might be tempted at times to offer an :class:`IndirectActorProducer`
+ which always returns the same instance, e.g. by using a static field. This is
+ not supported, as it goes against the meaning of an actor restart, which is
described here: :ref:`supervision-restart`.
+ When using a dependency injection framework, actor beans *MUST NOT* have
+ singleton scope.
+
UntypedActor API
================
@@ -180,6 +228,7 @@ termination (see `Stopping Actors`_). This service is provided by the
Registering a monitor is easy (see fourth line, the rest is for demonstrating
the whole functionality):
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#import-terminated
.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#watch
It should be noted that the :class:`Terminated` message is generated
@@ -206,14 +255,15 @@ Start Hook
Right after starting the actor, its :meth:`preStart` method is invoked.
-::
-
- @Override
- public void preStart() {
- // registering with other actors
- someService.tell(Register(getSelf());
- }
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#preStart
+This method is called when the actor is first created. During restarts it is
+called by the default implementation of :meth:`postRestart`, which means that
+by overriding that method you can choose whether the initialization code in
+this method is called only exactly once for this actor or for every restart.
+Initialization code which is part of the actor’s constructor will always be
+called when an instance of the actor class is created, which happens at every
+restart.
Restart Hooks
-------------
@@ -280,12 +330,9 @@ are used by the system to look up actors, e.g. when a remote message is
received and the recipient is searched, but they are also useful more directly:
actors may look up other actors by specifying absolute or relative
paths—logical or physical—and receive back an :class:`ActorSelection` with the
-result::
+result:
- // will look up this absolute path
- getContext().actorSelection("/user/serviceA/actor");
- // will look up sibling beneath same supervisor
- getContext().actorSelection("../joe");
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#selection-local
The supplied path is parsed as a :class:`java.net.URI`, which basically means
that it is split on ``/`` into path elements. If the path starts with ``/``, it
@@ -297,12 +344,9 @@ It should be noted that the ``..`` in actor paths here always means the logical
structure, i.e. the supervisor.
The path elements of an actor selection may contain wildcard patterns allowing for
-broadcasting of messages to that section::
+broadcasting of messages to that section:
- // will look all children to serviceB with names starting with worker
- getContext().actorSelection("/user/serviceB/worker*");
- // will look up all siblings beneath same supervisor
- getContext().actorSelection("../*");
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#selection-wildcard
Messages can be sent via the :class:`ActorSelection` and the path of the
:class:`ActorSelection` is looked up when delivering each message. If the selection
@@ -315,11 +359,11 @@ and automatically reply to with a ``ActorIdentity`` message containing the
:class:`ActorRef`.
.. includecode:: code/docs/actor/UntypedActorDocTestBase.java
- :include: identify-imports,identify
+ :include: import-identify,identify
-Remote actor addresses may also be looked up, if :ref:`remoting ` is enabled::
+Remote actor addresses may also be looked up, if :ref:`remoting ` is enabled:
- getContext().actorSelection("akka.tcp://app@otherhost:1234/user/serviceB");
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#selection-remote
An example demonstrating remote actor look-up is given in :ref:`remote-lookup-sample-java`.
@@ -369,28 +413,24 @@ 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
to your message, since the sender reference is sent along with the message.
+.. _actors-tell-sender-java:
+
Tell: Fire-forget
-----------------
This is the preferred way of sending messages. No blocking waiting for a
message. This gives the best concurrency and scalability characteristics.
-.. code-block:: java
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#tell
- actor.tell("Hello");
-
-.. _actors-tell-sender-java:
-
-Or with the sender reference passed along with the message and available to the receiving Actor
-in its ``getSender: ActorRef`` member field. The target actor can use this
-to reply to the original sender, by using ``getSender().tell(replyMsg)``.
-
-.. code-block:: java
-
- actor.tell("Hello", getSelf());
-
-If invoked without the sender parameter the sender will be
-:obj:`deadLetters` actor reference in the target actor.
+The sender reference is passed along with the message and available within the
+receiving actor via its :meth:`getSender()` method while processing this
+message. Inside of an actor it is usually :meth:`getSelf` who shall be the
+sender, but there can be cases where replies shall be routed to some other
+actor—e.g. the parent—in which the second argument to :meth:`tell` would be a
+different one. Outside of an actor and if no reply is needed the second
+argument can be ``null``; if a reply is needed outside of an actor you can use
+the ask-pattern described next..
Ask: Send-And-Receive-Future
----------------------------
@@ -398,8 +438,7 @@ Ask: Send-And-Receive-Future
The ``ask`` pattern involves actors as well as futures, hence it is offered as
a use pattern rather than a method on :class:`ActorRef`:
-.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#import-askPipe
-
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#import-ask
.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#ask-pipe
This example demonstrates ``ask`` together with the ``pipe`` pattern on
@@ -454,9 +493,7 @@ through a 'mediator'. This can be useful when writing actors that work as
routers, load-balancers, replicators etc.
You need to pass along your context variable as well.
-.. code-block:: java
-
- myActor.forward(message, getContext());
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#forward
Receive messages
================
@@ -484,12 +521,8 @@ for replying later, or passing on to other actors. If there is no sender (a
message was sent without an actor or future context) then the sender
defaults to a 'dead-letter' actor ref.
-.. code-block:: java
-
- public void onReceive(Object request) {
- String result = process(request);
- getSender().tell(result); // will have dead-letter actor as default
- }
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#reply
+ :exclude: calculate-result
Receive timeout
===============
@@ -506,7 +539,7 @@ timeout there must have been an idle period beforehand as configured via this me
Once set, the receive timeout stays in effect (i.e. continues firing repeatedly after inactivity
periods). Pass in `Duration.Undefined` to switch off this feature.
-.. includecode:: code/docs/actor/MyReceivedTimeoutUntypedActor.java#receive-timeout
+.. includecode:: code/docs/actor/MyReceiveTimeoutUntypedActor.java#receive-timeout
.. _stopping-actors-java:
@@ -543,12 +576,8 @@ whole system.
The :meth:`postStop()` hook is invoked after an actor is fully stopped. This
enables cleaning up of resources:
-.. code-block:: java
-
- @Override
- public void postStop() {
- // close some file or database connection
- }
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#postStop
+ :exclude: clean-up-resources-here
.. note::
@@ -570,9 +599,6 @@ in the mailbox.
Use it like this:
-.. includecode:: code/docs/actor/UntypedActorDocTestBase.java
- :include: import-actors
-
.. includecode:: code/docs/actor/UntypedActorDocTestBase.java
:include: poison-pill
@@ -659,6 +685,7 @@ order as they have been received originally.
Here is an example of the ``UntypedActorWithStash`` class in action:
+.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#import-stash
.. includecode:: code/docs/actor/UntypedActorDocTestBase.java#stash
Invoking ``stash()`` adds the current message (the message that the
@@ -702,9 +729,6 @@ See :ref:`supervision-directives` for more information.
Use ``Kill`` like this:
-.. includecode:: code/docs/actor/UntypedActorDocTestBase.java
- :include: import-actors
-
.. includecode:: code/docs/actor/UntypedActorDocTestBase.java
:include: kill
diff --git a/akka-docs/rst/project/migration-guide-2.1.x-2.2.x.rst b/akka-docs/rst/project/migration-guide-2.1.x-2.2.x.rst
index 2133be9e34..73a8409eb5 100644
--- a/akka-docs/rst/project/migration-guide-2.1.x-2.2.x.rst
+++ b/akka-docs/rst/project/migration-guide-2.1.x-2.2.x.rst
@@ -10,6 +10,26 @@ simple, mechanical source-level changes in client code.
When migrating from 1.3.x to 2.1.x you should first follow the instructions for
migrating :ref:`1.3.x to 2.0.x ` and then :ref:`2.0.x to 2.1.x `.
+Deprecated Closure-Taking Props
+===============================
+
+:class:`Props` instances used to contain a closure which produces an
+:class:`Actor` instance when invoked. This approach is flawed in that closures
+are usually created in-line and thus carry a reference to their enclosing
+object; this is not well known among programmers, in particular it can be
+surprising that innocent-looking actor creation should not be serializable if
+the e.g. the enclosing class is an actor.
+
+Thus we have decided to deprecate ``Props(new MyActor(...))`` and
+:class:`UntypedActorFactory` in favor of basing :class:`Props` on a
+:class:`Class` and a sequence of constructor arguments. This has the added
+benefit of allowing easier integration with dependency injection frameworks,
+see :ref:`actor-create-factory`.
+
+The deprecated methods will be retained until the possibility of reintroducing
+a similar syntax in a safe fashion has been properly researched (in case of
+Scala it might be possible to use macros to this effect).
+
Immutable everywhere
====================
diff --git a/akka-docs/rst/scala/actors.rst b/akka-docs/rst/scala/actors.rst
index 6bd14235fe..78ff547ddf 100644
--- a/akka-docs/rst/scala/actors.rst
+++ b/akka-docs/rst/scala/actors.rst
@@ -43,114 +43,145 @@ Here is an example:
.. includecode:: code/docs/actor/ActorDocSpec.scala
:include: imports1,my-actor
-Please note that the Akka Actor ``receive`` message loop is exhaustive, which is
-different compared to Erlang and Scala Actors. This means that you need to
-provide a pattern match for all messages that it can accept and if you want to
-be able to handle unknown messages then you need to have a default case as in
-the example above. Otherwise an ``akka.actor.UnhandledMessage(message, sender, recipient)`` will be
-published to the ``ActorSystem``'s ``EventStream``.
+Please note that the Akka Actor ``receive`` message loop is exhaustive, which
+is different compared to Erlang and the late Scala Actors. This means that you
+need to provide a pattern match for all messages that it can accept and if you
+want to be able to handle unknown messages then you need to have a default case
+as in the example above. Otherwise an ``akka.actor.UnhandledMessage(message,
+sender, recipient)`` will be published to the ``ActorSystem``'s
+``EventStream``.
+
+Note further that the return type of the behavior defined above is ``Unit``; if
+the actor shall reply to the received message then this must be done explicitly
+as explained below.
The result of the :meth:`receive` method is a partial function object, which is
stored within the actor as its “initial behavior”, see `Become/Unbecome`_ for
further information on changing the behavior of an actor after its
construction.
-Creating Actors with default constructor
-----------------------------------------
-
-.. includecode:: code/docs/actor/ActorDocSpec.scala
- :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
-``ActorRef`` is immutable and has a one to one relationship with the Actor it
-represents. The ``ActorRef`` is also serializable and network-aware. This means
-that you can serialize it, send it over the wire and use it on a remote host and
-it will still be representing the same Actor on the original node, across the
-network.
-
-In the above example the actor was created from the system. It is also possible
-to create actors from other actors with the actor ``context``. The difference is
-how the supervisor hierarchy is arranged. When using the context the current actor
-will be supervisor of the created child actor. When using the system it will be
-a top level actor, that is supervised by the system (internal guardian actor).
-
-.. includecode:: code/docs/actor/ActorDocSpec.scala#context-actorOf
-
-The name parameter is optional, but you should preferably name your actors, since
-that is used in log messages and for identifying actors. The name must not be empty
-or start with ``$``, but it may contain URL encoded characters (eg. ``%20`` for a blank space).
-If the given name is already in use by another child to the
-same parent actor an `InvalidActorNameException` is thrown.
-
-Actors are automatically started asynchronously when created.
-When you create the ``Actor`` then it will automatically call the ``preStart``
-callback method on the ``Actor`` trait. This is an excellent place to
-add initialization code for the actor.
-
-.. code-block:: scala
-
- override def preStart() = {
- ... // initialization code
- }
-
-Creating Actors with non-default constructor
---------------------------------------------
-
-If your Actor has a constructor that takes parameters then you can't create it
-using ``actorOf(Props[TYPE])``. Instead you can use a variant of ``actorOf`` that takes
-a call-by-name block in which you can create the Actor in any way you like.
-
-Here is an example:
-
-.. includecode:: code/docs/actor/ActorDocSpec.scala#creating-constructor
-
-.. warning::
-
- You might be tempted at times to offer an ``Actor`` factory which always
- returns the same instance, e.g. by using a ``lazy val`` or an
- ``object ... extends Actor``. This is not supported, as it goes against the
- meaning of an actor restart, which is described here:
- :ref:`supervision-restart`.
-
-.. warning::
-
- Also avoid passing mutable state into the constructor of the Actor, since
- the call-by-name block can be executed by another thread.
-
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.
+:class:`Props` is a configuration class to specify options for the creation
+of actors, think of it as an immutable and thus freely shareable recipe for
+creating an actor including associated deployment information (e.g. which
+dispatcher to use, see more below). Here are some examples of how to create a
+:class:`Props` instance.
-.. includecode:: code/docs/actor/ActorDocSpec.scala#creating-props-config
+.. 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
+: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):
+
+.. includecode:: code/docs/actor/ActorDocSpec.scala#creating-props-deprecated
+
+The last one is deprecated because its functionality is available in full
+through :meth:`Props.apply()`.
+
+The first three are deprecated because the captured closure is 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.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).
+
+.. warning::
+
+ Declaring one actor within another is very dangerous and breaks actor
+ encapsulation. Never pass an actor’s ``this`` reference into :class:`Props`!
+
+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.
+
+.. includecode:: code/docs/actor/ActorDocSpec.scala#props-factory
Creating Actors with Props
--------------------------
-Actors are created by passing in a ``Props`` instance into the ``actorOf`` factory method.
+Actors are created by passing a :class:`Props` instance into the
+:meth:`actorOf` factory method which is available on :class:`ActorSystem` and
+:class:`ActorContext`.
-.. includecode:: code/docs/actor/ActorDocSpec.scala#creating-props
+.. includecode:: code/docs/actor/ActorDocSpec.scala#system-actorOf
+Using the :class:`ActorSystem` will create top-level actors, supervised by the
+actor system’s provided guardian actor, while using an actor’s context will
+create a child actor.
-Creating Actors using anonymous classes
----------------------------------------
+.. includecode:: code/docs/actor/ActorDocSpec.scala#context-actorOf
+ :exclude: plus-some-behavior
-When spawning actors for specific sub-tasks from within an actor, it may be convenient to include the code to be executed directly in place, using an anonymous class.
+It is recommended to create a hierarchy of children, grand-children and so on
+such that it fits the logical failure-handling structure of the application,
+see :ref:`actor-systems`.
-.. includecode:: code/docs/actor/ActorDocSpec.scala#anonymous-actor
+The call to :meth:`actorOf` returns an instance of :class:`ActorRef`. This is a
+handle to the actor instance and the only way to interact with it. The
+:class:`ActorRef` is immutable and has a one to one relationship with the Actor
+it represents. The :class:`ActorRef` is also serializable and network-aware.
+This means that you can serialize it, send it over the wire and use it on a
+remote host and it will still be representing the same Actor on the original
+node, across the network.
+
+The name parameter is optional, but you should preferably name your actors,
+since that is used in log messages and for identifying actors. The name must
+not be empty or start with ``$``, but it may contain URL encoded characters
+(eg. ``%20`` for a blank space). If the given name is already in use by
+another child to the same parent an `InvalidActorNameException` is thrown.
+
+Actors are automatically started asynchronously when created.
+
+Creating Actors with Factory Methods
+------------------------------------
+
+If your UntypedActor has a constructor that takes parameters then those need to
+be part of the :class:`Props` as well, as described `above `_. But there
+are cases when a factory method must be used, for example when the actual
+constructor arguments are determined by a dependency injection framework.
+
+.. includecode:: code/docs/actor/ActorDocSpec.scala
+ :include: creating-indirectly
+ :exclude: obtain-fresh-Actor-instance-from-DI-framework
.. warning::
- In this case you need to carefully avoid closing over the containing actor’s
- reference, i.e. do not call methods on the enclosing actor from within the
- anonymous Actor class. This would break the actor encapsulation and may
- introduce synchronization bugs and race conditions because the other actor’s
- code 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: :ref:`jmm-shared-state`
+ You might be tempted at times to offer an :class:`IndirectActorProducer`
+ which always returns the same instance, e.g. by using a ``lazy val``. This is
+ not supported, as it goes against the meaning of an actor restart, which is
+ described here: :ref:`supervision-restart`.
+
+ When using a dependency injection framework, actor beans *MUST NOT* have
+ singleton scope.
The Actor DSL
-------------
@@ -268,15 +299,9 @@ You can import the members in the :obj:`context` to avoid prefixing access with
.. includecode:: code/docs/actor/ActorDocSpec.scala#import-context
The remaining visible methods are user-overridable life-cycle hooks which are
-described in the following::
+described in the following:
- def preStart() {}
- def preRestart(reason: Throwable, message: Option[Any]) {
- context.children foreach (context.stop(_))
- postStop()
- }
- def postRestart(reason: Throwable) { preStart() }
- def postStop() {}
+.. includecode:: ../../../akka-actor/src/main/scala/akka/actor/Actor.scala#lifecycle-hooks
The implementations shown above are the defaults provided by the :class:`Actor`
trait.
@@ -319,13 +344,15 @@ Start Hook
Right after starting the actor, its :meth:`preStart` method is invoked.
-::
-
- override def preStart() {
- // registering with other actors
- someService ! Register(self)
- }
+.. includecode:: code/docs/actor/ActorDocSpec.scala#preStart
+This method is called when the actor is first created. During restarts it is
+called by the default implementation of :meth:`postRestart`, which means that
+by overriding that method you can choose whether the initialization code in
+this method is called only exactly once for this actor or for every restart.
+Initialization code which is part of the actor’s constructor will always be
+called when an instance of the actor class is created, which happens at every
+restart.
Restart Hooks
-------------
@@ -390,12 +417,9 @@ are used by the system to look up actors, e.g. when a remote message is
received and the recipient is searched, but they are also useful more directly:
actors may look up other actors by specifying absolute or relative
paths—logical or physical—and receive back an :class:`ActorSelection` with the
-result::
+result:
- // will look up this absolute path
- context.actorSelection("/user/serviceA/aggregator")
- // will look up sibling beneath same supervisor
- context.actorSelection("../joe")
+.. includecode:: code/docs/actor/ActorDocSpec.scala#selection-local
The supplied path is parsed as a :class:`java.net.URI`, which basically means
that it is split on ``/`` into path elements. If the path starts with ``/``, it
@@ -407,12 +431,9 @@ It should be noted that the ``..`` in actor paths here always means the logical
structure, i.e. the supervisor.
The path elements of an actor selection may contain wildcard patterns allowing for
-broadcasting of messages to that section::
+broadcasting of messages to that section:
- // will look all children to serviceB with names starting with worker
- context.actorSelection("/user/serviceB/worker*")
- // will look up all siblings beneath same supervisor
- context.actorSelection("../*")
+.. includecode:: code/docs/actor/ActorDocSpec.scala#selection-wildcard
Messages can be sent via the :class:`ActorSelection` and the path of the
:class:`ActorSelection` is looked up when delivering each message. If the selection
@@ -426,9 +447,9 @@ and automatically reply to with a ``ActorIdentity`` message containing the
.. includecode:: code/docs/actor/ActorDocSpec.scala#identify
-Remote actor addresses may also be looked up, if :ref:`remoting ` is enabled::
+Remote actor addresses may also be looked up, if :ref:`remoting ` is enabled:
- context.actorSelection("akka.tcp://app@otherhost:1234/user/serviceB")
+.. includecode:: code/docs/actor/ActorDocSpec.scala#selection-remote
An example demonstrating actor look-up is given in :ref:`remote-lookup-sample-scala`.
@@ -463,10 +484,6 @@ Here is an example:
// create a new case class message
val message = Register(user)
-Other good messages types are ``scala.Tuple2``, ``scala.List``, ``scala.Map``
-which are all immutable and great for pattern matching.
-
-
Send messages
=============
@@ -486,17 +503,15 @@ Message ordering is guaranteed on a per-sender basis.
a ``Promise`` into an ``ActorRef`` and it also needs to be reachable through
remoting. So always prefer ``tell`` for performance, and only ``ask`` if you must.
+.. _actors-tell-sender-scala:
+
Tell: Fire-forget
-----------------
This is the preferred way of sending messages. No blocking waiting for a
message. This gives the best concurrency and scalability characteristics.
-.. code-block:: scala
-
- actor ! "hello"
-
-.. _actors-tell-sender-scala:
+.. includecode:: code/docs/actor/ActorDocSpec.scala#tell
If invoked from within an Actor, then the sending actor reference will be
implicitly passed along with the message and available to the receiving Actor
@@ -573,25 +588,16 @@ original sender address/reference is maintained even though the message is going
through a 'mediator'. This can be useful when writing actors that work as
routers, load-balancers, replicators etc.
-.. code-block:: scala
-
- myActor.forward(message)
-
+.. includecode:: code/docs/actor/ActorDocSpec.scala#forward
Receive messages
================
An Actor has to implement the ``receive`` method to receive messages:
-.. code-block:: scala
+.. includecode:: ../../../akka-actor/src/main/scala/akka/actor/Actor.scala#receive
- def receive: PartialFunction[Any, Unit]
-
-Note: Akka has an alias to the ``PartialFunction[Any, Unit]`` type called
-``Receive`` (``akka.actor.Actor.Receive``), so you can use this type instead for
-clarity. But most often you don't need to spell it out.
-
-This method should return a ``PartialFunction``, e.g. a ‘match/case’ clause in
+This method returns a ``PartialFunction``, e.g. a ‘match/case’ clause in
which the message can be matched against the different case clauses using Scala
pattern matching. Here is an example:
@@ -669,11 +675,8 @@ whole system.
The :meth:`postStop()` hook is invoked after an actor is fully stopped. This
enables cleaning up of resources:
-.. code-block:: scala
-
- override def postStop() = {
- // close some file or database connection
- }
+.. includecode:: code/docs/actor/ActorDocSpec.scala#postStop
+ :exclude: clean-up-some-resources
.. note::
diff --git a/akka-docs/rst/scala/code/docs/actor/ActorDocSpec.scala b/akka-docs/rst/scala/code/docs/actor/ActorDocSpec.scala
index 70418b5722..60125052ea 100644
--- a/akka-docs/rst/scala/code/docs/actor/ActorDocSpec.scala
+++ b/akka-docs/rst/scala/code/docs/actor/ActorDocSpec.scala
@@ -37,11 +37,43 @@ case class Message(s: String)
//#context-actorOf
class FirstActor extends Actor {
- val myActor = context.actorOf(Props[MyActor], name = "myactor")
- //#context-actorOf
+ val child = context.actorOf(Props[MyActor], name = "myChild")
+ //#plus-some-behavior
def receive = {
case x ⇒ sender ! x
}
+ //#plus-some-behavior
+}
+//#context-actorOf
+
+class ActorWithArgs(arg: String) extends Actor {
+ def receive = { case _ ⇒ () }
+}
+
+class DemoActorWrapper extends Actor {
+ //#props-factory
+ object DemoActor {
+ /**
+ * Create Props for an actor of this type.
+ * @param name The name to be passed to this actor’s constructor.
+ * @return a Props for creating this actor, which can then be further configured
+ * (e.g. calling `.withDispatcher()` on it)
+ */
+ def apply(name: String): Props = Props(classOf[DemoActor], name)
+ }
+
+ class DemoActor(name: String) extends Actor {
+ def receive = {
+ case x ⇒ // some behavior
+ }
+ }
+
+ // ...
+
+ context.actorOf(DemoActor("hello"))
+ //#props-factory
+
+ def receive = Actor.emptyBehavior
}
class AnonymousActor extends Actor {
@@ -61,11 +93,21 @@ class AnonymousActor extends Actor {
//#anonymous-actor
}
-//#system-actorOf
-object Main extends App {
- val system = ActorSystem("MySystem")
- val myActor = system.actorOf(Props[MyActor], name = "myactor")
- //#system-actorOf
+class Hook extends Actor {
+ var child: ActorRef = _
+ //#preStart
+ override def preStart() {
+ child = context.actorOf(Props[MyActor], "child")
+ }
+ //#preStart
+ def receive = Actor.emptyBehavior
+ //#postStop
+ override def postStop() {
+ //#clean-up-some-resources
+ ()
+ //#clean-up-some-resources
+ }
+ //#postStop
}
class ReplyException extends Actor {
@@ -142,22 +184,23 @@ case class MyMsg(subject: String)
class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
"import context" in {
- //#import-context
- class FirstActor extends Actor {
- import context._
- val myActor = actorOf(Props[MyActor], name = "myactor")
- def receive = {
- case x ⇒ myActor ! x
+ new AnyRef {
+ //#import-context
+ class FirstActor extends Actor {
+ import context._
+ val myActor = actorOf(Props[MyActor], name = "myactor")
+ def receive = {
+ case x ⇒ myActor ! x
+ }
}
+ //#import-context
+
+ val first = system.actorOf(Props(classOf[FirstActor], this), name = "first")
+ system.stop(first)
}
- //#import-context
-
- val first = system.actorOf(Props(new FirstActor), name = "first")
- system.stop(first)
-
}
- "creating actor with AkkaSpec.actorOf" in {
+ "creating actor with system.actorOf" in {
val myActor = system.actorOf(Props[MyActor])
// testing the actor
@@ -183,44 +226,99 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
}
"creating actor with constructor" in {
- class MyActor(arg: String) extends Actor {
- def receive = { case _ ⇒ () }
- }
-
//#creating-constructor
// allows passing in arguments to the MyActor constructor
- val myActor = system.actorOf(Props(new MyActor("...")), name = "myactor")
+ val myActor = system.actorOf(Props[MyActor], name = "myactor")
//#creating-constructor
system.stop(myActor)
}
"creating a Props config" in {
- //#creating-props-config
+ //#creating-props
import akka.actor.Props
- val props1 = Props.empty
- val props2 = Props[MyActor]
- val props3 = Props(new MyActor)
+
+ val props1 = Props[MyActor]
+ val props3 = Props(classOf[ActorWithArgs], "arg")
+ //#creating-props
+
+ //#creating-props-deprecated
+ // DEPRECATED: encourages to close over enclosing class
val props4 = Props(
creator = { () ⇒ new MyActor },
dispatcher = "my-dispatcher")
+
+ // DEPRECATED: encourages to close over enclosing class
val props5 = props1.withCreator(new MyActor)
- val props6 = props5.withDispatcher("my-dispatcher")
- //#creating-props-config
+
+ // DEPRECATED: encourages to close over enclosing class
+ val props6 = Props(new MyActor)
+
+ // DEPRECATED due to duplicate functionality with Props.apply()
+ val props7 = props1.withCreator(classOf[MyActor])
+ //#creating-props-deprecated
}
"creating actor with Props" in {
- //#creating-props
- import akka.actor.Props
- val myActor = system.actorOf(Props[MyActor].withDispatcher("my-dispatcher"),
- name = "myactor2")
- //#creating-props
+ //#system-actorOf
+ import akka.actor.ActorSystem
- system.stop(myActor)
+ // ActorSystem is a heavy object: create only one per application
+ val system = ActorSystem("mySystem")
+ val myActor = system.actorOf(Props[MyActor].withDispatcher("my-dispatcher"), "myactor2")
+ //#system-actorOf
+ system.shutdown()
+ }
+
+ "creating actor with IndirectActorProducer" in {
+ class Echo(name: String) extends Actor {
+ def receive = {
+ case n: Int ⇒ sender ! name
+ case message ⇒
+ val target = testActor
+ //#forward
+ target forward message
+ //#forward
+ }
+ }
+
+ val a: { def actorRef: ActorRef } = new AnyRef {
+ val applicationContext = this
+
+ //#creating-indirectly
+ import akka.actor.IndirectActorProducer
+
+ class DependencyInjector(applicationContext: AnyRef, beanName: String)
+ extends IndirectActorProducer {
+
+ override def actorClass = classOf[Actor]
+ override def produce =
+ //#obtain-fresh-Actor-instance-from-DI-framework
+ new Echo(beanName)
+
+ def this(beanName: String) = this("", beanName)
+ //#obtain-fresh-Actor-instance-from-DI-framework
+ }
+
+ val actorRef = system.actorOf(
+ Props(classOf[DependencyInjector], applicationContext, "hello"),
+ "helloBean")
+ //#creating-indirectly
+ }
+ val actorRef = a.actorRef
+
+ val message = 42
+ implicit val self = testActor
+ //#tell
+ actorRef ! message
+ //#tell
+ expectMsg("hello")
+ actorRef ! "huhu"
+ expectMsg("huhu")
}
"using implicit timeout" in {
- val myActor = system.actorOf(Props(new FirstActor))
+ val myActor = system.actorOf(Props[FirstActor])
//#using-implicit-timeout
import scala.concurrent.duration._
import akka.util.Timeout
@@ -233,7 +331,7 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
}
"using explicit timeout" in {
- val myActor = system.actorOf(Props(new FirstActor))
+ val myActor = system.actorOf(Props[FirstActor])
//#using-explicit-timeout
import scala.concurrent.duration._
import akka.pattern.ask
@@ -262,28 +360,28 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
//#receive-timeout
}
- "using hot-swap" in {
- //#hot-swap-actor
- class HotSwapActor extends Actor {
- import context._
- def angry: Receive = {
- case "foo" ⇒ sender ! "I am already angry?"
- case "bar" ⇒ become(happy)
- }
-
- def happy: Receive = {
- case "bar" ⇒ sender ! "I am already happy :-)"
- case "foo" ⇒ become(angry)
- }
-
- def receive = {
- case "foo" ⇒ become(angry)
- case "bar" ⇒ become(happy)
- }
+ //#hot-swap-actor
+ class HotSwapActor extends Actor {
+ import context._
+ def angry: Receive = {
+ case "foo" ⇒ sender ! "I am already angry?"
+ case "bar" ⇒ become(happy)
}
- //#hot-swap-actor
- val actor = system.actorOf(Props(new HotSwapActor), name = "hot")
+ def happy: Receive = {
+ case "bar" ⇒ sender ! "I am already happy :-)"
+ case "foo" ⇒ become(angry)
+ }
+
+ def receive = {
+ case "foo" ⇒ become(angry)
+ case "bar" ⇒ become(happy)
+ }
+ }
+ //#hot-swap-actor
+
+ "using hot-swap" in {
+ val actor = system.actorOf(Props(classOf[HotSwapActor], this), name = "hot")
}
"using Stash" in {
@@ -307,55 +405,77 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
}
"using watch" in {
- //#watch
- import akka.actor.{ Actor, Props, Terminated }
+ new AnyRef {
+ //#watch
+ import akka.actor.{ Actor, Props, Terminated }
- class WatchActor extends Actor {
- val child = context.actorOf(Props.empty, "child")
- context.watch(child) // <-- this is the only call needed for registration
- var lastSender = system.deadLetters
+ class WatchActor extends Actor {
+ val child = context.actorOf(Props.empty, "child")
+ context.watch(child) // <-- this is the only call needed for registration
+ var lastSender = system.deadLetters
- def receive = {
- case "kill" ⇒ context.stop(child); lastSender = sender
- case Terminated(`child`) ⇒ lastSender ! "finished"
+ def receive = {
+ case "kill" ⇒
+ context.stop(child); lastSender = sender
+ case Terminated(`child`) ⇒ lastSender ! "finished"
+ }
}
+ //#watch
+ val a = system.actorOf(Props(classOf[WatchActor], this))
+ implicit val sender = testActor
+ a ! "kill"
+ expectMsg("finished")
}
- //#watch
- val a = system.actorOf(Props(new WatchActor))
- implicit val sender = testActor
- a ! "kill"
- expectMsg("finished")
+ }
+
+ "demonstrate ActorSelection" in {
+ val context = system
+ //#selection-local
+ // will look up this absolute path
+ context.actorSelection("/user/serviceA/aggregator")
+ // will look up sibling beneath same supervisor
+ context.actorSelection("../joe")
+ //#selection-local
+ //#selection-wildcard
+ // will look all children to serviceB with names starting with worker
+ context.actorSelection("/user/serviceB/worker*")
+ // will look up all siblings beneath same supervisor
+ context.actorSelection("../*")
+ //#selection-wildcard
+ //#selection-remote
+ context.actorSelection("akka.tcp://app@otherhost:1234/user/serviceB")
+ //#selection-remote
}
"using Identify" in {
- //#identify
- import akka.actor.{ Actor, Props, Identify, ActorIdentity, Terminated }
+ new AnyRef {
+ //#identify
+ import akka.actor.{ Actor, Props, Identify, ActorIdentity, Terminated }
- class Follower extends Actor {
- val identifyId = 1
- context.actorSelection("/user/another") ! Identify(identifyId)
+ class Follower extends Actor {
+ val identifyId = 1
+ context.actorSelection("/user/another") ! Identify(identifyId)
- def receive = {
- case ActorIdentity(`identifyId`, Some(ref)) ⇒
- context.watch(ref)
- context.become(active(ref))
- case ActorIdentity(`identifyId`, None) ⇒ context.stop(self)
+ def receive = {
+ case ActorIdentity(`identifyId`, Some(ref)) ⇒
+ context.watch(ref)
+ context.become(active(ref))
+ case ActorIdentity(`identifyId`, None) ⇒ context.stop(self)
+ }
+
+ def active(another: ActorRef): Actor.Receive = {
+ case Terminated(`another`) ⇒ context.stop(self)
+ }
}
+ //#identify
- def active(another: ActorRef): Actor.Receive = {
- case Terminated(`another`) ⇒ context.stop(self)
- }
+ val a = system.actorOf(Props.empty)
+ val b = system.actorOf(Props(classOf[Follower], this))
+ watch(b)
+ system.stop(a)
+ expectMsgType[akka.actor.Terminated].actor must be === b
}
- //#identify
-
- val a = system.actorOf(Props(new Actor {
- def receive = Actor.emptyBehavior
- }))
- val b = system.actorOf(Props(new Follower))
- watch(b)
- system.stop(a)
- expectMsgType[akka.actor.Terminated].actor must be === b
}
"using pattern gracefulStop" in {
@@ -397,20 +517,22 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
//#ask-pipeTo
}
- "replying with own or other sender" in {
- val actor = system.actorOf(Props(new Actor {
- def receive = {
- case ref: ActorRef ⇒
- //#reply-with-sender
- sender.tell("reply", context.parent) // replies will go back to parent
- sender.!("reply")(context.parent) // alternative syntax (beware of the parens!)
+ class Replier extends Actor {
+ def receive = {
+ case ref: ActorRef ⇒
//#reply-with-sender
- case x ⇒
- //#reply-without-sender
- sender ! x // replies will go to this actor
+ sender.tell("reply", context.parent) // replies will go back to parent
+ sender.!("reply")(context.parent) // alternative syntax (beware of the parens!)
+ //#reply-with-sender
+ case x ⇒
//#reply-without-sender
- }
- }))
+ sender ! x // replies will go to this actor
+ //#reply-without-sender
+ }
+ }
+
+ "replying with own or other sender" in {
+ val actor = system.actorOf(Props(classOf[Replier], this))
implicit val me = testActor
actor ! 42
expectMsg(42)
@@ -430,51 +552,51 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
})
}
- "using ComposableActor" in {
- //#receive-orElse2
- class PartialFunctionBuilder[A, B] {
- import scala.collection.immutable.Vector
+ //#receive-orElse2
+ class PartialFunctionBuilder[A, B] {
+ import scala.collection.immutable.Vector
- // Abbreviate to make code fit
- type PF = PartialFunction[A, B]
+ // Abbreviate to make code fit
+ type PF = PartialFunction[A, B]
- private var pfsOption: Option[Vector[PF]] = Some(Vector.empty)
+ private var pfsOption: Option[Vector[PF]] = Some(Vector.empty)
- private def mapPfs[C](f: Vector[PF] ⇒ (Option[Vector[PF]], C)): C = {
- pfsOption.fold(throw new IllegalStateException("Already built"))(f) match {
- case (newPfsOption, result) ⇒ {
- pfsOption = newPfsOption
- result
- }
+ private def mapPfs[C](f: Vector[PF] ⇒ (Option[Vector[PF]], C)): C = {
+ pfsOption.fold(throw new IllegalStateException("Already built"))(f) match {
+ case (newPfsOption, result) ⇒ {
+ pfsOption = newPfsOption
+ result
}
}
-
- def +=(pf: PF): Unit =
- mapPfs { case pfs ⇒ (Some(pfs :+ pf), ()) }
-
- def result(): PF =
- mapPfs { case pfs ⇒ (None, pfs.foldLeft[PF](Map.empty) { _ orElse _ }) }
}
- trait ComposableActor extends Actor {
- protected lazy val receiveBuilder = new PartialFunctionBuilder[Any, Unit]
- final def receive = receiveBuilder.result()
- }
+ def +=(pf: PF): Unit =
+ mapPfs { case pfs ⇒ (Some(pfs :+ pf), ()) }
- trait TheirComposableActor extends ComposableActor {
- receiveBuilder += {
- case "foo" ⇒ sender ! "foo received"
- }
- }
+ def result(): PF =
+ mapPfs { case pfs ⇒ (None, pfs.foldLeft[PF](Map.empty) { _ orElse _ }) }
+ }
- class MyComposableActor extends TheirComposableActor {
- receiveBuilder += {
- case "bar" ⇒ sender ! "bar received"
- }
- }
- //#receive-orElse2
+ trait ComposableActor extends Actor {
+ protected lazy val receiveBuilder = new PartialFunctionBuilder[Any, Unit]
+ final def receive = receiveBuilder.result()
+ }
- val composed = system.actorOf(Props(new MyComposableActor))
+ trait TheirComposableActor extends ComposableActor {
+ receiveBuilder += {
+ case "foo" ⇒ sender ! "foo received"
+ }
+ }
+
+ class MyComposableActor extends TheirComposableActor {
+ receiveBuilder += {
+ case "bar" ⇒ sender ! "bar received"
+ }
+ }
+ //#receive-orElse2
+
+ "using ComposableActor" in {
+ val composed = system.actorOf(Props(classOf[MyComposableActor], this))
implicit val me = testActor
composed ! "foo"
expectMsg("foo received")
diff --git a/akka-docs/rst/scala/code/docs/actor/FSMDocSpec.scala b/akka-docs/rst/scala/code/docs/actor/FSMDocSpec.scala
index 59c62e93b9..40d5817eac 100644
--- a/akka-docs/rst/scala/code/docs/actor/FSMDocSpec.scala
+++ b/akka-docs/rst/scala/code/docs/actor/FSMDocSpec.scala
@@ -14,180 +14,181 @@ import scala.collection.immutable
class FSMDocSpec extends MyFavoriteTestFrameWorkPlusAkkaTestKit {
- "simple finite state machine" must {
- //#fsm-code-elided
- //#simple-imports
- import akka.actor.{ Actor, ActorRef, FSM }
- import scala.concurrent.duration._
- //#simple-imports
- //#simple-events
- // received events
- case class SetTarget(ref: ActorRef)
- case class Queue(obj: Any)
- case object Flush
+ //#fsm-code-elided
+ //#simple-imports
+ import akka.actor.{ Actor, ActorRef, FSM }
+ import scala.concurrent.duration._
+ //#simple-imports
+ //#simple-events
+ // received events
+ case class SetTarget(ref: ActorRef)
+ case class Queue(obj: Any)
+ case object Flush
- // sent events
- case class Batch(obj: immutable.Seq[Any])
- //#simple-events
- //#simple-state
- // states
- sealed trait State
- case object Idle extends State
- case object Active extends State
+ // sent events
+ case class Batch(obj: immutable.Seq[Any])
+ //#simple-events
+ //#simple-state
+ // states
+ sealed trait State
+ case object Idle extends State
+ case object Active extends State
- sealed trait Data
- case object Uninitialized extends Data
- case class Todo(target: ActorRef, queue: immutable.Seq[Any]) extends Data
- //#simple-state
- //#simple-fsm
- class Buncher extends Actor with FSM[State, Data] {
+ sealed trait Data
+ case object Uninitialized extends Data
+ case class Todo(target: ActorRef, queue: immutable.Seq[Any]) extends Data
+ //#simple-state
+ //#simple-fsm
+ class Buncher extends Actor with FSM[State, Data] {
- //#fsm-body
- startWith(Idle, Uninitialized)
+ //#fsm-body
+ startWith(Idle, Uninitialized)
- //#when-syntax
- when(Idle) {
- case Event(SetTarget(ref), Uninitialized) ⇒
- stay using Todo(ref, Vector.empty)
+ //#when-syntax
+ when(Idle) {
+ case Event(SetTarget(ref), Uninitialized) ⇒
+ stay using Todo(ref, Vector.empty)
+ }
+ //#when-syntax
+
+ //#transition-elided
+ onTransition {
+ case Active -> Idle ⇒
+ stateData match {
+ case Todo(ref, queue) ⇒ ref ! Batch(queue)
+ }
+ }
+ //#transition-elided
+ //#when-syntax
+
+ when(Active, stateTimeout = 1 second) {
+ case Event(Flush | StateTimeout, t: Todo) ⇒
+ goto(Idle) using t.copy(queue = Vector.empty)
+ }
+ //#when-syntax
+
+ //#unhandled-elided
+ whenUnhandled {
+ // common code for both states
+ case Event(Queue(obj), t @ Todo(_, v)) ⇒
+ goto(Active) using t.copy(queue = v :+ obj)
+
+ case Event(e, s) ⇒
+ log.warning("received unhandled request {} in state {}/{}", e, stateName, s)
+ stay
+ }
+ //#unhandled-elided
+ //#fsm-body
+
+ initialize()
+ }
+ //#simple-fsm
+ object DemoCode {
+ trait StateType
+ case object SomeState extends StateType
+ case object Processing extends StateType
+ case object Error extends StateType
+ case object Idle extends StateType
+ case object Active extends StateType
+
+ class Dummy extends Actor with FSM[StateType, Int] {
+ class X
+ val newData = 42
+ object WillDo
+ object Tick
+
+ //#modifier-syntax
+ when(SomeState) {
+ case Event(msg, _) ⇒
+ goto(Processing) using (newData) forMax (5 seconds) replying (WillDo)
}
- //#when-syntax
+ //#modifier-syntax
- //#transition-elided
+ //#transition-syntax
onTransition {
- case Active -> Idle ⇒
- stateData match {
- case Todo(ref, queue) ⇒ ref ! Batch(queue)
- }
+ case Idle -> Active ⇒ setTimer("timeout", Tick, 1 second, true)
+ case Active -> _ ⇒ cancelTimer("timeout")
+ case x -> Idle ⇒ log.info("entering Idle from " + x)
}
- //#transition-elided
- //#when-syntax
+ //#transition-syntax
- when(Active, stateTimeout = 1 second) {
- case Event(Flush | StateTimeout, t: Todo) ⇒
- goto(Idle) using t.copy(queue = Vector.empty)
+ //#alt-transition-syntax
+ onTransition(handler _)
+
+ def handler(from: StateType, to: StateType) {
+ // handle it here ...
}
- //#when-syntax
+ //#alt-transition-syntax
- //#unhandled-elided
+ //#stop-syntax
+ when(Error) {
+ case Event("stop", _) ⇒
+ // do cleanup ...
+ stop()
+ }
+ //#stop-syntax
+
+ //#transform-syntax
+ when(SomeState)(transform {
+ case Event(bytes: ByteString, read) ⇒ stay using (read + bytes.length)
+ } using {
+ case s @ FSM.State(state, read, timeout, stopReason, replies) if read > 1000 ⇒
+ goto(Processing)
+ })
+ //#transform-syntax
+
+ //#alt-transform-syntax
+ val processingTrigger: PartialFunction[State, State] = {
+ case s @ FSM.State(state, read, timeout, stopReason, replies) if read > 1000 ⇒
+ goto(Processing)
+ }
+
+ when(SomeState)(transform {
+ case Event(bytes: ByteString, read) ⇒ stay using (read + bytes.length)
+ } using processingTrigger)
+ //#alt-transform-syntax
+
+ //#termination-syntax
+ onTermination {
+ case StopEvent(FSM.Normal, state, data) ⇒ // ...
+ case StopEvent(FSM.Shutdown, state, data) ⇒ // ...
+ case StopEvent(FSM.Failure(cause), state, data) ⇒ // ...
+ }
+ //#termination-syntax
+
+ //#unhandled-syntax
whenUnhandled {
- // common code for both states
- case Event(Queue(obj), t @ Todo(_, v)) ⇒
- goto(Active) using t.copy(queue = v :+ obj)
-
- case Event(e, s) ⇒
- log.warning("received unhandled request {} in state {}/{}", e, stateName, s)
+ case Event(x: X, data) ⇒
+ log.info("Received unhandled event: " + x)
stay
+ case Event(msg, _) ⇒
+ log.warning("Received unknown event: " + msg)
+ goto(Error)
}
- //#unhandled-elided
- //#fsm-body
-
- initialize()
- }
- //#simple-fsm
- object DemoCode {
- trait StateType
- case object SomeState extends StateType
- case object Processing extends StateType
- case object Error extends StateType
- case object Idle extends StateType
- case object Active extends StateType
-
- class Dummy extends Actor with FSM[StateType, Int] {
- class X
- val newData = 42
- object WillDo
- object Tick
-
- //#modifier-syntax
- when(SomeState) {
- case Event(msg, _) ⇒
- goto(Processing) using (newData) forMax (5 seconds) replying (WillDo)
- }
- //#modifier-syntax
-
- //#transition-syntax
- onTransition {
- case Idle -> Active ⇒ setTimer("timeout", Tick, 1 second, true)
- case Active -> _ ⇒ cancelTimer("timeout")
- case x -> Idle ⇒ log.info("entering Idle from " + x)
- }
- //#transition-syntax
-
- //#alt-transition-syntax
- onTransition(handler _)
-
- def handler(from: StateType, to: StateType) {
- // handle it here ...
- }
- //#alt-transition-syntax
-
- //#stop-syntax
- when(Error) {
- case Event("stop", _) ⇒
- // do cleanup ...
- stop()
- }
- //#stop-syntax
-
- //#transform-syntax
- when(SomeState)(transform {
- case Event(bytes: ByteString, read) ⇒ stay using (read + bytes.length)
- } using {
- case s @ FSM.State(state, read, timeout, stopReason, replies) if read > 1000 ⇒
- goto(Processing)
- })
- //#transform-syntax
-
- //#alt-transform-syntax
- val processingTrigger: PartialFunction[State, State] = {
- case s @ FSM.State(state, read, timeout, stopReason, replies) if read > 1000 ⇒
- goto(Processing)
- }
-
- when(SomeState)(transform {
- case Event(bytes: ByteString, read) ⇒ stay using (read + bytes.length)
- } using processingTrigger)
- //#alt-transform-syntax
-
- //#termination-syntax
- onTermination {
- case StopEvent(FSM.Normal, state, data) ⇒ // ...
- case StopEvent(FSM.Shutdown, state, data) ⇒ // ...
- case StopEvent(FSM.Failure(cause), state, data) ⇒ // ...
- }
- //#termination-syntax
-
- //#unhandled-syntax
- whenUnhandled {
- case Event(x: X, data) ⇒
- log.info("Received unhandled event: " + x)
- stay
- case Event(msg, _) ⇒
- log.warning("Received unknown event: " + msg)
- goto(Error)
- }
- //#unhandled-syntax
-
- }
-
- //#logging-fsm
- import akka.actor.LoggingFSM
- class MyFSM extends Actor with LoggingFSM[StateType, Data] {
- //#body-elided
- override def logDepth = 12
- onTermination {
- case StopEvent(FSM.Failure(_), state, data) ⇒
- val lastEvents = getLog.mkString("\n\t")
- log.warning("Failure in state " + state + " with data " + data + "\n" +
- "Events leading up to this point:\n\t" + lastEvents)
- }
- // ...
- //#body-elided
- }
- //#logging-fsm
+ //#unhandled-syntax
}
- //#fsm-code-elided
+
+ //#logging-fsm
+ import akka.actor.LoggingFSM
+ class MyFSM extends Actor with LoggingFSM[StateType, Data] {
+ //#body-elided
+ override def logDepth = 12
+ onTermination {
+ case StopEvent(FSM.Failure(_), state, data) ⇒
+ val lastEvents = getLog.mkString("\n\t")
+ log.warning("Failure in state " + state + " with data " + data + "\n" +
+ "Events leading up to this point:\n\t" + lastEvents)
+ }
+ // ...
+ //#body-elided
+ }
+ //#logging-fsm
+
+ }
+ //#fsm-code-elided
+
+ "simple finite state machine" must {
"demonstrate NullFunction" in {
class A extends Actor with FSM[Int, Null] {
@@ -199,7 +200,7 @@ class FSMDocSpec extends MyFavoriteTestFrameWorkPlusAkkaTestKit {
}
"batch correctly" in {
- val buncher = system.actorOf(Props(new Buncher))
+ val buncher = system.actorOf(Props(classOf[Buncher], this))
buncher ! SetTarget(testActor)
buncher ! Queue(42)
buncher ! Queue(43)
@@ -212,7 +213,7 @@ class FSMDocSpec extends MyFavoriteTestFrameWorkPlusAkkaTestKit {
}
"not batch if uninitialized" in {
- val buncher = system.actorOf(Props(new Buncher))
+ val buncher = system.actorOf(Props(classOf[Buncher], this))
buncher ! Queue(42)
expectNoMsg
}
diff --git a/akka-docs/rst/scala/code/docs/actor/FaultHandlingDocSample.scala b/akka-docs/rst/scala/code/docs/actor/FaultHandlingDocSample.scala
index c3d07f3dc8..303331e966 100644
--- a/akka-docs/rst/scala/code/docs/actor/FaultHandlingDocSample.scala
+++ b/akka-docs/rst/scala/code/docs/actor/FaultHandlingDocSample.scala
@@ -168,7 +168,7 @@ class CounterService extends Actor {
case Entry(k, v) if k == key && counter == None ⇒
// Reply from Storage of the initial value, now we can create the Counter
- val c = context.actorOf(Props(new Counter(key, v)))
+ val c = context.actorOf(Props(classOf[Counter], key, v))
counter = Some(c)
// Tell the counter to use current storage
c ! UseStorage(storage)
diff --git a/akka-docs/rst/scala/code/docs/actor/SchedulerDocSpec.scala b/akka-docs/rst/scala/code/docs/actor/SchedulerDocSpec.scala
index fb54e361af..f4de04aac2 100644
--- a/akka-docs/rst/scala/code/docs/actor/SchedulerDocSpec.scala
+++ b/akka-docs/rst/scala/code/docs/actor/SchedulerDocSpec.scala
@@ -38,27 +38,30 @@ class SchedulerDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
}
"schedule a recurring task" in {
- //#schedule-recurring
- val Tick = "tick"
- val tickActor = system.actorOf(Props(new Actor {
- def receive = {
- case Tick ⇒ //Do something
+ new AnyRef {
+ //#schedule-recurring
+ val Tick = "tick"
+ class TickActor extends Actor {
+ def receive = {
+ case Tick ⇒ //Do something
+ }
}
- }))
- //Use system's dispatcher as ExecutionContext
- import system.dispatcher
+ val tickActor = system.actorOf(Props(classOf[TickActor], this))
+ //Use system's dispatcher as ExecutionContext
+ import system.dispatcher
- //This will schedule to send the Tick-message
- //to the tickActor after 0ms repeating every 50ms
- val cancellable =
- system.scheduler.schedule(0 milliseconds,
- 50 milliseconds,
- tickActor,
- Tick)
+ //This will schedule to send the Tick-message
+ //to the tickActor after 0ms repeating every 50ms
+ val cancellable =
+ system.scheduler.schedule(0 milliseconds,
+ 50 milliseconds,
+ tickActor,
+ Tick)
- //This cancels further Ticks to be sent
- cancellable.cancel()
- //#schedule-recurring
- system.stop(tickActor)
+ //This cancels further Ticks to be sent
+ cancellable.cancel()
+ //#schedule-recurring
+ system.stop(tickActor)
+ }
}
}
diff --git a/akka-docs/rst/scala/code/docs/camel/CustomRouteExample.scala b/akka-docs/rst/scala/code/docs/camel/CustomRouteExample.scala
index aed7811efd..49cac853c5 100644
--- a/akka-docs/rst/scala/code/docs/camel/CustomRouteExample.scala
+++ b/akka-docs/rst/scala/code/docs/camel/CustomRouteExample.scala
@@ -44,8 +44,8 @@ object CustomRouteExample {
// example from a MicroKernel
val system = ActorSystem("some-system")
val producer = system.actorOf(Props[Producer1])
- val mediator = system.actorOf(Props(new Transformer(producer)))
- val consumer = system.actorOf(Props(new Consumer3(mediator)))
+ val mediator = system.actorOf(Props(classOf[Transformer], producer))
+ val consumer = system.actorOf(Props(classOf[Consumer3], mediator))
CamelExtension(system).context.addRoutes(new CustomRouteBuilder)
//#CustomRouteExample
}
diff --git a/akka-docs/rst/scala/code/docs/camel/HttpExample.scala b/akka-docs/rst/scala/code/docs/camel/HttpExample.scala
index 4181607a52..a2fd16944b 100644
--- a/akka-docs/rst/scala/code/docs/camel/HttpExample.scala
+++ b/akka-docs/rst/scala/code/docs/camel/HttpExample.scala
@@ -43,8 +43,8 @@ object HttpExample {
// to your boot class.
val system = ActorSystem("some-system")
val httpTransformer = system.actorOf(Props[HttpTransformer])
- val httpProducer = system.actorOf(Props(new HttpProducer(httpTransformer)))
- val httpConsumer = system.actorOf(Props(new HttpConsumer(httpProducer)))
+ val httpProducer = system.actorOf(Props(classOf[HttpProducer], httpTransformer))
+ val httpConsumer = system.actorOf(Props(classOf[HttpConsumer], httpProducer))
//#HttpExample
}
diff --git a/akka-docs/rst/scala/code/docs/camel/Producers.scala b/akka-docs/rst/scala/code/docs/camel/Producers.scala
index 8835ec7df3..c9c69a86c0 100644
--- a/akka-docs/rst/scala/code/docs/camel/Producers.scala
+++ b/akka-docs/rst/scala/code/docs/camel/Producers.scala
@@ -45,8 +45,8 @@ object Producers {
}
val system = ActorSystem("some-system")
val receiver = system.actorOf(Props[ResponseReceiver])
- val forwardResponse = system.actorOf(Props(
- new Forwarder("http://localhost:8080/news/akka", receiver)))
+ val forwardResponse = system.actorOf(
+ Props(classOf[Forwarder], this, "http://localhost:8080/news/akka", receiver))
// the Forwarder sends out a request to the web page and forwards the response to
// the ResponseReceiver
forwardResponse ! "some request"
@@ -81,7 +81,7 @@ object Producers {
}
val system = ActorSystem("some-system")
- val producer = system.actorOf(Props(new OnewaySender("activemq:FOO.BAR")))
+ val producer = system.actorOf(Props(classOf[OnewaySender], this, "activemq:FOO.BAR"))
producer ! "Some message"
//#Oneway
diff --git a/akka-docs/rst/scala/code/docs/camel/PublishSubscribe.scala b/akka-docs/rst/scala/code/docs/camel/PublishSubscribe.scala
index 430fcdbb3e..2263a02277 100644
--- a/akka-docs/rst/scala/code/docs/camel/PublishSubscribe.scala
+++ b/akka-docs/rst/scala/code/docs/camel/PublishSubscribe.scala
@@ -1,47 +1,44 @@
package docs.camel
object PublishSubscribe {
- {
- //#PubSub
- import akka.actor.{ Actor, ActorRef, ActorSystem, Props }
- import akka.camel.{ Producer, CamelMessage, Consumer }
+ //#PubSub
+ import akka.actor.{ Actor, ActorRef, ActorSystem, Props }
+ import akka.camel.{ Producer, CamelMessage, Consumer }
- class Subscriber(name: String, uri: String) extends Actor with Consumer {
- def endpointUri = uri
+ class Subscriber(name: String, uri: String) extends Actor with Consumer {
+ def endpointUri = uri
- def receive = {
- case msg: CamelMessage ⇒ println("%s received: %s" format (name, msg.body))
- }
+ def receive = {
+ case msg: CamelMessage ⇒ println("%s received: %s" format (name, msg.body))
}
-
- class Publisher(name: String, uri: String) extends Actor with Producer {
-
- def endpointUri = uri
-
- // one-way communication with JMS
- override def oneway = true
- }
-
- class PublisherBridge(uri: String, publisher: ActorRef) extends Actor with Consumer {
- def endpointUri = uri
-
- def receive = {
- case msg: CamelMessage ⇒ {
- publisher ! msg.bodyAs[String]
- sender ! ("message published")
- }
- }
- }
-
- // Add below to a Boot class
- // Setup publish/subscribe example
- val system = ActorSystem("some-system")
- val jmsUri = "jms:topic:test"
- val jmsSubscriber1 = system.actorOf(Props(new Subscriber("jms-subscriber-1", jmsUri)))
- val jmsSubscriber2 = system.actorOf(Props(new Subscriber("jms-subscriber-2", jmsUri)))
- val jmsPublisher = system.actorOf(Props(new Publisher("jms-publisher", jmsUri)))
- val jmsPublisherBridge = system.actorOf(Props(new PublisherBridge("jetty:http://0.0.0.0:8877/camel/pub/jms", jmsPublisher)))
- //#PubSub
-
}
+
+ class Publisher(name: String, uri: String) extends Actor with Producer {
+
+ def endpointUri = uri
+
+ // one-way communication with JMS
+ override def oneway = true
+ }
+
+ class PublisherBridge(uri: String, publisher: ActorRef) extends Actor with Consumer {
+ def endpointUri = uri
+
+ def receive = {
+ case msg: CamelMessage ⇒ {
+ publisher ! msg.bodyAs[String]
+ sender ! ("message published")
+ }
+ }
+ }
+
+ // Add below to a Boot class
+ // Setup publish/subscribe example
+ val system = ActorSystem("some-system")
+ val jmsUri = "jms:topic:test"
+ val jmsSubscriber1 = system.actorOf(Props(classOf[Subscriber], "jms-subscriber-1", jmsUri))
+ val jmsSubscriber2 = system.actorOf(Props(classOf[Subscriber], "jms-subscriber-2", jmsUri))
+ val jmsPublisher = system.actorOf(Props(classOf[Publisher], "jms-publisher", jmsUri))
+ val jmsPublisherBridge = system.actorOf(Props(classOf[PublisherBridge], "jetty:http://0.0.0.0:8877/camel/pub/jms", jmsPublisher))
+ //#PubSub
}
diff --git a/akka-docs/rst/scala/code/docs/dispatcher/DispatcherDocSpec.scala b/akka-docs/rst/scala/code/docs/dispatcher/DispatcherDocSpec.scala
index 634e7b4f84..4c803d4a7c 100644
--- a/akka-docs/rst/scala/code/docs/dispatcher/DispatcherDocSpec.scala
+++ b/akka-docs/rst/scala/code/docs/dispatcher/DispatcherDocSpec.scala
@@ -210,11 +210,11 @@ class DispatcherDocSpec extends AkkaSpec(DispatcherDocSpec.config) {
}
"defining priority dispatcher" in {
- //#prio-dispatcher
+ new AnyRef {
+ //#prio-dispatcher
- // We create a new Actor that just prints out what it processes
- val a = system.actorOf(
- Props(new Actor {
+ // We create a new Actor that just prints out what it processes
+ class Logger extends Actor {
val log: LoggingAdapter = Logging(context.system, this)
self ! 'lowpriority
@@ -229,22 +229,24 @@ class DispatcherDocSpec extends AkkaSpec(DispatcherDocSpec.config) {
def receive = {
case x ⇒ log.info(x.toString)
}
- }).withDispatcher("prio-dispatcher"))
+ }
+ val a = system.actorOf(Props(classOf[Logger], this).withDispatcher("prio-dispatcher"))
- /*
- Logs:
- 'highpriority
- 'highpriority
- 'pigdog
- 'pigdog2
- 'pigdog3
- 'lowpriority
- 'lowpriority
- */
- //#prio-dispatcher
+ /*
+ * Logs:
+ * 'highpriority
+ * 'highpriority
+ * 'pigdog
+ * 'pigdog2
+ * 'pigdog3
+ * 'lowpriority
+ * 'lowpriority
+ */
+ //#prio-dispatcher
- watch(a)
- expectMsgPF() { case Terminated(`a`) ⇒ () }
+ watch(a)
+ expectMsgPF() { case Terminated(`a`) ⇒ () }
+ }
}
"defining balancing dispatcher" in {
diff --git a/akka-docs/rst/scala/code/docs/event/LoggingDocSpec.scala b/akka-docs/rst/scala/code/docs/event/LoggingDocSpec.scala
index ba5963fd8c..7725b62f43 100644
--- a/akka-docs/rst/scala/code/docs/event/LoggingDocSpec.scala
+++ b/akka-docs/rst/scala/code/docs/event/LoggingDocSpec.scala
@@ -72,21 +72,24 @@ class LoggingDocSpec extends AkkaSpec {
import LoggingDocSpec.MyActor
"use a logging actor" in {
- val myActor = system.actorOf(Props(new MyActor))
+ val myActor = system.actorOf(Props[MyActor])
myActor ! "test"
}
"allow registration to dead letters" in {
- //#deadletters
- import akka.actor.{ Actor, DeadLetter, Props }
+ new AnyRef {
+ //#deadletters
+ import akka.actor.{ Actor, DeadLetter, Props }
- val listener = system.actorOf(Props(new Actor {
- def receive = {
- case d: DeadLetter ⇒ println(d)
+ class Listener extends Actor {
+ def receive = {
+ case d: DeadLetter ⇒ println(d)
+ }
}
- }))
- system.eventStream.subscribe(listener, classOf[DeadLetter])
- //#deadletters
+ val listener = system.actorOf(Props(classOf[Listener], this))
+ system.eventStream.subscribe(listener, classOf[DeadLetter])
+ //#deadletters
+ }
}
"demonstrate logging more arguments" in {
diff --git a/akka-docs/rst/scala/code/docs/io/HTTPServer.scala b/akka-docs/rst/scala/code/docs/io/HTTPServer.scala
index f9792c06b7..34909b438b 100644
--- a/akka-docs/rst/scala/code/docs/io/HTTPServer.scala
+++ b/akka-docs/rst/scala/code/docs/io/HTTPServer.scala
@@ -237,6 +237,6 @@ case class OKResponse(body: ByteString, keepAlive: Boolean)
object Main extends App {
val port = Option(System.getenv("PORT")) map (_.toInt) getOrElse 8080
val system = ActorSystem()
- val server = system.actorOf(Props(new HttpServer(port)))
+ val server = system.actorOf(Props(classOf[HttpServer], port))
}
//#main
diff --git a/akka-docs/rst/scala/code/docs/io/Pipelines.scala b/akka-docs/rst/scala/code/docs/io/Pipelines.scala
index d853c4b644..3c42b83ba7 100644
--- a/akka-docs/rst/scala/code/docs/io/Pipelines.scala
+++ b/akka-docs/rst/scala/code/docs/io/Pipelines.scala
@@ -167,37 +167,8 @@ class PipelinesDocSpec extends AkkaSpec {
}
"demonstrate management port and context" in {
- //#actor
- class Processor(cmds: ActorRef, evts: ActorRef) extends Actor {
-
- val ctx = new HasActorContext with HasByteOrder {
- def getContext = Processor.this.context
- def byteOrder = java.nio.ByteOrder.BIG_ENDIAN
- }
-
- val pipeline = PipelineFactory.buildWithSinkFunctions(ctx,
- new TickGenerator(1000.millis) >>
- new MessageStage >>
- new LengthFieldFrame(10000) //
- )(
- // failure in the pipeline will fail this actor
- cmd ⇒ cmds ! cmd.get,
- evt ⇒ evts ! evt.get)
-
- def receive = {
- case m: Message ⇒ pipeline.injectCommand(m)
- case b: ByteString ⇒ pipeline.injectEvent(b)
- case t: TickGenerator.Trigger ⇒ pipeline.managementCommand(t)
- }
- }
- //#actor
-
import TickGenerator.Tick
- val proc = system.actorOf(Props(new Processor(testActor, testActor) {
- override def receive = ({
- case "fail!" ⇒ throw new RuntimeException("FAIL!")
- }: Receive) orElse super.receive
- }), "processor")
+ val proc = system.actorOf(Props(classOf[P], this, testActor, testActor), "processor")
expectMsgType[Tick]
proc ! msg
val encoded = expectMsgType[ByteString]
@@ -222,4 +193,35 @@ class PipelinesDocSpec extends AkkaSpec {
}
+ //#actor
+ class Processor(cmds: ActorRef, evts: ActorRef) extends Actor {
+
+ val ctx = new HasActorContext with HasByteOrder {
+ def getContext = Processor.this.context
+ def byteOrder = java.nio.ByteOrder.BIG_ENDIAN
+ }
+
+ val pipeline = PipelineFactory.buildWithSinkFunctions(ctx,
+ new TickGenerator(1000.millis) >>
+ new MessageStage >>
+ new LengthFieldFrame(10000) //
+ )(
+ // failure in the pipeline will fail this actor
+ cmd ⇒ cmds ! cmd.get,
+ evt ⇒ evts ! evt.get)
+
+ def receive = {
+ case m: Message ⇒ pipeline.injectCommand(m)
+ case b: ByteString ⇒ pipeline.injectEvent(b)
+ case t: TickGenerator.Trigger ⇒ pipeline.managementCommand(t)
+ }
+ }
+ //#actor
+
+ class P(cmds: ActorRef, evts: ActorRef) extends Processor(cmds, evts) {
+ override def receive = ({
+ case "fail!" ⇒ throw new RuntimeException("FAIL!")
+ }: Receive) orElse super.receive
+ }
+
}
\ No newline at end of file
diff --git a/akka-docs/rst/scala/code/docs/pattern/SchedulerPatternSpec.scala b/akka-docs/rst/scala/code/docs/pattern/SchedulerPatternSpec.scala
index 697557113f..433a98cbd0 100644
--- a/akka-docs/rst/scala/code/docs/pattern/SchedulerPatternSpec.scala
+++ b/akka-docs/rst/scala/code/docs/pattern/SchedulerPatternSpec.scala
@@ -88,12 +88,12 @@ class SchedulerPatternSpec extends AkkaSpec {
}
"send periodic ticks from the constructor" taggedAs TimingTest in {
- testSchedule(system.actorOf(Props(new ScheduleInConstructor(testActor))),
+ testSchedule(system.actorOf(Props(classOf[ScheduleInConstructor], testActor)),
3000 millis, 2000 millis)
}
"send ticks from the preStart and receive" taggedAs TimingTest in {
- testSchedule(system.actorOf(Props(new ScheduleInConstructor(testActor))),
+ testSchedule(system.actorOf(Props(classOf[ScheduleInConstructor], testActor)),
3000 millis, 2500 millis)
}
}
diff --git a/akka-docs/rst/scala/code/docs/testkit/TestKitUsageSpec.scala b/akka-docs/rst/scala/code/docs/testkit/TestKitUsageSpec.scala
index 6cdc0a88b2..d8f9e1c14e 100644
--- a/akka-docs/rst/scala/code/docs/testkit/TestKitUsageSpec.scala
+++ b/akka-docs/rst/scala/code/docs/testkit/TestKitUsageSpec.scala
@@ -34,15 +34,15 @@ class TestKitUsageSpec
with WordSpec with ShouldMatchers with BeforeAndAfterAll {
import TestKitUsageSpec._
- val echoRef = system.actorOf(Props(new EchoActor))
- val forwardRef = system.actorOf(Props(new ForwardingActor(testActor)))
- val filterRef = system.actorOf(Props(new FilteringActor(testActor)))
+ val echoRef = system.actorOf(Props[EchoActor])
+ val forwardRef = system.actorOf(Props(classOf[ForwardingActor], testActor))
+ val filterRef = system.actorOf(Props(classOf[FilteringActor], testActor))
val randomHead = Random.nextInt(6)
val randomTail = Random.nextInt(10)
val headList = immutable.Seq().padTo(randomHead, "0")
val tailList = immutable.Seq().padTo(randomTail, "1")
val seqRef =
- system.actorOf(Props(new SequencingActor(testActor, headList, tailList)))
+ system.actorOf(Props(classOf[SequencingActor], testActor, headList, tailList))
override def afterAll {
system.shutdown()
diff --git a/akka-docs/rst/scala/code/docs/testkit/TestkitDocSpec.scala b/akka-docs/rst/scala/code/docs/testkit/TestkitDocSpec.scala
index 7e9b0794a7..3696e9e434 100644
--- a/akka-docs/rst/scala/code/docs/testkit/TestkitDocSpec.scala
+++ b/akka-docs/rst/scala/code/docs/testkit/TestkitDocSpec.scala
@@ -208,9 +208,7 @@ class TestkitDocSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
"demonstrate probe watch" in {
import akka.testkit.TestProbe
- val target = system.actorOf(Props(new Actor {
- def receive = Actor.emptyBehavior
- }))
+ val target = system.actorOf(Props.empty)
//#test-probe-watch
val probe = TestProbe()
probe watch target
@@ -237,7 +235,7 @@ class TestkitDocSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
import akka.actor.Props
//#test-probe-forward
val probe = TestProbe()
- val source = system.actorOf(Props(new Source(probe.ref)))
+ val source = system.actorOf(Props(classOf[Source], probe.ref))
val dest = system.actorOf(Props[Destination])
source ! "start"
probe.expectMsg("work")
diff --git a/akka-docs/rst/scala/code/docs/transactor/TransactorDocSpec.scala b/akka-docs/rst/scala/code/docs/transactor/TransactorDocSpec.scala
index 10025f01df..6807dd4645 100644
--- a/akka-docs/rst/scala/code/docs/transactor/TransactorDocSpec.scala
+++ b/akka-docs/rst/scala/code/docs/transactor/TransactorDocSpec.scala
@@ -199,6 +199,7 @@ class TransactorDocSpec extends AkkaSpec {
val system = ActorSystem("transactors")
+ // FIXME, or remove the whole transactor module, srsly
lazy val underlyingCounter = new Counter
val counter = system.actorOf(Props(underlyingCounter), name = "counter")
val coordinated = Coordinated()(Timeout(5 seconds))
diff --git a/akka-docs/rst/scala/code/docs/zeromq/ZeromqDocSpec.scala b/akka-docs/rst/scala/code/docs/zeromq/ZeromqDocSpec.scala
index 83877d1714..005898e763 100644
--- a/akka-docs/rst/scala/code/docs/zeromq/ZeromqDocSpec.scala
+++ b/akka-docs/rst/scala/code/docs/zeromq/ZeromqDocSpec.scala
@@ -4,7 +4,6 @@
package docs.zeromq
import language.postfixOps
-
import scala.concurrent.duration._
import akka.actor.{ Actor, Props }
import akka.util.ByteString
@@ -12,6 +11,7 @@ import akka.testkit._
import akka.zeromq.{ ZeroMQVersion, ZeroMQExtension, SocketType, Bind }
import java.text.SimpleDateFormat
import java.util.Date
+import akka.actor.ActorRef
object ZeromqDocSpec {
@@ -122,18 +122,25 @@ class ZeromqDocSpec extends AkkaSpec("akka.loglevel=INFO") {
Bind("tcp://127.0.0.1:21231"))
//#pub-socket
- //#sub-socket
import akka.zeromq._
- val listener = system.actorOf(Props(new Actor {
- def receive: Receive = {
- case Connecting ⇒ //...
- case m: ZMQMessage ⇒ //...
- case _ ⇒ //...
+ val sub: { def subSocket: ActorRef; def listener: ActorRef } = new AnyRef {
+ //#sub-socket
+ import akka.zeromq._
+
+ class Listener extends Actor {
+ def receive: Receive = {
+ case Connecting ⇒ //...
+ case m: ZMQMessage ⇒ //...
+ case _ ⇒ //...
+ }
}
- }))
- val subSocket = ZeroMQExtension(system).newSocket(SocketType.Sub,
- Listener(listener), Connect("tcp://127.0.0.1:21231"), SubscribeAll)
- //#sub-socket
+
+ val listener = system.actorOf(Props(classOf[Listener], this))
+ val subSocket = ZeroMQExtension(system).newSocket(SocketType.Sub,
+ Listener(listener), Connect("tcp://127.0.0.1:21231"), SubscribeAll)
+ //#sub-socket
+ }
+ val listener = sub.listener
//#sub-topic-socket
val subTopicSocket = ZeroMQExtension(system).newSocket(SocketType.Sub,
@@ -149,7 +156,7 @@ class ZeromqDocSpec extends AkkaSpec("akka.loglevel=INFO") {
pubSocket ! ZMQMessage(ByteString("foo.bar"), ByteString(payload))
//#pub-topic
- system.stop(subSocket)
+ system.stop(sub.subSocket)
system.stop(subTopicSocket)
//#high-watermark
diff --git a/akka-remote/src/main/java/akka/remote/RemoteProtocol.java b/akka-remote/src/main/java/akka/remote/RemoteProtocol.java
index db3de8f925..31179c4408 100644
--- a/akka-remote/src/main/java/akka/remote/RemoteProtocol.java
+++ b/akka-remote/src/main/java/akka/remote/RemoteProtocol.java
@@ -299,7 +299,7 @@ public final class RemoteProtocol {
maybeForceBuilderInitialization();
}
- private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ private Builder(BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
@@ -886,7 +886,7 @@ public final class RemoteProtocol {
maybeForceBuilderInitialization();
}
- private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ private Builder(BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
@@ -1882,7 +1882,7 @@ public final class RemoteProtocol {
maybeForceBuilderInitialization();
}
- private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ private Builder(BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
@@ -2432,7 +2432,7 @@ public final class RemoteProtocol {
maybeForceBuilderInitialization();
}
- private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ private Builder(BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
@@ -2841,7 +2841,7 @@ public final class RemoteProtocol {
maybeForceBuilderInitialization();
}
- private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ private Builder(BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
@@ -3315,7 +3315,7 @@ public final class RemoteProtocol {
maybeForceBuilderInitialization();
}
- private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ private Builder(BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
@@ -3858,7 +3858,7 @@ public final class RemoteProtocol {
maybeForceBuilderInitialization();
}
- private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ private Builder(BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
@@ -4486,7 +4486,7 @@ public final class RemoteProtocol {
maybeForceBuilderInitialization();
}
- private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ private Builder(BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
@@ -5034,26 +5034,24 @@ public final class RemoteProtocol {
public interface PropsProtocolOrBuilder
extends com.google.protobuf.MessageOrBuilder {
- // required string dispatcher = 1;
- boolean hasDispatcher();
- String getDispatcher();
-
// required .DeployProtocol deploy = 2;
boolean hasDeploy();
akka.remote.RemoteProtocol.DeployProtocol getDeploy();
akka.remote.RemoteProtocol.DeployProtocolOrBuilder getDeployOrBuilder();
- // optional string fromClassCreator = 3;
- boolean hasFromClassCreator();
- String getFromClassCreator();
+ // required string clazz = 3;
+ boolean hasClazz();
+ String getClazz();
- // optional bytes creator = 4;
- boolean hasCreator();
- com.google.protobuf.ByteString getCreator();
+ // repeated bytes args = 4;
+ java.util.List getArgsList();
+ int getArgsCount();
+ com.google.protobuf.ByteString getArgs(int index);
- // optional bytes routerConfig = 5;
- boolean hasRouterConfig();
- com.google.protobuf.ByteString getRouterConfig();
+ // repeated string classes = 5;
+ java.util.List getClassesList();
+ int getClassesCount();
+ String getClasses(int index);
}
public static final class PropsProtocol extends
com.google.protobuf.GeneratedMessage
@@ -5084,43 +5082,11 @@ public final class RemoteProtocol {
}
private int bitField0_;
- // required string dispatcher = 1;
- public static final int DISPATCHER_FIELD_NUMBER = 1;
- private java.lang.Object dispatcher_;
- public boolean hasDispatcher() {
- return ((bitField0_ & 0x00000001) == 0x00000001);
- }
- public String getDispatcher() {
- java.lang.Object ref = dispatcher_;
- if (ref instanceof String) {
- return (String) ref;
- } else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- String s = bs.toStringUtf8();
- if (com.google.protobuf.Internal.isValidUtf8(bs)) {
- dispatcher_ = s;
- }
- return s;
- }
- }
- private com.google.protobuf.ByteString getDispatcherBytes() {
- java.lang.Object ref = dispatcher_;
- if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8((String) ref);
- dispatcher_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
-
// required .DeployProtocol deploy = 2;
public static final int DEPLOY_FIELD_NUMBER = 2;
private akka.remote.RemoteProtocol.DeployProtocol deploy_;
public boolean hasDeploy() {
- return ((bitField0_ & 0x00000002) == 0x00000002);
+ return ((bitField0_ & 0x00000001) == 0x00000001);
}
public akka.remote.RemoteProtocol.DeployProtocol getDeploy() {
return deploy_;
@@ -5129,14 +5095,14 @@ public final class RemoteProtocol {
return deploy_;
}
- // optional string fromClassCreator = 3;
- public static final int FROMCLASSCREATOR_FIELD_NUMBER = 3;
- private java.lang.Object fromClassCreator_;
- public boolean hasFromClassCreator() {
- return ((bitField0_ & 0x00000004) == 0x00000004);
+ // required string clazz = 3;
+ public static final int CLAZZ_FIELD_NUMBER = 3;
+ private java.lang.Object clazz_;
+ public boolean hasClazz() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
}
- public String getFromClassCreator() {
- java.lang.Object ref = fromClassCreator_;
+ public String getClazz() {
+ java.lang.Object ref = clazz_;
if (ref instanceof String) {
return (String) ref;
} else {
@@ -5144,60 +5110,67 @@ public final class RemoteProtocol {
(com.google.protobuf.ByteString) ref;
String s = bs.toStringUtf8();
if (com.google.protobuf.Internal.isValidUtf8(bs)) {
- fromClassCreator_ = s;
+ clazz_ = s;
}
return s;
}
}
- private com.google.protobuf.ByteString getFromClassCreatorBytes() {
- java.lang.Object ref = fromClassCreator_;
+ private com.google.protobuf.ByteString getClazzBytes() {
+ java.lang.Object ref = clazz_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8((String) ref);
- fromClassCreator_ = b;
+ clazz_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
- // optional bytes creator = 4;
- public static final int CREATOR_FIELD_NUMBER = 4;
- private com.google.protobuf.ByteString creator_;
- public boolean hasCreator() {
- return ((bitField0_ & 0x00000008) == 0x00000008);
+ // repeated bytes args = 4;
+ public static final int ARGS_FIELD_NUMBER = 4;
+ private java.util.List args_;
+ public java.util.List
+ getArgsList() {
+ return args_;
}
- public com.google.protobuf.ByteString getCreator() {
- return creator_;
+ public int getArgsCount() {
+ return args_.size();
+ }
+ public com.google.protobuf.ByteString getArgs(int index) {
+ return args_.get(index);
}
- // optional bytes routerConfig = 5;
- public static final int ROUTERCONFIG_FIELD_NUMBER = 5;
- private com.google.protobuf.ByteString routerConfig_;
- public boolean hasRouterConfig() {
- return ((bitField0_ & 0x00000010) == 0x00000010);
+ // repeated string classes = 5;
+ public static final int CLASSES_FIELD_NUMBER = 5;
+ private com.google.protobuf.LazyStringList classes_;
+ public java.util.List
+ getClassesList() {
+ return classes_;
}
- public com.google.protobuf.ByteString getRouterConfig() {
- return routerConfig_;
+ public int getClassesCount() {
+ return classes_.size();
+ }
+ public String getClasses(int index) {
+ return classes_.get(index);
}
private void initFields() {
- dispatcher_ = "";
deploy_ = akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance();
- fromClassCreator_ = "";
- creator_ = com.google.protobuf.ByteString.EMPTY;
- routerConfig_ = com.google.protobuf.ByteString.EMPTY;
+ clazz_ = "";
+ args_ = java.util.Collections.emptyList();;
+ classes_ = com.google.protobuf.LazyStringArrayList.EMPTY;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized != -1) return isInitialized == 1;
- if (!hasDispatcher()) {
+ if (!hasDeploy()) {
memoizedIsInitialized = 0;
return false;
}
- if (!hasDeploy()) {
+ if (!hasClazz()) {
memoizedIsInitialized = 0;
return false;
}
@@ -5213,19 +5186,16 @@ public final class RemoteProtocol {
throws java.io.IOException {
getSerializedSize();
if (((bitField0_ & 0x00000001) == 0x00000001)) {
- output.writeBytes(1, getDispatcherBytes());
- }
- if (((bitField0_ & 0x00000002) == 0x00000002)) {
output.writeMessage(2, deploy_);
}
- if (((bitField0_ & 0x00000004) == 0x00000004)) {
- output.writeBytes(3, getFromClassCreatorBytes());
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(3, getClazzBytes());
}
- if (((bitField0_ & 0x00000008) == 0x00000008)) {
- output.writeBytes(4, creator_);
+ for (int i = 0; i < args_.size(); i++) {
+ output.writeBytes(4, args_.get(i));
}
- if (((bitField0_ & 0x00000010) == 0x00000010)) {
- output.writeBytes(5, routerConfig_);
+ for (int i = 0; i < classes_.size(); i++) {
+ output.writeBytes(5, classes_.getByteString(i));
}
getUnknownFields().writeTo(output);
}
@@ -5238,23 +5208,29 @@ public final class RemoteProtocol {
size = 0;
if (((bitField0_ & 0x00000001) == 0x00000001)) {
size += com.google.protobuf.CodedOutputStream
- .computeBytesSize(1, getDispatcherBytes());
+ .computeMessageSize(2, deploy_);
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
size += com.google.protobuf.CodedOutputStream
- .computeMessageSize(2, deploy_);
+ .computeBytesSize(3, getClazzBytes());
}
- if (((bitField0_ & 0x00000004) == 0x00000004)) {
- size += com.google.protobuf.CodedOutputStream
- .computeBytesSize(3, getFromClassCreatorBytes());
+ {
+ int dataSize = 0;
+ for (int i = 0; i < args_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(args_.get(i));
+ }
+ size += dataSize;
+ size += 1 * getArgsList().size();
}
- if (((bitField0_ & 0x00000008) == 0x00000008)) {
- size += com.google.protobuf.CodedOutputStream
- .computeBytesSize(4, creator_);
- }
- if (((bitField0_ & 0x00000010) == 0x00000010)) {
- size += com.google.protobuf.CodedOutputStream
- .computeBytesSize(5, routerConfig_);
+ {
+ int dataSize = 0;
+ for (int i = 0; i < classes_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(classes_.getByteString(i));
+ }
+ size += dataSize;
+ size += 1 * getClassesList().size();
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
@@ -5366,7 +5342,7 @@ public final class RemoteProtocol {
maybeForceBuilderInitialization();
}
- private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ private Builder(BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
@@ -5381,20 +5357,18 @@ public final class RemoteProtocol {
public Builder clear() {
super.clear();
- dispatcher_ = "";
- bitField0_ = (bitField0_ & ~0x00000001);
if (deployBuilder_ == null) {
deploy_ = akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance();
} else {
deployBuilder_.clear();
}
+ bitField0_ = (bitField0_ & ~0x00000001);
+ clazz_ = "";
bitField0_ = (bitField0_ & ~0x00000002);
- fromClassCreator_ = "";
+ args_ = java.util.Collections.emptyList();;
bitField0_ = (bitField0_ & ~0x00000004);
- creator_ = com.google.protobuf.ByteString.EMPTY;
+ classes_ = com.google.protobuf.LazyStringArrayList.EMPTY;
bitField0_ = (bitField0_ & ~0x00000008);
- routerConfig_ = com.google.protobuf.ByteString.EMPTY;
- bitField0_ = (bitField0_ & ~0x00000010);
return this;
}
@@ -5436,27 +5410,26 @@ public final class RemoteProtocol {
if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
to_bitField0_ |= 0x00000001;
}
- result.dispatcher_ = dispatcher_;
- if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
- to_bitField0_ |= 0x00000002;
- }
if (deployBuilder_ == null) {
result.deploy_ = deploy_;
} else {
result.deploy_ = deployBuilder_.build();
}
- if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
- to_bitField0_ |= 0x00000004;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
}
- result.fromClassCreator_ = fromClassCreator_;
- if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
- to_bitField0_ |= 0x00000008;
+ result.clazz_ = clazz_;
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ args_ = java.util.Collections.unmodifiableList(args_);
+ bitField0_ = (bitField0_ & ~0x00000004);
}
- result.creator_ = creator_;
- if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
- to_bitField0_ |= 0x00000010;
+ result.args_ = args_;
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ classes_ = new com.google.protobuf.UnmodifiableLazyStringList(
+ classes_);
+ bitField0_ = (bitField0_ & ~0x00000008);
}
- result.routerConfig_ = routerConfig_;
+ result.classes_ = classes_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@@ -5473,31 +5446,42 @@ public final class RemoteProtocol {
public Builder mergeFrom(akka.remote.RemoteProtocol.PropsProtocol other) {
if (other == akka.remote.RemoteProtocol.PropsProtocol.getDefaultInstance()) return this;
- if (other.hasDispatcher()) {
- setDispatcher(other.getDispatcher());
- }
if (other.hasDeploy()) {
mergeDeploy(other.getDeploy());
}
- if (other.hasFromClassCreator()) {
- setFromClassCreator(other.getFromClassCreator());
+ if (other.hasClazz()) {
+ setClazz(other.getClazz());
}
- if (other.hasCreator()) {
- setCreator(other.getCreator());
+ if (!other.args_.isEmpty()) {
+ if (args_.isEmpty()) {
+ args_ = other.args_;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ } else {
+ ensureArgsIsMutable();
+ args_.addAll(other.args_);
+ }
+ onChanged();
}
- if (other.hasRouterConfig()) {
- setRouterConfig(other.getRouterConfig());
+ if (!other.classes_.isEmpty()) {
+ if (classes_.isEmpty()) {
+ classes_ = other.classes_;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ } else {
+ ensureClassesIsMutable();
+ classes_.addAll(other.classes_);
+ }
+ onChanged();
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
public final boolean isInitialized() {
- if (!hasDispatcher()) {
+ if (!hasDeploy()) {
return false;
}
- if (!hasDeploy()) {
+ if (!hasClazz()) {
return false;
}
@@ -5531,11 +5515,6 @@ public final class RemoteProtocol {
}
break;
}
- case 10: {
- bitField0_ |= 0x00000001;
- dispatcher_ = input.readBytes();
- break;
- }
case 18: {
akka.remote.RemoteProtocol.DeployProtocol.Builder subBuilder = akka.remote.RemoteProtocol.DeployProtocol.newBuilder();
if (hasDeploy()) {
@@ -5546,18 +5525,18 @@ public final class RemoteProtocol {
break;
}
case 26: {
- bitField0_ |= 0x00000004;
- fromClassCreator_ = input.readBytes();
+ bitField0_ |= 0x00000002;
+ clazz_ = input.readBytes();
break;
}
case 34: {
- bitField0_ |= 0x00000008;
- creator_ = input.readBytes();
+ ensureArgsIsMutable();
+ args_.add(input.readBytes());
break;
}
case 42: {
- bitField0_ |= 0x00000010;
- routerConfig_ = input.readBytes();
+ ensureClassesIsMutable();
+ classes_.add(input.readBytes());
break;
}
}
@@ -5566,48 +5545,12 @@ public final class RemoteProtocol {
private int bitField0_;
- // required string dispatcher = 1;
- private java.lang.Object dispatcher_ = "";
- public boolean hasDispatcher() {
- return ((bitField0_ & 0x00000001) == 0x00000001);
- }
- public String getDispatcher() {
- java.lang.Object ref = dispatcher_;
- if (!(ref instanceof String)) {
- String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
- dispatcher_ = s;
- return s;
- } else {
- return (String) ref;
- }
- }
- public Builder setDispatcher(String value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000001;
- dispatcher_ = value;
- onChanged();
- return this;
- }
- public Builder clearDispatcher() {
- bitField0_ = (bitField0_ & ~0x00000001);
- dispatcher_ = getDefaultInstance().getDispatcher();
- onChanged();
- return this;
- }
- void setDispatcher(com.google.protobuf.ByteString value) {
- bitField0_ |= 0x00000001;
- dispatcher_ = value;
- onChanged();
- }
-
// required .DeployProtocol deploy = 2;
private akka.remote.RemoteProtocol.DeployProtocol deploy_ = akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance();
private com.google.protobuf.SingleFieldBuilder<
akka.remote.RemoteProtocol.DeployProtocol, akka.remote.RemoteProtocol.DeployProtocol.Builder, akka.remote.RemoteProtocol.DeployProtocolOrBuilder> deployBuilder_;
public boolean hasDeploy() {
- return ((bitField0_ & 0x00000002) == 0x00000002);
+ return ((bitField0_ & 0x00000001) == 0x00000001);
}
public akka.remote.RemoteProtocol.DeployProtocol getDeploy() {
if (deployBuilder_ == null) {
@@ -5626,7 +5569,7 @@ public final class RemoteProtocol {
} else {
deployBuilder_.setMessage(value);
}
- bitField0_ |= 0x00000002;
+ bitField0_ |= 0x00000001;
return this;
}
public Builder setDeploy(
@@ -5637,12 +5580,12 @@ public final class RemoteProtocol {
} else {
deployBuilder_.setMessage(builderForValue.build());
}
- bitField0_ |= 0x00000002;
+ bitField0_ |= 0x00000001;
return this;
}
public Builder mergeDeploy(akka.remote.RemoteProtocol.DeployProtocol value) {
if (deployBuilder_ == null) {
- if (((bitField0_ & 0x00000002) == 0x00000002) &&
+ if (((bitField0_ & 0x00000001) == 0x00000001) &&
deploy_ != akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance()) {
deploy_ =
akka.remote.RemoteProtocol.DeployProtocol.newBuilder(deploy_).mergeFrom(value).buildPartial();
@@ -5653,7 +5596,7 @@ public final class RemoteProtocol {
} else {
deployBuilder_.mergeFrom(value);
}
- bitField0_ |= 0x00000002;
+ bitField0_ |= 0x00000001;
return this;
}
public Builder clearDeploy() {
@@ -5663,11 +5606,11 @@ public final class RemoteProtocol {
} else {
deployBuilder_.clear();
}
- bitField0_ = (bitField0_ & ~0x00000002);
+ bitField0_ = (bitField0_ & ~0x00000001);
return this;
}
public akka.remote.RemoteProtocol.DeployProtocol.Builder getDeployBuilder() {
- bitField0_ |= 0x00000002;
+ bitField0_ |= 0x00000001;
onChanged();
return getDeployFieldBuilder().getBuilder();
}
@@ -5692,88 +5635,147 @@ public final class RemoteProtocol {
return deployBuilder_;
}
- // optional string fromClassCreator = 3;
- private java.lang.Object fromClassCreator_ = "";
- public boolean hasFromClassCreator() {
- return ((bitField0_ & 0x00000004) == 0x00000004);
+ // required string clazz = 3;
+ private java.lang.Object clazz_ = "";
+ public boolean hasClazz() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
}
- public String getFromClassCreator() {
- java.lang.Object ref = fromClassCreator_;
+ public String getClazz() {
+ java.lang.Object ref = clazz_;
if (!(ref instanceof String)) {
String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
- fromClassCreator_ = s;
+ clazz_ = s;
return s;
} else {
return (String) ref;
}
}
- public Builder setFromClassCreator(String value) {
+ public Builder setClazz(String value) {
if (value == null) {
throw new NullPointerException();
}
- bitField0_ |= 0x00000004;
- fromClassCreator_ = value;
+ bitField0_ |= 0x00000002;
+ clazz_ = value;
onChanged();
return this;
}
- public Builder clearFromClassCreator() {
+ public Builder clearClazz() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ clazz_ = getDefaultInstance().getClazz();
+ onChanged();
+ return this;
+ }
+ void setClazz(com.google.protobuf.ByteString value) {
+ bitField0_ |= 0x00000002;
+ clazz_ = value;
+ onChanged();
+ }
+
+ // repeated bytes args = 4;
+ private java.util.List args_ = java.util.Collections.emptyList();;
+ private void ensureArgsIsMutable() {
+ if (!((bitField0_ & 0x00000004) == 0x00000004)) {
+ args_ = new java.util.ArrayList(args_);
+ bitField0_ |= 0x00000004;
+ }
+ }
+ public java.util.List
+ getArgsList() {
+ return java.util.Collections.unmodifiableList(args_);
+ }
+ public int getArgsCount() {
+ return args_.size();
+ }
+ public com.google.protobuf.ByteString getArgs(int index) {
+ return args_.get(index);
+ }
+ public Builder setArgs(
+ int index, com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureArgsIsMutable();
+ args_.set(index, value);
+ onChanged();
+ return this;
+ }
+ public Builder addArgs(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureArgsIsMutable();
+ args_.add(value);
+ onChanged();
+ return this;
+ }
+ public Builder addAllArgs(
+ java.lang.Iterable extends com.google.protobuf.ByteString> values) {
+ ensureArgsIsMutable();
+ super.addAll(values, args_);
+ onChanged();
+ return this;
+ }
+ public Builder clearArgs() {
+ args_ = java.util.Collections.emptyList();;
bitField0_ = (bitField0_ & ~0x00000004);
- fromClassCreator_ = getDefaultInstance().getFromClassCreator();
onChanged();
return this;
}
- void setFromClassCreator(com.google.protobuf.ByteString value) {
- bitField0_ |= 0x00000004;
- fromClassCreator_ = value;
- onChanged();
- }
- // optional bytes creator = 4;
- private com.google.protobuf.ByteString creator_ = com.google.protobuf.ByteString.EMPTY;
- public boolean hasCreator() {
- return ((bitField0_ & 0x00000008) == 0x00000008);
+ // repeated string classes = 5;
+ private com.google.protobuf.LazyStringList classes_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ private void ensureClassesIsMutable() {
+ if (!((bitField0_ & 0x00000008) == 0x00000008)) {
+ classes_ = new com.google.protobuf.LazyStringArrayList(classes_);
+ bitField0_ |= 0x00000008;
+ }
}
- public com.google.protobuf.ByteString getCreator() {
- return creator_;
+ public java.util.List
+ getClassesList() {
+ return java.util.Collections.unmodifiableList(classes_);
}
- public Builder setCreator(com.google.protobuf.ByteString value) {
+ public int getClassesCount() {
+ return classes_.size();
+ }
+ public String getClasses(int index) {
+ return classes_.get(index);
+ }
+ public Builder setClasses(
+ int index, String value) {
if (value == null) {
throw new NullPointerException();
}
- bitField0_ |= 0x00000008;
- creator_ = value;
+ ensureClassesIsMutable();
+ classes_.set(index, value);
onChanged();
return this;
}
- public Builder clearCreator() {
+ public Builder addClasses(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureClassesIsMutable();
+ classes_.add(value);
+ onChanged();
+ return this;
+ }
+ public Builder addAllClasses(
+ java.lang.Iterable values) {
+ ensureClassesIsMutable();
+ super.addAll(values, classes_);
+ onChanged();
+ return this;
+ }
+ public Builder clearClasses() {
+ classes_ = com.google.protobuf.LazyStringArrayList.EMPTY;
bitField0_ = (bitField0_ & ~0x00000008);
- creator_ = getDefaultInstance().getCreator();
onChanged();
return this;
}
-
- // optional bytes routerConfig = 5;
- private com.google.protobuf.ByteString routerConfig_ = com.google.protobuf.ByteString.EMPTY;
- public boolean hasRouterConfig() {
- return ((bitField0_ & 0x00000010) == 0x00000010);
- }
- public com.google.protobuf.ByteString getRouterConfig() {
- return routerConfig_;
- }
- public Builder setRouterConfig(com.google.protobuf.ByteString value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000010;
- routerConfig_ = value;
+ void addClasses(com.google.protobuf.ByteString value) {
+ ensureClassesIsMutable();
+ classes_.add(value);
onChanged();
- return this;
- }
- public Builder clearRouterConfig() {
- bitField0_ = (bitField0_ & ~0x00000010);
- routerConfig_ = getDefaultInstance().getRouterConfig();
- onChanged();
- return this;
}
// @@protoc_insertion_point(builder_scope:PropsProtocol)
@@ -6110,7 +6112,7 @@ public final class RemoteProtocol {
maybeForceBuilderInitialization();
}
- private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ private Builder(BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
@@ -6522,11 +6524,10 @@ public final class RemoteProtocol {
"l\030\004 \001(\t\"\216\001\n\027DaemonMsgCreateProtocol\022\035\n\005p" +
"rops\030\001 \002(\0132\016.PropsProtocol\022\037\n\006deploy\030\002 \002" +
"(\0132\017.DeployProtocol\022\014\n\004path\030\003 \002(\t\022%\n\nsup" +
- "ervisor\030\004 \002(\0132\021.ActorRefProtocol\"\205\001\n\rPro",
- "psProtocol\022\022\n\ndispatcher\030\001 \002(\t\022\037\n\006deploy" +
- "\030\002 \002(\0132\017.DeployProtocol\022\030\n\020fromClassCrea" +
- "tor\030\003 \001(\t\022\017\n\007creator\030\004 \001(\014\022\024\n\014routerConf" +
- "ig\030\005 \001(\014\"g\n\016DeployProtocol\022\014\n\004path\030\001 \002(\t" +
+ "ervisor\030\004 \002(\0132\021.ActorRefProtocol\"^\n\rProp",
+ "sProtocol\022\037\n\006deploy\030\002 \002(\0132\017.DeployProtoc" +
+ "ol\022\r\n\005clazz\030\003 \002(\t\022\014\n\004args\030\004 \003(\014\022\017\n\007class" +
+ "es\030\005 \003(\t\"g\n\016DeployProtocol\022\014\n\004path\030\001 \002(\t" +
"\022\016\n\006config\030\002 \001(\014\022\024\n\014routerConfig\030\003 \001(\014\022\r" +
"\n\005scope\030\004 \001(\014\022\022\n\ndispatcher\030\005 \001(\t*7\n\013Com" +
"mandType\022\013\n\007CONNECT\020\001\022\014\n\010SHUTDOWN\020\002\022\r\n\tH" +
@@ -6606,7 +6607,7 @@ public final class RemoteProtocol {
internal_static_PropsProtocol_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_PropsProtocol_descriptor,
- new java.lang.String[] { "Dispatcher", "Deploy", "FromClassCreator", "Creator", "RouterConfig", },
+ new java.lang.String[] { "Deploy", "Clazz", "Args", "Classes", },
akka.remote.RemoteProtocol.PropsProtocol.class,
akka.remote.RemoteProtocol.PropsProtocol.Builder.class);
internal_static_DeployProtocol_descriptor =
diff --git a/akka-remote/src/main/protocol/RemoteProtocol.proto b/akka-remote/src/main/protocol/RemoteProtocol.proto
index 76c649dd00..0102c8e7b9 100644
--- a/akka-remote/src/main/protocol/RemoteProtocol.proto
+++ b/akka-remote/src/main/protocol/RemoteProtocol.proto
@@ -95,11 +95,10 @@ message DaemonMsgCreateProtocol {
* Serialization of akka.actor.Props
*/
message PropsProtocol {
- required string dispatcher = 1;
required DeployProtocol deploy = 2;
- optional string fromClassCreator = 3;
- optional bytes creator = 4;
- optional bytes routerConfig = 5;
+ required string clazz = 3;
+ repeated bytes args = 4;
+ repeated string classes = 5;
}
/**
diff --git a/akka-remote/src/main/scala/akka/remote/serialization/DaemonMsgCreateSerializer.scala b/akka-remote/src/main/scala/akka/remote/serialization/DaemonMsgCreateSerializer.scala
index ad9e7128e9..d97c68bb50 100644
--- a/akka-remote/src/main/scala/akka/remote/serialization/DaemonMsgCreateSerializer.scala
+++ b/akka-remote/src/main/scala/akka/remote/serialization/DaemonMsgCreateSerializer.scala
@@ -12,7 +12,6 @@ import akka.actor.{ Actor, ActorRef, Deploy, ExtendedActorSystem, NoScopeGiven,
import akka.remote.DaemonMsgCreate
import akka.remote.RemoteProtocol.{ DaemonMsgCreateProtocol, DeployProtocol, PropsProtocol }
import akka.routing.{ NoRouter, RouterConfig }
-import akka.actor.FromClassCreator
import scala.reflect.ClassTag
import util.{ Failure, Success }
@@ -51,15 +50,11 @@ private[akka] class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) e
}
def propsProto = {
- val builder = PropsProtocol.newBuilder.
- setDispatcher(props.dispatcher).
- setDeploy(deployProto(props.deploy))
- props.creator match {
- case FromClassCreator(clazz) ⇒ builder.setFromClassCreator(clazz.getName)
- case creator ⇒ builder.setCreator(serialize(creator))
- }
- if (props.routerConfig != NoRouter)
- builder.setRouterConfig(serialize(props.routerConfig))
+ val builder = PropsProtocol.newBuilder
+ .setClazz(props.clazz.getName)
+ .setDeploy(deployProto(props.deploy))
+ props.args map serialize foreach builder.addArgs
+ props.args map (_.getClass.getName) foreach builder.addClasses
builder.build
}
@@ -95,21 +90,11 @@ private[akka] class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) e
}
def props = {
- val creator =
- if (proto.getProps.hasFromClassCreator)
- FromClassCreator(system.dynamicAccess.getClassFor[Actor](proto.getProps.getFromClassCreator).get)
- else
- deserialize(proto.getProps.getCreator, classOf[() ⇒ Actor])
-
- val routerConfig =
- if (proto.getProps.hasRouterConfig) deserialize(proto.getProps.getRouterConfig, classOf[RouterConfig])
- else NoRouter
-
- Props(
- creator = creator,
- dispatcher = proto.getProps.getDispatcher,
- routerConfig = routerConfig,
- deploy = deploy(proto.getProps.getDeploy))
+ import scala.collection.JavaConverters._
+ val clazz = system.dynamicAccess.getClassFor[AnyRef](proto.getProps.getClazz).get
+ val args: Vector[AnyRef] = (proto.getProps.getArgsList.asScala zip proto.getProps.getClassesList.asScala)
+ .map(p ⇒ deserialize(p._1, system.dynamicAccess.getClassFor[AnyRef](p._2).get))(collection.breakOut)
+ Props(deploy(proto.getProps.getDeploy), clazz, args)
}
DaemonMsgCreate(
@@ -119,7 +104,7 @@ private[akka] class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) e
supervisor = deserializeActorRef(system, proto.getSupervisor))
}
- protected def serialize(any: AnyRef): ByteString = ByteString.copyFrom(serialization.serialize(any).get)
+ protected def serialize(any: Any): ByteString = ByteString.copyFrom(serialization.serialize(any.asInstanceOf[AnyRef]).get)
protected def deserialize[T: ClassTag](data: ByteString, clazz: Class[T]): T = {
val bytes = data.toByteArray
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 ea95aef975..760753cd2b 100644
--- a/akka-remote/src/test/scala/akka/remote/serialization/DaemonMsgCreateSerializerSpec.scala
+++ b/akka-remote/src/test/scala/akka/remote/serialization/DaemonMsgCreateSerializerSpec.scala
@@ -9,7 +9,7 @@ import language.postfixOps
import akka.serialization.SerializationExtension
import com.typesafe.config.ConfigFactory
import akka.testkit.AkkaSpec
-import akka.actor.{ Actor, Address, Props, Deploy, OneForOneStrategy, SupervisorStrategy, FromClassCreator }
+import akka.actor.{ Actor, Address, Props, Deploy, OneForOneStrategy, SupervisorStrategy }
import akka.remote.{ DaemonMsgCreate, RemoteScope }
import akka.routing.{ RoundRobinRouter, FromConfig }
import scala.concurrent.duration._
@@ -87,11 +87,13 @@ class DaemonMsgCreateSerializerSpec extends AkkaSpec {
def assertDaemonMsgCreate(expected: DaemonMsgCreate, got: DaemonMsgCreate): Unit = {
// can't compare props.creator when function
- if (expected.props.creator.isInstanceOf[FromClassCreator])
- assert(got.props.creator === expected.props.creator)
- assert(got.props.dispatcher === expected.props.dispatcher)
- assert(got.props.dispatcher === expected.props.dispatcher)
- assert(got.props.routerConfig === expected.props.routerConfig)
+ assert(got.props.clazz === expected.props.clazz)
+ assert(got.props.args.length === expected.props.args.length)
+ got.props.args zip expected.props.args foreach {
+ case (g, e) ⇒
+ if (e.isInstanceOf[Function0[_]]) ()
+ else assert(g === e)
+ }
assert(got.props.deploy === expected.props.deploy)
assert(got.deploy === expected.deploy)
assert(got.path === expected.path)