Deprecate actorFor in favor of ActorSelection, see #3074
* Deprecate all actorFor methods * resolveActorRef in provider * Identify auto receive message * Support ActorPath in actorSelection * Support remote actor selections * Additional tests of actor selection * Update tests (keep most actorFor tests) * Update samples to use actorSelection * Updates to documentation * Migration guide, including motivation
This commit is contained in:
parent
641e499cc4
commit
887af975ae
80 changed files with 1496 additions and 619 deletions
|
|
@ -176,12 +176,13 @@ public class TypedActorDocTestBase {
|
|||
|
||||
@Test public void proxyAnyActorRef() {
|
||||
try {
|
||||
final ActorRef actorRefToRemoteActor = system.deadLetters();
|
||||
//#typed-actor-remote
|
||||
Squarer typedActor =
|
||||
TypedActor.get(system).
|
||||
typedActorOf(
|
||||
new TypedProps<Squarer>(Squarer.class),
|
||||
system.actorFor("akka://SomeSystem@somehost:2552/user/some/foobar")
|
||||
actorRefToRemoteActor
|
||||
);
|
||||
//Use "typedActor" as a FooBar
|
||||
//#typed-actor-remote
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import akka.dispatch.Futures;
|
|||
import akka.dispatch.Mapper;
|
||||
import scala.concurrent.Await;
|
||||
import scala.concurrent.duration.Duration;
|
||||
import akka.testkit.AkkaSpec;
|
||||
import akka.util.Timeout;
|
||||
//#import-future
|
||||
|
||||
|
|
@ -31,6 +32,12 @@ import akka.japi.Procedure;
|
|||
import akka.actor.Terminated;
|
||||
//#import-watch
|
||||
|
||||
//#import-identify
|
||||
import akka.actor.ActorSelection;
|
||||
import akka.actor.Identify;
|
||||
import akka.actor.ActorIdentity;
|
||||
//#import-identify
|
||||
|
||||
//#import-gracefulStop
|
||||
import static akka.pattern.Patterns.gracefulStop;
|
||||
import scala.concurrent.Future;
|
||||
|
|
@ -58,6 +65,8 @@ import akka.actor.UntypedActor;
|
|||
import akka.actor.UntypedActorFactory;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import scala.Option;
|
||||
import java.lang.Object;
|
||||
import java.util.Iterator;
|
||||
|
|
@ -65,6 +74,19 @@ import akka.pattern.Patterns;
|
|||
|
||||
public class UntypedActorDocTestBase {
|
||||
|
||||
private static ActorSystem system;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeAll() {
|
||||
system = ActorSystem.create("MySystem", AkkaSpec.testConf());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterAll() {
|
||||
system.shutdown();
|
||||
system = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createProps() {
|
||||
//#creating-props-config
|
||||
|
|
@ -96,86 +118,71 @@ public class UntypedActorDocTestBase {
|
|||
@Test
|
||||
public void contextActorOf() {
|
||||
//#context-actorOf
|
||||
ActorSystem system = ActorSystem.create("MySystem");
|
||||
ActorRef myActor = system.actorOf(new Props(MyUntypedActor.class), "myactor");
|
||||
ActorRef myActor = system.actorOf(new Props(MyUntypedActor.class), "myactor2");
|
||||
//#context-actorOf
|
||||
myActor.tell("test", null);
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorActorOf() {
|
||||
ActorSystem system = ActorSystem.create("MySystem");
|
||||
//#creating-constructor
|
||||
// allows passing in arguments to the MyActor constructor
|
||||
ActorRef myActor = system.actorOf(new Props(new UntypedActorFactory() {
|
||||
public UntypedActor create() {
|
||||
return new MyActor("...");
|
||||
}
|
||||
}), "myactor");
|
||||
}), "myactor3");
|
||||
//#creating-constructor
|
||||
myActor.tell("test", null);
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propsActorOf() {
|
||||
ActorSystem system = ActorSystem.create("MySystem");
|
||||
//#creating-props
|
||||
ActorRef myActor = system.actorOf(
|
||||
new Props(MyUntypedActor.class).withDispatcher("my-dispatcher"), "myactor");
|
||||
new Props(MyUntypedActor.class).withDispatcher("my-dispatcher"), "myactor4");
|
||||
//#creating-props
|
||||
myActor.tell("test", null);
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usingAsk() throws Exception {
|
||||
ActorSystem system = ActorSystem.create("MySystem");
|
||||
ActorRef myActor = system.actorOf(new Props(new UntypedActorFactory() {
|
||||
public UntypedActor create() {
|
||||
return new MyAskActor();
|
||||
}
|
||||
}), "myactor");
|
||||
}), "myactor5");
|
||||
|
||||
//#using-ask
|
||||
Future<Object> future = Patterns.ask(myActor, "Hello", 1000);
|
||||
Object result = Await.result(future, Duration.create(1, TimeUnit.SECONDS));
|
||||
//#using-ask
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void receiveTimeout() {
|
||||
ActorSystem system = ActorSystem.create("MySystem");
|
||||
ActorRef myActor = system.actorOf(new Props(MyReceivedTimeoutUntypedActor.class));
|
||||
myActor.tell("Hello", null);
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usePoisonPill() {
|
||||
ActorSystem system = ActorSystem.create("MySystem");
|
||||
ActorRef myActor = system.actorOf(new Props(MyUntypedActor.class));
|
||||
//#poison-pill
|
||||
myActor.tell(PoisonPill.getInstance(), null);
|
||||
//#poison-pill
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useKill() {
|
||||
ActorSystem system = ActorSystem.create("MySystem");
|
||||
ActorRef victim = system.actorOf(new Props(MyUntypedActor.class));
|
||||
//#kill
|
||||
victim.tell(Kill.getInstance(), null);
|
||||
//#kill
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useBecome() {
|
||||
ActorSystem system = ActorSystem.create("MySystem");
|
||||
ActorRef myActor = system.actorOf(new Props(new UntypedActorFactory() {
|
||||
public UntypedActor create() {
|
||||
return new HotSwapActor();
|
||||
|
|
@ -184,21 +191,24 @@ public class UntypedActorDocTestBase {
|
|||
myActor.tell("foo", null);
|
||||
myActor.tell("bar", null);
|
||||
myActor.tell("bar", null);
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useWatch() throws Exception {
|
||||
ActorSystem system = ActorSystem.create("MySystem");
|
||||
ActorRef myActor = system.actorOf(new Props(WatchActor.class));
|
||||
Future<Object> future = Patterns.ask(myActor, "kill", 1000);
|
||||
assert Await.result(future, Duration.create("1 second")).equals("finished");
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useIdentify() throws Exception {
|
||||
ActorRef a = system.actorOf(new Props(MyUntypedActor.class), "another");
|
||||
ActorRef b = system.actorOf(new Props(Follower.class));
|
||||
system.stop(a);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usePatternsGracefulStop() throws Exception {
|
||||
ActorSystem system = ActorSystem.create("MySystem");
|
||||
ActorRef actorRef = system.actorOf(new Props(MyUntypedActor.class));
|
||||
//#gracefulStop
|
||||
try {
|
||||
|
|
@ -210,7 +220,6 @@ public class UntypedActorDocTestBase {
|
|||
// the actor wasn't stopped within 5 seconds
|
||||
}
|
||||
//#gracefulStop
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
class Result {
|
||||
|
|
@ -225,7 +234,6 @@ public class UntypedActorDocTestBase {
|
|||
|
||||
@Test
|
||||
public void usePatternsAskPipe() {
|
||||
ActorSystem system = ActorSystem.create("MySystem");
|
||||
ActorRef actorA = system.actorOf(new Props(MyUntypedActor.class));
|
||||
ActorRef actorB = system.actorOf(new Props(MyUntypedActor.class));
|
||||
ActorRef actorC = system.actorOf(new Props(MyUntypedActor.class));
|
||||
|
|
@ -251,7 +259,6 @@ public class UntypedActorDocTestBase {
|
|||
|
||||
pipe(transformed, system.dispatcher()).to(actorC);
|
||||
//#ask-pipe
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
public static class MyActor extends UntypedActor {
|
||||
|
|
@ -399,4 +406,40 @@ public class UntypedActorDocTestBase {
|
|||
}
|
||||
//#watch
|
||||
|
||||
static
|
||||
//#identify
|
||||
public class Follower extends UntypedActor {
|
||||
String identifyId = "1";
|
||||
{
|
||||
ActorSelection selection =
|
||||
getContext().actorSelection("/user/another");
|
||||
selection.tell(new Identify(identifyId), getSelf());
|
||||
}
|
||||
ActorRef another;
|
||||
|
||||
@Override
|
||||
public void onReceive(Object message) {
|
||||
if (message instanceof ActorIdentity) {
|
||||
ActorIdentity identity = (ActorIdentity) message;
|
||||
if (identity.correlationId().equals(identifyId)) {
|
||||
ActorRef ref = identity.getRef();
|
||||
if (ref == null)
|
||||
getContext().stop(getSelf());
|
||||
else {
|
||||
another = ref;
|
||||
getContext().watch(another);
|
||||
}
|
||||
}
|
||||
} else if (message instanceof Terminated) {
|
||||
final Terminated t = (Terminated) message;
|
||||
if (t.getActor().equals(another)) {
|
||||
getContext().stop(getSelf());
|
||||
}
|
||||
} else {
|
||||
unhandled(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
//#identify
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,10 +49,10 @@ public class SerializationDocTestBase {
|
|||
//#my-own-serializer
|
||||
|
||||
@Test public void serializeActorRefs() {
|
||||
final ActorSystem theActorSystem =
|
||||
final ExtendedActorSystem extendedSystem = (ExtendedActorSystem)
|
||||
ActorSystem.create("whatever");
|
||||
final ActorRef theActorRef =
|
||||
theActorSystem.deadLetters(); // Of course this should be you
|
||||
extendedSystem.deadLetters(); // Of course this should be you
|
||||
|
||||
//#actorref-serializer
|
||||
// Serialize
|
||||
|
|
@ -63,10 +63,10 @@ public class SerializationDocTestBase {
|
|||
|
||||
// Deserialize
|
||||
// (beneath fromBinary)
|
||||
final ActorRef deserializedActorRef = theActorSystem.actorFor(identifier);
|
||||
final ActorRef deserializedActorRef = extendedSystem.provider().resolveActorRef(identifier);
|
||||
// Then just use the ActorRef
|
||||
//#actorref-serializer
|
||||
theActorSystem.shutdown();
|
||||
extendedSystem.shutdown();
|
||||
}
|
||||
|
||||
static
|
||||
|
|
@ -150,7 +150,7 @@ public class SerializationDocTestBase {
|
|||
return new DefaultAddressExt(system);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//#external-address-default
|
||||
|
||||
public void demonstrateDefaultAddress() {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import akka.actor.ActorKilledException;
|
|||
import akka.actor.ActorRef;
|
||||
import akka.actor.ActorSystem;
|
||||
import akka.actor.Kill;
|
||||
import akka.actor.PoisonPill;
|
||||
import akka.actor.Props;
|
||||
import akka.actor.Terminated;
|
||||
import akka.actor.UntypedActor;
|
||||
|
|
@ -30,7 +31,7 @@ import akka.testkit.JavaTestKit;
|
|||
import scala.concurrent.duration.Duration;
|
||||
|
||||
public class TestKitDocTest {
|
||||
|
||||
|
||||
//#test-actor-ref
|
||||
static class MyActor extends UntypedActor {
|
||||
public void onReceive(Object o) throws Exception {
|
||||
|
|
@ -42,18 +43,18 @@ public class TestKitDocTest {
|
|||
}
|
||||
public boolean testMe() { return true; }
|
||||
}
|
||||
|
||||
|
||||
//#test-actor-ref
|
||||
|
||||
|
||||
private static ActorSystem system;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() {
|
||||
final Config config = ConfigFactory.parseString(
|
||||
"akka.loggers = [akka.testkit.TestEventListener]");
|
||||
system = ActorSystem.create("demoSystem", config);
|
||||
}
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void cleanup() {
|
||||
system.shutdown();
|
||||
|
|
@ -68,7 +69,7 @@ public class TestKitDocTest {
|
|||
assertTrue(actor.testMe());
|
||||
}
|
||||
//#test-actor-ref
|
||||
|
||||
|
||||
@Test
|
||||
public void demonstrateAsk() throws Exception {
|
||||
//#test-behavior
|
||||
|
|
@ -79,7 +80,7 @@ public class TestKitDocTest {
|
|||
assertEquals(42, Await.result(future, Duration.Zero()));
|
||||
//#test-behavior
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void demonstrateExceptions() {
|
||||
//#test-expecting-exceptions
|
||||
|
|
@ -93,7 +94,7 @@ public class TestKitDocTest {
|
|||
}
|
||||
//#test-expecting-exceptions
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void demonstrateWithin() {
|
||||
//#test-within
|
||||
|
|
@ -108,7 +109,7 @@ public class TestKitDocTest {
|
|||
}};
|
||||
//#test-within
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void demonstrateExpectMsg() {
|
||||
//#test-expectmsg
|
||||
|
|
@ -128,7 +129,7 @@ public class TestKitDocTest {
|
|||
}};
|
||||
//#test-expectmsg
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void demonstrateReceiveWhile() {
|
||||
//#test-receivewhile
|
||||
|
|
@ -136,7 +137,7 @@ public class TestKitDocTest {
|
|||
getRef().tell(42, null);
|
||||
getRef().tell(43, null);
|
||||
getRef().tell("hello", null);
|
||||
final String[] out =
|
||||
final String[] out =
|
||||
new ReceiveWhile<String>(String.class, duration("1 second")) {
|
||||
// do not put code outside this method, will run afterwards
|
||||
protected String match(Object in) {
|
||||
|
|
@ -168,7 +169,7 @@ public class TestKitDocTest {
|
|||
//#test-receivewhile-full
|
||||
}};
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void demonstrateAwaitCond() {
|
||||
//#test-awaitCond
|
||||
|
|
@ -205,7 +206,7 @@ public class TestKitDocTest {
|
|||
}};
|
||||
//#test-awaitAssert
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked") // due to generic varargs
|
||||
public void demonstrateExpect() {
|
||||
|
|
@ -236,7 +237,7 @@ public class TestKitDocTest {
|
|||
assertArrayEquals(new String[] {"hello", "world"}, all);
|
||||
}};
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void demonstrateIgnoreMsg() {
|
||||
//#test-ignoreMsg
|
||||
|
|
@ -268,7 +269,7 @@ public class TestKitDocTest {
|
|||
}};
|
||||
//#duration-dilation
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void demonstrateProbe() {
|
||||
//#test-probe
|
||||
|
|
@ -282,11 +283,11 @@ public class TestKitDocTest {
|
|||
target.forward(msg, getContext());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
new JavaTestKit(system) {{
|
||||
// create a test probe
|
||||
final JavaTestKit probe = new JavaTestKit(system);
|
||||
|
||||
|
||||
// create a forwarder, injecting the probe’s testActor
|
||||
final Props props = new Props(new UntypedActorFactory() {
|
||||
private static final long serialVersionUID = 8927158735963950216L;
|
||||
|
|
@ -295,7 +296,7 @@ public class TestKitDocTest {
|
|||
}
|
||||
});
|
||||
final ActorRef forwarder = system.actorOf(props, "forwarder");
|
||||
|
||||
|
||||
// verify correct forwarding
|
||||
forwarder.tell(42, getRef());
|
||||
probe.expectMsgEquals(42);
|
||||
|
|
@ -303,7 +304,7 @@ public class TestKitDocTest {
|
|||
}};
|
||||
//#test-probe
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void demonstrateSpecialProbe() {
|
||||
//#test-special-probe
|
||||
|
|
@ -323,20 +324,21 @@ public class TestKitDocTest {
|
|||
}};
|
||||
//#test-special-probe
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void demonstrateWatch() {
|
||||
final ActorRef target = system.actorFor("/buh");
|
||||
final ActorRef target = system.actorOf(new Props(MyActor.class));
|
||||
//#test-probe-watch
|
||||
new JavaTestKit(system) {{
|
||||
final JavaTestKit probe = new JavaTestKit(system);
|
||||
probe.watch(target);
|
||||
target.tell(PoisonPill.getInstance(), null);
|
||||
final Terminated msg = probe.expectMsgClass(Terminated.class);
|
||||
assertEquals(msg.getActor(), target);
|
||||
}};
|
||||
//#test-probe-watch
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void demonstrateReply() {
|
||||
//#test-probe-reply
|
||||
|
|
@ -350,7 +352,7 @@ public class TestKitDocTest {
|
|||
}};
|
||||
//#test-probe-reply
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void demonstrateForward() {
|
||||
//#test-probe-forward
|
||||
|
|
@ -364,7 +366,7 @@ public class TestKitDocTest {
|
|||
}};
|
||||
//#test-probe-forward
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void demonstrateWithinProbe() {
|
||||
try {
|
||||
|
|
@ -382,7 +384,7 @@ public class TestKitDocTest {
|
|||
// expected to fail
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void demonstrateAutoPilot() {
|
||||
//#test-auto-pilot
|
||||
|
|
@ -404,7 +406,7 @@ public class TestKitDocTest {
|
|||
}};
|
||||
//#test-auto-pilot
|
||||
}
|
||||
|
||||
|
||||
// only compilation
|
||||
public void demonstrateCTD() {
|
||||
//#calling-thread-dispatcher
|
||||
|
|
@ -413,24 +415,24 @@ public class TestKitDocTest {
|
|||
.withDispatcher(CallingThreadDispatcher.Id()));
|
||||
//#calling-thread-dispatcher
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void demonstrateEventFilter() {
|
||||
//#test-event-filter
|
||||
new JavaTestKit(system) {{
|
||||
assertEquals("demoSystem", system.name());
|
||||
final ActorRef victim = system.actorOf(Props.empty(), "victim");
|
||||
|
||||
|
||||
final int result = new EventFilter<Integer>(ActorKilledException.class) {
|
||||
protected Integer run() {
|
||||
victim.tell(Kill.getInstance(), null);
|
||||
return 42;
|
||||
}
|
||||
}.from("akka://demoSystem/user/victim").occurrences(1).exec();
|
||||
|
||||
|
||||
assertEquals(42, result);
|
||||
}};
|
||||
//#test-event-filter
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,17 +70,24 @@ reference file for more information:
|
|||
Looking up Remote Actors
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
``actorFor(path)`` will obtain an ``ActorRef`` to an Actor on a remote node::
|
||||
``actorSelection(path)`` will obtain an ``ActorSelection`` to an Actor on a remote node::
|
||||
|
||||
ActorRef actor = context.actorFor("akka.tcp://app@10.0.0.1:2552/user/serviceA/worker");
|
||||
ActorSelection selection =
|
||||
context.actorSelection("akka.tcp://app@10.0.0.1:2552/user/serviceA/worker");
|
||||
|
||||
As you can see from the example above the following pattern is used to find an ``ActorRef`` on a remote node::
|
||||
As you can see from the example above the following pattern is used to find an actor on a remote node::
|
||||
|
||||
akka.<protocol>://<actorsystemname>@<hostname>:<port>/<actor path>
|
||||
|
||||
Once you obtained a reference to the actor you can interact with it they same way you would with a local actor, e.g.::
|
||||
Once you obtained a selection to the actor you can interact with it they same way you would with a local actor, e.g.::
|
||||
|
||||
actor.tell("Pretty awesome feature", getSelf());
|
||||
selection.tell("Pretty awesome feature", getSelf());
|
||||
|
||||
To acquire an :class:`ActorRef` for an :class:`ActorSelection` you need to
|
||||
send a message to the selection and use the ``getSender`` reference of the reply from
|
||||
the actor. There is a built-in ``Identify`` message that all Actors will understand
|
||||
and automatically reply to with a ``ActorIdentity`` message containing the
|
||||
:class:`ActorRef`.
|
||||
|
||||
.. note::
|
||||
|
||||
|
|
@ -264,9 +271,9 @@ and it is created from an actor system using the aforementioned client’s confi
|
|||
.. includecode:: ../../../akka-samples/akka-sample-remote/src/main/java/sample/remote/calculator/java/JLookupApplication.java
|
||||
:include: setup
|
||||
|
||||
Requests which come in via ``doSomething`` will be sent to the client actor
|
||||
along with the reference which was looked up earlier. Observe how the actor
|
||||
system name using in ``actorFor`` matches the remote system’s name, as do IP
|
||||
Requests which come in via ``doSomething`` will be sent to the client actor,
|
||||
which will use the actor reference that was identified earlier. Observe how the actor
|
||||
system name using in ``actorSelection`` matches the remote system’s name, as do IP
|
||||
and port number. Top-level actors are always created below the ``"/user"``
|
||||
guardian, which supervises them.
|
||||
|
||||
|
|
@ -481,14 +488,14 @@ SSL can be used as the remote transport by adding ``akka.remote.netty.ssl``
|
|||
to the ``enabled-transport`` configuration section. See a description of the settings
|
||||
in the :ref:`remoting-java-configuration` section.
|
||||
|
||||
The SSL support is implemented with Java Secure Socket Extension, please consult the offical
|
||||
The SSL support is implemented with Java Secure Socket Extension, please consult the offical
|
||||
`Java Secure Socket Extension documentation <http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html>`_
|
||||
and related resources for troubleshooting.
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
When using SHA1PRNG on Linux it's recommended specify ``-Djava.security.egd=file:/dev/./urandom`` as argument
|
||||
When using SHA1PRNG on Linux it's recommended specify ``-Djava.security.egd=file:/dev/./urandom`` as argument
|
||||
to the JVM to prevent blocking. It is NOT as secure because it reuses the seed.
|
||||
Use '/dev/./urandom', not '/dev/urandom' as that doesn't work according to
|
||||
Use '/dev/./urandom', not '/dev/urandom' as that doesn't work according to
|
||||
`Bug ID: 6202721 <http://bugs.sun.com/view_bug.do?bug_id=6202721>`_.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -206,11 +206,11 @@ Proxying
|
|||
--------
|
||||
|
||||
You can use the ``typedActorOf`` that takes a TypedProps and an ActorRef to proxy the given ActorRef as a TypedActor.
|
||||
This is usable if you want to communicate remotely with TypedActors on other machines, just look them up with ``actorFor`` and pass the ``ActorRef`` to ``typedActorOf``.
|
||||
This is usable if you want to communicate remotely with TypedActors on other machines, just pass the ``ActorRef`` to ``typedActorOf``.
|
||||
|
||||
Lookup & Remoting
|
||||
-----------------
|
||||
|
||||
Since ``TypedActors`` are backed by ``Akka Actors``, you can use ``actorFor`` together with ``typedActorOf`` to proxy ``ActorRefs`` potentially residing on remote nodes.
|
||||
Since ``TypedActors`` are backed by ``Akka Actors``, you can use ``typedActorOf`` to proxy ``ActorRefs`` potentially residing on remote nodes.
|
||||
|
||||
.. includecode:: code/docs/actor/TypedActorDocTestBase.java#typed-actor-remote
|
||||
|
|
|
|||
|
|
@ -27,8 +27,7 @@ Creating Actors
|
|||
Since Akka enforces parental supervision every actor is supervised and
|
||||
(potentially) the supervisor of its children, it is advisable that you
|
||||
familiarize yourself with :ref:`actor-systems` and :ref:`supervision` and it
|
||||
may also help to read :ref:`actorOf-vs-actorFor` (the whole of
|
||||
:ref:`addressing` is recommended reading in any case).
|
||||
may also help to read :ref:`addressing`.
|
||||
|
||||
Defining an Actor class
|
||||
-----------------------
|
||||
|
|
@ -130,7 +129,7 @@ The :class:`UntypedActor` class defines only one abstract method, the above ment
|
|||
If the current actor behavior does not match a received message, it's recommended that
|
||||
you call the :meth:`unhandled` method, which by default publishes a ``new
|
||||
akka.actor.UnhandledMessage(message, sender, recipient)`` on the actor system’s
|
||||
event stream (set configuration item ``akka.actor.debug.unhandled`` to ``on``
|
||||
event stream (set configuration item ``akka.actor.debug.unhandled`` to ``on``
|
||||
to have them converted into actual Debug messages).
|
||||
|
||||
In addition, it offers:
|
||||
|
|
@ -227,7 +226,7 @@ mentioned above:
|
|||
in turn by its supervisor, or if an actor is restarted due to a sibling’s
|
||||
failure. If the message is available, then that message’s sender is also
|
||||
accessible in the usual way (i.e. by calling ``getSender()``).
|
||||
|
||||
|
||||
This method is the best place for cleaning up, preparing hand-over to the
|
||||
fresh actor instance, etc. By default it stops all children and calls
|
||||
:meth:`postStop`.
|
||||
|
|
@ -264,8 +263,10 @@ sent to a stopped actor will be redirected to the :obj:`deadLetters` of the
|
|||
:obj:`ActorSystem`.
|
||||
|
||||
|
||||
Identifying Actors
|
||||
==================
|
||||
.. _actorSelection-java:
|
||||
|
||||
Identifying Actors via Actor Selection
|
||||
======================================
|
||||
|
||||
As described in :ref:`addressing`, each actor has a unique logical path, which
|
||||
is obtained by following the chain of actors from child to parent until
|
||||
|
|
@ -274,11 +275,13 @@ differ if the supervision chain includes any remote supervisors. These paths
|
|||
are used by the system to look up actors, e.g. when a remote message is
|
||||
received and the recipient is searched, but they are also useful more directly:
|
||||
actors may look up other actors by specifying absolute or relative
|
||||
paths—logical or physical—and receive back an :class:`ActorRef` with the
|
||||
paths—logical or physical—and receive back an :class:`ActorSelection` with the
|
||||
result::
|
||||
|
||||
getContext().actorFor("/user/serviceA/actor") // will look up this absolute path
|
||||
getContext().actorFor("../joe") // will look up sibling beneath same supervisor
|
||||
// will look up this absolute path
|
||||
getContext().actorSelection("/user/serviceA/actor");
|
||||
// will look up sibling beneath same supervisor
|
||||
getContext().actorSelection("../joe");
|
||||
|
||||
The supplied path is parsed as a :class:`java.net.URI`, which basically means
|
||||
that it is split on ``/`` into path elements. If the path starts with ``/``, it
|
||||
|
|
@ -289,18 +292,43 @@ currently traversed actor, otherwise it will step “down” to the named child.
|
|||
It should be noted that the ``..`` in actor paths here always means the logical
|
||||
structure, i.e. the supervisor.
|
||||
|
||||
If the path being looked up does not exist, a special actor reference is
|
||||
returned which behaves like the actor system’s dead letter queue but retains
|
||||
its identity (i.e. the path which was looked up).
|
||||
The path elements of an actor selection may contain wildcard patterns allowing for
|
||||
broadcasting of messages to that section::
|
||||
|
||||
Remote actor addresses may also be looked up, if remoting is enabled::
|
||||
// will look all children to serviceB with names starting with worker
|
||||
getContext().actorSelection("/user/serviceB/worker*");
|
||||
// will look up all siblings beneath same supervisor
|
||||
getContext().actorSelection("../*");
|
||||
|
||||
getContext().actorFor("akka.tcp://app@otherhost:1234/user/serviceB")
|
||||
Messages can be sent via the :class:`ActorSelection` and the path of the
|
||||
:class:`ActorSelection` is looked up when delivering each message. If the selection
|
||||
does not match any actors the message will be dropped.
|
||||
|
||||
These look-ups return a (possibly remote) actor reference immediately, so you
|
||||
will have to send to it and await a reply in order to verify that ``serviceB``
|
||||
is actually reachable and running. An example demonstrating actor look-up is
|
||||
given in :ref:`remote-lookup-sample-java`.
|
||||
To acquire an :class:`ActorRef` for an :class:`ActorSelection` you need to
|
||||
send a message to the selection and use the ``getSender`` reference of the reply from
|
||||
the actor. There is a built-in ``Identify`` message that all Actors will understand
|
||||
and automatically reply to with a ``ActorIdentity`` message containing the
|
||||
:class:`ActorRef`.
|
||||
|
||||
.. includecode:: code/docs/actor/UntypedActorDocTestBase.java
|
||||
:include: identify-imports,identify
|
||||
|
||||
Remote actor addresses may also be looked up, if :ref:`remoting <remoting-java>` is enabled::
|
||||
|
||||
getContext().actorSelection("akka.tcp://app@otherhost:1234/user/serviceB");
|
||||
|
||||
An example demonstrating remote actor look-up is given in :ref:`remote-lookup-sample-java`.
|
||||
|
||||
.. note::
|
||||
|
||||
``actorFor`` is deprecated in favor of ``actorSelection`` because actor references
|
||||
acquired with ``actorFor`` behave differently for local and remote actors.
|
||||
In the case of a local actor reference, the named actor needs to exist before the
|
||||
lookup, or else the acquired reference will be an :class:`EmptyLocalActorRef`.
|
||||
This will be true even if an actor with that exact path is created after acquiring
|
||||
the actor reference. For remote actor references acquired with `actorFor` the
|
||||
behaviour is different and sending messages to such a reference will under the hood
|
||||
look up the actor by path on the remote system for every message send.
|
||||
|
||||
Messages and immutability
|
||||
=========================
|
||||
|
|
@ -603,7 +631,7 @@ The other way of using :meth:`become` does not replace but add to the top of
|
|||
the behavior stack. In this case care must be taken to ensure that the number
|
||||
of “pop” operations (i.e. :meth:`unbecome`) matches the number of “push” ones
|
||||
in the long run, otherwise this amounts to a memory leak (which is why this
|
||||
behavior is not the default).
|
||||
behavior is not the default).
|
||||
|
||||
.. includecode:: code/docs/actor/UntypedActorSwapper.java#swapper
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue