diff --git a/akka-contrib/docs/cluster-singleton.rst b/akka-contrib/docs/cluster-singleton.rst index d28a548b0a..9452cf624f 100644 --- a/akka-contrib/docs/cluster-singleton.rst +++ b/akka-contrib/docs/cluster-singleton.rst @@ -62,7 +62,7 @@ Here we limit the singleton to nodes tagged with the ``"worker"`` role, but all role, can be used by specifying ``None`` as ``role`` parameter. The corresponding Java API for the ``singeltonProps`` function is ``akka.contrib.pattern.ClusterSingletonPropsFactory``. -The Java API constructor takes a plain String for the role parameter and ``null`` means that all nodes, independent of +The Java API takes a plain String for the role parameter and ``null`` means that all nodes, independent of role, are used. Here we use an application specific ``terminationMessage`` to be able to close the diff --git a/akka-contrib/src/main/scala/akka/contrib/pattern/ClusterClient.scala b/akka-contrib/src/main/scala/akka/contrib/pattern/ClusterClient.scala index 668f17e3c2..7a774bc4e8 100644 --- a/akka-contrib/src/main/scala/akka/contrib/pattern/ClusterClient.scala +++ b/akka-contrib/src/main/scala/akka/contrib/pattern/ClusterClient.scala @@ -7,6 +7,7 @@ import java.net.URLEncoder import scala.collection.immutable import scala.concurrent.duration._ import akka.actor.Actor +import akka.actor.ActorIdentity import akka.actor.ActorLogging import akka.actor.ActorRef import akka.actor.ActorSelection @@ -16,6 +17,7 @@ import akka.actor.ExtendedActorSystem import akka.actor.Extension import akka.actor.ExtensionId import akka.actor.ExtensionIdProvider +import akka.actor.Identify import akka.actor.Props import akka.actor.ReceiveTimeout import akka.actor.Terminated @@ -26,12 +28,44 @@ import akka.cluster.MemberStatus import akka.routing.ConsistentHash import akka.routing.MurmurHash -/** - * INTERNAL API - */ -private object ClusterClient { - case object PingTick - case object RefreshContactsTick +object ClusterClient { + + /** + * Scala API: Factory method for `ClusterClient` [[akka.actor.Props]]. + */ + def props( + initialContacts: Set[ActorSelection], + pingInterval: FiniteDuration = 3.second, + refreshContactsInterval: FiniteDuration = 1.minute): Props = + Props(classOf[ClusterClient], initialContacts, pingInterval, refreshContactsInterval) + + /** + * Java API: Factory method for `ClusterClient` [[akka.actor.Props]]. + */ + def props( + initialContacts: java.util.Set[ActorSelection], + pingInterval: FiniteDuration, + refreshContactsInterval: FiniteDuration): Props = { + import scala.collection.JavaConverters._ + props(initialContacts.asScala.toSet, pingInterval, refreshContactsInterval) + } + + /** + * Java API: Factory method for `ClusterClient` [[akka.actor.Props]] with + * default values. + */ + def defaultProps(initialContacts: java.util.Set[ActorSelection]): Props = { + import scala.collection.JavaConverters._ + props(initialContacts.asScala.toSet) + } + + /** + * INTERNAL API + */ + private[pattern] object Internal { + case object PingTick + case object RefreshContactsTick + } } /** @@ -49,15 +83,19 @@ private object ClusterClient { * Messages are wrapped in [[DistributedPubSubMediator.Send]], [[DistributedPubSubMediator.SendToAll]] * or [[DistributedPubSubMediator.Publish]] with the semantics described in * [[DistributedPubSubMediator]]. + * + * Use the factory method [[ClusterClient#props]]) to create the + * [[akka.actor.Props]] for the actor. */ class ClusterClient( initialContacts: Set[ActorSelection], - pingInterval: FiniteDuration = 3.second, - refreshContactsInterval: FiniteDuration = 1.minute) + pingInterval: FiniteDuration, + refreshContactsInterval: FiniteDuration) extends Actor with ActorLogging { import ClusterClient._ - import ClusterReceptionist._ + import ClusterClient.Internal._ + import ClusterReceptionist.Internal._ import DistributedPubSubMediator.{ Send, SendToAll, Publish } var contacts: immutable.IndexedSeq[ActorSelection] = initialContacts.toVector @@ -177,46 +215,72 @@ class ClusterReceptionistExtension(system: ExtendedActorSystem) extends Extensio val name = config.getString("name") // important to use val mediator here to activate it outside of ClusterReceptionist constructor val mediator = pubSubMediator - system.actorOf(Props(new ClusterReceptionist(mediator, role, numberOfContacts, - responseTunnelReceiveTimeout)), name) + system.actorOf(ClusterReceptionist.props(mediator, role, numberOfContacts, + responseTunnelReceiveTimeout), name) } } } -/** - * INTERNAL API - */ -private[pattern] object ClusterReceptionist { - @SerialVersionUID(1L) - case object GetContacts - @SerialVersionUID(1L) - case class Contacts(contactPoints: immutable.IndexedSeq[ActorSelection]) - @SerialVersionUID(1L) - case object Ping - @SerialVersionUID(1L) - case object Pong - - // FIXME change to akka.actor.Identify when that is in master - @SerialVersionUID(1L) - case class Identify(messageId: Any) - @SerialVersionUID(1L) - case class ActorIdentity(correlationId: Any, ref: Option[ActorRef]) - - def roleOption(role: String): Option[String] = role match { - case null | "" ⇒ None - case _ ⇒ Some(role) - } +object ClusterReceptionist { /** - * Replies are tunneled via this actor, child of the receptionist, to avoid - * inbound connections from other cluster nodes to the client. + * Scala API: Factory method for `ClusterReceptionist` [[akka.actor.Props]]. */ - class ClientResponseTunnel(client: ActorRef, timeout: FiniteDuration) extends Actor { - context.setReceiveTimeout(timeout) - def receive = { - case Ping ⇒ // keep alive from client - case ReceiveTimeout ⇒ context stop self - case msg ⇒ client forward msg + def props( + pubSubMediator: ActorRef, + role: Option[String], + numberOfContacts: Int = 3, + responseTunnelReceiveTimeout: FiniteDuration = 30.seconds): Props = + Props(classOf[ClusterReceptionist], pubSubMediator, role, numberOfContacts, responseTunnelReceiveTimeout) + + /** + * Java API: Factory method for `ClusterReceptionist` [[akka.actor.Props]]. + */ + def props( + pubSubMediator: ActorRef, + role: String, + numberOfContacts: Int, + responseTunnelReceiveTimeout: FiniteDuration): Props = + props(pubSubMediator, Internal.roleOption(role), numberOfContacts, responseTunnelReceiveTimeout) + + /** + * Java API: Factory method for `ClusterReceptionist` [[akka.actor.Props]] + * with default values. + */ + def props( + pubSubMediator: ActorRef, + role: String): Props = + props(pubSubMediator, Internal.roleOption(role)) + + /** + * INTERNAL API + */ + private[pattern] object Internal { + @SerialVersionUID(1L) + case object GetContacts + @SerialVersionUID(1L) + case class Contacts(contactPoints: immutable.IndexedSeq[ActorSelection]) + @SerialVersionUID(1L) + case object Ping + @SerialVersionUID(1L) + case object Pong + + def roleOption(role: String): Option[String] = role match { + case null | "" ⇒ None + case _ ⇒ Some(role) + } + + /** + * Replies are tunneled via this actor, child of the receptionist, to avoid + * inbound connections from other cluster nodes to the client. + */ + class ClientResponseTunnel(client: ActorRef, timeout: FiniteDuration) extends Actor { + context.setReceiveTimeout(timeout) + def receive = { + case Ping ⇒ // keep alive from client + case ReceiveTimeout ⇒ context stop self + case msg ⇒ client forward msg + } } } @@ -226,7 +290,7 @@ private[pattern] object ClusterReceptionist { * [[ClusterClient]] connects to this actor to retrieve. The `ClusterReceptionist` is * supposed to be started on all nodes, or all nodes with specified role, in the cluster. * The receptionist can be started with the [[ClusterReceptionistExtension]] or as an - * ordinary actor. + * ordinary actor (use the factory method [[ClusterReceptionist#props]]). * * The receptionist forwards messages from the client to the associated [[DistributedPubSubMediator]], * i.e. the client can send messages to any actor in the cluster that is registered in the @@ -245,19 +309,13 @@ private[pattern] object ClusterReceptionist { class ClusterReceptionist( pubSubMediator: ActorRef, role: Option[String], - numberOfContacts: Int = 3, - responseTunnelReceiveTimeout: FiniteDuration = 30.seconds) + numberOfContacts: Int, + responseTunnelReceiveTimeout: FiniteDuration) extends Actor with ActorLogging { import DistributedPubSubMediator.{ Send, SendToAll, Publish } - /** - * Java API constructor with default values. - */ - def this(pubSubMediator: ActorRef, role: String) = - this(pubSubMediator, ClusterReceptionist.roleOption(role)) - - import ClusterReceptionist._ + import ClusterReceptionist.Internal._ val cluster = Cluster(context.system) import cluster.selfAddress @@ -300,7 +358,7 @@ class ClusterReceptionist( context.child(encName) match { case Some(tunnel) ⇒ tunnel case None ⇒ - context.actorOf(Props(new ClientResponseTunnel(client, responseTunnelReceiveTimeout)), encName) + context.actorOf(Props(classOf[ClientResponseTunnel], client, responseTunnelReceiveTimeout), encName) } } @@ -312,10 +370,6 @@ class ClusterReceptionist( responseTunnel(sender) ! Ping // keep alive sender ! Pong - // FIXME remove when akka.actor.Identify when is in master - case Identify(messageId) ⇒ - sender ! ActorIdentity(messageId, Some(self)) - case GetContacts ⇒ // Consistent hashing is used to ensure that the reply to GetContacts // is the same from all nodes (most of the time) and it also diff --git a/akka-contrib/src/main/scala/akka/contrib/pattern/ClusterSingletonManager.scala b/akka-contrib/src/main/scala/akka/contrib/pattern/ClusterSingletonManager.scala index 8dbdb0be0e..a4b9c303ae 100644 --- a/akka-contrib/src/main/scala/akka/contrib/pattern/ClusterSingletonManager.scala +++ b/akka-contrib/src/main/scala/akka/contrib/pattern/ClusterSingletonManager.scala @@ -20,6 +20,48 @@ import akka.AkkaException object ClusterSingletonManager { + /** + * Scala API: Factory method for `ClusterSingletonManager` [[akka.actor.Props]]. + */ + def props( + singletonProps: Option[Any] ⇒ Props, + singletonName: String, + terminationMessage: Any, + role: Option[String], + maxHandOverRetries: Int = 20, + maxTakeOverRetries: Int = 15, + retryInterval: FiniteDuration = 1.second, + loggingEnabled: Boolean = true): Props = + Props(classOf[ClusterSingletonManager], singletonProps, singletonName, terminationMessage, role, + maxHandOverRetries, maxTakeOverRetries, retryInterval, loggingEnabled) + + /** + * Java API: Factory method for `ClusterSingletonManager` [[akka.actor.Props]]. + */ + def props( + singletonName: String, + terminationMessage: Any, + role: String, + maxHandOverRetries: Int, + maxTakeOverRetries: Int, + retryInterval: FiniteDuration, + loggingEnabled: Boolean, + singletonPropsFactory: ClusterSingletonPropsFactory): Props = + props(handOverData ⇒ singletonPropsFactory.create(handOverData.orNull), singletonName, terminationMessage, + ClusterSingletonManager.Internal.roleOption(role), maxHandOverRetries, maxTakeOverRetries, retryInterval) + + /** + * Java API: Factory method for `ClusterSingletonManager` [[akka.actor.Props]] + * with default values. + */ + def defaultProps( + singletonName: String, + terminationMessage: Any, + role: String, + singletonPropsFactory: ClusterSingletonPropsFactory): Props = + props(handOverData ⇒ singletonPropsFactory.create(handOverData.orNull), singletonName, terminationMessage, + ClusterSingletonManager.Internal.roleOption(role)) + /** * INTERNAL API * public due to the `with FSM` type parameters @@ -237,6 +279,9 @@ class ClusterSingletonManagerIsStuck(message: String) extends AkkaException(mess * it is supposed to be running on. Alternatively the singleton actor may * broadcast its existence when it is started. * + * Use factory method [[ClusterSingletonManager#props] to create the + * [[akka.actor.Props]] for the actor. + * * ==Arguments== * * '''''singletonProps''''' Factory for [[akka.actor.Props]] of the @@ -294,42 +339,16 @@ class ClusterSingletonManager( singletonName: String, terminationMessage: Any, role: Option[String], - maxHandOverRetries: Int = 20, - maxTakeOverRetries: Int = 15, - retryInterval: FiniteDuration = 1.second, - loggingEnabled: Boolean = true) + maxHandOverRetries: Int, + maxTakeOverRetries: Int, + retryInterval: FiniteDuration, + loggingEnabled: Boolean) extends Actor with FSM[ClusterSingletonManager.State, ClusterSingletonManager.Data] { // to ensure that new leader doesn't start singleton actor before previous is stopped for certain corner cases require(maxTakeOverRetries < maxHandOverRetries, s"maxTakeOverRetries [${maxTakeOverRetries}]must be < maxHandOverRetries [${maxHandOverRetries}]") - /** - * Full Java API constructor. - */ - def this( - singletonName: String, - terminationMessage: Any, - role: String, - maxHandOverRetries: Int, - maxTakeOverRetries: Int, - retryInterval: FiniteDuration, - loggingEnabled: Boolean, - singletonPropsFactory: ClusterSingletonPropsFactory) = - this(handOverData ⇒ singletonPropsFactory.create(handOverData.orNull), singletonName, terminationMessage, - ClusterSingletonManager.Internal.roleOption(role), maxHandOverRetries, maxTakeOverRetries, retryInterval) - - /** - * Java API constructor with default values. - */ - def this( - singletonName: String, - terminationMessage: Any, - role: String, - singletonPropsFactory: ClusterSingletonPropsFactory) = - this(handOverData ⇒ singletonPropsFactory.create(handOverData.orNull), singletonName, terminationMessage, - ClusterSingletonManager.Internal.roleOption(role)) - import ClusterSingletonManager._ import ClusterSingletonManager.Internal._ import ClusterSingletonManager.Internal.LeaderChangedBuffer._ @@ -396,7 +415,8 @@ class ClusterSingletonManager( when(Start) { case Event(StartLeaderChangedBuffer, _) ⇒ - leaderChangedBuffer = context.actorOf(Props(new LeaderChangedBuffer(role)).withDispatcher(context.props.dispatcher)) + leaderChangedBuffer = context.actorOf(Props(classOf[LeaderChangedBuffer], role). + withDispatcher(context.props.dispatcher)) getNextLeaderChanged() stay diff --git a/akka-contrib/src/main/scala/akka/contrib/pattern/DistributedPubSubMediator.scala b/akka-contrib/src/main/scala/akka/contrib/pattern/DistributedPubSubMediator.scala index e8f9c16b4a..8559e9e2a6 100644 --- a/akka-contrib/src/main/scala/akka/contrib/pattern/DistributedPubSubMediator.scala +++ b/akka-contrib/src/main/scala/akka/contrib/pattern/DistributedPubSubMediator.scala @@ -27,6 +27,31 @@ import akka.cluster.Member import akka.cluster.MemberStatus object DistributedPubSubMediator { + + /** + * Scala API: Factory method for `DistributedPubSubMediator` [[akka.actor.Props]]. + */ + def props( + role: Option[String], + gossipInterval: FiniteDuration = 1.second, + removedTimeToLive: FiniteDuration = 2.minutes): Props = + Props(classOf[DistributedPubSubMediator], role, gossipInterval, removedTimeToLive) + + /** + * Java API: Factory method for `DistributedPubSubMediator` [[akka.actor.Props]]. + */ + def props( + role: String, + gossipInterval: FiniteDuration, + removedTimeToLive: FiniteDuration): Props = + props(Internal.roleOption(role), gossipInterval, removedTimeToLive) + + /** + * Java API: Factory method for `DistributedPubSubMediator` [[akka.actor.Props]] + * with default values. + */ + def defaultProps(role: String): Props = props(Internal.roleOption(role)) + @SerialVersionUID(1L) case class Put(ref: ActorRef) @SerialVersionUID(1L) @@ -176,15 +201,10 @@ object DistributedPubSubMediator { */ class DistributedPubSubMediator( role: Option[String], - gossipInterval: FiniteDuration = 1.second, - removedTimeToLive: FiniteDuration = 2.minutes) + gossipInterval: FiniteDuration, + removedTimeToLive: FiniteDuration) extends Actor with ActorLogging { - /** - * Java API constructor with default values. - */ - def this(role: String) = this(DistributedPubSubMediator.Internal.roleOption(role)) - import DistributedPubSubMediator._ import DistributedPubSubMediator.Internal._ @@ -275,7 +295,7 @@ class DistributedPubSubMediator( context.child(encTopic) match { case Some(t) ⇒ t forward msg case None ⇒ - val t = context.actorOf(Props(new Topic(removedTimeToLive)), name = encTopic) + val t = context.actorOf(Props(classOf[Topic], removedTimeToLive), name = encTopic) t forward msg put(mkKey(t), Some(t)) context.watch(t) @@ -448,7 +468,7 @@ class DistributedPubSubExtension(system: ExtendedActorSystem) extends Extension val gossipInterval = Duration(config.getMilliseconds("gossip-interval"), MILLISECONDS) val removedTimeToLive = Duration(config.getMilliseconds("removed-time-to-live"), MILLISECONDS) val name = config.getString("name") - system.actorOf(Props(new DistributedPubSubMediator(role, gossipInterval, removedTimeToLive)), + system.actorOf(DistributedPubSubMediator.props(role, gossipInterval, removedTimeToLive), name) } } diff --git a/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/ClusterClientSpec.scala b/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/ClusterClientSpec.scala index ba0c8c6224..11fb75a9e6 100644 --- a/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/ClusterClientSpec.scala +++ b/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/ClusterClientSpec.scala @@ -95,7 +95,7 @@ class ClusterClientSpec extends MultiNodeSpec(ClusterClientSpec) with STMultiNod join(third, first) join(fourth, first) runOn(fourth) { - val service = system.actorOf(Props(new TestService(testActor)), "testService") + val service = system.actorOf(Props(classOf[TestService], testActor), "testService") mediator ! Put(service) } runOn(first, second, third, fourth) { @@ -107,7 +107,7 @@ class ClusterClientSpec extends MultiNodeSpec(ClusterClientSpec) with STMultiNod "communicate to actor on any node in cluster" in within(10 seconds) { runOn(client) { - val c = system.actorOf(Props(new ClusterClient(initialContacts))) + val c = system.actorOf(ClusterClient.props(initialContacts)) awaitAssert { c ! Send("/user/testService", "hello", localAffinity = true) @@ -142,7 +142,7 @@ class ClusterClientSpec extends MultiNodeSpec(ClusterClientSpec) with STMultiNod //#client runOn(client) { - val c = system.actorOf(Props(new ClusterClient(initialContacts))) + val c = system.actorOf(ClusterClient.props(initialContacts)) c ! DistributedPubSubMediator.Send("/user/serviceA", "hello", localAffinity = true) c ! DistributedPubSubMediator.SendToAll("/user/serviceB", "hi") } @@ -163,14 +163,14 @@ class ClusterClientSpec extends MultiNodeSpec(ClusterClientSpec) with STMultiNod "re-establish connection to receptionist when connection is lost" in within(30 seconds) { runOn(first, second, third, fourth) { - val service2 = system.actorOf(Props(new TestService(testActor)), "service2") + val service2 = system.actorOf(Props(classOf[TestService], testActor), "service2") mediator ! Put(service2) awaitCount(8) } enterBarrier("service2-replicated") runOn(client) { - val c = system.actorOf(Props(new ClusterClient(initialContacts))) + val c = system.actorOf(ClusterClient.props(initialContacts)) awaitAssert { c ! Send("/user/service2", "bonjour", localAffinity = true) diff --git a/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/ClusterSingletonManagerChaosSpec.scala b/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/ClusterSingletonManagerChaosSpec.scala index 5b4784f407..9b745e60c4 100644 --- a/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/ClusterSingletonManagerChaosSpec.scala +++ b/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/ClusterSingletonManagerChaosSpec.scala @@ -88,11 +88,11 @@ class ClusterSingletonManagerChaosSpec extends MultiNodeSpec(ClusterSingletonMan } def createSingleton(): ActorRef = { - system.actorOf(Props(new ClusterSingletonManager( - singletonProps = handOverData ⇒ Props(new Echo(testActor)), + system.actorOf(ClusterSingletonManager.props( + singletonProps = handOverData ⇒ Props(classOf[Echo], testActor), singletonName = "echo", terminationMessage = PoisonPill, - role = None)), + role = None), name = "singleton") } diff --git a/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/ClusterSingletonManagerSpec.scala b/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/ClusterSingletonManagerSpec.scala index fc4d7d9bfc..cc56bd410b 100644 --- a/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/ClusterSingletonManagerSpec.scala +++ b/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/ClusterSingletonManagerSpec.scala @@ -239,12 +239,12 @@ class ClusterSingletonManagerSpec extends MultiNodeSpec(ClusterSingletonManagerS def createSingleton(): ActorRef = { //#create-singleton-manager - system.actorOf(Props(new ClusterSingletonManager( + system.actorOf(ClusterSingletonManager.props( singletonProps = handOverData ⇒ - Props(new Consumer(handOverData, queue, testActor)), + Props(classOf[Consumer], handOverData, queue, testActor), singletonName = "consumer", terminationMessage = End, - role = Some("worker"))), + role = Some("worker")), name = "singleton") //#create-singleton-manager } diff --git a/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/DistributedPubSubMediatorSpec.scala b/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/DistributedPubSubMediatorSpec.scala index a3dc568d8a..70c241e059 100644 --- a/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/DistributedPubSubMediatorSpec.scala +++ b/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/DistributedPubSubMediatorSpec.scala @@ -110,7 +110,7 @@ class DistributedPubSubMediatorSpec extends MultiNodeSpec(DistributedPubSubMedia var chatUsers: Map[String, ActorRef] = Map.empty def createChatUser(name: String): ActorRef = { - var a = system.actorOf(Props(new TestChatUser(mediator, testActor)), name) + var a = system.actorOf(Props(classOf[TestChatUser], mediator, testActor), name) chatUsers += (name -> a) a } diff --git a/akka-contrib/src/test/java/akka/contrib/pattern/DistributedPubSubMediatorTest.java b/akka-contrib/src/test/java/akka/contrib/pattern/DistributedPubSubMediatorTest.java index 2b6f0a0943..ea2d7b77f9 100644 --- a/akka-contrib/src/test/java/akka/contrib/pattern/DistributedPubSubMediatorTest.java +++ b/akka-contrib/src/test/java/akka/contrib/pattern/DistributedPubSubMediatorTest.java @@ -32,15 +32,15 @@ public class DistributedPubSubMediatorTest { @Test public void demonstrateUsage() { //#start-subscribers - system.actorOf(new Props(Subscriber.class), "subscriber1"); + system.actorOf(Props.create(Subscriber.class), "subscriber1"); //another node - system.actorOf(new Props(Subscriber.class), "subscriber2"); - system.actorOf(new Props(Subscriber.class), "subscriber3"); + system.actorOf(Props.create(Subscriber.class), "subscriber2"); + system.actorOf(Props.create(Subscriber.class), "subscriber3"); //#start-subscribers //#publish-message //somewhere else - ActorRef publisher = system.actorOf(new Props(Publisher.class), "publisher"); + ActorRef publisher = system.actorOf(Props.create(Publisher.class), "publisher"); // after a while the subscriptions are replicated publisher.tell("hello", null); //#publish-message @@ -51,11 +51,9 @@ public class DistributedPubSubMediatorTest { LoggingAdapter log = Logging.getLogger(getContext().system(), this); public Subscriber() { - ActorRef mediator = - DistributedPubSubExtension.get(getContext().system()).mediator(); + ActorRef mediator = DistributedPubSubExtension.get(getContext().system()).mediator(); // subscribe to the topic named "content" - mediator.tell(new DistributedPubSubMediator.Subscribe("content", getSelf()), - getSelf()); + mediator.tell(new DistributedPubSubMediator.Subscribe("content", getSelf()), getSelf()); } public void onReceive(Object msg) { @@ -74,15 +72,13 @@ public class DistributedPubSubMediatorTest { public class Publisher extends UntypedActor { // activate the extension - ActorRef mediator = - DistributedPubSubExtension.get(getContext().system()).mediator(); + ActorRef mediator = DistributedPubSubExtension.get(getContext().system()).mediator(); public void onReceive(Object msg) { if (msg instanceof String) { String in = (String) msg; String out = in.toUpperCase(); - mediator.tell(new DistributedPubSubMediator.Publish("content", out), - getSelf()); + mediator.tell(new DistributedPubSubMediator.Publish("content", out), getSelf()); } else { unhandled(msg); } diff --git a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/factorial/japi/FactorialBackendMain.java b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/factorial/japi/FactorialBackendMain.java index 7041fd9428..73351f2317 100644 --- a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/factorial/japi/FactorialBackendMain.java +++ b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/factorial/japi/FactorialBackendMain.java @@ -18,9 +18,9 @@ public class FactorialBackendMain { ActorSystem system = ActorSystem.create("ClusterSystem", config); - system.actorOf(new Props(FactorialBackend.class), "factorialBackend"); + system.actorOf(Props.create(FactorialBackend.class), "factorialBackend"); - system.actorOf(new Props(MetricsListener.class), "metricsListener"); + system.actorOf(Props.create(MetricsListener.class), "metricsListener"); } diff --git a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/factorial/japi/FactorialFrontend.java b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/factorial/japi/FactorialFrontend.java index 0ee5fc0624..1dbe3592b6 100644 --- a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/factorial/japi/FactorialFrontend.java +++ b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/factorial/japi/FactorialFrontend.java @@ -20,7 +20,7 @@ public class FactorialFrontend extends UntypedActor { LoggingAdapter log = Logging.getLogger(getContext().system(), this); ActorRef backend = getContext().actorOf( - new Props(FactorialBackend.class).withRouter(FromConfig.getInstance()), + Props.create(FactorialBackend.class).withRouter(FromConfig.getInstance()), "factorialBackendRouter"); public FactorialFrontend(int upToN, boolean repeat) { @@ -66,7 +66,7 @@ abstract class FactorialFrontend2 extends UntypedActor { boolean allowLocalRoutees = true; String useRole = "backend"; ActorRef backend = getContext().actorOf( - new Props(FactorialBackend.class).withRouter(new ClusterRouterConfig( + Props.create(FactorialBackend.class).withRouter(new ClusterRouterConfig( new AdaptiveLoadBalancingRouter(HeapMetricsSelector.getInstance(), 0), new ClusterRouterSettings( totalInstances, routeesPath, allowLocalRoutees, useRole))), @@ -82,7 +82,7 @@ abstract class FactorialFrontend3 extends UntypedActor { boolean allowLocalRoutees = false; String useRole = "backend"; ActorRef backend = getContext().actorOf( - new Props(FactorialBackend.class).withRouter(new ClusterRouterConfig( + Props.create(FactorialBackend.class).withRouter(new ClusterRouterConfig( new AdaptiveLoadBalancingRouter( SystemLoadAverageMetricsSelector.getInstance(), 0), new ClusterRouterSettings( diff --git a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/factorial/japi/FactorialFrontendMain.java b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/factorial/japi/FactorialFrontendMain.java index c92c2a3eff..3cd6271aa7 100644 --- a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/factorial/japi/FactorialFrontendMain.java +++ b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/factorial/japi/FactorialFrontendMain.java @@ -4,8 +4,6 @@ import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; import akka.actor.ActorSystem; import akka.actor.Props; -import akka.actor.UntypedActor; -import akka.actor.UntypedActorFactory; import akka.cluster.Cluster; public class FactorialFrontendMain { @@ -22,12 +20,7 @@ public class FactorialFrontendMain { Cluster.get(system).registerOnMemberUp(new Runnable() { @Override public void run() { - system.actorOf(new Props(new UntypedActorFactory() { - @Override - public UntypedActor create() { - return new FactorialFrontend(upToN, true); - } - }), "factorialFrontend"); + system.actorOf(Props.create(FactorialFrontend.class, upToN, true), "factorialFrontend"); } }); //#registerOnUp diff --git a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/simple/japi/SimpleClusterApp.java b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/simple/japi/SimpleClusterApp.java index 96d467b2b2..7aebbdd510 100644 --- a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/simple/japi/SimpleClusterApp.java +++ b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/simple/japi/SimpleClusterApp.java @@ -18,7 +18,7 @@ public class SimpleClusterApp { ActorSystem system = ActorSystem.create("ClusterSystem"); // Create an actor that handles cluster domain events - ActorRef clusterListener = system.actorOf(new Props( + ActorRef clusterListener = system.actorOf(Props.create( SimpleClusterListener.class), "clusterListener"); // Add subscription of cluster events diff --git a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/simple/japi/SimpleClusterListener.java b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/simple/japi/SimpleClusterListener.java index b0ec99b2fa..c5dc955303 100644 --- a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/simple/japi/SimpleClusterListener.java +++ b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/simple/japi/SimpleClusterListener.java @@ -4,6 +4,7 @@ import akka.actor.UntypedActor; import akka.cluster.ClusterEvent.ClusterDomainEvent; import akka.cluster.ClusterEvent.CurrentClusterState; import akka.cluster.ClusterEvent.MemberUp; +import akka.cluster.ClusterEvent.MemberRemoved; import akka.cluster.ClusterEvent.UnreachableMember; import akka.event.Logging; import akka.event.LoggingAdapter; @@ -25,6 +26,10 @@ public class SimpleClusterListener extends UntypedActor { UnreachableMember mUnreachable = (UnreachableMember) message; log.info("Member detected as unreachable: {}", mUnreachable.member()); + } else if (message instanceof MemberRemoved) { + MemberRemoved mRemoved = (MemberRemoved) message; + log.info("Member is Removed: {}", mRemoved.member()); + } else if (message instanceof ClusterDomainEvent) { // ignore diff --git a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsSampleClientMain.java b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsSampleClientMain.java index 7ce373231b..55152d034f 100644 --- a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsSampleClientMain.java +++ b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsSampleClientMain.java @@ -2,20 +2,12 @@ package sample.cluster.stats.japi; import akka.actor.ActorSystem; import akka.actor.Props; -import akka.actor.UntypedActor; -import akka.actor.UntypedActorFactory; public class StatsSampleClientMain { public static void main(String[] args) throws Exception { // note that client is not a compute node, role not defined ActorSystem system = ActorSystem.create("ClusterSystem"); - system.actorOf(new Props(new UntypedActorFactory() { - @Override - public UntypedActor create() { - return new StatsSampleClient("/user/statsService"); - } - }), "client"); - + system.actorOf(Props.create(StatsSampleClient.class, "/user/statsService"), "client"); } } diff --git a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsSampleMain.java b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsSampleMain.java index e8c808f8c4..7a9d6cca16 100644 --- a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsSampleMain.java +++ b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsSampleMain.java @@ -18,8 +18,8 @@ public class StatsSampleMain { ActorSystem system = ActorSystem.create("ClusterSystem", config); - system.actorOf(new Props(StatsWorker.class), "statsWorker"); - system.actorOf(new Props(StatsService.class), "statsService"); + system.actorOf(Props.create(StatsWorker.class), "statsWorker"); + system.actorOf(Props.create(StatsService.class), "statsService"); } } diff --git a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsSampleOneMasterClientMain.java b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsSampleOneMasterClientMain.java index 942ff37d62..96d8924ca9 100644 --- a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsSampleOneMasterClientMain.java +++ b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsSampleOneMasterClientMain.java @@ -1,24 +1,15 @@ package sample.cluster.stats.japi; import akka.actor.ActorSystem; -import akka.actor.PoisonPill; import akka.actor.Props; -import akka.actor.UntypedActor; -import akka.actor.UntypedActorFactory; -import akka.contrib.pattern.ClusterSingletonManager; -import akka.contrib.pattern.ClusterSingletonPropsFactory; public class StatsSampleOneMasterClientMain { public static void main(String[] args) throws Exception { // note that client is not a compute node, role not defined ActorSystem system = ActorSystem.create("ClusterSystem"); - system.actorOf(new Props(new UntypedActorFactory() { - @Override - public UntypedActor create() { - return new StatsSampleClient("/user/statsFacade"); - } - }), "client"); + system.actorOf(Props.create(StatsSampleClient.class, "/user/statsFacade"), + "client"); } diff --git a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsSampleOneMasterMain.java b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsSampleOneMasterMain.java index be4e8789a6..0f150951c5 100644 --- a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsSampleOneMasterMain.java +++ b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsSampleOneMasterMain.java @@ -5,7 +5,6 @@ import com.typesafe.config.ConfigFactory; import akka.actor.ActorSystem; import akka.actor.PoisonPill; import akka.actor.Props; -import akka.actor.UntypedActorFactory; import akka.contrib.pattern.ClusterSingletonManager; import akka.contrib.pattern.ClusterSingletonPropsFactory; @@ -23,22 +22,17 @@ public class StatsSampleOneMasterMain { ActorSystem system = ActorSystem.create("ClusterSystem", config); //#create-singleton-manager - system.actorOf(new Props(new UntypedActorFactory() { - @Override - public ClusterSingletonManager create() { - return new ClusterSingletonManager("statsService", PoisonPill.getInstance(), - "compute", - new ClusterSingletonPropsFactory() { - @Override - public Props create(Object handOverData) { - return new Props(StatsService.class); - } - }); - } - }), "singleton"); + system.actorOf(ClusterSingletonManager.defaultProps( + "statsService", PoisonPill.getInstance(), "compute", + new ClusterSingletonPropsFactory() { + @Override + public Props create(Object handOverData) { + return Props.create(StatsService.class); + } + }), "singleton"); //#create-singleton-manager - system.actorOf(new Props(StatsFacade.class), "statsFacade"); + system.actorOf(Props.create(StatsFacade.class), "statsFacade"); } } diff --git a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsService.java b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsService.java index 81342c7d13..967fa91693 100644 --- a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsService.java +++ b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/stats/japi/StatsService.java @@ -5,7 +5,6 @@ import sample.cluster.stats.japi.StatsMessages.StatsJob; import akka.actor.ActorRef; import akka.actor.Props; import akka.actor.UntypedActor; -import akka.actor.UntypedActorFactory; import akka.cluster.routing.ClusterRouterConfig; import akka.cluster.routing.ClusterRouterSettings; import akka.routing.ConsistentHashingRouter; @@ -17,7 +16,7 @@ import akka.routing.FromConfig; public class StatsService extends UntypedActor { ActorRef workerRouter = getContext().actorOf( - new Props(StatsWorker.class).withRouter(FromConfig.getInstance()), + Props.create(StatsWorker.class).withRouter(FromConfig.getInstance()), "workerRouter"); @Override @@ -32,12 +31,7 @@ public class StatsService extends UntypedActor { // create actor that collects replies from workers ActorRef aggregator = getContext().actorOf( - new Props(new UntypedActorFactory() { - @Override - public UntypedActor create() { - return new StatsAggregator(words.length, replyTo); - } - })); + Props.create(StatsAggregator.class, words.length, replyTo)); // send each word to a worker for (String word : words) { @@ -62,7 +56,7 @@ abstract class StatsService2 extends UntypedActor { boolean allowLocalRoutees = true; String useRole = "compute"; ActorRef workerRouter = getContext().actorOf( - new Props(StatsWorker.class).withRouter(new ClusterRouterConfig( + Props.create(StatsWorker.class).withRouter(new ClusterRouterConfig( new ConsistentHashingRouter(0), new ClusterRouterSettings( totalInstances, routeesPath, allowLocalRoutees, useRole))), "workerRouter2"); @@ -77,7 +71,7 @@ abstract class StatsService3 extends UntypedActor { boolean allowLocalRoutees = false; String useRole = "compute"; ActorRef workerRouter = getContext().actorOf( - new Props(StatsWorker.class).withRouter(new ClusterRouterConfig( + Props.create(StatsWorker.class).withRouter(new ClusterRouterConfig( new ConsistentHashingRouter(0), new ClusterRouterSettings( totalInstances, maxInstancesPerNode, allowLocalRoutees, useRole))), "workerRouter3"); diff --git a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/transformation/japi/TransformationBackendMain.java b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/transformation/japi/TransformationBackendMain.java index dea1cff39d..804469e77b 100644 --- a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/transformation/japi/TransformationBackendMain.java +++ b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/transformation/japi/TransformationBackendMain.java @@ -13,7 +13,7 @@ public class TransformationBackendMain { ActorSystem system = ActorSystem.create("ClusterSystem"); - system.actorOf(new Props(TransformationBackend.class), "backend"); + system.actorOf(Props.create(TransformationBackend.class), "backend"); } diff --git a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/transformation/japi/TransformationFrontendMain.java b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/transformation/japi/TransformationFrontendMain.java index 6037d928a5..8a11f78600 100644 --- a/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/transformation/japi/TransformationFrontendMain.java +++ b/akka-samples/akka-sample-cluster/src/main/java/sample/cluster/transformation/japi/TransformationFrontendMain.java @@ -22,7 +22,7 @@ public class TransformationFrontendMain { ActorSystem system = ActorSystem.create("ClusterSystem"); - ActorRef frontend = system.actorOf(new Props( + ActorRef frontend = system.actorOf(Props.create( TransformationFrontend.class), "frontend"); Timeout timeout = new Timeout(Duration.create(5, TimeUnit.SECONDS)); final ExecutionContext ec = system.dispatcher(); diff --git a/akka-samples/akka-sample-cluster/src/main/scala/sample/cluster/factorial/FactorialSample.scala b/akka-samples/akka-sample-cluster/src/main/scala/sample/cluster/factorial/FactorialSample.scala index cc6c58fcfe..636831ff3b 100644 --- a/akka-samples/akka-sample-cluster/src/main/scala/sample/cluster/factorial/FactorialSample.scala +++ b/akka-samples/akka-sample-cluster/src/main/scala/sample/cluster/factorial/FactorialSample.scala @@ -29,7 +29,7 @@ object FactorialFrontend { system.log.info("Factorials will start when 2 backend members in the cluster.") //#registerOnUp Cluster(system) registerOnMemberUp { - system.actorOf(Props(new FactorialFrontend(upToN, repeat = true)), + system.actorOf(Props(classOf[FactorialFrontend], upToN, true), name = "factorialFrontend") } //#registerOnUp diff --git a/akka-samples/akka-sample-cluster/src/main/scala/sample/cluster/simple/SimpleClusterApp.scala b/akka-samples/akka-sample-cluster/src/main/scala/sample/cluster/simple/SimpleClusterApp.scala index 38290f2176..a6e905b00c 100644 --- a/akka-samples/akka-sample-cluster/src/main/scala/sample/cluster/simple/SimpleClusterApp.scala +++ b/akka-samples/akka-sample-cluster/src/main/scala/sample/cluster/simple/SimpleClusterApp.scala @@ -5,7 +5,6 @@ import akka.cluster.Cluster import akka.cluster.ClusterEvent._ object SimpleClusterApp { - def main(args: Array[String]): Unit = { // Override the configuration of the port @@ -14,20 +13,23 @@ object SimpleClusterApp { // Create an Akka system val system = ActorSystem("ClusterSystem") - val clusterListener = system.actorOf(Props(new Actor with ActorLogging { - def receive = { - case state: CurrentClusterState ⇒ - log.info("Current members: {}", state.members) - case MemberUp(member) ⇒ - log.info("Member is Up: {}", member) - case UnreachableMember(member) ⇒ - log.info("Member detected as unreachable: {}", member) - case _: ClusterDomainEvent ⇒ // ignore - - } - }), name = "clusterListener") + val clusterListener = system.actorOf(Props[SimpleClusterListener], + name = "clusterListener") Cluster(system).subscribe(clusterListener, classOf[ClusterDomainEvent]) } +} +class SimpleClusterListener extends Actor with ActorLogging { + def receive = { + case state: CurrentClusterState ⇒ + log.info("Current members: {}", state.members) + case MemberUp(member) ⇒ + log.info("Member is Up: {}", member) + case UnreachableMember(member) ⇒ + log.info("Member detected as unreachable: {}", member) + case MemberRemoved(member) ⇒ + log.info("Member is Removed: {}", member) + case _: ClusterDomainEvent ⇒ // ignore + } } \ No newline at end of file diff --git a/akka-samples/akka-sample-cluster/src/main/scala/sample/cluster/stats/StatsSample.scala b/akka-samples/akka-sample-cluster/src/main/scala/sample/cluster/stats/StatsSample.scala index 9854c3d4fd..a248b0a4c2 100644 --- a/akka-samples/akka-sample-cluster/src/main/scala/sample/cluster/stats/StatsSample.scala +++ b/akka-samples/akka-sample-cluster/src/main/scala/sample/cluster/stats/StatsSample.scala @@ -41,7 +41,7 @@ class StatsService extends Actor { val replyTo = sender // important to not close over sender // create actor that collects replies from workers val aggregator = context.actorOf(Props( - new StatsAggregator(words.size, replyTo))) + classOf[StatsAggregator], words.size, replyTo)) words foreach { word ⇒ workerRouter.tell( ConsistentHashableEnvelope(word, word), aggregator) @@ -146,9 +146,9 @@ object StatsSampleOneMaster { val system = ActorSystem("ClusterSystem", config) //#create-singleton-manager - system.actorOf(Props(new ClusterSingletonManager( + system.actorOf(ClusterSingletonManager.props( singletonProps = _ ⇒ Props[StatsService], singletonName = "statsService", - terminationMessage = PoisonPill, role = Some("compute"))), + terminationMessage = PoisonPill, role = Some("compute")), name = "singleton") //#create-singleton-manager system.actorOf(Props[StatsFacade], name = "statsFacade") @@ -159,7 +159,7 @@ object StatsSampleClient { def main(args: Array[String]): Unit = { // note that client is not a compute node, role not defined val system = ActorSystem("ClusterSystem") - system.actorOf(Props(new StatsSampleClient("/user/statsService")), "client") + system.actorOf(Props(classOf[StatsSampleClient], "/user/statsService"), "client") } } @@ -167,7 +167,7 @@ object StatsSampleOneMasterClient { def main(args: Array[String]): Unit = { // note that client is not a compute node, role not defined val system = ActorSystem("ClusterSystem") - system.actorOf(Props(new StatsSampleClient("/user/statsFacade")), "client") + system.actorOf(Props(classOf[StatsSampleClient], "/user/statsFacade"), "client") } } diff --git a/akka-samples/akka-sample-cluster/src/multi-jvm/scala/sample/cluster/stats/StatsSampleSingleMasterSpec.scala b/akka-samples/akka-sample-cluster/src/multi-jvm/scala/sample/cluster/stats/StatsSampleSingleMasterSpec.scala index 84751684cf..093992c24a 100644 --- a/akka-samples/akka-sample-cluster/src/multi-jvm/scala/sample/cluster/stats/StatsSampleSingleMasterSpec.scala +++ b/akka-samples/akka-sample-cluster/src/multi-jvm/scala/sample/cluster/stats/StatsSampleSingleMasterSpec.scala @@ -85,9 +85,9 @@ abstract class StatsSampleSingleMasterSpec extends MultiNodeSpec(StatsSampleSing Cluster(system).unsubscribe(testActor) - system.actorOf(Props(new ClusterSingletonManager( + system.actorOf(ClusterSingletonManager.props( singletonProps = _ ⇒ Props[StatsService], singletonName = "statsService", - terminationMessage = PoisonPill, role = Some("compute"))), name = "singleton") + terminationMessage = PoisonPill, role = Some("compute")), name = "singleton") system.actorOf(Props[StatsFacade], "statsFacade") diff --git a/akka-samples/akka-sample-cluster/src/multi-jvm/scala/sample/cluster/stats/japi/StatsSampleSingleMasterJapiSpec.scala b/akka-samples/akka-sample-cluster/src/multi-jvm/scala/sample/cluster/stats/japi/StatsSampleSingleMasterJapiSpec.scala index 9860b443db..40e524b343 100644 --- a/akka-samples/akka-sample-cluster/src/multi-jvm/scala/sample/cluster/stats/japi/StatsSampleSingleMasterJapiSpec.scala +++ b/akka-samples/akka-sample-cluster/src/multi-jvm/scala/sample/cluster/stats/japi/StatsSampleSingleMasterJapiSpec.scala @@ -85,13 +85,13 @@ abstract class StatsSampleSingleMasterJapiSpec extends MultiNodeSpec(StatsSample Cluster(system).unsubscribe(testActor) - system.actorOf(Props(new ClusterSingletonManager( + system.actorOf(ClusterSingletonManager.defaultProps( singletonName = "statsService", terminationMessage = PoisonPill, role = null, singletonPropsFactory = new ClusterSingletonPropsFactory { def create(handOverData: Any) = Props[StatsService] - })), name = "singleton") + }), name = "singleton") system.actorOf(Props[StatsFacade], "statsFacade")