From 4e1100f84de5ec681d40cc1b4a99f0616cbb7da7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bjo=CC=88rn=20Antonsson?= Date: Mon, 14 Oct 2013 13:12:17 +0200 Subject: [PATCH] =doc #3639 Show complete custom mailbox example. --- .../docs/dispatcher/DispatcherDocTest.java | 83 ++++++++----------- .../docs/dispatcher/MyUnboundedJMailbox.java | 51 ++++++++++++ .../MyUnboundedJMessageQueueSemantics.java | 11 +++ akka-docs/rst/java/mailboxes.rst | 14 +++- .../docs/dispatcher/DispatcherDocSpec.scala | 72 +++++++++++----- .../docs/dispatcher/MyUnboundedMailbox.scala | 59 +++++++++++++ akka-docs/rst/scala/mailboxes.rst | 11 ++- .../testkit/AkkaJUnitActorSystemResource.java | 14 +++- 8 files changed, 237 insertions(+), 78 deletions(-) create mode 100644 akka-docs/rst/java/code/docs/dispatcher/MyUnboundedJMailbox.java create mode 100644 akka-docs/rst/java/code/docs/dispatcher/MyUnboundedJMessageQueueSemantics.java create mode 100644 akka-docs/rst/scala/code/docs/dispatcher/MyUnboundedMailbox.scala diff --git a/akka-docs/rst/java/code/docs/dispatcher/DispatcherDocTest.java b/akka-docs/rst/java/code/docs/dispatcher/DispatcherDocTest.java index 8733f07efa..70b8af2964 100644 --- a/akka-docs/rst/java/code/docs/dispatcher/DispatcherDocTest.java +++ b/akka-docs/rst/java/code/docs/dispatcher/DispatcherDocTest.java @@ -3,6 +3,15 @@ */ package docs.dispatcher; +import akka.dispatch.RequiresMessageQueue; +import akka.testkit.AkkaSpec; +import com.typesafe.config.ConfigFactory; +import docs.actor.MyBoundedUntypedActor; +import docs.actor.MyUntypedActor; +import org.junit.ClassRule; +import org.junit.Test; +import scala.concurrent.ExecutionContext; + //#imports import akka.actor.*; //#imports @@ -18,35 +27,14 @@ import akka.dispatch.PriorityGenerator; import akka.dispatch.UnboundedPriorityMailbox; import akka.testkit.AkkaJUnitActorSystemResource; import akka.testkit.JavaTestKit; -import akka.testkit.TestKit; import com.typesafe.config.Config; //#imports-prio-mailbox -//#imports-custom -import akka.dispatch.Envelope; -import akka.dispatch.MessageQueue; -import akka.dispatch.MailboxType; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; - -//#imports-custom - //#imports-required-mailbox //#imports-required-mailbox -import docs.actor.MyBoundedUntypedActor; -import org.junit.ClassRule; -import org.junit.Test; -import scala.Option; -import scala.concurrent.ExecutionContext; - -import com.typesafe.config.ConfigFactory; - -import docs.actor.MyUntypedActor; -import akka.testkit.AkkaSpec; - public class DispatcherDocTest { @ClassRule @@ -185,34 +173,29 @@ public class DispatcherDocTest { } //#prio-mailbox - static - //#mailbox-implementation-example - public class MyUnboundedMailbox implements MailboxType { - - // This constructor signature must exist, it will be called by Akka - public MyUnboundedMailbox(ActorSystem.Settings settings, Config config) { - // put your initialization code here - } - - // The create method is called to create the MessageQueue - public MessageQueue create(Option owner, Option system) { - return new MessageQueue() { - private final Queue queue = new ConcurrentLinkedQueue(); - - // these must be implemented; queue used as example - public void enqueue(ActorRef receiver, Envelope handle) { - queue.offer(handle); - } - public Envelope dequeue() { return queue.poll(); } - public int numberOfMessages() { return queue.size(); } - public boolean hasMessages() { return !queue.isEmpty(); } - public void cleanUp(ActorRef owner, MessageQueue deadLetters) { - for (Envelope handle: queue) { - deadLetters.enqueue(owner, handle); - } - } - }; - } + @Test + public void requiredMailboxDispatcher() throws Exception { + ActorRef myActor = system.actorOf(Props.create(MyUntypedActor.class) + .withDispatcher("custom-dispatcher")); } - //#mailbox-implementation-example + + static + //#require-mailbox-on-actor + public class MySpecialActor extends UntypedActor implements + RequiresMessageQueue { + //#require-mailbox-on-actor + @Override + public void onReceive(Object message) throws Exception { + unhandled(message); + } + //#require-mailbox-on-actor + // ... + } + //#require-mailbox-on-actor + + @Test + public void requiredMailboxActor() throws Exception { + ActorRef myActor = system.actorOf(Props.create(MySpecialActor.class)); + } + } diff --git a/akka-docs/rst/java/code/docs/dispatcher/MyUnboundedJMailbox.java b/akka-docs/rst/java/code/docs/dispatcher/MyUnboundedJMailbox.java new file mode 100644 index 0000000000..54793fbdf2 --- /dev/null +++ b/akka-docs/rst/java/code/docs/dispatcher/MyUnboundedJMailbox.java @@ -0,0 +1,51 @@ +/** + * Copyright (C) 2009-2013 Typesafe Inc. + */ +package docs.dispatcher; + +//#mailbox-implementation-example +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.dispatch.Envelope; +import akka.dispatch.MailboxType; +import akka.dispatch.MessageQueue; +import akka.dispatch.ProducesMessageQueue; +import com.typesafe.config.Config; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.Queue; +import scala.Option; + +public class MyUnboundedJMailbox implements MailboxType, + ProducesMessageQueue { + + // This is the MessageQueue implementation + public static class MyMessageQueue implements MessageQueue, + MyUnboundedJMessageQueueSemantics { + private final Queue queue = + new ConcurrentLinkedQueue(); + + // these must be implemented; queue used as example + public void enqueue(ActorRef receiver, Envelope handle) { + queue.offer(handle); + } + public Envelope dequeue() { return queue.poll(); } + public int numberOfMessages() { return queue.size(); } + public boolean hasMessages() { return !queue.isEmpty(); } + public void cleanUp(ActorRef owner, MessageQueue deadLetters) { + for (Envelope handle: queue) { + deadLetters.enqueue(owner, handle); + } + } + } + + // This constructor signature must exist, it will be called by Akka + public MyUnboundedJMailbox(ActorSystem.Settings settings, Config config) { + // put your initialization code here + } + + // The create method is called to create the MessageQueue + public MessageQueue create(Option owner, Option system) { + return new MyMessageQueue(); + } +} +//#mailbox-implementation-example diff --git a/akka-docs/rst/java/code/docs/dispatcher/MyUnboundedJMessageQueueSemantics.java b/akka-docs/rst/java/code/docs/dispatcher/MyUnboundedJMessageQueueSemantics.java new file mode 100644 index 0000000000..fac322b864 --- /dev/null +++ b/akka-docs/rst/java/code/docs/dispatcher/MyUnboundedJMessageQueueSemantics.java @@ -0,0 +1,11 @@ +/** + * Copyright (C) 2009-2013 Typesafe Inc. + */ + +package docs.dispatcher; + +//#mailbox-implementation-example +// Marker interface used for mailbox requirements mapping +public interface MyUnboundedJMessageQueueSemantics { +} +//#mailbox-implementation-example diff --git a/akka-docs/rst/java/mailboxes.rst b/akka-docs/rst/java/mailboxes.rst index ea145b1f72..cb972ed011 100644 --- a/akka-docs/rst/java/mailboxes.rst +++ b/akka-docs/rst/java/mailboxes.rst @@ -197,9 +197,9 @@ Creating your own Mailbox type An example is worth a thousand quacks: -.. includecode:: code/docs/dispatcher/DispatcherDocTest.java#imports-custom +.. includecode:: code/docs/dispatcher/MyUnboundedJMailbox.java#mailbox-implementation-example -.. includecode:: code/docs/dispatcher/DispatcherDocTest.java#mailbox-implementation-example +.. includecode:: code/docs/dispatcher/MyUnboundedJMessageQueueSemantics.java#mailbox-implementation-example And then you just specify the FQCN of your MailboxType as the value of the "mailbox-type" in the dispatcher configuration, or the mailbox configuration. @@ -214,6 +214,16 @@ configuration, or the mailbox configuration. this mailbox type; the mailbox type will be instantiated once for each dispatcher or mailbox setting using it. +You can also use the mailbox as a requirement on the dispatcher like this: + +.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#custom-mailbox-config-java + + +Or by defining the requirement on your actor class like this: + +.. includecode:: code/docs/dispatcher/DispatcherDocTest.java#require-mailbox-on-actor + + Special Semantics of ``system.actorOf`` ======================================= diff --git a/akka-docs/rst/scala/code/docs/dispatcher/DispatcherDocSpec.scala b/akka-docs/rst/scala/code/docs/dispatcher/DispatcherDocSpec.scala index f007722a7f..777ecfa2dc 100644 --- a/akka-docs/rst/scala/code/docs/dispatcher/DispatcherDocSpec.scala +++ b/akka-docs/rst/scala/code/docs/dispatcher/DispatcherDocSpec.scala @@ -13,6 +13,7 @@ import akka.event.LoggingAdapter import scala.concurrent.duration._ import akka.actor._ import docs.dispatcher.DispatcherDocSpec.MyBoundedActor +import akka.dispatch.RequiresMessageQueue object DispatcherDocSpec { val javaConfig = """ @@ -29,6 +30,22 @@ object DispatcherDocSpec { //Other mailbox configuration goes here } //#prio-mailbox-config-java + + //#custom-mailbox-config-java + custom-dispatcher { + mailbox-requirement = + "docs.dispatcher.MyUnboundedJMessageQueueSemantics" + } + + akka.actor.mailbox.requirements { + "docs.dispatcher.MyUnboundedJMessageQueueSemantics" = + custom-dispatcher-mailbox + } + + custom-dispatcher-mailbox { + mailbox-type = "docs.dispatcher.MyUnboundedJMailbox" + } + //#custom-mailbox-config-java """ val config = """ @@ -154,6 +171,21 @@ object DispatcherDocSpec { } //#required-mailbox-config + //#custom-mailbox-config + custom-dispatcher { + mailbox-requirement = + "docs.dispatcher.MyUnboundedMessageQueueSemantics" + } + + akka.actor.mailbox.requirements { + "docs.dispatcher.MyUnboundedMessageQueueSemantics" = + custom-dispatcher-mailbox + } + + custom-dispatcher-mailbox { + mailbox-type = "docs.dispatcher.MyUnboundedMailbox" + } + //#custom-mailbox-config """ //#prio-mailbox @@ -195,33 +227,22 @@ object DispatcherDocSpec { with RequiresMessageQueue[BoundedMessageQueueSemantics] //#required-mailbox-class - //#mailbox-implementation-example - class MyUnboundedMailbox extends akka.dispatch.MailboxType { - import akka.actor.{ ActorRef, ActorSystem } - import com.typesafe.config.Config - import java.util.concurrent.ConcurrentLinkedQueue - import akka.dispatch.{ - Envelope, - MessageQueue, - UnboundedQueueBasedMessageQueue + //#require-mailbox-on-actor + class MySpecialActor extends Actor + with RequiresMessageQueue[MyUnboundedMessageQueueSemantics] { + //#require-mailbox-on-actor + def receive = { + case _ ⇒ } - - // This constructor signature must exist, it will be called by Akka - def this(settings: ActorSystem.Settings, config: Config) = this() - - // The create method is called to create the MessageQueue - final override def create(owner: Option[ActorRef], - system: Option[ActorSystem]): MessageQueue = - new UnboundedQueueBasedMessageQueue { - final val queue = new ConcurrentLinkedQueue[Envelope]() - } + //#require-mailbox-on-actor + // ... } - //#mailbox-implementation-example + //#require-mailbox-on-actor } class DispatcherDocSpec extends AkkaSpec(DispatcherDocSpec.config) { - import DispatcherDocSpec.MyActor + import DispatcherDocSpec._ "defining dispatcher in config" in { val context = system @@ -325,4 +346,13 @@ class DispatcherDocSpec extends AkkaSpec(DispatcherDocSpec.config) { val dispatcher = system.dispatchers.lookup("my-balancing-dispatcher") } + "require custom mailbox on dispatcher" in { + val myActor = system.actorOf(Props[MyActor].withDispatcher( + "custom-dispatcher")) + } + + "require custom mailbox on actor" in { + val myActor = system.actorOf(Props[MySpecialActor]) + } + } diff --git a/akka-docs/rst/scala/code/docs/dispatcher/MyUnboundedMailbox.scala b/akka-docs/rst/scala/code/docs/dispatcher/MyUnboundedMailbox.scala new file mode 100644 index 0000000000..a1db8c753f --- /dev/null +++ b/akka-docs/rst/scala/code/docs/dispatcher/MyUnboundedMailbox.scala @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2009-2013 Typesafe Inc. + */ + +package docs.dispatcher + +//#mailbox-implementation-example +import akka.actor.ActorRef +import akka.actor.ActorSystem +import akka.dispatch.Envelope +import akka.dispatch.MailboxType +import akka.dispatch.MessageQueue +import akka.dispatch.ProducesMessageQueue +import com.typesafe.config.Config +import java.util.concurrent.ConcurrentLinkedQueue +import scala.Option + +// Marker trait used for mailbox requirements mapping +trait MyUnboundedMessageQueueSemantics + +object MyUnboundedMailbox { + // This is the MessageQueue implementation + class MyMessageQueue extends MessageQueue + with MyUnboundedMessageQueueSemantics { + + private final val queue = new ConcurrentLinkedQueue[Envelope]() + + // these must be implemented; queue used as example + def enqueue(receiver: ActorRef, handle: Envelope): Unit = + queue.offer(handle) + def dequeue(): Envelope = queue.poll() + def numberOfMessages: Int = queue.size + def hasMessages: Boolean = !queue.isEmpty + def cleanUp(owner: ActorRef, deadLetters: MessageQueue) { + while (hasMessages) { + deadLetters.enqueue(owner, dequeue()) + } + } + } +} + +// This is the Mailbox implementation +class MyUnboundedMailbox extends MailboxType + with ProducesMessageQueue[MyUnboundedMailbox.MyMessageQueue] { + + import MyUnboundedMailbox._ + + // This constructor signature must exist, it will be called by Akka + def this(settings: ActorSystem.Settings, config: Config) = { + // put your initialization code here + this() + } + + // The create method is called to create the MessageQueue + final override def create(owner: Option[ActorRef], + system: Option[ActorSystem]): MessageQueue = + new MyMessageQueue() +} +//#mailbox-implementation-example diff --git a/akka-docs/rst/scala/mailboxes.rst b/akka-docs/rst/scala/mailboxes.rst index e679dda3ad..2d4d805f3c 100644 --- a/akka-docs/rst/scala/mailboxes.rst +++ b/akka-docs/rst/scala/mailboxes.rst @@ -197,7 +197,7 @@ Creating your own Mailbox type An example is worth a thousand quacks: -.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#mailbox-implementation-example +.. includecode:: ../scala/code/docs/dispatcher/MyUnboundedMailbox.scala#mailbox-implementation-example And then you just specify the FQCN of your MailboxType as the value of the "mailbox-type" in the dispatcher configuration, or the mailbox configuration. @@ -212,6 +212,15 @@ configuration, or the mailbox configuration. this mailbox type; the mailbox type will be instantiated once for each dispatcher or mailbox setting using it. +You can also use the mailbox as a requirement on the dispatcher like this: + +.. includecode:: code/docs/dispatcher/DispatcherDocSpec.scala#custom-mailbox-config-java + + +Or by defining the requirement on your actor class like this: + +.. includecode:: code/docs/dispatcher/DispatcherDocSpec.scala#require-mailbox-on-actor + Special Semantics of ``system.actorOf`` ======================================= diff --git a/akka-testkit/src/test/java/akka/testkit/AkkaJUnitActorSystemResource.java b/akka-testkit/src/test/java/akka/testkit/AkkaJUnitActorSystemResource.java index 83335cc98d..caaf7ec06a 100644 --- a/akka-testkit/src/test/java/akka/testkit/AkkaJUnitActorSystemResource.java +++ b/akka-testkit/src/test/java/akka/testkit/AkkaJUnitActorSystemResource.java @@ -34,10 +34,16 @@ public class AkkaJUnitActorSystemResource extends ExternalResource { private final Config config; private ActorSystem createSystem(String name, Config config) { - if (config == null) - return ActorSystem.create(name); - else - return ActorSystem.create(name, config); + try { + if (config == null) + return ActorSystem.create(name); + else + return ActorSystem.create(name, config); + } + catch (Exception e) { + e.printStackTrace(); + return null; + } } public AkkaJUnitActorSystemResource(String name, Config config) {