UntypedActor hooks default to super.<whatever> now, plus updated ScalaDoc
This commit is contained in:
parent
488576c62a
commit
7d6c74d75c
3 changed files with 104 additions and 78 deletions
|
|
@ -156,15 +156,44 @@ object Actor {
|
||||||
/**
|
/**
|
||||||
* Actor base trait that should be extended by or mixed to create an Actor with the semantics of the 'Actor Model':
|
* Actor base trait that should be extended by or mixed to create an Actor with the semantics of the 'Actor Model':
|
||||||
* <a href="http://en.wikipedia.org/wiki/Actor_model">http://en.wikipedia.org/wiki/Actor_model</a>
|
* <a href="http://en.wikipedia.org/wiki/Actor_model">http://en.wikipedia.org/wiki/Actor_model</a>
|
||||||
* <p/>
|
|
||||||
* An actor has a well-defined (non-cyclic) life-cycle.
|
|
||||||
* <pre>
|
|
||||||
* => RUNNING (created and started actor) - can receive messages
|
|
||||||
* => SHUTDOWN (when 'stop' or 'exit' is invoked) - can't do anything
|
|
||||||
* </pre>
|
|
||||||
*
|
*
|
||||||
* <p/>
|
* An actor has a well-defined (non-cyclic) life-cycle.
|
||||||
* The Actor's own ActorRef is available in the 'self' member variable.
|
* - ''RUNNING'' (created and started actor) - can receive messages
|
||||||
|
* - ''SHUTDOWN'' (when 'stop' or 'exit' is invoked) - can't do anything
|
||||||
|
*
|
||||||
|
* The Actor's own [[akka.actor.ActorRef]] is available as `self`, the current
|
||||||
|
* message’s sender as `sender` and the [[akka.actor.ActorContext]] as
|
||||||
|
* `context`. The only abstract method is `receive` which shall return the
|
||||||
|
* initial behavior of the actor as a partial function (behavior can be changed
|
||||||
|
* using `context.become` and `context.unbecome`).
|
||||||
|
*
|
||||||
|
* {{{
|
||||||
|
* class ExampleActor extends Actor {
|
||||||
|
* def receive = {
|
||||||
|
* // directly calculated reply
|
||||||
|
* case Request(r) => sender ! calculate(r)
|
||||||
|
*
|
||||||
|
* // just to demonstrate how to stop yourself
|
||||||
|
* case Shutdown => context.stop(self)
|
||||||
|
*
|
||||||
|
* // error kernel with child replying directly to “customer”
|
||||||
|
* case Dangerous(r) => context.actorOf(Props[ReplyToOriginWorker]).tell(PerformWork(r), sender)
|
||||||
|
*
|
||||||
|
* // error kernel with reply going through us
|
||||||
|
* case OtherJob(r) => context.actorOf(Props[ReplyToMeWorker]) ! JobRequest(r, sender)
|
||||||
|
* case JobReply(result, orig_s) => orig_s ! result
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }}}
|
||||||
|
*
|
||||||
|
* The last line demonstrates the essence of the error kernel design: spawn
|
||||||
|
* one-off actors which terminate after doing their job, pass on `sender` to
|
||||||
|
* allow direct reply if that is what makes sense, or round-trip the sender
|
||||||
|
* as shown with the fictitious JobRequest/JobReply message pair.
|
||||||
|
*
|
||||||
|
* If you don’t like writing `context` you can always `import context._` to get
|
||||||
|
* direct access to `actorOf`, `stop` etc. This is not default in order to keep
|
||||||
|
* the name-space clean.
|
||||||
*/
|
*/
|
||||||
trait Actor {
|
trait Actor {
|
||||||
|
|
||||||
|
|
@ -218,25 +247,8 @@ trait Actor {
|
||||||
final def sender: ActorRef = context.sender
|
final def sender: ActorRef = context.sender
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User overridable callback/setting.
|
* This defines the initial actor behavior, it must return a partial function
|
||||||
* <p/>
|
* with the actor logic.
|
||||||
* Partial function implementing the actor logic.
|
|
||||||
* To be implemented by concrete actor class.
|
|
||||||
* <p/>
|
|
||||||
* Example code:
|
|
||||||
* <pre>
|
|
||||||
* def receive = {
|
|
||||||
* case Ping =>
|
|
||||||
* println("got a 'Ping' message")
|
|
||||||
* sender ! "pong"
|
|
||||||
*
|
|
||||||
* case OneWay =>
|
|
||||||
* println("got a 'OneWay' message")
|
|
||||||
*
|
|
||||||
* case unknown =>
|
|
||||||
* println("unknown message: " + unknown)
|
|
||||||
* }
|
|
||||||
* </pre>
|
|
||||||
*/
|
*/
|
||||||
protected def receive: Receive
|
protected def receive: Receive
|
||||||
|
|
||||||
|
|
@ -258,11 +270,10 @@ trait Actor {
|
||||||
def postStop() {}
|
def postStop() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User overridable callback.
|
* User overridable callback: '''By default it disposes of all children and then calls `postStop()`.'''
|
||||||
* <p/>
|
* <p/>
|
||||||
* Is called on a crashed Actor right BEFORE it is restarted to allow clean
|
* Is called on a crashed Actor right BEFORE it is restarted to allow clean
|
||||||
* up of resources before Actor is terminated.
|
* up of resources before Actor is terminated.
|
||||||
* By default it disposes of all children calls postStop().
|
|
||||||
*/
|
*/
|
||||||
def preRestart(reason: Throwable, message: Option[Any]) {
|
def preRestart(reason: Throwable, message: Option[Any]) {
|
||||||
context.children foreach (context.stop(_))
|
context.children foreach (context.stop(_))
|
||||||
|
|
@ -270,10 +281,9 @@ trait Actor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User overridable callback.
|
* User overridable callback: By default it calls `preStart()`.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Is called right AFTER restart on the newly created Actor to allow reinitialization after an Actor crash.
|
* Is called right AFTER restart on the newly created Actor to allow reinitialization after an Actor crash.
|
||||||
* By default it calls preStart()
|
|
||||||
*/
|
*/
|
||||||
def postRestart(reason: Throwable) { preStart() }
|
def postRestart(reason: Throwable) { preStart() }
|
||||||
|
|
||||||
|
|
@ -281,7 +291,9 @@ trait Actor {
|
||||||
* User overridable callback.
|
* User overridable callback.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Is called when a message isn't handled by the current behavior of the actor
|
* Is called when a message isn't handled by the current behavior of the actor
|
||||||
* by default it does: EventHandler.warning(self, message)
|
* by default it fails with either a [[akka.actor.DeathPactException]] (in
|
||||||
|
* case of an unhandled [[akka.actor.Terminated]] message) or a
|
||||||
|
* [[akka.actor.UnhandledMessageException]].
|
||||||
*/
|
*/
|
||||||
def unhandled(message: Any) {
|
def unhandled(message: Any) {
|
||||||
message match {
|
message match {
|
||||||
|
|
|
||||||
|
|
@ -365,18 +365,12 @@ class ActorSystemImpl(val name: String, applicationConfig: Config) extends Actor
|
||||||
def stop(actor: ActorRef): Unit = {
|
def stop(actor: ActorRef): Unit = {
|
||||||
implicit val timeout = settings.CreationTimeout
|
implicit val timeout = settings.CreationTimeout
|
||||||
val path = actor.path
|
val path = actor.path
|
||||||
if (path.parent == guardian.path) {
|
val guard = guardian.path
|
||||||
(guardian ? StopChild(actor)).get match {
|
val sys = systemGuardian.path
|
||||||
case ex: Exception ⇒ throw ex
|
path.parent match {
|
||||||
case _ ⇒
|
case `guard` ⇒ (guardian ? StopChild(actor)).get
|
||||||
}
|
case `sys` ⇒ (systemGuardian ? StopChild(actor)).get
|
||||||
} else if (path.parent == systemGuardian.path) {
|
case _ ⇒ actor.asInstanceOf[InternalActorRef].stop()
|
||||||
(systemGuardian ? StopChild(actor)).get match {
|
|
||||||
case ex: Exception ⇒ throw ex
|
|
||||||
case _ ⇒
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
actor.asInstanceOf[InternalActorRef].stop()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,46 +8,67 @@ import akka.japi.{ Creator, Procedure }
|
||||||
import akka.dispatch.{ MessageDispatcher, Promise }
|
import akka.dispatch.{ MessageDispatcher, Promise }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Actor base trait that should be extended by or mixed to create an Actor with the semantics of the 'Actor Model':
|
||||||
|
* <a href="http://en.wikipedia.org/wiki/Actor_model">http://en.wikipedia.org/wiki/Actor_model</a>
|
||||||
|
*
|
||||||
|
* This class is the Java cousin to the [[akka.actor.Actor]] Scala interface.
|
||||||
* Subclass this abstract class to create a MDB-style untyped actor.
|
* Subclass this abstract class to create a MDB-style untyped actor.
|
||||||
* <p/>
|
*
|
||||||
* This class is meant to be used from Java.
|
* An actor has a well-defined (non-cyclic) life-cycle.
|
||||||
* <p/>
|
* - ''RUNNING'' (created and started actor) - can receive messages
|
||||||
|
* - ''SHUTDOWN'' (when 'stop' or 'exit' is invoked) - can't do anything
|
||||||
|
*
|
||||||
|
* The Actor's own [[akka.actor.ActorRef]] is available as `getSelf()`, the current
|
||||||
|
* message’s sender as `getSender()` and the [[akka.actor.UntypedActorContext]] as
|
||||||
|
* `getContext()`. The only abstract method is `onReceive()` which is invoked for
|
||||||
|
* each processed message unless dynamically overridden using `getContext().become()`.
|
||||||
|
*
|
||||||
* Here is an example on how to create and use an UntypedActor:
|
* Here is an example on how to create and use an UntypedActor:
|
||||||
* <pre>
|
*
|
||||||
|
* {{{
|
||||||
* public class SampleUntypedActor extends UntypedActor {
|
* public class SampleUntypedActor extends UntypedActor {
|
||||||
|
*
|
||||||
|
* public class Reply {
|
||||||
|
* final public ActorRef sender;
|
||||||
|
* final public Result result;
|
||||||
|
* Reply(ActorRef sender, Result result) {
|
||||||
|
* this.sender = sender;
|
||||||
|
* this.result = result;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
* public void onReceive(Object message) throws Exception {
|
* public void onReceive(Object message) throws Exception {
|
||||||
* if (message instanceof String) {
|
* if (message instanceof String) {
|
||||||
* String msg = (String)message;
|
* String msg = (String)message;
|
||||||
*
|
*
|
||||||
* if (msg.equals("UseReply")) {
|
* if (msg.equals("UseSender")) {
|
||||||
* // Reply to original sender of message using the 'reply' method
|
* // Reply to original sender of message
|
||||||
* getContext().getSender().tell(msg + ":" + getSelf().getAddress());
|
* getSender().tell(msg + ":" + getSelf());
|
||||||
*
|
|
||||||
* } else if (msg.equals("UseSender") && getSender().isDefined()) {
|
|
||||||
* // Reply to original sender of message using the sender reference
|
|
||||||
* // also passing along my own reference (the self)
|
|
||||||
* getSender().get().tell(msg, getSelf());
|
|
||||||
*
|
*
|
||||||
* } else if (msg.equals("SendToSelf")) {
|
* } else if (msg.equals("SendToSelf")) {
|
||||||
* // Send message to the actor itself recursively
|
* // Send message to the actor itself recursively
|
||||||
* getSelf().tell(msg)
|
* getSelf().tell("SomeOtherMessage");
|
||||||
*
|
*
|
||||||
* } else if (msg.equals("ForwardMessage")) {
|
* } else if (msg.equals("ErrorKernelWithDirectReply")) {
|
||||||
* // Retreive an actor from the ActorRegistry by ID and get an ActorRef back
|
* // Send work to one-off child which will reply directly to original sender
|
||||||
* ActorRef actorRef = Actor.registry.local.actorsFor("some-actor-id").head();
|
* getContext().actorOf(new Props(Worker.class)).tell("DoSomeDangerousWork", getSender());
|
||||||
|
*
|
||||||
|
* } else if (msg.equals("ErrorKernelWithReplyHere")) {
|
||||||
|
* // Send work to one-off child and collect the answer, reply handled further down
|
||||||
|
* getContext().actorOf(new Props(Worker.class)).tell("DoWorkAndReplyToMe");
|
||||||
*
|
*
|
||||||
* } else throw new IllegalArgumentException("Unknown message: " + message);
|
* } else throw new IllegalArgumentException("Unknown message: " + message);
|
||||||
|
*
|
||||||
|
* } else if (message instanceof Reply) {
|
||||||
|
*
|
||||||
|
* final Reply reply = (Reply) message;
|
||||||
|
* // might want to do some processing/book-keeping here
|
||||||
|
* reply.sender.tell(reply.result);
|
||||||
|
*
|
||||||
* } else throw new IllegalArgumentException("Unknown message: " + message);
|
* } else throw new IllegalArgumentException("Unknown message: " + message);
|
||||||
* }
|
* }
|
||||||
*
|
|
||||||
* public static void main(String[] args) {
|
|
||||||
* ActorSystem system = ActorSystem.create("Sample");
|
|
||||||
* ActorRef actor = system.actorOf(SampleUntypedActor.class);
|
|
||||||
* actor.tell("SendToSelf");
|
|
||||||
* actor.stop();
|
|
||||||
* }
|
* }
|
||||||
* }
|
* }}}
|
||||||
* </pre>
|
|
||||||
*/
|
*/
|
||||||
abstract class UntypedActor extends Actor {
|
abstract class UntypedActor extends Actor {
|
||||||
|
|
||||||
|
|
@ -65,8 +86,9 @@ abstract class UntypedActor extends Actor {
|
||||||
def getSelf(): ActorRef = self
|
def getSelf(): ActorRef = self
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The reference sender Actor of the last received message.
|
* The reference sender Actor of the currently processed message. This is
|
||||||
* Is defined if the message was sent from another Actor, else None.
|
* always a legal destination to send to, even if there is no logical recipient
|
||||||
|
* for the reply, in which case it will be sent to the dead letter mailbox.
|
||||||
*/
|
*/
|
||||||
def getSender(): ActorRef = sender
|
def getSender(): ActorRef = sender
|
||||||
|
|
||||||
|
|
@ -77,7 +99,7 @@ abstract class UntypedActor extends Actor {
|
||||||
* Actor are automatically started asynchronously when created.
|
* Actor are automatically started asynchronously when created.
|
||||||
* Empty default implementation.
|
* Empty default implementation.
|
||||||
*/
|
*/
|
||||||
override def preStart() {}
|
override def preStart(): Unit = super.preStart()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User overridable callback.
|
* User overridable callback.
|
||||||
|
|
@ -85,24 +107,22 @@ abstract class UntypedActor extends Actor {
|
||||||
* Is called asynchronously after 'actor.stop()' is invoked.
|
* Is called asynchronously after 'actor.stop()' is invoked.
|
||||||
* Empty default implementation.
|
* Empty default implementation.
|
||||||
*/
|
*/
|
||||||
override def postStop() {}
|
override def postStop(): Unit = super.postStop()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User overridable callback.
|
* User overridable callback: '''By default it disposes of all children and then calls `postStop()`.'''
|
||||||
* <p/>
|
* <p/>
|
||||||
* Is called on a crashed Actor right BEFORE it is restarted to allow clean
|
* Is called on a crashed Actor right BEFORE it is restarted to allow clean
|
||||||
* up of resources before Actor is terminated.
|
* up of resources before Actor is terminated.
|
||||||
* By default it calls postStop()
|
|
||||||
*/
|
*/
|
||||||
override def preRestart(reason: Throwable, message: Option[Any]) { postStop() }
|
override def preRestart(reason: Throwable, message: Option[Any]): Unit = super.preRestart(reason, message)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User overridable callback.
|
* User overridable callback: By default it calls `preStart()`.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Is called right AFTER restart on the newly created Actor to allow reinitialization after an Actor crash.
|
* Is called right AFTER restart on the newly created Actor to allow reinitialization after an Actor crash.
|
||||||
* By default it calls preStart()
|
|
||||||
*/
|
*/
|
||||||
override def postRestart(reason: Throwable) { preStart() }
|
override def postRestart(reason: Throwable): Unit = super.postRestart(reason)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User overridable callback.
|
* User overridable callback.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue