Merge remote branch 'upstream/master'
This commit is contained in:
commit
fda2fa6397
6 changed files with 50 additions and 44 deletions
|
|
@ -64,6 +64,7 @@ So your listener Actor needs to be able to handle these two messages. Example:
|
|||
ActorRegistered event = (ActorRegistered) message;
|
||||
EventHandler.info(this, String.format("Actor registered: %s - %s",
|
||||
event.actor().actorClassName(), event.actor().getUuid()));
|
||||
event.actor().actorClassName(), event.actor().getUuid()));
|
||||
} else if (message instanceof ActorUnregistered) {
|
||||
// ...
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ An Actor has to implement the ‘receive’ method to receive messages:
|
|||
|
||||
protected def receive: PartialFunction[Any, Unit]
|
||||
|
||||
Note: Akka has an alias to the 'PartialFunction[Any, Unit]' type called 'Receive', so you can use this type instead for clarity. But most often you don't need to spell it out.
|
||||
Note: Akka has an alias to the 'PartialFunction[Any, Unit]' type called 'Receive' (akka.actor.Actor.Receive), so you can use this type instead for clarity. But most often you don't need to spell it out.
|
||||
|
||||
This method should return a PartialFunction, e.g. a ‘match/case’ clause in which the message can be matched against the different case clauses using Scala pattern matching. Here is an example:
|
||||
|
||||
|
|
@ -263,7 +263,7 @@ If you want to send a message back to the original sender of the message you jus
|
|||
val result = process(request)
|
||||
self.reply(result)
|
||||
|
||||
In this case the 'result' will be send back to the Actor that send the 'request'.
|
||||
In this case the 'result' will be send back to the Actor that sent the 'request'.
|
||||
|
||||
The 'reply' method throws an 'IllegalStateException' if unable to determine what to reply to, e.g. the sender is not an actor. You can also use the more forgiving 'reply_?' method which returns 'true' if reply was sent, and 'false' if unable to determine what to reply to.
|
||||
|
||||
|
|
@ -545,24 +545,28 @@ In generic base Actor:
|
|||
|
||||
.. code-block:: scala
|
||||
|
||||
import akka.actor.Actor.Receive
|
||||
|
||||
abstract class GenericActor extends Actor {
|
||||
|
||||
// to be defined in subclassing actor
|
||||
def specificMessageHandler: PartialFunction[Any, Unit]
|
||||
|
||||
def specificMessageHandler: Receive
|
||||
|
||||
// generic message handler
|
||||
def genericMessageHandler = {
|
||||
... // generic message handler
|
||||
def genericMessageHandler: Receive = {
|
||||
case event => printf("generic: %s\n", event)
|
||||
}
|
||||
|
||||
|
||||
def receive = specificMessageHandler orElse genericMessageHandler
|
||||
}
|
||||
|
||||
In subclassing Actor:
|
||||
|
||||
`<code format="scala">`_
|
||||
class SpecificActor extends GenericActor {
|
||||
def specificMessageHandler = {
|
||||
... // specific message handler
|
||||
case event: MyMsg => printf("specific: %s\n", event.subject)
|
||||
}
|
||||
}
|
||||
`<code>`_
|
||||
|
||||
case class MyMsg(subject: String)
|
||||
`<code>`_
|
||||
|
|
@ -3,15 +3,10 @@ SLF4J
|
|||
|
||||
This module is available in the 'akka-slf4j.jar'. It has one single dependency; the slf4j-api jar.
|
||||
|
||||
Logging trait
|
||||
-------------
|
||||
|
||||
You can use the 'akka.event.slf4j.Logging' trait to mix in logging behavior into your classes and use the 'log' Logger member variable. But the preferred way is to use the event handler (see below).
|
||||
|
||||
Event Handler
|
||||
-------------
|
||||
|
||||
This module also includes an SLF4J Event Handler that works with Akka's standar Event Handler. You enabled it in the 'event-handlers' element in akka.conf. Here you can also define the log level.
|
||||
This module includes a SLF4J Event Handler that works with Akka's standard Event Handler. You enabled it in the 'event-handlers' element in akka.conf. Here you can also define the log level.
|
||||
|
||||
.. code-block:: ruby
|
||||
|
||||
|
|
|
|||
|
|
@ -23,13 +23,15 @@ If you have a POJO with an interface implementation separation like this:
|
|||
.. code-block:: java
|
||||
|
||||
interface RegistrationService {
|
||||
void register(User user, Credentials cred)
|
||||
User getUserFor(String username)
|
||||
void register(User user, Credentials cred);
|
||||
User getUserFor(String username);
|
||||
}
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
public class RegistrationServiceImpl implements RegistrationService extends TypedActor {
|
||||
import akka.actor.TypedActor;
|
||||
|
||||
public class RegistrationServiceImpl extends TypedActor implements RegistrationService {
|
||||
public void register(User user, Credentials cred) {
|
||||
... // register user
|
||||
}
|
||||
|
|
@ -69,9 +71,12 @@ Using a configuration object:
|
|||
|
||||
.. code-block:: java
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import akka.actor.TypedActorConfiguration;
|
||||
import akka.util.FiniteDuration;
|
||||
|
||||
TypedActorConfiguration config = new TypedActorConfiguration()
|
||||
.timeout(3000)
|
||||
.makeTransactionRequired();
|
||||
.timeout(new FiniteDuration(3000, MILLISECONDS));
|
||||
|
||||
RegistrationService service = (RegistrationService) TypedActor.newInstance(RegistrationService.class, config);
|
||||
|
||||
|
|
@ -161,7 +166,7 @@ Here is an example how you can use it to in a 'void' (e.g. fire-forget) method t
|
|||
class PingImpl implements Ping extends TypedActor {
|
||||
|
||||
public void hit(int count) {
|
||||
Pong pong = (Pong) context.getSender();
|
||||
Pong pong = (Pong) getContext().getSender();
|
||||
pong.hit(count++);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ If you are using the `Spring Framework <http://springsource.org>`_ then take a l
|
|||
Creating Typed Actors
|
||||
---------------------
|
||||
|
||||
**IMPORTANT:** The Typed Actors class must have access modifier 'public' and can't be an inner class (unless it is an inner class in an 'object').
|
||||
**IMPORTANT:** The Typed Actors class must have access modifier 'public' (which is default) and can't be an inner class (unless it is an inner class in an 'object').
|
||||
|
||||
Akka turns POJOs with interface and implementation into asynchronous (Typed) Actors. Akka is using `AspectWerkz’s Proxy <http://blogs.codehaus.org/people/jboner/archives/000914_awproxy_proxy_on_steriods.html>`_ implementation, which is the `most performant <http://docs.codehaus.org/display/AW/AOP+Benchmark>`_ proxy implementation there exists.
|
||||
|
||||
|
|
@ -22,6 +22,8 @@ If you have a POJO with an interface implementation separation like this:
|
|||
|
||||
.. code-block:: scala
|
||||
|
||||
import akka.actor.TypedActor
|
||||
|
||||
trait RegistrationService {
|
||||
def register(user: User, cred: Credentials): Unit
|
||||
def getUserFor(username: String): User
|
||||
|
|
@ -64,10 +66,12 @@ Configuration factory class
|
|||
Using a configuration object:
|
||||
|
||||
.. code-block:: scala
|
||||
import akka.actor.TypedActorConfiguration
|
||||
import akka.util.Duration
|
||||
import akka.util.duration._
|
||||
|
||||
val config = new TypedActorConfiguration
|
||||
.timeout(3000)
|
||||
.makeTransactionRequired
|
||||
val config = TypedActorConfiguration()
|
||||
.timeout(3000 millis)
|
||||
|
||||
val service = TypedActor.newInstance(classOf[RegistrationService], classOf[RegistrationServiceImpl], config)
|
||||
|
||||
|
|
|
|||
|
|
@ -26,8 +26,6 @@ Here is an example:
|
|||
}
|
||||
}
|
||||
|
||||
The 'UntypedActor' class inherits from the 'akka.util.Logging' class which defines a logger in the 'log' field that you can use to log. The logging uses SLF4j backed by logback - for more information on how to configure the logger see `Logging <logging>`_.
|
||||
|
||||
Creating Actors
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
@ -35,7 +33,7 @@ Creating an Actor is done using the 'akka.actor.Actors.actorOf' factory method.
|
|||
|
||||
.. code-block:: java
|
||||
|
||||
ActorRef actor = Actors.actorOf(SampleUntypedActor.class);
|
||||
ActorRef myActor = Actors.actorOf(SampleUntypedActor.class);
|
||||
myActor.start();
|
||||
|
||||
Normally you would want to import the 'actorOf' method like this:
|
||||
|
|
@ -43,7 +41,7 @@ Normally you would want to import the 'actorOf' method like this:
|
|||
.. code-block:: java
|
||||
|
||||
import static akka.actor.Actors.*;
|
||||
ActorRef actor = actorOf(SampleUntypedActor.class);
|
||||
ActorRef myActor = actorOf(SampleUntypedActor.class);
|
||||
|
||||
To avoid prefix it with 'Actors' every time you use it.
|
||||
|
||||
|
|
@ -51,7 +49,7 @@ You can also create & start the actor in one statement:
|
|||
|
||||
.. code-block:: java
|
||||
|
||||
ActorRef actor = actorOf(SampleUntypedActor.class).start();
|
||||
ActorRef myActor = actorOf(SampleUntypedActor.class).start();
|
||||
|
||||
The call to 'actorOf' returns an instance of 'ActorRef'. This is a handle to the 'UntypedActor' instance which you can use to interact with the Actor, like send messages to it etc. more on this shortly. The 'ActorRef' is immutble and has a one to one relationship with the Actor it represents. The 'ActorRef' is also serializable and network-aware. This means that you can serialize it, send it over the wire and use it on a remote host and it will still be representing the same Actor on the original node, across the network.
|
||||
|
||||
|
|
@ -156,7 +154,7 @@ Using 'sendRequestReplyFuture' will send a message to the receiving Actor asynch
|
|||
|
||||
.. code-block:: java
|
||||
|
||||
Future future= actorRef.sendRequestReplyFuture("Hello", getContext(), 1000);
|
||||
Future future = actorRef.sendRequestReplyFuture("Hello", getContext(), 1000);
|
||||
|
||||
The 'Future' interface looks like this:
|
||||
|
||||
|
|
@ -177,7 +175,7 @@ So the normal way of working with futures is something like this:
|
|||
|
||||
.. code-block:: java
|
||||
|
||||
Future future= actorRef.sendRequestReplyFuture("Hello", getContext(), 1000);
|
||||
Future future = actorRef.sendRequestReplyFuture("Hello", getContext(), 1000);
|
||||
future.await();
|
||||
if (future.isCompleted()) {
|
||||
Option resultOption = future.result();
|
||||
|
|
@ -190,13 +188,6 @@ So the normal way of working with futures is something like this:
|
|||
|
||||
The 'onComplete' callback can be used to register a callback to get a notification when the Future completes. Gives you a way to avoid blocking.
|
||||
|
||||
We also have a utility class 'Futures' that have a couple of convenience methods:
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
void awaitAll(Future[] futures);
|
||||
Future awaitOne(Future[] futures)
|
||||
|
||||
Forward message
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
@ -209,7 +200,7 @@ You can forward a message from one actor to another. This means that the origina
|
|||
Receive messages
|
||||
----------------
|
||||
|
||||
When an actor receives a message is passed into the 'onReceive' method, this is an abstract method on the 'UntypedActor' base class that needs to be defined.
|
||||
When an actor receives a message it is passed into the 'onReceive' method, this is an abstract method on the 'UntypedActor' base class that needs to be defined.
|
||||
|
||||
Here is an example:
|
||||
|
||||
|
|
@ -218,8 +209,10 @@ Here is an example:
|
|||
public class SampleUntypedActor extends UntypedActor {
|
||||
|
||||
public void onReceive(Object message) throws Exception {
|
||||
if (message instanceof String) log.info("Received String message: %s", message);
|
||||
else throw new IllegalArgumentException("Unknown message: " + message);
|
||||
if (message instanceof String)
|
||||
EventHandler.info(this, String.format("Received String message: %s", message));
|
||||
else
|
||||
throw new IllegalArgumentException("Unknown message: " + message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -243,7 +236,7 @@ If you want to send a message back to the original sender of the message you jus
|
|||
}
|
||||
}
|
||||
|
||||
In this case we will a reply back to the Actor that send the message.
|
||||
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.
|
||||
|
||||
|
|
@ -393,6 +386,8 @@ Use it like this:
|
|||
|
||||
.. code-block:: java
|
||||
|
||||
import static akka.actor.Actors.*;
|
||||
|
||||
actor.sendOneWay(poisonPill());
|
||||
|
||||
Killing an Actor
|
||||
|
|
@ -404,6 +399,8 @@ Use it like this:
|
|||
|
||||
.. code-block:: java
|
||||
|
||||
import static akka.actor.Actors.*;
|
||||
|
||||
// kill the actor called 'victim'
|
||||
victim.sendOneWay(kill());
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue