removing replySafe and replyUnsafe in favor of the unified reply/tryReply

This commit is contained in:
Viktor Klang 2011-07-20 15:58:28 +02:00
parent 4258abfc9f
commit b23a8fffeb
20 changed files with 54 additions and 74 deletions

View file

@ -2,6 +2,6 @@ package akka.actor;
public class JavaAPITestActor extends UntypedActor {
public void onReceive(Object msg) {
getContext().replySafe("got it!");
getContext().tryReply("got it!");
}
}

View file

@ -273,26 +273,29 @@ trait ActorRef extends ActorRefShared with ForwardableChannel with java.lang.Com
}
/**
* Akka Java API. <p/>
* Use <code>getContext().replyUnsafe(..)</code> to reply with a message to the original sender of the message currently
* being processed.
* Akka Scala & Java API
* Use <code>self.reply(..)</code> to reply with a message to the original sender of the message currently
* being processed. This method fails if the original sender of the message could not be determined with an
* IllegalStateException.
*
* If you don't want deal with this IllegalStateException, but just a boolean, just use the <code>tryReply(...)</code>
* version.
*
* <p/>
* Throws an IllegalStateException if unable to determine what to reply to.
*/
@deprecated("will be removed in 2.0, use reply instead", "1.2")
def replyUnsafe(message: AnyRef) {
reply(message)
}
def reply(message: Any) = channel.!(message)(this)
/**
* Akka Java API. <p/>
* Use <code>getContext().replySafe(..)</code> to reply with a message to the original sender of the message currently
* being processed.
* Akka Scala & Java API
* Use <code>tryReply(..)</code> to try reply with a message to the original sender of the message currently
* being processed. This method
* <p/>
* Returns true if reply was sent, and false if unable to determine what to reply to.
*
* If you would rather have an exception, check the <code>reply(..)</code> version.
*/
@deprecated("will be removed in 2.0, use tryReply instead", "1.2")
def replySafe(message: AnyRef): Boolean = tryReply(message)
def tryReply(message: Any): Boolean = channel.safe_!(message)(this)
/**
* Sets the dispatcher for this actor. Needs to be invoked before the actor is started.
@ -1242,29 +1245,6 @@ trait ScalaActorRef extends ActorRefShared with ForwardableChannel {
} else throw new ActorInitializationException(
"Actor has not been started, you need to invoke 'actor.start()' before using it")
}
/**
* Use <code>self.reply(..)</code> to reply with a message to the original sender of the message currently
* being processed. This method fails if the original sender of the message could not be determined with an
* IllegalStateException.
*
* If you don't want deal with this IllegalStateException, but just a boolean, just use the <code>tryReply(...)</code>
* version.
*
* <p/>
* Throws an IllegalStateException if unable to determine what to reply to.
*/
def reply(message: Any) = channel.!(message)(this)
/**
* Use <code>tryReply(..)</code> to try reply with a message to the original sender of the message currently
* being processed. This method
* <p/>
* Returns true if reply was sent, and false if unable to determine what to reply to.
*
* If you would rather have an exception, check the <code>reply(..)</code> version.
*/
def tryReply(message: Any): Boolean = channel.safe_!(message)(this)
}
case class SerializedActorRef(uuid: Uuid,

View file

@ -19,8 +19,8 @@ import akka.japi.{ Creator, Procedure }
* String msg = (String)message;
*
* if (msg.equals("UseReply")) {
* // Reply to original sender of message using the 'replyUnsafe' method
* getContext().replyUnsafe(msg + ":" + getContext().getUuid());
* // Reply to original sender of message using the 'reply' method
* getContext().reply(msg + ":" + getContext().getUuid());
*
* } else if (msg.equals("UseSender") && getContext().getSender().isDefined()) {
* // Reply to original sender of message using the sender reference

View file

@ -15,7 +15,7 @@ public class SampleUntypedConsumer extends UntypedConsumerActor {
Message msg = (Message)message;
String body = msg.getBodyAs(String.class);
String header = msg.getHeaderAs("test", String.class);
getContext().replySafe(String.format("%s %s", body, header));
getContext().tryReply(String.format("%s %s", body, header));
}
}

View file

@ -17,7 +17,7 @@ public class SampleUntypedConsumerBlocking extends UntypedConsumerActor {
Message msg = (Message)message;
String body = msg.getBodyAs(String.class);
String header = msg.getHeaderAs("test", String.class);
getContext().replySafe(String.format("%s %s", body, header));
getContext().tryReply(String.format("%s %s", body, header));
}
}

View file

