diff --git a/akka-actor-tests/src/test/java/akka/actor/JavaAPI.java b/akka-actor-tests/src/test/java/akka/actor/JavaAPI.java index 61c829f540..741cc0bb00 100644 --- a/akka-actor-tests/src/test/java/akka/actor/JavaAPI.java +++ b/akka-actor-tests/src/test/java/akka/actor/JavaAPI.java @@ -31,4 +31,10 @@ public class JavaAPI { }); assertNotNull(ref); } + + @Test void mustAcceptSingleArgTryTell() { + ActorRef ref = Actors.actorOf(JavaAPITestActor.class); + ref.tryTell("hallo"); + ref.tryTell("hallo", ref); + } } diff --git a/akka-actor-tests/src/test/scala/akka/actor/actor/ChannelSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/actor/ChannelSpec.scala index 8ed25e2f9a..d1da159244 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/actor/ChannelSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/actor/ChannelSpec.scala @@ -32,6 +32,16 @@ class ChannelSpec extends WordSpec with MustMatchers { }).start() a ! "hallo" s must be(("hallo", a)) + + { + implicit val actor = a + ch tryTell "buh" + } + s must be(("buh", a)) + ch.!("world")(a) + s must be(("world", a)) + ch.tryTell("bippy")(a) + s must be(("bippy", a)) } } diff --git a/akka-actor/src/main/scala/akka/actor/ActorRef.scala b/akka-actor/src/main/scala/akka/actor/ActorRef.scala index 56094892d2..0e7f3e7e96 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorRef.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorRef.scala @@ -303,7 +303,7 @@ abstract class ActorRef extends ActorRefShared with ForwardableChannel with Repl * * If you would rather have an exception, check the reply(..) version. */ - def tryReply(message: Any): Boolean = channel.tryTell(message, this) + def tryReply(message: Any): Boolean = channel.tryTell(message)(this) /** * Sets the dispatcher for this actor. Needs to be invoked before the actor is started. diff --git a/akka-actor/src/main/scala/akka/actor/Channel.scala b/akka-actor/src/main/scala/akka/actor/Channel.scala index 692ca8d048..f50332cf87 100644 --- a/akka-actor/src/main/scala/akka/actor/Channel.scala +++ b/akka-actor/src/main/scala/akka/actor/Channel.scala @@ -4,6 +4,23 @@ package akka.actor +/* + * This package is just used to hide the tryTell method from the Scala parts: + * it will be public to javac's eyes by virtue of §5.2 of the SLS. + */ +package japi { + trait Channel[-T] { self: akka.actor.Channel[T] ⇒ + private[japi] def tryTell(msg: T): Boolean = { + try { + self.!(msg)(NullChannel) + true + } catch { + case _: Exception ⇒ false + } + } + } +} + /** * Abstraction for unification of sender and senderFuture for later reply. * Can be stored away and used at a later point in time. @@ -12,13 +29,39 @@ package akka.actor * untyped, as there is no way to utilize its real static type without * requiring runtime-costly manifests. */ -trait Channel[-T] { +trait Channel[-T] extends japi.Channel[T] { /** * Scala API.

* Sends the specified message to the channel. */ - def !(msg: T)(implicit channel: UntypedChannel): Unit + def !(msg: T)(implicit sender: UntypedChannel): Unit + + /** + * Scala and Java API.

+ * Try to send the specified message to the channel, i.e. fire-and-forget + * semantics, including the sender reference if possible (not supported on + * all channels).

+ * From Java: + *

+   * actor.tryTell(message);
+   * actor.tryTell(message, context);
+   * 
+ *

+ * From Scala: + *

+   * actor tryTell message
+   * actor.tryTell(message)(sender)
+   * 
+ */ + def tryTell(msg: T)(implicit sender: UntypedChannel): Boolean = { + try { + this.!(msg)(sender) + true + } catch { + case _: Exception ⇒ false + } + } /** * Try to send an exception. Not all channel types support this, one notable @@ -47,32 +90,6 @@ trait Channel[-T] { */ def tell(msg: T, sender: UntypedChannel): Unit = this.!(msg)(sender) - /** - * Try to send the specified message to the channel, i.e. fire-and-forget semantics.

- *

-   * channel.tell(message);
-   * 
- */ - def tryTell(msg: T): Boolean = this.tryTell(msg, NullChannel) - - /** - * Java API.

- * Try to send the specified message to the channel, i.e. fire-and-forget - * semantics, including the sender reference if possible (not supported on - * all channels).

- *

-   * actor.tell(message, context);
-   * 
- */ - def tryTell(msg: T, sender: UntypedChannel): Boolean = { - try { - this.!(msg)(sender) - true - } catch { - case _: Exception ⇒ false - } - } - } /** diff --git a/akka-docs/scala/actors.rst b/akka-docs/scala/actors.rst index 16bdc06079..69ebc4edbc 100644 --- a/akka-docs/scala/actors.rst +++ b/akka-docs/scala/actors.rst @@ -349,7 +349,8 @@ Simply call ``self.channel`` and then you can forward that to others, store it a case request => val result = process(request) - self.channel ! result + self.channel ! result // will throw an exception if there is no sender information + self.channel tryTell result // will return Boolean whether reply succeeded The :class:`Channel` trait is contravariant in the expected message type. Since ``self.channel`` is subtype of ``Channel[Any]``, you may specialise your return