diff --git a/akka-actor-tests/src/test/java/akka/actor/StashJavaAPI.java b/akka-actor-tests/src/test/java/akka/actor/StashJavaAPI.java index 469c3df206..3487ead16c 100644 --- a/akka-actor-tests/src/test/java/akka/actor/StashJavaAPI.java +++ b/akka-actor-tests/src/test/java/akka/actor/StashJavaAPI.java @@ -6,8 +6,6 @@ import akka.testkit.TestProbe; import org.junit.ClassRule; import org.junit.Test; -import com.typesafe.config.ConfigFactory; - public class StashJavaAPI { @ClassRule @@ -16,14 +14,30 @@ public class StashJavaAPI { private final ActorSystem system = actorSystemResource.getSystem(); - @Test - public void mustBeAbleToUseStash() { - ActorRef ref = system.actorOf(Props.create(StashJavaAPITestActor.class)); - final TestProbe probe = new TestProbe(system); - probe.send(ref, "Hello"); - probe.send(ref, "Hello2"); - probe.send(ref, "Hello12"); - probe.expectMsg(5); + private void testAStashApi(Props props) { + ActorRef ref = system.actorOf(props); + final TestProbe probe = new TestProbe(system); + probe.send(ref, "Hello"); + probe.send(ref, "Hello2"); + probe.send(ref, "Hello12"); + probe.expectMsg(5); } + @Test + public void mustBeAbleToUseStash() { + testAStashApi(Props.create(StashJavaAPITestActors.WithStash.class)); + } + + @Test + public void mustBeAbleToUseUnboundedStash() { + testAStashApi(Props.create(StashJavaAPITestActors.WithUnboundedStash.class)); + } + + @Test + public void mustBeAbleToUseUnrestrictedStash() { + testAStashApi(Props.create(StashJavaAPITestActors.WithUnrestrictedStash.class) + .withMailbox("akka.actor.mailbox.unbounded-deque-based")); + } + + } diff --git a/akka-actor-tests/src/test/java/akka/actor/StashJavaAPITestActor.java b/akka-actor-tests/src/test/java/akka/actor/StashJavaAPITestActor.java deleted file mode 100644 index 5d12f5d8e2..0000000000 --- a/akka-actor-tests/src/test/java/akka/actor/StashJavaAPITestActor.java +++ /dev/null @@ -1,24 +0,0 @@ -package akka.actor; - -import static org.junit.Assert.*; - -public class StashJavaAPITestActor extends UntypedActorWithStash { - int count = 0; - - public void onReceive(Object msg) { - if (msg instanceof String) { - if (count < 0) { - getSender().tell(new Integer(((String) msg).length()), getSelf()); - } else if (count == 2) { - count = -1; - unstashAll(); - } else { - count += 1; - stash(); - } - } else if (msg instanceof Integer) { - int value = ((Integer) msg).intValue(); - assertEquals(value, 5); - } - } -} diff --git a/akka-actor-tests/src/test/java/akka/actor/StashJavaAPITestActors.java b/akka-actor-tests/src/test/java/akka/actor/StashJavaAPITestActors.java new file mode 100644 index 0000000000..435707b9dd --- /dev/null +++ b/akka-actor-tests/src/test/java/akka/actor/StashJavaAPITestActors.java @@ -0,0 +1,53 @@ +package akka.actor; + +import static org.junit.Assert.*; + +public class StashJavaAPITestActors { + + /* + * Helper method to make the tests of UntypedActorWithStash, UntypedActorWithUnboundedStash and + * UntypedActorWithUnrestrictedStash more DRY since mixin is not possible. + */ + private static int testReceive(Object msg, int count, ActorRef sender, ActorRef self, UnrestrictedStash stash) { + if (msg instanceof String) { + if (count < 0) { + sender.tell(new Integer(((String) msg).length()), self); + } else if (count == 2) { + stash.unstashAll(); + return -1; + } else { + stash.stash(); + return count + 1; + } + } else if (msg instanceof Integer) { + int value = ((Integer) msg).intValue(); + assertEquals(value, 5); + } + return count; + } + + public static class WithStash extends UntypedActorWithStash { + int count = 0; + + public void onReceive(Object msg) { + count = testReceive(msg, count, getSender(), getSelf(), this); + } + } + + public static class WithUnboundedStash extends UntypedActorWithUnboundedStash { + int count = 0; + + public void onReceive(Object msg) { + count = testReceive(msg, count, getSender(), getSelf(), this); + } + } + + public static class WithUnrestrictedStash extends UntypedActorWithUnrestrictedStash { + int count = 0; + + public void onReceive(Object msg) { + count = testReceive(msg, count, getSender(), getSelf(), this); + } + } +} + diff --git a/akka-actor/src/main/scala/akka/actor/Stash.scala b/akka-actor/src/main/scala/akka/actor/Stash.scala index fabefdabc5..6cd8e82a3b 100644 --- a/akka-actor/src/main/scala/akka/actor/Stash.scala +++ b/akka-actor/src/main/scala/akka/actor/Stash.scala @@ -30,7 +30,19 @@ import akka.AkkaException * * * Note that the `Stash` trait can only be used together with actors that have a deque-based - * mailbox. + * mailbox. By default Stash based actors request a Deque based mailbox since the stash + * trait extends `RequiresMessageQueue[DequeBasedMessageQueueSemantics]`. + * You can override the default mailbox provided when `DequeBasedMessageQueueSemantics` are requested via config: + *
+ * akka.actor.mailbox.requirements {
+ * "akka.dispatch.BoundedDequeBasedMessageQueueSemantics" = your-custom-mailbox
+ * }
+ *
+ * Alternatively, you can add your own requirement marker to the actor and configure a mailbox type to be used
+ * for your marker.
+ *
+ * For a `Stash` that also enforces unboundedness of the deque see [[akka.actor.UnboundedStash]]. For a `Stash`
+ * that does not enforce any mailbox type see [[akka.actor.UnrestrictedStash]].
*
* Note that the `Stash` trait must be mixed into (a subclass of) the `Actor` trait before
* any trait/class that overrides the `preRestart` callback. This means it's not possible to write
@@ -39,10 +51,14 @@ import akka.AkkaException
trait Stash extends UnrestrictedStash with RequiresMessageQueue[DequeBasedMessageQueueSemantics]
/**
- * The `UnboundedStash` trait is a version of `Stash` that enforces an unbounded stash for you actor.
+ * The `UnboundedStash` trait is a version of [[akka.actor.Stash]] that enforces an unbounded stash for you actor.
*/
trait UnboundedStash extends UnrestrictedStash with RequiresMessageQueue[UnboundedDequeBasedMessageQueueSemantics]
+/**
+ * A version of [[akka.actor.Stash]] that does not enforce any mailbox type. The proper mailbox has to be configured
+ * manually, and the mailbox should extend the [[akka.dispatch.DequeBasedMessageQueueSemantics]] marker trait.
+ */
trait UnrestrictedStash extends Actor {
/* The private stash of the actor. It is only accessible using `stash()` and
* `unstashAll()`.
diff --git a/akka-actor/src/main/scala/akka/actor/UntypedActorWithStash.scala b/akka-actor/src/main/scala/akka/actor/UntypedActorWithStash.scala
index 4cf36dcd99..3e8d5d435b 100644
--- a/akka-actor/src/main/scala/akka/actor/UntypedActorWithStash.scala
+++ b/akka-actor/src/main/scala/akka/actor/UntypedActorWithStash.scala
@@ -29,10 +29,32 @@ package akka.actor
* }
* }
*
+ * Note that the subclasses of `UntypedActorWithStash` by default request a Deque based mailbox since this class
+ * implements the `RequiresMessageQueue
+ * akka.actor.mailbox.requirements {
+ * "akka.dispatch.BoundedDequeBasedMessageQueueSemantics" = your-custom-mailbox
+ * }
+ *
+ * Alternatively, you can add your own requirement marker to the actor and configure a mailbox type to be used
+ * for your marker.
+ *
+ * For a `Stash` based actor that enforces unbounded deques see [[akka.actor.UntypedActorWithUnboundedStash]].
+ * There is also an unrestricted version [[akka.actor.UntypedActorWithUnrestrictedStash]] that does not
+ * enforce the mailbox type.
*/
abstract class UntypedActorWithStash extends UntypedActor with Stash
/**
- * Actor base class that enforces an unbounded stash for the actor.
+ * Actor base class with `Stash` that enforces an unbounded deque for the actor. The proper mailbox has to be configured
+ * manually, and the mailbox should extend the [[akka.dispatch.DequeBasedMessageQueueSemantics]] marker trait.
+ * See [[akka.actor.UntypedActorWithStash]] for details on how `Stash` works.
*/
abstract class UntypedActorWithUnboundedStash extends UntypedActor with UnboundedStash
+
+/**
+ * Actor base class with `Stash` that does not enforce any mailbox type. The mailbox of the actor has to be configured
+ * manually. See [[akka.actor.UntypedActorWithStash]] for details on how `Stash` works.
+ */
+abstract class UntypedActorWithUnrestrictedStash extends UntypedActor with UnrestrictedStash
diff --git a/akka-docs/rst/java/untyped-actors.rst b/akka-docs/rst/java/untyped-actors.rst
index 1fc6cf5644..c2220affe7 100644
--- a/akka-docs/rst/java/untyped-actors.rst
+++ b/akka-docs/rst/java/untyped-actors.rst
@@ -708,6 +708,14 @@ mailbox. This way, the stashed messages can be processed in the same
order as they have been received originally. An actor that extends
``UntypedActorWithStash`` will automatically get a deque-based mailbox.
+.. note::
+
+ The abstract class ``UntypedActorWithStash`` implements the marker
+ interface ``RequiresMessageQueue