@ -291,13 +291,13 @@ Now we can create the worker actor. This is done by extending in the ``UntypedA
double result = calculatePiFor(work.getStart(), work.getNrOfElements());
// reply with the result
getContext().replyUnsafe(new Result(result));
getContext().reply(new Result(result));
} else throw new IllegalArgumentException("Unknown message [" + message + "]");
}
}
As you can see we have now created an ``UntypedActor`` with a ``onReceive`` method as a handler for the ``Work`` message. In this handler we invoke the ``calculatePiFor(..)`` method, wrap the result in a ``Result`` message and send it back to the original sender using ``getContext().replyUnsafe(..)``. In Akka the sender reference is implicitly passed along with the message so that the receiver can always reply or store away the sender reference for future use.
As you can see we have now created an ``UntypedActor`` with a ``onReceive`` method as a handler for the ``Work`` message. In this handler we invoke the ``calculatePiFor(..)`` method, wrap the result in a ``Result`` message and send it back to the original sender using ``getContext().reply(..)``. In Akka the sender reference is implicitly passed along with the message so that the receiver can always reply or store away the sender reference for future use.
The only thing missing in our ``Worker`` actor is the implementation on the ``calculatePiFor(..)`` method::
@ -587,7 +587,7 @@ Before we package it up and run it, let's take a look at the full code now, with
double result = calculatePiFor(work.getStart(), work.getNrOfElements())
// reply with the result
getContext().replyUnsafe(new Result(result));
getContext().reply(new Result(result));
} else throw new IllegalArgumentException("Unknown message [" + message + "]");
}

View file

@ -342,22 +342,22 @@ Supervised actors have the option to reply to the initial sender within preResta
// do something that may throw an exception
// ...
getContext().replySafe("ok");
getContext().tryReply("ok");
}
@Override
public void preRestart(Throwable reason) {
getContext().replySafe(reason.getMessage());
getContext().tryReply(reason.getMessage());
}
@Override
public void postStop() {
getContext().replySafe("stopped by supervisor");
getContext().tryReply("stopped by supervisor");
}
}
- A reply within preRestart or postRestart must be a safe reply via getContext().replySafe() because a getContext().replyUnsafe() will throw an exception when the actor is restarted without having failed. This can be the case in context of AllForOne restart strategies.
- A reply within postStop must be a safe reply via getContext().replySafe() because a getContext().replyUnsafe() will throw an exception when the actor has been stopped by the application (and not by a supervisor) after successful execution of receive (or no execution at all).
- A reply within preRestart or postRestart must be a safe reply via getContext().tryReply() because a getContext().reply() will throw an exception when the actor is restarted without having failed. This can be the case in context of AllForOne restart strategies.
- A reply within postStop must be a safe reply via getContext().tryReply() because a getContext().reply() will throw an exception when the actor has been stopped by the application (and not by a supervisor) after successful execution of receive (or no execution at all).
Handling too many actor restarts within a specific time limit
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -20,7 +20,7 @@ Step 1: Define the Actor
public class SerializationTestActor extends UntypedActor {
public void onReceive(Object msg) {
getContext().replySafe("got it!");
getContext().tryReply("got it!");
}
}
@ -101,10 +101,10 @@ Step 1: Define the Actor
public void onReceive(Object msg) {
if (msg.equals("hello")) {
count = count + 1;
getContext().replyUnsafe("world " + count);
getContext().reply("world " + count);
} else if (msg instanceof String) {
count = count + 1;
getContext().replyUnsafe("hello " + msg + " " + count);
getContext().reply("hello " + msg + " " + count);
} else {
throw new IllegalArgumentException("invalid message type");
}

View file

@ -95,7 +95,7 @@ Here is an example of coordinating two simple counter UntypedActors so that they
});
}
} else if (incoming.equals("GetCount")) {
getContext().replyUnsafe(count.get());
getContext().reply(count.get());
}
}
}

View file

@ -247,10 +247,10 @@ which you do by Channel.sendOneWay(msg)
We recommend that you as first choice use the channel abstraction instead of the other ways described in the following sections.
Reply using the 'replySafe' and 'replyUnsafe' methods
Reply using the 'tryReply' and 'reply' methods
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you want to send a message back to the original sender of the message you just received then you can use the 'getContext().replyUnsafe(..)' method.
If you want to send a message back to the original sender of the message you just received then you can use the 'getContext().reply(..)' method.
.. code-block:: java
@ -258,15 +258,15 @@ If you want to send a message back to the original sender of the message you jus
if (message instanceof String) {
String msg = (String)message;
if (msg.equals("Hello")) {
// Reply to original sender of message using the 'replyUnsafe' method
getContext().replyUnsafe(msg + " from " + getContext().getUuid());
// Reply to original sender of message using the 'reply' method
getContext().reply(msg + " from " + getContext().getUuid());
}
}
}
In this case we will a reply back to the Actor that sent the message.
The 'replyUnsafe' method throws an 'IllegalStateException' if unable to determine what to reply to, e.g. the sender has not been passed along with the message when invoking one of 'send*' methods. You can also use the more forgiving 'replySafe' method which returns 'true' if reply was sent, and 'false' if unable to determine what to reply to.
The 'reply' method throws an 'IllegalStateException' if unable to determine what to reply to, e.g. the sender has not been passed along with the message when invoking one of 'send*' methods. You can also use the more forgiving 'tryReply' method which returns 'true' if reply was sent, and 'false' if unable to determine what to reply to.
.. code-block:: java
@ -274,8 +274,8 @@ The 'replyUnsafe' method throws an 'IllegalStateException' if unable to determin
if (message instanceof String) {
String msg = (String)message;
if (msg.equals("Hello")) {
// Reply to original sender of message using the 'replyUnsafe' method
if (getContext().replySafe(msg + " from " + getContext().getUuid())) ... // success
// Reply to original sender of message using the 'reply' method
if (getContext().tryReply(msg + " from " + getContext().getUuid())) ... // success
else ... // handle failure
}
}

View file

@ -246,7 +246,7 @@ from localhost on port 8877.
public void onReceive(Object message) {
Message msg = (Message)message;
String body = msg.getBodyAs(String.class);
getContext().replySafe(String.format("Hello %s", body));
getContext().tryReply(String.format("Hello %s", body));
}
}
@ -659,10 +659,10 @@ acknowledgement).
public void onReceive(Object message) {
// ...
getContext().replyUnsafe(ack()) // on success
getContext().reply(ack()) // on success
// ...
val e: Exception = ...
getContext().replyUnsafe(new Failure(e)) // on failure
getContext().reply(new Failure(e)) // on failure
}
}
@ -855,7 +855,7 @@ following consumer actor class.
}
public void onReceive(Object message) {
getContext().replySafe("response from remote actor 1");
getContext().tryReply("response from remote actor 1");
}
}
@ -1423,7 +1423,7 @@ For initiating a a two-way message exchange, one of the
public class SampleUntypedActor extends UntypedActor {
public void onReceive(Object msg) {
getContext().replySafe(CamelContextManager.getMandatoryTemplate().requestBody("direct:news", msg));
getContext().tryReply(CamelContextManager.getMandatoryTemplate().requestBody("direct:news", msg));
}
}
@ -1995,7 +1995,7 @@ ends at the target actor.
public void onReceive(Object message) {
Message msg = (Message) message;
String body = msg.getBodyAs(String.class);
getContext().replySafe(String.format("Hello %s", body));
getContext().tryReply(String.format("Hello %s", body));
}
}

View file

@ -15,6 +15,6 @@ public class UntypedConsumer1 extends UntypedConsumerActor {
public void onReceive(Object message) {
Message msg = (Message)message;
String body = msg.getBodyAs(String.class);
getContext().replySafe(String.format("received %s", body));
getContext().tryReply(String.format("received %s", body));
}
}

View file

@ -15,7 +15,7 @@ public class SampleRemoteUntypedConsumer extends UntypedConsumerActor {
Message msg = (Message)message;
String body = msg.getBodyAs(String.class);
String header = msg.getHeaderAs("test", String.class);
getContext().replySafe(String.format("%s %s", body, header));
getContext().tryReply(String.format("%s %s", body, header));
}
}

View file

@ -10,7 +10,7 @@ public class PongActor extends UntypedActor {
public void onReceive(Object message) throws Exception {
if (message instanceof String) {
System.out.println("Pongeceived String message: " + message);
getContext().replyUnsafe(message + " from " + getContext().getUuid());
getContext().reply(message + " from " + getContext().getUuid());
} else {
throw new IllegalArgumentException("Unknown message: " + message);
}

View file

@ -32,7 +32,7 @@ public class UntypedCoordinatedCounter extends UntypedActor {
} else if (incoming instanceof String) {
String message = (String) incoming;
if (message.equals("GetCount")) {
getContext().replyUnsafe(count.get());
getContext().reply(count.get());
}
}
}

View file

@ -26,7 +26,7 @@ public class UntypedCounter extends UntypedTransactor {
@Override public boolean normally(Object message) {
if ("GetCount".equals(message)) {
getContext().replyUnsafe(count.get());
getContext().reply(count.get());
return true;
} else return false;
}

View file

@ -57,7 +57,7 @@ public class UntypedCoordinatedCounter extends UntypedActor {
} else if (incoming instanceof String) {
String message = (String) incoming;
if (message.equals("GetCount")) {
getContext().replyUnsafe(count.get());
getContext().reply(count.get());
}
}
}

View file

@ -70,7 +70,7 @@ public class UntypedCounter extends UntypedTransactor {
@Override public boolean normally(Object message) {
if ("GetCount".equals(message)) {
getContext().replyUnsafe(count.get());
getContext().reply(count.get());
return true;
} else return false;
}

View file

@ -76,7 +76,7 @@ public class Pi {
double result = calculatePiFor(work.getStart(), work.getNrOfElements());
// reply with the result
getContext().replyUnsafe(new Result(result));
getContext().reply(new Result(result));
} else throw new IllegalArgumentException("Unknown message [" + message + "]");
}

View file

@ -73,7 +73,7 @@ public class Pi {
public void onReceive(Object message) {
if (message instanceof Work) {
Work work = (Work) message;
getContext().replyUnsafe(new Result(calculatePiFor(work.getArg(), work.getNrOfElements()))); // perform the work
getContext().reply(new Result(calculatePiFor(work.getArg(), work.getNrOfElements()))); // perform the work
} else throw new IllegalArgumentException("Unknown message [" + message + "]");
}
}