improve AbstractActor, #21717

* Receive class that wraps PartialFunction, to avoid
  scary scala types
* move AbstractActorContext to AbstractActor.ActorContext
* converting docs, many, many UntypedActor
* removing UntypedActor docs
* add unit test for ReceiveBuilder
* MiMa filters
* consistent use of getContext(), self(), sender()
* rename cross references
* migration guide
* skip samples for now
* improve match type safetyi, add matchUnchecked
  * the `? extends P` caused code like this to compile:
    `match(String.class, (Integer i) -> {})`
  * added matchUnchecked, since it can still be useful (um, convenient)
    to be able to do:
    `matchUnchecked(List.class, (List<String> list) -> {})`
* eleminate some scala.Option
  * preRestart
  * findChild
  * ActorIdentity.getActorRef
This commit is contained in:
Patrik Nordwall 2016-12-13 10:59:29 +01:00
parent 3617fe8b41
commit 4bd6b7aab1
157 changed files with 3290 additions and 8882 deletions

View file

@ -1,639 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor;
import akka.actor.*;
import akka.japi.pf.ReceiveBuilder;
import akka.testkit.ErrorFilter;
import akka.testkit.EventFilter;
import akka.testkit.TestEvent;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import docs.AbstractJavaTest;
import org.scalatest.junit.JUnitSuite;
import scala.PartialFunction;
import scala.runtime.BoxedUnit;
import static docs.actor.Messages.Swap.Swap;
import static akka.japi.Util.immutableSeq;
import java.util.concurrent.TimeUnit;
import akka.testkit.JavaTestKit;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
//#import-props
import akka.actor.Props;
//#import-props
//#import-actorRef
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
//#import-actorRef
//#import-identify
import akka.actor.ActorIdentity;
import akka.actor.ActorSelection;
import akka.actor.Identify;
//#import-identify
//#import-graceFulStop
import akka.pattern.AskTimeoutException;
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;
import scala.concurrent.Future;
import static akka.pattern.Patterns.gracefulStop;
//#import-graceFulStop
public class ActorDocTest extends AbstractJavaTest {
public static Config config = ConfigFactory.parseString(
"akka {\n" +
" loggers = [\"akka.testkit.TestEventListener\"]\n" +
" loglevel = \"WARNING\"\n" +
" stdout-loglevel = \"WARNING\"\n" +
"}\n"
);
static ActorSystem system = null;
@BeforeClass
public static void beforeClass() {
system = ActorSystem.create("ActorDocTest", config);
}
@AfterClass
public static void afterClass() throws Exception {
Await.result(system.terminate(), Duration.create("5 seconds"));
}
static
//#context-actorOf
public class FirstActor extends AbstractActor {
final ActorRef child = context().actorOf(Props.create(MyActor.class), "myChild");
//#plus-some-behavior
public FirstActor() {
receive(ReceiveBuilder.
matchAny(x -> {
sender().tell(x, self());
}).build()
);
}
//#plus-some-behavior
}
//#context-actorOf
static public abstract class SomeActor extends AbstractActor {
//#receive-constructor
public SomeActor() {
receive(ReceiveBuilder.
//#and-some-behavior
match(String.class, s -> System.out.println(s.toLowerCase())).
//#and-some-behavior
build());
}
//#receive-constructor
@Override
//#receive
public abstract PartialFunction<Object, BoxedUnit> receive();
//#receive
}
static public class ActorWithArgs extends AbstractActor {
private final String args;
ActorWithArgs(String args) {
this.args = args;
receive(ReceiveBuilder.
matchAny(x -> { }).build()
);
}
}
static
//#props-factory
public class DemoActor extends AbstractActor {
/**
* Create Props for an actor of this type.
* @param magicNumber The magic number to be passed to this actors constructor.
* @return a Props for creating this actor, which can then be further configured
* (e.g. calling `.withDispatcher()` on it)
*/
static Props props(Integer magicNumber) {
// You need to specify the actual type of the returned actor
// since Java 8 lambdas have some runtime type information erased
return Props.create(DemoActor.class, () -> new DemoActor(magicNumber));
}
private final Integer magicNumber;
DemoActor(Integer magicNumber) {
this.magicNumber = magicNumber;
receive(ReceiveBuilder.
match(Integer.class, i -> {
sender().tell(i + magicNumber, self());
}).build()
);
}
}
//#props-factory
static
//#props-factory
public class SomeOtherActor extends AbstractActor {
// Props(new DemoActor(42)) would not be safe
ActorRef demoActor = context().actorOf(DemoActor.props(42), "demo");
// ...
//#props-factory
public SomeOtherActor() {
receive(emptyBehavior());
}
//#props-factory
}
//#props-factory
public static class Hook extends AbstractActor {
ActorRef target = null;
public Hook() {
receive(emptyBehavior());
}
//#preStart
@Override
public void preStart() {
target = context().actorOf(Props.create(MyActor.class, "target"));
}
//#preStart
//#postStop
@Override
public void postStop() {
//#clean-up-some-resources
final String message = "stopped";
//#tell
// dont forget to think about who is the sender (2nd argument)
target.tell(message, self());
//#tell
final Object result = "";
//#forward
target.forward(result, context());
//#forward
target = null;
//#clean-up-some-resources
}
//#postStop
// compilation test only
public void compileSelections() {
//#selection-local
// will look up this absolute path
context().actorSelection("/user/serviceA/actor");
// will look up sibling beneath same supervisor
context().actorSelection("../joe");
//#selection-local
//#selection-wildcard
// will look all children to serviceB with names starting with worker
context().actorSelection("/user/serviceB/worker*");
// will look up all siblings beneath same supervisor
context().actorSelection("../*");
//#selection-wildcard
//#selection-remote
context().actorSelection("akka.tcp://app@otherhost:1234/user/serviceB");
//#selection-remote
}
}
public static class ReplyException extends AbstractActor {
public ReplyException() {
receive(ReceiveBuilder.
matchAny(x -> {
//#reply-exception
try {
String result = operation();
sender().tell(result, self());
} catch (Exception e) {
sender().tell(new akka.actor.Status.Failure(e), self());
throw e;
}
//#reply-exception
}).build()
);
}
private String operation() {
return "Hi";
}
}
static
//#gracefulStop-actor
public class Manager extends AbstractActor {
private static enum Shutdown {
Shutdown
}
public static final Shutdown SHUTDOWN = Shutdown.Shutdown;
private ActorRef worker =
context().watch(context().actorOf(Props.create(Cruncher.class), "worker"));
public Manager() {
receive(ReceiveBuilder.
matchEquals("job", s -> {
worker.tell("crunch", self());
}).
matchEquals(SHUTDOWN, x -> {
worker.tell(PoisonPill.getInstance(), self());
context().become(shuttingDown);
}).build()
);
}
public PartialFunction<Object, BoxedUnit> shuttingDown =
ReceiveBuilder.
matchEquals("job", s -> {
sender().tell("service unavailable, shutting down", self());
}).
match(Terminated.class, t -> t.actor().equals(worker), t -> {
context().stop(self());
}).build();
}
//#gracefulStop-actor
@Test
public void usePatternsGracefulStop() throws Exception {
ActorRef actorRef = system.actorOf(Props.create(Manager.class));
//#gracefulStop
try {
Future<Boolean> stopped =
gracefulStop(actorRef, Duration.create(5, TimeUnit.SECONDS), Manager.SHUTDOWN);
Await.result(stopped, Duration.create(6, TimeUnit.SECONDS));
// the actor has been stopped
} catch (AskTimeoutException e) {
// the actor wasn't stopped within 5 seconds
}
//#gracefulStop
}
public static class Cruncher extends AbstractActor {
public Cruncher() {
receive(ReceiveBuilder.
matchEquals("crunch", s -> { }).build()
);
}
}
static
//#swapper
public class Swapper extends AbstractLoggingActor {
public Swapper() {
receive(ReceiveBuilder.
matchEquals(Swap, s -> {
log().info("Hi");
context().become(ReceiveBuilder.
matchEquals(Swap, x -> {
log().info("Ho");
context().unbecome(); // resets the latest 'become' (just for fun)
}).build(), false); // push on top instead of replace
}).build()
);
}
}
//#swapper
static
//#swapper
public class SwapperApp {
public static void main(String[] args) {
ActorSystem system = ActorSystem.create("SwapperSystem");
ActorRef swapper = system.actorOf(Props.create(Swapper.class), "swapper");
swapper.tell(Swap, ActorRef.noSender()); // logs Hi
swapper.tell(Swap, ActorRef.noSender()); // logs Ho
swapper.tell(Swap, ActorRef.noSender()); // logs Hi
swapper.tell(Swap, ActorRef.noSender()); // logs Ho
swapper.tell(Swap, ActorRef.noSender()); // logs Hi
swapper.tell(Swap, ActorRef.noSender()); // logs Ho
system.terminate();
}
}
//#swapper
@Test
public void creatingActorWithSystemActorOf() {
//#system-actorOf
// ActorSystem is a heavy object: create only one per application
final ActorSystem system = ActorSystem.create("MySystem", config);
final ActorRef myActor = system.actorOf(Props.create(FirstActor.class), "myactor");
//#system-actorOf
try {
new JavaTestKit(system) {
{
myActor.tell("hello", getRef());
expectMsgEquals("hello");
}
};
} finally {
JavaTestKit.shutdownActorSystem(system);
}
}
@Test
public void creatingPropsConfig() {
//#creating-props
Props props1 = Props.create(MyActor.class);
Props props2 = Props.create(ActorWithArgs.class,
() -> new ActorWithArgs("arg")); // careful, see below
Props props3 = Props.create(ActorWithArgs.class, "arg");
//#creating-props
//#creating-props-deprecated
// NOT RECOMMENDED within another actor:
// encourages to close over enclosing class
Props props7 = Props.create(ActorWithArgs.class,
() -> new ActorWithArgs("arg"));
//#creating-props-deprecated
}
@Test(expected=IllegalArgumentException.class)
public void creatingPropsIllegal() {
//#creating-props-illegal
// This will throw an IllegalArgumentException since some runtime
// type information of the lambda is erased.
// Use Props.create(actorClass, Creator) instead.
Props props = Props.create(() -> new ActorWithArgs("arg"));
//#creating-props-illegal
}
static
//#receive-timeout
public class ReceiveTimeoutActor extends AbstractActor {
//#receive-timeout
ActorRef target = context().system().deadLetters();
//#receive-timeout
public ReceiveTimeoutActor() {
// To set an initial delay
context().setReceiveTimeout(Duration.create("10 seconds"));
receive(ReceiveBuilder.
matchEquals("Hello", s -> {
// To set in a response to a message
context().setReceiveTimeout(Duration.create("1 second"));
//#receive-timeout
target = sender();
target.tell("Hello world", self());
//#receive-timeout
}).
match(ReceiveTimeout.class, r -> {
// To turn it off
context().setReceiveTimeout(Duration.Undefined());
//#receive-timeout
target.tell("timeout", self());
//#receive-timeout
}).build()
);
}
}
//#receive-timeout
@Test
public void using_receiveTimeout() {
final ActorRef myActor = system.actorOf(Props.create(ReceiveTimeoutActor.class));
new JavaTestKit(system) {
{
myActor.tell("Hello", getRef());
expectMsgEquals("Hello world");
expectMsgEquals("timeout");
}
};
}
static
//#hot-swap-actor
public class HotSwapActor extends AbstractActor {
private PartialFunction<Object, BoxedUnit> angry;
private PartialFunction<Object, BoxedUnit> happy;
public HotSwapActor() {
angry =
ReceiveBuilder.
matchEquals("foo", s -> {
sender().tell("I am already angry?", self());
}).
matchEquals("bar", s -> {
context().become(happy);
}).build();
happy = ReceiveBuilder.
matchEquals("bar", s -> {
sender().tell("I am already happy :-)", self());
}).
matchEquals("foo", s -> {
context().become(angry);
}).build();
receive(ReceiveBuilder.
matchEquals("foo", s -> {
context().become(angry);
}).
matchEquals("bar", s -> {
context().become(happy);
}).build()
);
}
}
//#hot-swap-actor
@Test
public void using_hot_swap() {
final ActorRef actor = system.actorOf(Props.create(HotSwapActor.class), "hot");
new JavaTestKit(system) {
{
actor.tell("foo", getRef());
actor.tell("foo", getRef());
expectMsgEquals("I am already angry?");
actor.tell("bar", getRef());
actor.tell("bar", getRef());
expectMsgEquals("I am already happy :-)");
actor.tell("foo", getRef());
actor.tell("foo", getRef());
expectMsgEquals("I am already angry?");
expectNoMsg(Duration.create(1, TimeUnit.SECONDS));
}
};
}
static
//#stash
public class ActorWithProtocol extends AbstractActorWithStash {
public ActorWithProtocol() {
receive(ReceiveBuilder.
matchEquals("open", s -> {
context().become(ReceiveBuilder.
matchEquals("write", ws -> { /* do writing */ }).
matchEquals("close", cs -> {
unstashAll();
context().unbecome();
}).
matchAny(msg -> stash()).build(), false);
}).
matchAny(msg -> stash()).build()
);
}
}
//#stash
@Test
public void using_Stash() {
final ActorRef actor = system.actorOf(Props.create(ActorWithProtocol.class), "stash");
}
static
//#watch
public class WatchActor extends AbstractActor {
private final ActorRef child = context().actorOf(Props.empty(), "target");
private ActorRef lastSender = system.deadLetters();
public WatchActor() {
context().watch(child); // <-- this is the only call needed for registration
receive(ReceiveBuilder.
matchEquals("kill", s -> {
context().stop(child);
lastSender = sender();
}).
match(Terminated.class, t -> t.actor().equals(child), t -> {
lastSender.tell("finished", self());
}).build()
);
}
}
//#watch
@Test
public void using_watch() {
ActorRef actor = system.actorOf(Props.create(WatchActor.class));
new JavaTestKit(system) {
{
actor.tell("kill", getRef());
expectMsgEquals("finished");
}
};
}
static
//#identify
public class Follower extends AbstractActor {
final Integer identifyId = 1;
public Follower(){
ActorSelection selection = context().actorSelection("/user/another");
selection.tell(new Identify(identifyId), self());
receive(ReceiveBuilder.
match(ActorIdentity.class, id -> id.getRef() != null, id -> {
ActorRef ref = id.getRef();
context().watch(ref);
context().become(active(ref));
}).
match(ActorIdentity.class, id -> id.getRef() == null, id -> {
context().stop(self());
}).build()
);
}
final PartialFunction<Object, BoxedUnit> active(final ActorRef another) {
return ReceiveBuilder.
match(Terminated.class, t -> t.actor().equals(another), t -> {
context().stop(self());
}).build();
}
}
//#identify
@Test
public void using_Identify() {
ActorRef a = system.actorOf(Props.empty());
ActorRef b = system.actorOf(Props.create(Follower.class));
new JavaTestKit(system) {
{
watch(b);
system.stop(a);
assertEquals(expectMsgClass(Duration.create(2, TimeUnit.SECONDS), Terminated.class).actor(), b);
}
};
}
public static class NoReceiveActor extends AbstractActor {
}
@Test
public void noReceiveActor() {
EventFilter ex1 = new ErrorFilter(ActorInitializationException.class);
EventFilter[] ignoreExceptions = { ex1 };
try {
system.eventStream().publish(new TestEvent.Mute(immutableSeq(ignoreExceptions)));
new JavaTestKit(system) {{
final ActorRef victim = new EventFilter<ActorRef>(ActorInitializationException.class) {
protected ActorRef run() {
return system.actorOf(Props.create(NoReceiveActor.class), "victim");
}
}.message("Actor behavior has not been set with receive(...)").occurrences(1).exec();
assertEquals(true, victim.isTerminated());
}};
} finally {
system.eventStream().publish(new TestEvent.UnMute(immutableSeq(ignoreExceptions)));
}
}
public static class MultipleReceiveActor extends AbstractActor {
public MultipleReceiveActor() {
receive(ReceiveBuilder.
match(String.class, s1 -> s1.toLowerCase().equals("become"), s1 -> {
sender().tell(s1.toUpperCase(), self());
receive(ReceiveBuilder.
match(String.class, s2 -> {
sender().tell(s2.toLowerCase(), self());
}).build()
);
}).
match(String.class, s1 -> {
sender().tell(s1.toUpperCase(), self());
}).build()
);
}
}
@Test
public void multipleReceiveActor() {
EventFilter ex1 = new ErrorFilter(IllegalActorStateException.class);
EventFilter[] ignoreExceptions = { ex1 };
try {
system.eventStream().publish(new TestEvent.Mute(immutableSeq(ignoreExceptions)));
new JavaTestKit(system) {{
new EventFilter<Boolean>(IllegalActorStateException.class) {
protected Boolean run() {
ActorRef victim = system.actorOf(Props.create(MultipleReceiveActor.class), "victim2");
victim.tell("Foo", getRef());
expectMsgEquals("FOO");
victim.tell("bEcoMe", getRef());
expectMsgEquals("BECOME");
victim.tell("Foo", getRef());
// if it's upper case, then the actor was restarted
expectMsgEquals("FOO");
return true;
}
}.message("Actor behavior has already been set with receive(...), " +
"use context().become(...) to change it later").occurrences(1).exec();
}};
} finally {
system.eventStream().publish(new TestEvent.UnMute(immutableSeq(ignoreExceptions)));
}
}
}

View file

@ -1,209 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor;
//#imports-data
import java.util.ArrayList;
import java.util.List;
import akka.actor.ActorRef;
//#imports-data
//#imports-actor
import akka.event.LoggingAdapter;
import akka.event.Logging;
import akka.actor.UntypedActor;
//#imports-actor
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.testkit.JavaTestKit;
import akka.testkit.TestProbe;
import akka.testkit.AkkaSpec;
import docs.AbstractJavaTest;
public class FSMDocTest extends AbstractJavaTest {
static
//#data
public final class SetTarget {
final ActorRef ref;
public SetTarget(ActorRef ref) {
this.ref = ref;
}
}
//#data
static
//#data
public final class Queue {
final Object o;
public Queue(Object o) {
this.o = o;
}
}
//#data
static
//#data
public final Object flush = new Object();
//#data
static
//#data
public final class Batch {
final List<Object> objects;
public Batch(List<Object> objects) {
this.objects = objects;
}
}
//#data
static
//#base
public abstract class MyFSMBase extends UntypedActor {
/*
* This is the mutable state of this state machine.
*/
protected enum State {
IDLE, ACTIVE;
}
private State state = State.IDLE;
private ActorRef target;
private List<Object> queue;
/*
* Then come all the mutator methods:
*/
protected void init(ActorRef target) {
this.target = target;
queue = new ArrayList<Object>();
}
protected void setState(State s) {
if (state != s) {
transition(state, s);
state = s;
}
}
protected void enqueue(Object o) {
if (queue != null)
queue.add(o);
}
protected List<Object> drainQueue() {
final List<Object> q = queue;
if (q == null)
throw new IllegalStateException("drainQueue(): not yet initialized");
queue = new ArrayList<Object>();
return q;
}
/*
* Here are the interrogation methods:
*/
protected boolean isInitialized() {
return target != null;
}
protected State getState() {
return state;
}
protected ActorRef getTarget() {
if (target == null)
throw new IllegalStateException("getTarget(): not yet initialized");
return target;
}
/*
* And finally the callbacks (only one in this example: react to state change)
*/
abstract protected void transition(State old, State next);
}
//#base
static
//#actor
public class MyFSM extends MyFSMBase {
private final LoggingAdapter log =
Logging.getLogger(getContext().system(), this);
@Override
public void onReceive(Object o) {
if (getState() == State.IDLE) {
if (o instanceof SetTarget)
init(((SetTarget) o).ref);
else
whenUnhandled(o);
} else if (getState() == State.ACTIVE) {
if (o == flush)
setState(State.IDLE);
else
whenUnhandled(o);
}
}
@Override
public void transition(State old, State next) {
if (old == State.ACTIVE) {
getTarget().tell(new Batch(drainQueue()), getSelf());
}
}
private void whenUnhandled(Object o) {
if (o instanceof Queue && isInitialized()) {
enqueue(((Queue) o).o);
setState(State.ACTIVE);
} else {
log.warning("received unknown message {} in state {}", o, getState());
}
}
}
//#actor
ActorSystem system;
@org.junit.Before
public void setUp() {
system = ActorSystem.create("FSMSystem", AkkaSpec.testConf());
}
@org.junit.Test
public void mustBunch() {
final ActorRef buncher = system.actorOf(Props.create(MyFSM.class));
final TestProbe probe = new TestProbe(system);
buncher.tell(new SetTarget(probe.ref()), ActorRef.noSender());
buncher.tell(new Queue(1), ActorRef.noSender());
buncher.tell(new Queue(2), ActorRef.noSender());
buncher.tell(flush, ActorRef.noSender());
buncher.tell(new Queue(3), ActorRef.noSender());
final Batch b = probe.expectMsgClass(Batch.class);
assert b.objects.size() == 2;
assert b.objects.contains(1);
assert b.objects.contains(2);
}
@org.junit.After
public void cleanup() {
JavaTestKit.shutdownActorSystem(system);
}
}

View file

@ -1,224 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor;
//#testkit
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.SupervisorStrategy;
import static akka.actor.SupervisorStrategy.resume;
import static akka.actor.SupervisorStrategy.restart;
import static akka.actor.SupervisorStrategy.stop;
import static akka.actor.SupervisorStrategy.escalate;
import akka.actor.SupervisorStrategy.Directive;
import akka.actor.OneForOneStrategy;
import akka.actor.Props;
import akka.actor.Terminated;
import akka.actor.UntypedActor;
import docs.AbstractJavaTest;
import scala.collection.immutable.Seq;
import scala.concurrent.Await;
import static akka.pattern.Patterns.ask;
import scala.concurrent.duration.Duration;
import akka.testkit.TestProbe;
//#testkit
import akka.testkit.ErrorFilter;
import akka.testkit.EventFilter;
import akka.testkit.TestEvent;
import akka.testkit.JavaTestKit;
import static java.util.concurrent.TimeUnit.SECONDS;
import static akka.japi.Util.immutableSeq;
import akka.japi.Function;
import scala.Option;
import org.junit.Test;
import org.junit.BeforeClass;
import org.junit.AfterClass;
//#testkit
public class FaultHandlingTest extends AbstractJavaTest {
//#testkit
static
//#supervisor
public class Supervisor extends UntypedActor {
//#strategy
private static SupervisorStrategy strategy =
new OneForOneStrategy(10, Duration.create("1 minute"),
new Function<Throwable, Directive>() {
@Override
public Directive apply(Throwable t) {
if (t instanceof ArithmeticException) {
return resume();
} else if (t instanceof NullPointerException) {
return restart();
} else if (t instanceof IllegalArgumentException) {
return stop();
} else {
return escalate();
}
}
});
@Override
public SupervisorStrategy supervisorStrategy() {
return strategy;
}
//#strategy
public void onReceive(Object o) {
if (o instanceof Props) {
getSender().tell(getContext().actorOf((Props) o), getSelf());
} else {
unhandled(o);
}
}
}
//#supervisor
static
//#supervisor2
public class Supervisor2 extends UntypedActor {
//#strategy2
private static SupervisorStrategy strategy = new OneForOneStrategy(10,
Duration.create("1 minute"),
new Function<Throwable, Directive>() {
@Override
public Directive apply(Throwable t) {
if (t instanceof ArithmeticException) {
return resume();
} else if (t instanceof NullPointerException) {
return restart();
} else if (t instanceof IllegalArgumentException) {
return stop();
} else {
return escalate();
}
}
});
@Override
public SupervisorStrategy supervisorStrategy() {
return strategy;
}
//#strategy2
public void onReceive(Object o) {
if (o instanceof Props) {
getSender().tell(getContext().actorOf((Props) o), getSelf());
} else {
unhandled(o);
}
}
@Override
public void preRestart(Throwable cause, Option<Object> msg) {
// do not kill all children, which is the default here
}
}
//#supervisor2
static
//#child
public class Child extends UntypedActor {
int state = 0;
public void onReceive(Object o) throws Exception {
if (o instanceof Exception) {
throw (Exception) o;
} else if (o instanceof Integer) {
state = (Integer) o;
} else if (o.equals("get")) {
getSender().tell(state, getSelf());
} else {
unhandled(o);
}
}
}
//#child
//#testkit
static ActorSystem system;
Duration timeout = Duration.create(5, SECONDS);
@BeforeClass
public static void start() {
system = ActorSystem.create("FaultHandlingTest");
}
@AfterClass
public static void cleanup() {
JavaTestKit.shutdownActorSystem(system);
system = null;
}
@Test
public void mustEmploySupervisorStrategy() throws Exception {
// code here
//#testkit
EventFilter ex1 = new ErrorFilter(ArithmeticException.class);
EventFilter ex2 = new ErrorFilter(NullPointerException.class);
EventFilter ex3 = new ErrorFilter(IllegalArgumentException.class);
EventFilter ex4 = new ErrorFilter(Exception.class);
EventFilter[] ignoreExceptions = { ex1, ex2, ex3, ex4 };
Seq<EventFilter> seq = immutableSeq(ignoreExceptions);
system.eventStream().publish(new TestEvent.Mute(seq));
//#create
Props superprops = Props.create(Supervisor.class);
ActorRef supervisor = system.actorOf(superprops, "supervisor");
ActorRef child = (ActorRef) Await.result(ask(supervisor,
Props.create(Child.class), 5000), timeout);
//#create
//#resume
child.tell(42, ActorRef.noSender());
assert Await.result(ask(child, "get", 5000), timeout).equals(42);
child.tell(new ArithmeticException(), ActorRef.noSender());
assert Await.result(ask(child, "get", 5000), timeout).equals(42);
//#resume
//#restart
child.tell(new NullPointerException(), ActorRef.noSender());
assert Await.result(ask(child, "get", 5000), timeout).equals(0);
//#restart
//#stop
final TestProbe probe = new TestProbe(system);
probe.watch(child);
child.tell(new IllegalArgumentException(), ActorRef.noSender());
probe.expectMsgClass(Terminated.class);
//#stop
//#escalate-kill
child = (ActorRef) Await.result(ask(supervisor,
Props.create(Child.class), 5000), timeout);
probe.watch(child);
assert Await.result(ask(child, "get", 5000), timeout).equals(0);
child.tell(new Exception(), ActorRef.noSender());
probe.expectMsgClass(Terminated.class);
//#escalate-kill
//#escalate-restart
superprops = Props.create(Supervisor2.class);
supervisor = system.actorOf(superprops);
child = (ActorRef) Await.result(ask(supervisor,
Props.create(Child.class), 5000), timeout);
child.tell(23, ActorRef.noSender());
assert Await.result(ask(child, "get", 5000), timeout).equals(23);
child.tell(new Exception(), ActorRef.noSender());
assert Await.result(ask(child, "get", 5000), timeout).equals(0);
//#escalate-restart
//#testkit
}
}
//#testkit

View file

@ -1,205 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor;
//#testkit
import akka.actor.*;
import static akka.actor.SupervisorStrategy.resume;
import static akka.actor.SupervisorStrategy.restart;
import static akka.actor.SupervisorStrategy.stop;
import static akka.actor.SupervisorStrategy.escalate;
import akka.japi.pf.DeciderBuilder;
import akka.japi.pf.ReceiveBuilder;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import org.scalatest.junit.JUnitSuite;
import scala.PartialFunction;
import scala.concurrent.Await;
import static akka.pattern.Patterns.ask;
import scala.concurrent.duration.Duration;
import akka.testkit.TestProbe;
//#testkit
import akka.testkit.ErrorFilter;
import akka.testkit.EventFilter;
import akka.testkit.TestEvent;
import akka.testkit.JavaTestKit;
import static java.util.concurrent.TimeUnit.SECONDS;
import static akka.japi.Util.immutableSeq;
import scala.Option;
import org.junit.Test;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import scala.runtime.BoxedUnit;
//#testkit
public class FaultHandlingTestJava8 extends JUnitSuite {
//#testkit
public static Config config = ConfigFactory.parseString(
"akka {\n" +
" loggers = [\"akka.testkit.TestEventListener\"]\n" +
" loglevel = \"WARNING\"\n" +
" stdout-loglevel = \"WARNING\"\n" +
"}\n");
static
//#supervisor
public class Supervisor extends AbstractActor {
//#strategy
private static SupervisorStrategy strategy =
new OneForOneStrategy(10, Duration.create("1 minute"), DeciderBuilder.
match(ArithmeticException.class, e -> resume()).
match(NullPointerException.class, e -> restart()).
match(IllegalArgumentException.class, e -> stop()).
matchAny(o -> escalate()).build());
@Override
public SupervisorStrategy supervisorStrategy() {
return strategy;
}
//#strategy
public Supervisor() {
receive(ReceiveBuilder.
match(Props.class, props -> {
sender().tell(context().actorOf(props), self());
}).build()
);
}
}
//#supervisor
static
//#supervisor2
public class Supervisor2 extends AbstractActor {
//#strategy2
private static SupervisorStrategy strategy =
new OneForOneStrategy(10, Duration.create("1 minute"), DeciderBuilder.
match(ArithmeticException.class, e -> resume()).
match(NullPointerException.class, e -> restart()).
match(IllegalArgumentException.class, e -> stop()).
matchAny(o -> escalate()).build());
@Override
public SupervisorStrategy supervisorStrategy() {
return strategy;
}
//#strategy2
public Supervisor2() {
receive(ReceiveBuilder.
match(Props.class, props -> {
sender().tell(context().actorOf(props), self());
}).build()
);
}
@Override
public void preRestart(Throwable cause, Option<Object> msg) {
// do not kill all children, which is the default here
}
}
//#supervisor2
static
//#child
public class Child extends AbstractActor {
int state = 0;
public Child() {
receive(ReceiveBuilder.
match(Exception.class, exception -> { throw exception; }).
match(Integer.class, i -> state = i).
matchEquals("get", s -> sender().tell(state, self())).build()
);
}
}
//#child
//#testkit
static ActorSystem system;
Duration timeout = Duration.create(5, SECONDS);
@BeforeClass
public static void start() {
system = ActorSystem.create("FaultHandlingTest", config);
}
@AfterClass
public static void cleanup() {
JavaTestKit.shutdownActorSystem(system);
system = null;
}
@Test
public void mustEmploySupervisorStrategy() throws Exception {
// code here
//#testkit
EventFilter ex1 = new ErrorFilter(ArithmeticException.class);
EventFilter ex2 = new ErrorFilter(NullPointerException.class);
EventFilter ex3 = new ErrorFilter(IllegalArgumentException.class);
EventFilter ex4 = new ErrorFilter(Exception.class);
EventFilter[] ignoreExceptions = { ex1, ex2, ex3, ex4 };
system.eventStream().publish(new TestEvent.Mute(immutableSeq(ignoreExceptions)));
//#create
Props superprops = Props.create(Supervisor.class);
ActorRef supervisor = system.actorOf(superprops, "supervisor");
ActorRef child = (ActorRef) Await.result(ask(supervisor,
Props.create(Child.class), 5000), timeout);
//#create
//#resume
child.tell(42, ActorRef.noSender());
assert Await.result(ask(child, "get", 5000), timeout).equals(42);
child.tell(new ArithmeticException(), ActorRef.noSender());
assert Await.result(ask(child, "get", 5000), timeout).equals(42);
//#resume
//#restart
child.tell(new NullPointerException(), ActorRef.noSender());
assert Await.result(ask(child, "get", 5000), timeout).equals(0);
//#restart
//#stop
final TestProbe probe = new TestProbe(system);
probe.watch(child);
child.tell(new IllegalArgumentException(), ActorRef.noSender());
probe.expectMsgClass(Terminated.class);
//#stop
//#escalate-kill
child = (ActorRef) Await.result(ask(supervisor,
Props.create(Child.class), 5000), timeout);
probe.watch(child);
assert Await.result(ask(child, "get", 5000), timeout).equals(0);
child.tell(new Exception(), ActorRef.noSender());
probe.expectMsgClass(Terminated.class);
//#escalate-kill
//#escalate-restart
superprops = Props.create(Supervisor2.class);
supervisor = system.actorOf(superprops);
child = (ActorRef) Await.result(ask(supervisor,
Props.create(Child.class), 5000), timeout);
child.tell(23, ActorRef.noSender());
assert Await.result(ask(child, "get", 5000), timeout).equals(23);
child.tell(new Exception(), ActorRef.noSender());
assert Await.result(ask(child, "get", 5000), timeout).equals(0);
//#escalate-restart
//#testkit
}
}
//#testkit

View file

@ -1,21 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.actor.PoisonPill;
import akka.actor.UntypedActor;
//#context-actorOf
public class FirstUntypedActor extends UntypedActor {
ActorRef myActor = getContext().actorOf(Props.create(MyActor.class), "myactor");
//#context-actorOf
public void onReceive(Object message) {
myActor.forward(message, getContext());
myActor.tell(PoisonPill.getInstance(), ActorRef.noSender());
}
}

View file

@ -1,87 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor;
import akka.actor.*;
import akka.japi.Procedure;
import akka.testkit.AkkaJUnitActorSystemResource;
import akka.testkit.JavaTestKit;
import docs.AbstractJavaTest;
import org.junit.ClassRule;
import org.junit.Test;
import scala.Option;
public class InitializationDocSpecJava extends AbstractJavaTest {
static public class PreStartInitExample extends UntypedActor {
public void onReceive(Object message) throws Exception {}
//#preStartInit
@Override
public void preStart() {
// Initialize children here
}
// Overriding postRestart to disable the call to preStart()
// after restarts
@Override
public void postRestart(Throwable reason) {
}
// The default implementation of preRestart() stops all the children
// of the actor. To opt-out from stopping the children, we
// have to override preRestart()
@Override
public void preRestart(Throwable reason, Option<Object> message)
throws Exception {
// Keep the call to postStop(), but no stopping of children
postStop();
}
//#preStartInit
}
public static class MessageInitExample extends UntypedActor {
//#messageInit
private String initializeMe = null;
@Override
public void onReceive(Object message) throws Exception {
if (message.equals("init")) {
initializeMe = "Up and running";
getContext().become(new Procedure<Object>() {
@Override
public void apply(Object message) throws Exception {
if (message.equals("U OK?"))
getSender().tell(initializeMe, getSelf());
}
});
}
}
//#messageInit
}
@ClassRule
public static AkkaJUnitActorSystemResource actorSystemResource =
new AkkaJUnitActorSystemResource("InitializationDocSpecJava");
private final ActorSystem system = actorSystemResource.getSystem();
@Test
public void testIt() {
new JavaTestKit(system) {{
ActorRef testactor = system.actorOf(Props.create(MessageInitExample.class), "testactor");
String probe = "U OK?";
testactor.tell(probe, getRef());
expectNoMsg();
testactor.tell("init", getRef());
testactor.tell(probe, getRef());
expectMsgEquals("Up and running");
}};
}
}

View file

@ -1,68 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor;
import akka.actor.*;
import akka.japi.pf.ReceiveBuilder;
import akka.testkit.JavaTestKit;
import docs.AbstractJavaTest;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import scala.PartialFunction;
import scala.concurrent.duration.Duration;
import scala.runtime.BoxedUnit;
import scala.concurrent.Await;
import java.util.concurrent.TimeUnit;
public class InitializationDocTest extends AbstractJavaTest {
static ActorSystem system = null;
@BeforeClass
public static void beforeClass() {
system = ActorSystem.create("InitializationDocTest");
}
@AfterClass
public static void afterClass() throws Exception {
Await.result(system.terminate(), Duration.create("5 seconds"));
}
public static class MessageInitExample extends AbstractActor {
private String initializeMe = null;
public MessageInitExample() {
//#messageInit
receive(ReceiveBuilder.
matchEquals("init", m1 -> {
initializeMe = "Up and running";
context().become(ReceiveBuilder.
matchEquals("U OK?", m2 -> {
sender().tell(initializeMe, self());
}).build());
}).build()
//#messageInit
);
}
}
@Test
public void testIt() {
new JavaTestKit(system) {{
ActorRef testactor = system.actorOf(Props.create(MessageInitExample.class), "testactor");
String msg = "U OK?";
testactor.tell(msg, getRef());
expectNoMsg(Duration.create(1, TimeUnit.SECONDS));
testactor.tell("init", getRef());
testactor.tell(msg, getRef());
expectMsgEquals("Up and running");
}};
}
}

View file

@ -1,33 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor;
//#imports
import akka.actor.AbstractActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import akka.japi.pf.ReceiveBuilder;
//#imports
//#my-actor
public class MyJavaActor extends AbstractActor {
private final LoggingAdapter log = Logging.getLogger(context().system(), this);
public MyJavaActor() {
receive(ReceiveBuilder.
match(String.class, s -> {
log.info("Received String message: {}", s);
//#my-actor
//#reply
sender().tell(s, self());
//#reply
//#my-actor
}).
matchAny(o -> log.info("received unknown message")).build()
);
}
}
//#my-actor

View file

@ -1,41 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor;
//#receive-timeout
import akka.actor.ActorRef;
import akka.actor.ReceiveTimeout;
import akka.actor.UntypedActor;
import scala.concurrent.duration.Duration;
public class MyReceiveTimeoutUntypedActor extends UntypedActor {
//#receive-timeout
ActorRef target = getContext().system().deadLetters();
//#receive-timeout
public MyReceiveTimeoutUntypedActor() {
// To set an initial delay
getContext().setReceiveTimeout(Duration.create("30 seconds"));
}
public void onReceive(Object message) {
if (message.equals("Hello")) {
// To set in a response to a message
getContext().setReceiveTimeout(Duration.create("1 second"));
//#receive-timeout
target = getSender();
target.tell("Hello world", getSelf());
//#receive-timeout
} else if (message instanceof ReceiveTimeout) {
// To turn it off
getContext().setReceiveTimeout(Duration.Undefined());
//#receive-timeout
target.tell("timeout", getSelf());
//#receive-timeout
} else {
unhandled(message);
}
}
}
//#receive-timeout

View file

@ -1,29 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor;
//#my-stopping-actor
import akka.actor.ActorRef;
import akka.actor.UntypedActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
public class MyStoppingActor extends UntypedActor {
ActorRef child = null;
// ... creation of child ...
public void onReceive(Object message) throws Exception {
if (message.equals("interrupt-child")) {
context().stop(child);
} else if (message.equals("done")) {
context().stop(getSelf());
} else {
unhandled(message);
}
}
}
//#my-stopping-actor

View file

@ -1,23 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor;
//#my-untyped-actor
import akka.actor.UntypedActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
public class MyUntypedActor extends UntypedActor {
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
public void onReceive(Object message) throws Exception {
if (message instanceof String) {
log.info("Received String message: {}", message);
getSender().tell(message, getSelf());
} else
unhandled(message);
}
}
//#my-untyped-actor

View file

@ -1,36 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor;
//#sample-actor
import akka.actor.AbstractActor;
import akka.japi.pf.ReceiveBuilder;
import scala.PartialFunction;
import scala.runtime.BoxedUnit;
public class SampleActor extends AbstractActor {
private PartialFunction<Object, BoxedUnit> guarded = ReceiveBuilder.
match(String.class, s -> s.contains("guard"), s -> {
sender().tell("contains(guard): " + s, self());
context().unbecome();
}).build();
public SampleActor() {
receive(ReceiveBuilder.
match(Double.class, d -> {
sender().tell(d.isNaN() ? 0 : d, self());
}).
match(Integer.class, i -> {
sender().tell(i * 10, self());
}).
match(String.class, s -> s.startsWith("guard"), s -> {
sender().tell("startsWith(guard): " + s.toUpperCase(), self());
context().become(guarded, false);
}).build()
);
}
}
//#sample-actor

View file

@ -1,56 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.testkit.JavaTestKit;
import docs.AbstractJavaTest;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
public class SampleActorTest extends AbstractJavaTest {
static ActorSystem system;
@BeforeClass
public static void setup() {
system = ActorSystem.create("SampleActorTest");
}
@AfterClass
public static void tearDown() {
JavaTestKit.shutdownActorSystem(system);
system = null;
}
@Test
public void testSampleActor()
{
new JavaTestKit(system) {{
final ActorRef subject = system.actorOf(Props.create(SampleActor.class), "sample-actor");
final ActorRef probeRef = getRef();
subject.tell(47.11, probeRef);
subject.tell("and no guard in the beginning", probeRef);
subject.tell("guard is a good thing", probeRef);
subject.tell(47.11, probeRef);
subject.tell(4711, probeRef);
subject.tell("and no guard in the beginning", probeRef);
subject.tell(4711, probeRef);
subject.tell("and an unmatched message", probeRef);
expectMsgEquals(47.11);
assertTrue(expectMsgClass(String.class).startsWith("startsWith(guard):"));
assertTrue(expectMsgClass(String.class).startsWith("contains(guard):"));
expectMsgEquals(47110);
expectNoMsg();
}};
}
}

View file

@ -11,10 +11,11 @@ import java.util.concurrent.TimeUnit;
//#imports1
//#imports2
import akka.actor.UntypedActor;
import akka.actor.Cancellable;
//#imports2
import docs.actorlambda.MyActor;
import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.testkit.AkkaSpec;
@ -28,7 +29,7 @@ public class SchedulerDocTest extends AbstractJavaTest {
AkkaSpec.testConf());
private final ActorSystem system = actorSystemResource.getSystem();
private ActorRef testActor = system.actorOf(Props.create(MyUntypedActor.class));
private ActorRef testActor = system.actorOf(Props.create(MyActor.class));
@Test
public void scheduleOneOffTask() {
@ -51,14 +52,14 @@ public class SchedulerDocTest extends AbstractJavaTest {
@Test
public void scheduleRecurringTask() {
//#schedule-recurring
class Ticker extends UntypedActor {
class Ticker extends AbstractActor {
@Override
public void onReceive(Object message) {
if (message.equals("Tick")) {
// Do someting
} else {
unhandled(message);
}
public Receive createReceive() {
return receiveBuilder()
.matchEquals("Tick", m -> {
// Do someting
})
.build();
}
}

View file

@ -1,794 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor;
//#import-ask
import static akka.pattern.Patterns.ask;
import static akka.pattern.Patterns.pipe;
//#import-ask
//#import-gracefulStop
import static akka.pattern.Patterns.gracefulStop;
//#import-gracefulStop
import akka.actor.PoisonPill;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import akka.testkit.AkkaJUnitActorSystemResource;
import docs.AbstractJavaTest;
import org.junit.ClassRule;
import org.junit.Test;
//#import-gracefulStop
import scala.concurrent.Await;
//#import-ask
import scala.concurrent.Future;
import scala.concurrent.duration.Duration;
//#import-ask
//#import-gracefulStop
//#import-indirect
import akka.actor.Actor;
//#import-indirect
//#import-identify
import akka.actor.ActorIdentity;
//#import-identify
import akka.actor.ActorKilledException;
//#import-identify
import akka.actor.ActorSelection;
//#import-identify
//#import-actorRef
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
//#import-actorRef
//#import-identify
import akka.actor.Identify;
//#import-identify
//#import-indirect
import akka.actor.IndirectActorProducer;
//#import-indirect
import akka.actor.OneForOneStrategy;
//#import-props
import akka.actor.Props;
import akka.japi.Creator;
//#import-props
import akka.actor.SupervisorStrategy;
import akka.actor.SupervisorStrategy.Directive;
//#import-terminated
import akka.actor.Terminated;
//#import-terminated
//#import-untypedActor
import akka.actor.UntypedActor;
//#import-untypedActor
//#import-stash
import akka.actor.UntypedActorWithStash;
//#import-stash
//#import-ask
import akka.dispatch.Futures;
import akka.dispatch.Mapper;
//#import-ask
import akka.japi.Function;
//#import-procedure
import akka.japi.Procedure;
//#import-procedure
//#import-gracefulStop
import akka.pattern.AskTimeoutException;
//#import-gracefulStop
import akka.pattern.Patterns;
import akka.testkit.AkkaSpec;
import akka.testkit.JavaTestKit;
//#import-ask
import akka.util.Timeout;
//#import-ask
public class UntypedActorDocTest extends AbstractJavaTest {
@ClassRule
public static AkkaJUnitActorSystemResource actorSystemResource =
new AkkaJUnitActorSystemResource("UntypedActorDocTest", AkkaSpec.testConf());
private final ActorSystem system = actorSystemResource.getSystem();
//#creating-props-config
static class MyActorC implements Creator<MyActor> {
@Override public MyActor create() {
return new MyActor("...");
}
}
//#creating-props-config
@SuppressWarnings("unused")
@Test
public void createProps() {
//#creating-props-config
Props props1 = Props.create(MyUntypedActor.class);
Props props2 = Props.create(MyActor.class, "...");
Props props3 = Props.create(new MyActorC());
//#creating-props-config
}
//#parametric-creator
static class ParametricCreator<T extends MyActor> implements Creator<T> {
@Override public T create() {
// ... fabricate actor here
//#parametric-creator
return null;
//#parametric-creator
}
}
//#parametric-creator
@Test
public void systemActorOf() {
//#system-actorOf
// ActorSystem is a heavy object: create only one per application
final ActorSystem system = ActorSystem.create("MySystem");
final ActorRef myActor = system.actorOf(Props.create(MyUntypedActor.class),
"myactor");
//#system-actorOf
try {
new JavaTestKit(system) {
{
myActor.tell("hello", getRef());
expectMsgEquals("hello");
}
};
} finally {
JavaTestKit.shutdownActorSystem(system);
}
}
@Test
public void contextActorOf() {
new JavaTestKit(system) {
{
//#context-actorOf
class A extends UntypedActor {
final ActorRef child =
getContext().actorOf(Props.create(MyUntypedActor.class), "myChild");
//#plus-some-behavior
@Override
public void onReceive(Object msg) {
getSender().tell(child, getSelf());
}
//#plus-some-behavior
}
//#context-actorOf
final ActorRef top = system.actorOf(Props.create(A.class, this));
top.tell("hello", getRef());
final ActorRef child = expectMsgClass(ActorRef.class);
child.tell("hello", getRef());
expectMsgEquals("hello");
}
};
}
// this is just to make the test below a tiny fraction nicer
private ActorSystem getContext() {
return system;
}
static
//#creating-indirectly
class DependencyInjector implements IndirectActorProducer {
final Object applicationContext;
final String beanName;
public DependencyInjector(Object applicationContext, String beanName) {
this.applicationContext = applicationContext;
this.beanName = beanName;
}
@Override
public Class<? extends Actor> actorClass() {
return MyActor.class;
}
@Override
public MyActor produce() {
MyActor result;
//#obtain-fresh-Actor-instance-from-DI-framework
result = new MyActor((String) applicationContext);
//#obtain-fresh-Actor-instance-from-DI-framework
return result;
}
}
//#creating-indirectly
@Test
public void indirectActorOf() {
final String applicationContext = "...";
//#creating-indirectly
final ActorRef myActor = getContext().actorOf(
Props.create(DependencyInjector.class, applicationContext, "MyActor"),
"myactor3");
//#creating-indirectly
new JavaTestKit(system) {
{
myActor.tell("hello", getRef());
expectMsgEquals("...");
}
};
}
@SuppressWarnings("unused")
@Test
public void usingAsk() throws Exception {
ActorRef myActor = system.actorOf(Props.create(MyAskActor.class, this), "myactor5");
//#using-ask
Future<Object> future = Patterns.ask(myActor, "Hello", 1000);
Object result = Await.result(future, Duration.create(1, TimeUnit.SECONDS));
//#using-ask
}
@Test
public void receiveTimeout() {
final ActorRef myActor = system.actorOf(Props.create(MyReceiveTimeoutUntypedActor.class));
new JavaTestKit(system) {
{
new Within(Duration.create(1, TimeUnit.SECONDS), Duration.create(1500,
TimeUnit.MILLISECONDS)) {
@Override
protected void run() {
myActor.tell("Hello", getRef());
expectMsgEquals("Hello world");
expectMsgEquals("timeout");
}
};
}
};
}
@Test
public void usePoisonPill() {
final ActorRef myActor = system.actorOf(Props.create(MyUntypedActor.class));
new JavaTestKit(system) {
{
final ActorRef sender = getRef();
//#poison-pill
myActor.tell(akka.actor.PoisonPill.getInstance(), sender);
//#poison-pill
watch(myActor);
expectTerminated(myActor);
}
};
}
@Test
public void useKill() {
new JavaTestKit(system) {
{
class Master extends UntypedActor {
private SupervisorStrategy strategy = new OneForOneStrategy(-1,
Duration.Undefined(), new Function<Throwable, Directive>() {
@Override
public Directive apply(Throwable thr) {
if (thr instanceof ActorKilledException) {
target.tell("killed", getSelf());
getContext().stop(getSelf());
return SupervisorStrategy.stop();
}
return SupervisorStrategy.escalate();
}
});
final ActorRef target;
ActorRef child;
//#preStart
@Override
public void preStart() {
child = getContext().actorOf(Props.empty());
}
//#preStart
@SuppressWarnings("unused")
public Master(ActorRef target) {
this.target = target;
/*
* Only compilation of `forward` is verified here.
*/
final Object result = "";
//#forward
target.forward(result, getContext());
//#forward
}
@Override
public SupervisorStrategy supervisorStrategy() {
return strategy;
}
//#reply
@Override
public void onReceive(Object msg) {
Object result =
//#calculate-result
child;
//#calculate-result
// do not forget the second argument!
getSender().tell(result, getSelf());
}
//#reply
//#postStop
@Override
public void postStop() {
//#clean-up-resources-here
final String message = "stopped";
//#tell
// dont forget to think about who is the sender (2nd argument)
target.tell(message, getSelf());
//#tell
//#clean-up-resources-here
}
//#postStop
}
final ActorRef master = system.actorOf(Props.create(Master.class, this, getRef()));
expectMsgEquals("");
master.tell("", getRef());
final ActorRef victim = expectMsgClass(ActorRef.class);
//#kill
victim.tell(akka.actor.Kill.getInstance(), ActorRef.noSender());
//#kill
expectMsgEquals("killed");
expectMsgEquals("stopped");
assert getLastSender().equals(master);
}
};
}
@Test
public void useBecome() {
new JavaTestKit(system) {
{
ActorRef myActor = system.actorOf(Props.create(HotSwapActor.class));
myActor.tell("foo", getRef());
myActor.tell("bar", getRef());
expectMsgEquals("I am already happy :-)");
myActor.tell("bar", getRef());
expectMsgEquals("I am already happy :-)");
}
};
}
@Test
public void useWatch() throws Exception {
ActorRef myActor = system.actorOf(Props.create(WatchActor.class));
Future<Object> future = Patterns.ask(myActor, "kill", 1000);
assert Await.result(future, Duration.create("1 second")).equals("finished");
}
// compilation test only
public void compileSelections() {
//#selection-local
// will look up this absolute path
getContext().actorSelection("/user/serviceA/actor");
// will look up sibling beneath same supervisor
getContext().actorSelection("../joe");
//#selection-local
//#selection-wildcard
// 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("../*");
//#selection-wildcard
//#selection-remote
getContext().actorSelection("akka.tcp://app@otherhost:1234/user/serviceB");
//#selection-remote
}
@Test
public void useIdentify() throws Exception {
new JavaTestKit(system) {
{
ActorRef a = system.actorOf(Props.create(MyUntypedActor.class), "another");
ActorRef b = system.actorOf(Props.create(Follower.class, getRef()));
expectMsgEquals(a);
system.stop(a);
watch(b);
expectTerminated(b);
}
};
}
@Test
public void usePatternsGracefulStop() throws Exception {
ActorRef actorRef = system.actorOf(Props.create(Manager.class));
//#gracefulStop
try {
Future<Boolean> stopped =
gracefulStop(actorRef, Duration.create(5, TimeUnit.SECONDS), Manager.SHUTDOWN);
Await.result(stopped, Duration.create(6, TimeUnit.SECONDS));
// the actor has been stopped
} catch (AskTimeoutException e) {
// the actor wasn't stopped within 5 seconds
}
//#gracefulStop
}
class Result {
final String x;
final String s;
public Result(String x, String s) {
this.x = x;
this.s = s;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((s == null) ? 0 : s.hashCode());
result = prime * result + ((x == null) ? 0 : x.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Result other = (Result) obj;
if (s == null) {
if (other.s != null)
return false;
} else if (!s.equals(other.s))
return false;
if (x == null) {
if (other.x != null)
return false;
} else if (!x.equals(other.x))
return false;
return true;
}
}
@Test
public void usePatternsAskPipe() {
new JavaTestKit(system) {
{
ActorRef actorA = system.actorOf(Props.create(MyUntypedActor.class));
ActorRef actorB = system.actorOf(Props.create(MyUntypedActor.class));
ActorRef actorC = getRef();
//#ask-pipe
final Timeout t = new Timeout(Duration.create(5, TimeUnit.SECONDS));
final ArrayList<Future<Object>> futures = new ArrayList<Future<Object>>();
futures.add(ask(actorA, "request", 1000)); // using 1000ms timeout
futures.add(ask(actorB, "another request", t)); // using timeout from
// above
final Future<Iterable<Object>> aggregate = Futures.sequence(futures,
system.dispatcher());
final Future<Result> transformed = aggregate.map(
new Mapper<Iterable<Object>, Result>() {
public Result apply(Iterable<Object> coll) {
final Iterator<Object> it = coll.iterator();
final String x = (String) it.next();
final String s = (String) it.next();
return new Result(x, s);
}
}, system.dispatcher());
pipe(transformed, system.dispatcher()).to(actorC);
//#ask-pipe
expectMsgEquals(new Result("request", "another request"));
}
};
}
static
//#props-factory
public class DemoActor extends UntypedActor {
/**
* Create Props for an actor of this type.
* @param magicNumber The magic number to be passed to this actors constructor.
* @return a Props for creating this actor, which can then be further configured
* (e.g. calling `.withDispatcher()` on it)
*/
public static Props props(final int magicNumber) {
return Props.create(new Creator<DemoActor>() {
private static final long serialVersionUID = 1L;
@Override
public DemoActor create() throws Exception {
return new DemoActor(magicNumber);
}
});
}
final int magicNumber;
public DemoActor(int magicNumber) {
this.magicNumber = magicNumber;
}
@Override
public void onReceive(Object msg) {
// some behavior here
}
}
//#props-factory
@Test
public void demoActor() {
//#props-factory
system.actorOf(DemoActor.props(42), "demo");
//#props-factory
}
static
//#messages-in-companion
public class DemoMessagesActor extends UntypedActor {
static public class Greeting {
private final String from;
public Greeting(String from) {
this.from = from;
}
public String getGreeter() {
return from;
}
}
public void onReceive(Object message) throws Exception {
if (message instanceof Greeting) {
getSender().tell("Hello " + ((Greeting) message).getGreeter(), getSelf());
} else
unhandled(message);
}
}
//#messages-in-companion
public static class MyActor extends UntypedActor {
final String s;
public MyActor(String s) {
this.s = s;
}
public void onReceive(Object message) {
getSender().tell(s, getSelf());
}
/*
* This section must be kept in sync with the actual Actor trait.
*
* BOYSCOUT RULE: whenever you read this, verify that!
*/
//#lifecycle-callbacks
public void preStart() {
}
public void preRestart(Throwable reason, scala.Option<Object> message) {
for (ActorRef each : getContext().getChildren()) {
getContext().unwatch(each);
getContext().stop(each);
}
postStop();
}
public void postRestart(Throwable reason) {
preStart();
}
public void postStop() {
}
//#lifecycle-callbacks
}
public class MyAskActor extends UntypedActor {
public void onReceive(Object message) throws Exception {
//#reply-exception
try {
String result = operation();
getSender().tell(result, getSelf());
} catch (Exception e) {
getSender().tell(new akka.actor.Status.Failure(e), getSelf());
throw e;
}
//#reply-exception
}
private String operation() {
return "Hi";
}
}
static
//#gracefulStop-actor
public class Manager extends UntypedActor {
public static final String SHUTDOWN = "shutdown";
ActorRef worker = getContext().watch(getContext().actorOf(
Props.create(Cruncher.class), "worker"));
public void onReceive(Object message) {
if (message.equals("job")) {
worker.tell("crunch", getSelf());
} else if (message.equals(SHUTDOWN)) {
worker.tell(PoisonPill.getInstance(), getSelf());
getContext().become(shuttingDown);
}
}
Procedure<Object> shuttingDown = new Procedure<Object>() {
@Override
public void apply(Object message) {
if (message.equals("job")) {
getSender().tell("service unavailable, shutting down", getSelf());
} else if (message instanceof Terminated) {
getContext().stop(getSelf());
}
}
};
}
//#gracefulStop-actor
static class Cruncher extends UntypedActor {
public void onReceive(Object message) {
// crunch...
}
}
static
//#hot-swap-actor
public class HotSwapActor extends UntypedActor {
Procedure<Object> angry = new Procedure<Object>() {
@Override
public void apply(Object message) {
if (message.equals("bar")) {
getSender().tell("I am already angry?", getSelf());
} else if (message.equals("foo")) {
getContext().become(happy);
}
}
};
Procedure<Object> happy = new Procedure<Object>() {
@Override
public void apply(Object message) {
if (message.equals("bar")) {
getSender().tell("I am already happy :-)", getSelf());
} else if (message.equals("foo")) {
getContext().become(angry);
}
}
};
public void onReceive(Object message) {
if (message.equals("bar")) {
getContext().become(angry);
} else if (message.equals("foo")) {
getContext().become(happy);
} else {
unhandled(message);
}
}
}
//#hot-swap-actor
static
//#stash
public class ActorWithProtocol extends UntypedActorWithStash {
public void onReceive(Object msg) {
if (msg.equals("open")) {
unstashAll();
getContext().become(new Procedure<Object>() {
public void apply(Object msg) throws Exception {
if (msg.equals("write")) {
// do writing...
} else if (msg.equals("close")) {
unstashAll();
getContext().unbecome();
} else {
stash();
}
}
}, false); // add behavior on top instead of replacing
} else {
stash();
}
}
}
//#stash
static
//#watch
public class WatchActor extends UntypedActor {
final ActorRef child = this.getContext().actorOf(Props.empty(), "child");
{
this.getContext().watch(child); // <-- the only call needed for registration
}
ActorRef lastSender = getContext().system().deadLetters();
@Override
public void onReceive(Object message) {
if (message.equals("kill")) {
getContext().stop(child);
lastSender = getSender();
} else if (message instanceof Terminated) {
final Terminated t = (Terminated) message;
if (t.getActor() == child) {
lastSender.tell("finished", getSelf());
}
} else {
unhandled(message);
}
}
}
//#watch
static
//#identify
public class Follower extends UntypedActor {
final String identifyId = "1";
{
ActorSelection selection =
getContext().actorSelection("/user/another");
selection.tell(new Identify(identifyId), getSelf());
}
ActorRef another;
//#test-omitted
final ActorRef probe;
public Follower(ActorRef probe) {
this.probe = probe;
}
//#test-omitted
@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);
//#test-omitted
probe.tell(ref, getSelf());
//#test-omitted
}
}
} else if (message instanceof Terminated) {
final Terminated t = (Terminated) message;
if (t.getActor().equals(another)) {
getContext().stop(getSelf());
}
} else {
unhandled(message);
}
}
}
//#identify
}

View file

@ -1,56 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor;
import static docs.actor.UntypedActorSwapper.Swap.SWAP;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.actor.ActorSystem;
import akka.actor.UntypedActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import akka.japi.Procedure;
//#swapper
public class UntypedActorSwapper {
public static class Swap {
public static Swap SWAP = new Swap();
private Swap() {
}
}
public static class Swapper extends UntypedActor {
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
public void onReceive(Object message) {
if (message == SWAP) {
log.info("Hi");
getContext().become(new Procedure<Object>() {
@Override
public void apply(Object message) {
log.info("Ho");
getContext().unbecome(); // resets the latest 'become'
}
}, false); // this signals stacking of the new behavior
} else {
unhandled(message);
}
}
}
public static void main(String... args) {
ActorSystem system = ActorSystem.create("MySystem");
ActorRef swap = system.actorOf(Props.create(Swapper.class));
swap.tell(SWAP, ActorRef.noSender()); // logs Hi
swap.tell(SWAP, ActorRef.noSender()); // logs Ho
swap.tell(SWAP, ActorRef.noSender()); // logs Hi
swap.tell(SWAP, ActorRef.noSender()); // logs Ho
swap.tell(SWAP, ActorRef.noSender()); // logs Hi
swap.tell(SWAP, ActorRef.noSender()); // logs Ho
}
}
//#swapper

View file

@ -1,136 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor.fsm;
//#simple-imports
import akka.actor.AbstractFSM;
import akka.actor.ActorRef;
import akka.japi.pf.UnitMatch;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import scala.concurrent.duration.Duration;
//#simple-imports
import static docs.actor.fsm.Buncher.Data;
import static docs.actor.fsm.Buncher.State.*;
import static docs.actor.fsm.Buncher.State;
import static docs.actor.fsm.Buncher.Uninitialized.*;
import static docs.actor.fsm.Events.*;
//#simple-fsm
public class Buncher extends AbstractFSM<State, Data> {
{
//#fsm-body
startWith(Idle, Uninitialized);
//#when-syntax
when(Idle,
matchEvent(SetTarget.class, Uninitialized.class,
(setTarget, uninitialized) ->
stay().using(new Todo(setTarget.getRef(), new LinkedList<>()))));
//#when-syntax
//#transition-elided
onTransition(
matchState(Active, Idle, () -> {
// reuse this matcher
final UnitMatch<Data> m = UnitMatch.create(
matchData(Todo.class,
todo -> todo.getTarget().tell(new Batch(todo.getQueue()), self())));
m.match(stateData());
}).
state(Idle, Active, () -> {/* Do something here */}));
//#transition-elided
when(Active, Duration.create(1, "second"),
matchEvent(Arrays.asList(Flush.class, StateTimeout()), Todo.class,
(event, todo) -> goTo(Idle).using(todo.copy(new LinkedList<>()))));
//#unhandled-elided
whenUnhandled(
matchEvent(Queue.class, Todo.class,
(queue, todo) -> goTo(Active).using(todo.addElement(queue.getObj()))).
anyEvent((event, state) -> {
log().warning("received unhandled request {} in state {}/{}",
event, stateName(), state);
return stay();
}));
//#unhandled-elided
initialize();
//#fsm-body
}
//#simple-fsm
static
//#simple-state
// states
enum State {
Idle, Active
}
//#simple-state
static
//#simple-state
// state data
interface Data {
}
//#simple-state
static
//#simple-state
enum Uninitialized implements Data {
Uninitialized
}
//#simple-state
static
//#simple-state
final class Todo implements Data {
private final ActorRef target;
private final List<Object> queue;
public Todo(ActorRef target, List<Object> queue) {
this.target = target;
this.queue = queue;
}
public ActorRef getTarget() {
return target;
}
public List<Object> getQueue() {
return queue;
}
//#boilerplate
@Override
public String toString() {
return "Todo{" +
"target=" + target +
", queue=" + queue +
'}';
}
public Todo addElement(Object element) {
List<Object> nQueue = new LinkedList<>(queue);
nQueue.add(element);
return new Todo(this.target, nQueue);
}
public Todo copy(List<Object> queue) {
return new Todo(this.target, queue);
}
public Todo copy(ActorRef target) {
return new Todo(target, this.queue);
}
//#boilerplate
}
//#simple-state
//#simple-fsm
}
//#simple-fsm

View file

@ -1,79 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor.fsm;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.testkit.JavaTestKit;
import docs.AbstractJavaTest;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.LinkedList;
import docs.actor.fsm.*;
import static docs.actor.fsm.Events.Batch;
import static docs.actor.fsm.Events.Queue;
import static docs.actor.fsm.Events.SetTarget;
import static docs.actor.fsm.Events.Flush.Flush;
//#test-code
public class BuncherTest extends AbstractJavaTest {
static ActorSystem system;
@BeforeClass
public static void setup() {
system = ActorSystem.create("BuncherTest");
}
@AfterClass
public static void tearDown() {
JavaTestKit.shutdownActorSystem(system);
system = null;
}
@Test
public void testBuncherActorBatchesCorrectly() {
new JavaTestKit(system) {{
final ActorRef buncher =
system.actorOf(Props.create(Buncher.class));
final ActorRef probe = getRef();
buncher.tell(new SetTarget(probe), probe);
buncher.tell(new Queue(42), probe);
buncher.tell(new Queue(43), probe);
LinkedList<Object> list1 = new LinkedList<>();
list1.add(42);
list1.add(43);
expectMsgEquals(new Batch(list1));
buncher.tell(new Queue(44), probe);
buncher.tell(Flush, probe);
buncher.tell(new Queue(45), probe);
LinkedList<Object> list2 = new LinkedList<>();
list2.add(44);
expectMsgEquals(new Batch(list2));
LinkedList<Object> list3 = new LinkedList<>();
list3.add(45);
expectMsgEquals(new Batch(list3));
system.stop(buncher);
}};
}
@Test
public void testBuncherActorDoesntBatchUninitialized() {
new JavaTestKit(system) {{
final ActorRef buncher =
system.actorOf(Props.create(Buncher.class));
final ActorRef probe = getRef();
buncher.tell(new Queue(42), probe);
expectNoMsg();
system.stop(buncher);
}};
}
}
//#test-code

View file

@ -1,108 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor.fsm;
import akka.actor.ActorRef;
import java.util.List;
public class Events {
static
//#simple-events
public final class SetTarget {
private final ActorRef ref;
public SetTarget(ActorRef ref) {
this.ref = ref;
}
public ActorRef getRef() {
return ref;
}
//#boilerplate
@Override
public String toString() {
return "SetTarget{" +
"ref=" + ref +
'}';
}
//#boilerplate
}
//#simple-events
static
//#simple-events
public final class Queue {
private final Object obj;
public Queue(Object obj) {
this.obj = obj;
}
public Object getObj() {
return obj;
}
//#boilerplate
@Override
public String toString() {
return "Queue{" +
"obj=" + obj +
'}';
}
//#boilerplate
}
//#simple-events
static
//#simple-events
public final class Batch {
private final List<Object> list;
public Batch(List<Object> list) {
this.list = list;
}
public List<Object> getList() {
return list;
}
//#boilerplate
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Batch batch = (Batch) o;
return list.equals(batch.list);
}
@Override
public int hashCode() {
return list.hashCode();
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append( "Batch{list=");
list.stream().forEachOrdered(e -> { builder.append(e); builder.append(","); });
int len = builder.length();
builder.replace(len, len, "}");
return builder.toString();
}
//#boilerplate
}
//#simple-events
static
//#simple-events
public enum Flush {
Flush
}
//#simple-events
}

View file

@ -1,180 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor.fsm;
import akka.actor.*;
import akka.testkit.JavaTestKit;
import docs.AbstractJavaTest;
import org.hamcrest.CoreMatchers;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import scala.concurrent.duration.Duration;
import static org.junit.Assert.*;
import static docs.actor.fsm.FSMDocTest.StateType.*;
import static docs.actor.fsm.FSMDocTest.Messages.*;
import static java.util.concurrent.TimeUnit.*;
public class FSMDocTest extends AbstractJavaTest {
static ActorSystem system;
@BeforeClass
public static void setup() {
system = ActorSystem.create("FSMDocTest");
}
@AfterClass
public static void tearDown() {
JavaTestKit.shutdownActorSystem(system);
system = null;
}
public static enum StateType {
SomeState,
Processing,
Idle,
Active,
Error
}
public static enum Messages {
WillDo,
Tick
}
public static enum Data {
Foo,
Bar
};
public static interface X {};
public static class DummyFSM extends AbstractFSM<StateType, Integer> {
Integer newData = 42;
//#alt-transition-syntax
public void handler(StateType from, StateType to) {
// handle transition here
}
//#alt-transition-syntax
{
//#modifier-syntax
when(SomeState, matchAnyEvent((msg, data) -> {
return goTo(Processing).using(newData).
forMax(Duration.create(5, SECONDS)).replying(WillDo);
}));
//#modifier-syntax
//#NullFunction
when(SomeState, AbstractFSM.NullFunction());
//#NullFunction
//#transition-syntax
onTransition(
matchState(Active, Idle, () -> setTimer("timeout",
Tick, Duration.create(1, SECONDS), true)).
state(Active, null, () -> cancelTimer("timeout")).
state(null, Idle, (f, t) -> log().info("entering Idle from " + f)));
//#transition-syntax
//#alt-transition-syntax
onTransition(this::handler);
//#alt-transition-syntax
//#stop-syntax
when(Error, matchEventEquals("stop", (event, data) -> {
// do cleanup ...
return stop();
}));
//#stop-syntax
//#termination-syntax
onTermination(
matchStop(Normal(),
(state, data) -> {/* Do something here */}).
stop(Shutdown(),
(state, data) -> {/* Do something here */}).
stop(Failure.class,
(reason, state, data) -> {/* Do something here */}));
//#termination-syntax
//#unhandled-syntax
whenUnhandled(
matchEvent(X.class, (x, data) -> {
log().info("Received unhandled event: " + x);
return stay();
}).
anyEvent((event, data) -> {
log().warning("Received unknown event: " + event);
return goTo(Error);
}));
}
//#unhandled-syntax
}
static
//#logging-fsm
public class MyFSM extends AbstractLoggingFSM<StateType, Data> {
//#body-elided
//#logging-fsm
ActorRef target = null;
//#logging-fsm
@Override
public int logDepth() { return 12; }
{
onTermination(
matchStop(Failure.class, (reason, state, data) -> {
String lastEvents = getLog().mkString("\n\t");
log().warning("Failure in state " + state + " with data " + data + "\n" +
"Events leading up to this point:\n\t" + lastEvents);
//#logging-fsm
target.tell(reason.cause(), self());
target.tell(state, self());
target.tell(data, self());
target.tell(lastEvents, self());
//#logging-fsm
})
);
//...
//#logging-fsm
startWith(SomeState, Data.Foo);
when(SomeState, matchEvent(ActorRef.class, Data.class, (ref, data) -> {
target = ref;
target.tell("going active", self());
return goTo(Active);
}));
when(Active, matchEventEquals("stop", (event, data) -> {
target.tell("stopping", self());
return stop(new Failure("This is not the error you're looking for"));
}));
initialize();
//#logging-fsm
}
//#body-elided
}
//#logging-fsm
@Test
public void testLoggingFSM()
{
new JavaTestKit(system) {{
final ActorRef logger =
system.actorOf(Props.create(MyFSM.class));
final ActorRef probe = getRef();
logger.tell(probe, probe);
expectMsgEquals("going active");
logger.tell("stop", probe);
expectMsgEquals("stopping");
expectMsgEquals("This is not the error you're looking for");
expectMsgEquals(Active);
expectMsgEquals(Data.Foo);
String msg = expectMsgClass(String.class);
assertThat(msg, CoreMatchers.startsWith("LogEntry(SomeState,Foo,Actor[akka://FSMDocTest/system/"));
}};
}
}

View file

@ -1,489 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor.japi;
//#all
//#imports
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import akka.actor.*;
import akka.dispatch.Mapper;
import akka.japi.Function;
import scala.concurrent.duration.Duration;
import akka.util.Timeout;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import static akka.japi.Util.classTag;
import static akka.actor.SupervisorStrategy.restart;
import static akka.actor.SupervisorStrategy.stop;
import static akka.actor.SupervisorStrategy.escalate;
import akka.actor.SupervisorStrategy.Directive;
import static akka.pattern.Patterns.ask;
import static akka.pattern.Patterns.pipe;
import static docs.actor.japi.FaultHandlingDocSample.WorkerApi.*;
import static docs.actor.japi.FaultHandlingDocSample.CounterServiceApi.*;
import static docs.actor.japi.FaultHandlingDocSample.CounterApi.*;
import static docs.actor.japi.FaultHandlingDocSample.StorageApi.*;
//#imports
public class FaultHandlingDocSample {
/**
* Runs the sample
*/
public static void main(String[] args) {
Config config = ConfigFactory.parseString("akka.loglevel = DEBUG \n" +
"akka.actor.debug.lifecycle = on");
ActorSystem system = ActorSystem.create("FaultToleranceSample", config);
ActorRef worker = system.actorOf(Props.create(Worker.class), "worker");
ActorRef listener = system.actorOf(Props.create(Listener.class), "listener");
// start the work and listen on progress
// note that the listener is used as sender of the tell,
// i.e. it will receive replies from the worker
worker.tell(Start, listener);
}
/**
* Listens on progress from the worker and shuts down the system when enough
* work has been done.
*/
public static class Listener extends UntypedActor {
final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
@Override
public void preStart() {
// If we don't get any progress within 15 seconds then the service
// is unavailable
getContext().setReceiveTimeout(Duration.create("15 seconds"));
}
public void onReceive(Object msg) {
log.debug("received message {}", msg);
if (msg instanceof Progress) {
Progress progress = (Progress) msg;
log.info("Current progress: {} %", progress.percent);
if (progress.percent >= 100.0) {
log.info("That's all, shutting down");
getContext().system().terminate();
}
} else if (msg == ReceiveTimeout.getInstance()) {
// No progress within 15 seconds, ServiceUnavailable
log.error("Shutting down due to unavailable service");
getContext().system().terminate();
} else {
unhandled(msg);
}
}
}
//#messages
public interface WorkerApi {
public static final Object Start = "Start";
public static final Object Do = "Do";
public static class Progress {
public final double percent;
public Progress(double percent) {
this.percent = percent;
}
public String toString() {
return String.format("%s(%s)", getClass().getSimpleName(), percent);
}
}
}
//#messages
/**
* Worker performs some work when it receives the Start message. It will
* continuously notify the sender of the Start message of current Progress.
* The Worker supervise the CounterService.
*/
public static class Worker extends UntypedActor {
final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
final Timeout askTimeout = new Timeout(Duration.create(5, "seconds"));
// The sender of the initial Start message will continuously be notified
// about progress
ActorRef progressListener;
final ActorRef counterService = getContext().actorOf(
Props.create(CounterService.class), "counter");
final int totalCount = 51;
// Stop the CounterService child if it throws ServiceUnavailable
private static SupervisorStrategy strategy = new OneForOneStrategy(-1,
Duration.Inf(), new Function<Throwable, Directive>() {
@Override
public Directive apply(Throwable t) {
if (t instanceof ServiceUnavailable) {
return stop();
} else {
return escalate();
}
}
});
@Override
public SupervisorStrategy supervisorStrategy() {
return strategy;
}
public void onReceive(Object msg) {
log.debug("received message {}", msg);
if (msg.equals(Start) && progressListener == null) {
progressListener = getSender();
getContext().system().scheduler().schedule(
Duration.Zero(), Duration.create(1, "second"), getSelf(), Do,
getContext().dispatcher(), null
);
} else if (msg.equals(Do)) {
counterService.tell(new Increment(1), getSelf());
counterService.tell(new Increment(1), getSelf());
counterService.tell(new Increment(1), getSelf());
// Send current progress to the initial sender
pipe(ask(counterService, GetCurrentCount, askTimeout)
.mapTo(classTag(CurrentCount.class))
.map(new Mapper<CurrentCount, Progress>() {
public Progress apply(CurrentCount c) {
return new Progress(100.0 * c.count / totalCount);
}
}, getContext().dispatcher()), getContext().dispatcher())
.to(progressListener);
} else {
unhandled(msg);
}
}
}
//#messages
public interface CounterServiceApi {
public static final Object GetCurrentCount = "GetCurrentCount";
public static class CurrentCount {
public final String key;
public final long count;
public CurrentCount(String key, long count) {
this.key = key;
this.count = count;
}
public String toString() {
return String.format("%s(%s, %s)", getClass().getSimpleName(), key, count);
}
}
public static class Increment {
public final long n;
public Increment(long n) {
this.n = n;
}
public String toString() {
return String.format("%s(%s)", getClass().getSimpleName(), n);
}
}
public static class ServiceUnavailable extends RuntimeException {
private static final long serialVersionUID = 1L;
public ServiceUnavailable(String msg) {
super(msg);
}
}
}
//#messages
/**
* Adds the value received in Increment message to a persistent counter.
* Replies with CurrentCount when it is asked for CurrentCount. CounterService
* supervise Storage and Counter.
*/
public static class CounterService extends UntypedActor {
// Reconnect message
static final Object Reconnect = "Reconnect";
private static class SenderMsgPair {
final ActorRef sender;
final Object msg;
SenderMsgPair(ActorRef sender, Object msg) {
this.msg = msg;
this.sender = sender;
}
}
final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
final String key = getSelf().path().name();
ActorRef storage;
ActorRef counter;
final List<SenderMsgPair> backlog = new ArrayList<SenderMsgPair>();
final int MAX_BACKLOG = 10000;
// Restart the storage child when StorageException is thrown.
// After 3 restarts within 5 seconds it will be stopped.
private static SupervisorStrategy strategy = new OneForOneStrategy(3,
Duration.create("5 seconds"), new Function<Throwable, Directive>() {
@Override
public Directive apply(Throwable t) {
if (t instanceof StorageException) {
return restart();
} else {
return escalate();
}
}
});
@Override
public SupervisorStrategy supervisorStrategy() {
return strategy;
}
@Override
public void preStart() {
initStorage();
}
/**
* The child storage is restarted in case of failure, but after 3 restarts,
* and still failing it will be stopped. Better to back-off than
* continuously failing. When it has been stopped we will schedule a
* Reconnect after a delay. Watch the child so we receive Terminated message
* when it has been terminated.
*/
void initStorage() {
storage = getContext().watch(getContext().actorOf(
Props.create(Storage.class), "storage"));
// Tell the counter, if any, to use the new storage
if (counter != null)
counter.tell(new UseStorage(storage), getSelf());
// We need the initial value to be able to operate
storage.tell(new Get(key), getSelf());
}
@Override
public void onReceive(Object msg) {
log.debug("received message {}", msg);
if (msg instanceof Entry && ((Entry) msg).key.equals(key) &&
counter == null) {
// Reply from Storage of the initial value, now we can create the Counter
final long value = ((Entry) msg).value;
counter = getContext().actorOf(Props.create(Counter.class, key, value));
// Tell the counter to use current storage
counter.tell(new UseStorage(storage), getSelf());
// and send the buffered backlog to the counter
for (SenderMsgPair each : backlog) {
counter.tell(each.msg, each.sender);
}
backlog.clear();
} else if (msg instanceof Increment) {
forwardOrPlaceInBacklog(msg);
} else if (msg.equals(GetCurrentCount)) {
forwardOrPlaceInBacklog(msg);
} else if (msg instanceof Terminated) {
// After 3 restarts the storage child is stopped.
// We receive Terminated because we watch the child, see initStorage.
storage = null;
// Tell the counter that there is no storage for the moment
counter.tell(new UseStorage(null), getSelf());
// Try to re-establish storage after while
getContext().system().scheduler().scheduleOnce(
Duration.create(10, "seconds"), getSelf(), Reconnect,
getContext().dispatcher(), null);
} else if (msg.equals(Reconnect)) {
// Re-establish storage after the scheduled delay
initStorage();
} else {
unhandled(msg);
}
}
void forwardOrPlaceInBacklog(Object msg) {
// We need the initial value from storage before we can start delegate to
// the counter. Before that we place the messages in a backlog, to be sent
// to the counter when it is initialized.
if (counter == null) {
if (backlog.size() >= MAX_BACKLOG)
throw new ServiceUnavailable("CounterService not available," +
" lack of initial value");
backlog.add(new SenderMsgPair(getSender(), msg));
} else {
counter.forward(msg, getContext());
}
}
}
//#messages
public interface CounterApi {
public static class UseStorage {
public final ActorRef storage;
public UseStorage(ActorRef storage) {
this.storage = storage;
}
public String toString() {
return String.format("%s(%s)", getClass().getSimpleName(), storage);
}
}
}
//#messages
/**
* The in memory count variable that will send current value to the Storage,
* if there is any storage available at the moment.
*/
public static class Counter extends UntypedActor {
final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
final String key;
long count;
ActorRef storage;
public Counter(String key, long initialValue) {
this.key = key;
this.count = initialValue;
}
@Override
public void onReceive(Object msg) {
log.debug("received message {}", msg);
if (msg instanceof UseStorage) {
storage = ((UseStorage) msg).storage;
storeCount();
} else if (msg instanceof Increment) {
count += ((Increment) msg).n;
storeCount();
} else if (msg.equals(GetCurrentCount)) {
getSender().tell(new CurrentCount(key, count), getSelf());
} else {
unhandled(msg);
}
}
void storeCount() {
// Delegate dangerous work, to protect our valuable state.
// We can continue without storage.
if (storage != null) {
storage.tell(new Store(new Entry(key, count)), getSelf());
}
}
}
//#messages
public interface StorageApi {
public static class Store {
public final Entry entry;
public Store(Entry entry) {
this.entry = entry;
}
public String toString() {
return String.format("%s(%s)", getClass().getSimpleName(), entry);
}
}
public static class Entry {
public final String key;
public final long value;
public Entry(String key, long value) {
this.key = key;
this.value = value;
}
public String toString() {
return String.format("%s(%s, %s)", getClass().getSimpleName(), key, value);
}
}
public static class Get {
public final String key;
public Get(String key) {
this.key = key;
}
public String toString() {
return String.format("%s(%s)", getClass().getSimpleName(), key);
}
}
public static class StorageException extends RuntimeException {
private static final long serialVersionUID = 1L;
public StorageException(String msg) {
super(msg);
}
}
}
//#messages
/**
* Saves key/value pairs to persistent storage when receiving Store message.
* Replies with current value when receiving Get message. Will throw
* StorageException if the underlying data store is out of order.
*/
public static class Storage extends UntypedActor {
final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
final DummyDB db = DummyDB.instance;
@Override
public void onReceive(Object msg) {
log.debug("received message {}", msg);
if (msg instanceof Store) {
Store store = (Store) msg;
db.save(store.entry.key, store.entry.value);
} else if (msg instanceof Get) {
Get get = (Get) msg;
Long value = db.load(get.key);
getSender().tell(new Entry(get.key, value == null ?
Long.valueOf(0L) : value), getSelf());
} else {
unhandled(msg);
}
}
}
//#dummydb
public static class DummyDB {
public static final DummyDB instance = new DummyDB();
private final Map<String, Long> db = new HashMap<String, Long>();
private DummyDB() {
}
public synchronized void save(String key, Long value) throws StorageException {
if (11 <= value && value <= 14)
throw new StorageException("Simulated store failure " + value);
db.put(key, value);
}
public synchronized Long load(String key) throws StorageException {
return db.get(key);
}
}
//#dummydb
}
//#all

View file

@ -1,470 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor.japi;
//#all
//#imports
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import akka.actor.*;
import akka.dispatch.Mapper;
import akka.event.LoggingReceive;
import akka.japi.pf.DeciderBuilder;
import akka.japi.pf.ReceiveBuilder;
import akka.util.Timeout;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import scala.concurrent.duration.Duration;
import scala.PartialFunction;
import scala.runtime.BoxedUnit;
import static akka.japi.Util.classTag;
import static akka.actor.SupervisorStrategy.resume;
import static akka.actor.SupervisorStrategy.restart;
import static akka.actor.SupervisorStrategy.stop;
import static akka.actor.SupervisorStrategy.escalate;
import static akka.pattern.Patterns.ask;
import static akka.pattern.Patterns.pipe;
import static docs.actor.japi.FaultHandlingDocSample.WorkerApi.*;
import static docs.actor.japi.FaultHandlingDocSample.CounterServiceApi.*;
import static docs.actor.japi.FaultHandlingDocSample.CounterApi.*;
import static docs.actor.japi.FaultHandlingDocSample.StorageApi.*;
//#imports
public class FaultHandlingDocSampleJava8 {
/**
* Runs the sample
*/
public static void main(String[] args) {
Config config = ConfigFactory.parseString(
"akka.loglevel = \"DEBUG\"\n" +
"akka.actor.debug {\n" +
" receive = on\n" +
" lifecycle = on\n" +
"}\n");
ActorSystem system = ActorSystem.create("FaultToleranceSample", config);
ActorRef worker = system.actorOf(Props.create(Worker.class), "worker");
ActorRef listener = system.actorOf(Props.create(Listener.class), "listener");
// start the work and listen on progress
// note that the listener is used as sender of the tell,
// i.e. it will receive replies from the worker
worker.tell(Start, listener);
}
/**
* Listens on progress from the worker and shuts down the system when enough
* work has been done.
*/
public static class Listener extends AbstractLoggingActor {
@Override
public void preStart() {
// If we don't get any progress within 15 seconds then the service
// is unavailable
context().setReceiveTimeout(Duration.create("15 seconds"));
}
public Listener() {
receive(LoggingReceive.create(ReceiveBuilder.
match(Progress.class, progress -> {
log().info("Current progress: {} %", progress.percent);
if (progress.percent >= 100.0) {
log().info("That's all, shutting down");
context().system().shutdown();
}
}).
matchEquals(ReceiveTimeout.getInstance(), x -> {
// No progress within 15 seconds, ServiceUnavailable
log().error("Shutting down due to unavailable service");
context().system().shutdown();
}).build(), context()
));
}
}
//#messages
public interface WorkerApi {
public static final Object Start = "Start";
public static final Object Do = "Do";
public static class Progress {
public final double percent;
public Progress(double percent) {
this.percent = percent;
}
public String toString() {
return String.format("%s(%s)", getClass().getSimpleName(), percent);
}
}
}
//#messages
/**
* Worker performs some work when it receives the Start message. It will
* continuously notify the sender of the Start message of current Progress.
* The Worker supervise the CounterService.
*/
public static class Worker extends AbstractLoggingActor {
final Timeout askTimeout = new Timeout(Duration.create(5, "seconds"));
// The sender of the initial Start message will continuously be notified
// about progress
ActorRef progressListener;
final ActorRef counterService = context().actorOf(
Props.create(CounterService.class), "counter");
final int totalCount = 51;
// Stop the CounterService child if it throws ServiceUnavailable
private static final SupervisorStrategy strategy =
new OneForOneStrategy(DeciderBuilder.
match(ServiceUnavailable.class, e -> stop()).
matchAny(o -> escalate()).build());
@Override
public SupervisorStrategy supervisorStrategy() {
return strategy;
}
public Worker() {
receive(LoggingReceive.create(ReceiveBuilder.
matchEquals(Start, x -> progressListener == null, x -> {
progressListener = sender();
context().system().scheduler().schedule(
Duration.Zero(), Duration.create(1, "second"), self(), Do,
context().dispatcher(), null
);
}).
matchEquals(Do, x -> {
counterService.tell(new Increment(1), self());
counterService.tell(new Increment(1), self());
counterService.tell(new Increment(1), self());
// Send current progress to the initial sender
pipe(ask(counterService, GetCurrentCount, askTimeout)
.mapTo(classTag(CurrentCount.class))
.map(new Mapper<CurrentCount, Progress>() {
public Progress apply(CurrentCount c) {
return new Progress(100.0 * c.count / totalCount);
}
}, context().dispatcher()), context().dispatcher())
.to(progressListener);
}).build(), context())
);
}
}
//#messages
public interface CounterServiceApi {
public static final Object GetCurrentCount = "GetCurrentCount";
public static class CurrentCount {
public final String key;
public final long count;
public CurrentCount(String key, long count) {
this.key = key;
this.count = count;
}
public String toString() {
return String.format("%s(%s, %s)", getClass().getSimpleName(), key, count);
}
}
public static class Increment {
public final long n;
public Increment(long n) {
this.n = n;
}
public String toString() {
return String.format("%s(%s)", getClass().getSimpleName(), n);
}
}
public static class ServiceUnavailable extends RuntimeException {
private static final long serialVersionUID = 1L;
public ServiceUnavailable(String msg) {
super(msg);
}
}
}
//#messages
/**
* Adds the value received in Increment message to a persistent counter.
* Replies with CurrentCount when it is asked for CurrentCount. CounterService
* supervise Storage and Counter.
*/
public static class CounterService extends AbstractLoggingActor {
// Reconnect message
static final Object Reconnect = "Reconnect";
private static class SenderMsgPair {
final ActorRef sender;
final Object msg;
SenderMsgPair(ActorRef sender, Object msg) {
this.msg = msg;
this.sender = sender;
}
}
final String key = self().path().name();
ActorRef storage;
ActorRef counter;
final List<SenderMsgPair> backlog = new ArrayList<>();
final int MAX_BACKLOG = 10000;
// Restart the storage child when StorageException is thrown.
// After 3 restarts within 5 seconds it will be stopped.
private static final SupervisorStrategy strategy =
new OneForOneStrategy(3, Duration.create("5 seconds"), DeciderBuilder.
match(StorageException.class, e -> restart()).
matchAny(o -> escalate()).build());
@Override
public SupervisorStrategy supervisorStrategy() {
return strategy;
}
@Override
public void preStart() {
initStorage();
}
/**
* The child storage is restarted in case of failure, but after 3 restarts,
* and still failing it will be stopped. Better to back-off than
* continuously failing. When it has been stopped we will schedule a
* Reconnect after a delay. Watch the child so we receive Terminated message
* when it has been terminated.
*/
void initStorage() {
storage = context().watch(context().actorOf(
Props.create(Storage.class), "storage"));
// Tell the counter, if any, to use the new storage
if (counter != null)
counter.tell(new UseStorage(storage), self());
// We need the initial value to be able to operate
storage.tell(new Get(key), self());
}
public CounterService() {
receive(LoggingReceive.create(ReceiveBuilder.
match(Entry.class, entry -> entry.key.equals(key) && counter == null, entry -> {
// Reply from Storage of the initial value, now we can create the Counter
final long value = entry.value;
counter = context().actorOf(Props.create(Counter.class, key, value));
// Tell the counter to use current storage
counter.tell(new UseStorage(storage), self());
// and send the buffered backlog to the counter
for (SenderMsgPair each : backlog) {
counter.tell(each.msg, each.sender);
}
backlog.clear();
}).
match(Increment.class, increment -> {
forwardOrPlaceInBacklog(increment);
}).
matchEquals(GetCurrentCount, gcc -> {
forwardOrPlaceInBacklog(gcc);
}).
match(Terminated.class, o -> {
// After 3 restarts the storage child is stopped.
// We receive Terminated because we watch the child, see initStorage.
storage = null;
// Tell the counter that there is no storage for the moment
counter.tell(new UseStorage(null), self());
// Try to re-establish storage after while
context().system().scheduler().scheduleOnce(
Duration.create(10, "seconds"), self(), Reconnect,
context().dispatcher(), null);
}).
matchEquals(Reconnect, o -> {
// Re-establish storage after the scheduled delay
initStorage();
}).build(), context())
);
}
void forwardOrPlaceInBacklog(Object msg) {
// We need the initial value from storage before we can start delegate to
// the counter. Before that we place the messages in a backlog, to be sent
// to the counter when it is initialized.
if (counter == null) {
if (backlog.size() >= MAX_BACKLOG)
throw new ServiceUnavailable("CounterService not available," +
" lack of initial value");
backlog.add(new SenderMsgPair(sender(), msg));
} else {
counter.forward(msg, context());
}
}
}
//#messages
public interface CounterApi {
public static class UseStorage {
public final ActorRef storage;
public UseStorage(ActorRef storage) {
this.storage = storage;
}
public String toString() {
return String.format("%s(%s)", getClass().getSimpleName(), storage);
}
}
}
//#messages
/**
* The in memory count variable that will send current value to the Storage,
* if there is any storage available at the moment.
*/
public static class Counter extends AbstractLoggingActor {
final String key;
long count;
ActorRef storage;
public Counter(String key, long initialValue) {
this.key = key;
this.count = initialValue;
receive(LoggingReceive.create(ReceiveBuilder.
match(UseStorage.class, useStorage -> {
storage = useStorage.storage;
storeCount();
}).
match(Increment.class, increment -> {
count += increment.n;
storeCount();
}).
matchEquals(GetCurrentCount, gcc -> {
sender().tell(new CurrentCount(key, count), self());
}).build(), context())
);
}
void storeCount() {
// Delegate dangerous work, to protect our valuable state.
// We can continue without storage.
if (storage != null) {
storage.tell(new Store(new Entry(key, count)), self());
}
}
}
//#messages
public interface StorageApi {
public static class Store {
public final Entry entry;
public Store(Entry entry) {
this.entry = entry;
}
public String toString() {
return String.format("%s(%s)", getClass().getSimpleName(), entry);
}
}
public static class Entry {
public final String key;
public final long value;
public Entry(String key, long value) {
this.key = key;
this.value = value;
}
public String toString() {
return String.format("%s(%s, %s)", getClass().getSimpleName(), key, value);
}
}
public static class Get {
public final String key;
public Get(String key) {
this.key = key;
}
public String toString() {
return String.format("%s(%s)", getClass().getSimpleName(), key);
}
}
public static class StorageException extends RuntimeException {
private static final long serialVersionUID = 1L;
public StorageException(String msg) {
super(msg);
}
}
}
//#messages
/**
* Saves key/value pairs to persistent storage when receiving Store message.
* Replies with current value when receiving Get message. Will throw
* StorageException if the underlying data store is out of order.
*/
public static class Storage extends AbstractLoggingActor {
final DummyDB db = DummyDB.instance;
public Storage() {
receive(LoggingReceive.create(ReceiveBuilder.
match(Store.class, store -> {
db.save(store.entry.key, store.entry.value);
}).
match(Get.class, get -> {
Long value = db.load(get.key);
sender().tell(new Entry(get.key, value == null ?
Long.valueOf(0L) : value), self());
}).build(), context())
);
}
}
//#dummydb
public static class DummyDB {
public static final DummyDB instance = new DummyDB();
private final Map<String, Long> db = new HashMap<String, Long>();
private DummyDB() {
}
public synchronized void save(String key, Long value) throws StorageException {
if (11 <= value && value <= 14)
throw new StorageException("Simulated store failure " + value);
db.put(key, value);
}
public synchronized Long load(String key) throws StorageException {
return db.get(key);
}
}
//#dummydb
}
//#all

View file

@ -12,19 +12,23 @@ import akka.testkit.TestEvent;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import docs.AbstractJavaTest;
import docs.actor.ActorDocTest.FirstActor;
import scala.PartialFunction;
import scala.runtime.BoxedUnit;
import static docs.actorlambda.Messages.Swap.Swap;
import static docs.actorlambda.Messages.*;
import static akka.japi.Util.immutableSeq;
import akka.actor.CoordinatedShutdown;
import static akka.pattern.PatternsCS.ask;
import akka.util.Timeout;
import akka.Done;
import java.util.concurrent.CompletionStage;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import akka.testkit.TestActors;
import akka.dispatch.Mapper;
import akka.dispatch.Futures;
import akka.util.Timeout;
import akka.testkit.JavaTestKit;
import org.junit.AfterClass;
@ -44,13 +48,25 @@ import akka.actor.ActorIdentity;
import akka.actor.ActorSelection;
import akka.actor.Identify;
//#import-identify
//#import-graceFulStop
//#import-ask
import static akka.pattern.Patterns.ask;
import static akka.pattern.Patterns.pipe;
import akka.dispatch.Futures;
import akka.dispatch.Mapper;
import akka.util.Timeout;
//#import-ask
//#import-gracefulStop
import akka.pattern.AskTimeoutException;
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;
//#import-ask
import scala.concurrent.Future;
import static akka.pattern.Patterns.gracefulStop;
//#import-graceFulStop
//#import-ask
//#import-gracefulStop
//#import-terminated
import akka.actor.Terminated;
//#import-terminated
public class ActorDocTest extends AbstractJavaTest {
@ -71,49 +87,111 @@ public class ActorDocTest extends AbstractJavaTest {
@AfterClass
public static void afterClass() throws Exception {
Await.ready(system.terminate(), Duration.create("5 seconds"));
Await.ready(system.terminate(), Duration.create(5, TimeUnit.SECONDS));
}
static
//#context-actorOf
public class FirstActor extends AbstractActor {
final ActorRef child = context().actorOf(Props.create(MyActor.class), "myChild");
final ActorRef child = getContext().actorOf(Props.create(MyActor.class), "myChild");
//#plus-some-behavior
public FirstActor() {
receive(ReceiveBuilder.
matchAny(x -> {
sender().tell(x, self());
}).build()
);
@Override
public Receive createReceive() {
return receiveBuilder()
.matchAny(x -> sender().tell(x, self()))
.build();
}
//#plus-some-behavior
}
//#context-actorOf
static public abstract class SomeActor extends AbstractActor {
//#receive-constructor
public SomeActor() {
receive(ReceiveBuilder.
//#and-some-behavior
match(String.class, s -> System.out.println(s.toLowerCase())).
//#and-some-behavior
build());
}
//#receive-constructor
static public class SomeActor extends AbstractActor {
//#createReceive
@Override
//#receive
public abstract PartialFunction<Object, BoxedUnit> receive();
//#receive
public Receive createReceive() {
return receiveBuilder()
.match(String.class, s -> System.out.println(s.toLowerCase()))
.build();
}
//#createReceive
}
static
//#well-structured
public class WellStructuredActor extends AbstractActor {
public static class Msg1 {}
public static class Msg2 {}
public static class Msg3 {}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Msg1.class, this::receiveMsg1)
.match(Msg2.class, this::receiveMsg2)
.match(Msg3.class, this::receiveMsg3)
.build();
}
private void receiveMsg1(Msg1 msg) {
// actual work
}
private void receiveMsg2(Msg2 msg) {
// actual work
}
private void receiveMsg3(Msg3 msg) {
// actual work
}
}
//#well-structured
static
//#optimized
public class OptimizedActor extends UntypedAbstractActor {
public static class Msg1 {}
public static class Msg2 {}
public static class Msg3 {}
@Override
public void onReceive(Object msg) throws Exception {
if (msg instanceof Msg1)
receiveMsg1((Msg1) msg);
else if (msg instanceof Msg1)
receiveMsg2((Msg2) msg);
else if (msg instanceof Msg3)
receiveMsg3((Msg3) msg);
else
unhandled(msg);
}
private void receiveMsg1(Msg1 msg) {
// actual work
}
private void receiveMsg2(Msg2 msg) {
// actual work
}
private void receiveMsg3(Msg3 msg) {
// actual work
}
}
//#optimized
static public class ActorWithArgs extends AbstractActor {
private final String args;
ActorWithArgs(String args) {
public ActorWithArgs(String args) {
this.args = args;
receive(ReceiveBuilder.
matchAny(x -> { }).build()
);
}
@Override
public Receive createReceive() {
return receiveBuilder().matchAny(x -> { }).build();
}
}
@ -133,14 +211,18 @@ public class ActorDocTest extends AbstractJavaTest {
}
private final Integer magicNumber;
DemoActor(Integer magicNumber) {
public DemoActor(Integer magicNumber) {
this.magicNumber = magicNumber;
receive(ReceiveBuilder.
match(Integer.class, i -> {
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Integer.class, i -> {
sender().tell(i + magicNumber, self());
}).build()
);
})
.build();
}
}
@ -149,11 +231,12 @@ public class ActorDocTest extends AbstractJavaTest {
//#props-factory
public class SomeOtherActor extends AbstractActor {
// Props(new DemoActor(42)) would not be safe
ActorRef demoActor = context().actorOf(DemoActor.props(42), "demo");
ActorRef demoActor = getContext().actorOf(DemoActor.props(42), "demo");
// ...
//#props-factory
public SomeOtherActor() {
receive(emptyBehavior());
@Override
public Receive createReceive() {
return AbstractActor.emptyBehavior();
}
//#props-factory
}
@ -174,26 +257,65 @@ public class ActorDocTest extends AbstractJavaTest {
return from;
}
}
DemoMessagesActor() {
receive(ReceiveBuilder.
match(Greeting.class, g -> {
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Greeting.class, g -> {
log().info("I was greeted by {}", g.getGreeter());
}).build()
);
};
})
.build();
}
}
//#messages-in-companion
public static class LifecycleMethods extends AbstractActor {
@Override
public Receive createReceive() {
return AbstractActor.emptyBehavior();
}
/*
* This section must be kept in sync with the actual Actor trait.
*
* BOYSCOUT RULE: whenever you read this, verify that!
*/
//#lifecycle-callbacks
public void preStart() {
}
public void preRestart(Throwable reason, Optional<Object> message) {
for (ActorRef each : getContext().getChildren()) {
getContext().unwatch(each);
getContext().stop(each);
}
postStop();
}
public void postRestart(Throwable reason) {
preStart();
}
public void postStop() {
}
//#lifecycle-callbacks
}
public static class Hook extends AbstractActor {
ActorRef target = null;
public Hook() {
receive(emptyBehavior());
@Override
public Receive createReceive() {
return AbstractActor.emptyBehavior();
}
//#preStart
@Override
public void preStart() {
target = context().actorOf(Props.create(MyActor.class, "target"));
target = getContext().actorOf(Props.create(MyActor.class, "target"));
}
//#preStart
//#postStop
@ -207,7 +329,7 @@ public class ActorDocTest extends AbstractJavaTest {
//#tell
final Object result = "";
//#forward
target.forward(result, context());
target.forward(result, getContext());
//#forward
target = null;
//#clean-up-some-resources
@ -218,28 +340,30 @@ public class ActorDocTest extends AbstractJavaTest {
public void compileSelections() {
//#selection-local
// will look up this absolute path
context().actorSelection("/user/serviceA/actor");
getContext().actorSelection("/user/serviceA/actor");
// will look up sibling beneath same supervisor
context().actorSelection("../joe");
getContext().actorSelection("../joe");
//#selection-local
//#selection-wildcard
// will look all children to serviceB with names starting with worker
context().actorSelection("/user/serviceB/worker*");
getContext().actorSelection("/user/serviceB/worker*");
// will look up all siblings beneath same supervisor
context().actorSelection("../*");
getContext().actorSelection("../*");
//#selection-wildcard
//#selection-remote
context().actorSelection("akka.tcp://app@otherhost:1234/user/serviceB");
getContext().actorSelection("akka.tcp://app@otherhost:1234/user/serviceB");
//#selection-remote
}
}
public static class ReplyException extends AbstractActor {
public ReplyException() {
receive(ReceiveBuilder.
matchAny(x -> {
@Override
public Receive createReceive() {
return receiveBuilder()
.matchAny(x -> {
//#reply-exception
try {
String result = operation();
@ -249,8 +373,8 @@ public class ActorDocTest extends AbstractJavaTest {
throw e;
}
//#reply-exception
}).build()
);
})
.build();
}
private String operation() {
@ -267,28 +391,31 @@ public class ActorDocTest extends AbstractJavaTest {
public static final Shutdown SHUTDOWN = Shutdown.Shutdown;
private ActorRef worker =
context().watch(context().actorOf(Props.create(Cruncher.class), "worker"));
getContext().watch(getContext().actorOf(Props.create(Cruncher.class), "worker"));
public Manager() {
receive(ReceiveBuilder.
matchEquals("job", s -> {
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals("job", s -> {
worker.tell("crunch", self());
}).
matchEquals(SHUTDOWN, x -> {
})
.matchEquals(SHUTDOWN, x -> {
worker.tell(PoisonPill.getInstance(), self());
context().become(shuttingDown);
}).build()
);
getContext().become(shuttingDown());
})
.build();
}
public PartialFunction<Object, BoxedUnit> shuttingDown =
ReceiveBuilder.
matchEquals("job", s -> {
sender().tell("service unavailable, shutting down", self());
}).
match(Terminated.class, t -> t.actor().equals(worker), t -> {
context().stop(self());
}).build();
private AbstractActor.Receive shuttingDown() {
return receiveBuilder()
.matchEquals("job", s ->
sender().tell("service unavailable, shutting down", self())
)
.match(Terminated.class, t -> t.actor().equals(worker), t ->
getContext().stop(self())
)
.build();
}
}
//#gracefulStop-actor
@ -309,27 +436,26 @@ public class ActorDocTest extends AbstractJavaTest {
public static class Cruncher extends AbstractActor {
public Cruncher() {
receive(ReceiveBuilder.
matchEquals("crunch", s -> { }).build()
);
@Override
public Receive createReceive() {
return receiveBuilder().matchEquals("crunch", s -> { }).build();
}
}
static
//#swapper
public class Swapper extends AbstractLoggingActor {
public Swapper() {
receive(ReceiveBuilder.
matchEquals(Swap, s -> {
log().info("Hi");
context().become(ReceiveBuilder.
matchEquals(Swap, x -> {
log().info("Ho");
context().unbecome(); // resets the latest 'become' (just for fun)
}).build(), false); // push on top instead of replace
}).build()
);
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals(Swap, s -> {
log().info("Hi");
getContext().become(receiveBuilder().
matchEquals(Swap, x -> {
log().info("Ho");
getContext().unbecome(); // resets the latest 'become' (just for fun)
}).build(), false); // push on top instead of replace
}).build();
}
}
@ -418,29 +544,32 @@ public class ActorDocTest extends AbstractJavaTest {
//#receive-timeout
public class ReceiveTimeoutActor extends AbstractActor {
//#receive-timeout
ActorRef target = context().system().deadLetters();
ActorRef target = getContext().system().deadLetters();
//#receive-timeout
public ReceiveTimeoutActor() {
// To set an initial delay
context().setReceiveTimeout(Duration.create("10 seconds"));
receive(ReceiveBuilder.
matchEquals("Hello", s -> {
getContext().setReceiveTimeout(Duration.create(10, TimeUnit.SECONDS));
}
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals("Hello", s -> {
// To set in a response to a message
context().setReceiveTimeout(Duration.create("1 second"));
getContext().setReceiveTimeout(Duration.create(1, TimeUnit.SECONDS));
//#receive-timeout
target = sender();
target.tell("Hello world", self());
//#receive-timeout
}).
match(ReceiveTimeout.class, r -> {
})
.match(ReceiveTimeout.class, r -> {
// To turn it off
context().setReceiveTimeout(Duration.Undefined());
getContext().setReceiveTimeout(Duration.Undefined());
//#receive-timeout
target.tell("timeout", self());
//#receive-timeout
}).build()
);
})
.build();
}
}
//#receive-timeout
@ -460,35 +589,40 @@ public class ActorDocTest extends AbstractJavaTest {
static
//#hot-swap-actor
public class HotSwapActor extends AbstractActor {
private PartialFunction<Object, BoxedUnit> angry;
private PartialFunction<Object, BoxedUnit> happy;
private AbstractActor.Receive angry;
private AbstractActor.Receive happy;
public HotSwapActor() {
angry =
ReceiveBuilder.
matchEquals("foo", s -> {
receiveBuilder()
.matchEquals("foo", s -> {
sender().tell("I am already angry?", self());
}).
matchEquals("bar", s -> {
context().become(happy);
}).build();
})
.matchEquals("bar", s -> {
getContext().become(happy);
})
.build();
happy = ReceiveBuilder.
matchEquals("bar", s -> {
happy = receiveBuilder()
.matchEquals("bar", s -> {
sender().tell("I am already happy :-)", self());
}).
matchEquals("foo", s -> {
context().become(angry);
}).build();
receive(ReceiveBuilder.
matchEquals("foo", s -> {
context().become(angry);
}).
matchEquals("bar", s -> {
context().become(happy);
}).build()
);
})
.matchEquals("foo", s -> {
getContext().become(angry);
})
.build();
}
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals("foo", s ->
getContext().become(angry)
)
.matchEquals("bar", s ->
getContext().become(happy)
)
.build();
}
}
//#hot-swap-actor
@ -516,19 +650,21 @@ public class ActorDocTest extends AbstractJavaTest {
static
//#stash
public class ActorWithProtocol extends AbstractActorWithStash {
public ActorWithProtocol() {
receive(ReceiveBuilder.
matchEquals("open", s -> {
context().become(ReceiveBuilder.
matchEquals("write", ws -> { /* do writing */ }).
matchEquals("close", cs -> {
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals("open", s -> {
getContext().become(receiveBuilder()
.matchEquals("write", ws -> { /* do writing */ })
.matchEquals("close", cs -> {
unstashAll();
context().unbecome();
}).
matchAny(msg -> stash()).build(), false);
}).
matchAny(msg -> stash()).build()
);
getContext().unbecome();
})
.matchAny(msg -> stash())
.build(), false);
})
.matchAny(msg -> stash())
.build();
}
}
//#stash
@ -541,21 +677,24 @@ public class ActorDocTest extends AbstractJavaTest {
static
//#watch
public class WatchActor extends AbstractActor {
private final ActorRef child = context().actorOf(Props.empty(), "target");
private final ActorRef child = getContext().actorOf(Props.empty(), "target");
private ActorRef lastSender = system.deadLetters();
public WatchActor() {
context().watch(child); // <-- this is the only call needed for registration
receive(ReceiveBuilder.
matchEquals("kill", s -> {
context().stop(child);
getContext().watch(child); // <-- this is the only call needed for registration
}
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals("kill", s -> {
getContext().stop(child);
lastSender = sender();
}).
match(Terminated.class, t -> t.actor().equals(child), t -> {
})
.match(Terminated.class, t -> t.actor().equals(child), t -> {
lastSender.tell("finished", self());
}).build()
);
})
.build();
}
}
//#watch
@ -578,26 +717,30 @@ public class ActorDocTest extends AbstractJavaTest {
final Integer identifyId = 1;
public Follower(){
ActorSelection selection = context().actorSelection("/user/another");
ActorSelection selection = getContext().actorSelection("/user/another");
selection.tell(new Identify(identifyId), self());
receive(ReceiveBuilder.
match(ActorIdentity.class, id -> id.getRef() != null, id -> {
ActorRef ref = id.getRef();
context().watch(ref);
context().become(active(ref));
}).
match(ActorIdentity.class, id -> id.getRef() == null, id -> {
context().stop(self());
}).build()
);
}
final PartialFunction<Object, BoxedUnit> active(final ActorRef another) {
return ReceiveBuilder.
match(Terminated.class, t -> t.actor().equals(another), t -> {
context().stop(self());
}).build();
@Override
public Receive createReceive() {
return receiveBuilder()
.match(ActorIdentity.class, id -> id.getActorRef().isPresent(), id -> {
ActorRef ref = id.getActorRef().get();
getContext().watch(ref);
getContext().become(active(ref));
})
.match(ActorIdentity.class, id -> !id.getActorRef().isPresent(), id -> {
getContext().stop(self());
})
.build();
}
final AbstractActor.Receive active(final ActorRef another) {
return receiveBuilder()
.match(Terminated.class, t -> t.actor().equals(another), t ->
getContext().stop(self())
)
.build();
}
}
//#identify
@ -615,73 +758,70 @@ public class ActorDocTest extends AbstractJavaTest {
}
};
}
public static class NoReceiveActor extends AbstractActor {
}
@Test
public void noReceiveActor() {
EventFilter ex1 = new ErrorFilter(ActorInitializationException.class);
EventFilter[] ignoreExceptions = { ex1 };
try {
system.eventStream().publish(new TestEvent.Mute(immutableSeq(ignoreExceptions)));
new JavaTestKit(system) {{
final ActorRef victim = new EventFilter<ActorRef>(ActorInitializationException.class) {
protected ActorRef run() {
return system.actorOf(Props.create(NoReceiveActor.class), "victim");
}
}.message("Actor behavior has not been set with receive(...)").occurrences(1).exec();
public void usePatternsAskPipe() {
new JavaTestKit(system) {
{
ActorRef actorA = system.actorOf(TestActors.echoActorProps());
ActorRef actorB = system.actorOf(TestActors.echoActorProps());
ActorRef actorC = getRef();
assertEquals(true, victim.isTerminated());
}};
} finally {
system.eventStream().publish(new TestEvent.UnMute(immutableSeq(ignoreExceptions)));
}
//#ask-pipe
final Timeout t = new Timeout(Duration.create(5, TimeUnit.SECONDS));
final ArrayList<Future<Object>> futures = new ArrayList<Future<Object>>();
futures.add(ask(actorA, "request", 1000)); // using 1000ms timeout
futures.add(ask(actorB, "another request", t)); // using timeout from
// above
final Future<Iterable<Object>> aggregate = Futures.sequence(futures,
system.dispatcher());
final Future<Result> transformed = aggregate.map(
new Mapper<Iterable<Object>, Result>() {
public Result apply(Iterable<Object> coll) {
final Iterator<Object> it = coll.iterator();
final String x = (String) it.next();
final String s = (String) it.next();
return new Result(x, s);
}
}, system.dispatcher());
pipe(transformed, system.dispatcher()).to(actorC);
//#ask-pipe
expectMsgEquals(new Result("request", "another request"));
}
};
}
public static class MultipleReceiveActor extends AbstractActor {
public MultipleReceiveActor() {
receive(ReceiveBuilder.
match(String.class, s1 -> s1.toLowerCase().equals("become"), s1 -> {
sender().tell(s1.toUpperCase(), self());
receive(ReceiveBuilder.
match(String.class, s2 -> {
sender().tell(s2.toLowerCase(), self());
}).build()
);
}).
match(String.class, s1 -> {
sender().tell(s1.toUpperCase(), self());
}).build()
);
}
}
@Test
public void multipleReceiveActor() {
EventFilter ex1 = new ErrorFilter(IllegalActorStateException.class);
EventFilter[] ignoreExceptions = { ex1 };
try {
system.eventStream().publish(new TestEvent.Mute(immutableSeq(ignoreExceptions)));
new JavaTestKit(system) {{
new EventFilter<Boolean>(IllegalActorStateException.class) {
protected Boolean run() {
ActorRef victim = system.actorOf(Props.create(MultipleReceiveActor.class), "victim2");
victim.tell("Foo", getRef());
expectMsgEquals("FOO");
victim.tell("bEcoMe", getRef());
expectMsgEquals("BECOME");
victim.tell("Foo", getRef());
// if it's upper case, then the actor was restarted
expectMsgEquals("FOO");
return true;
}
}.message("Actor behavior has already been set with receive(...), " +
"use context().become(...) to change it later").occurrences(1).exec();
}};
} finally {
system.eventStream().publish(new TestEvent.UnMute(immutableSeq(ignoreExceptions)));
}
public void useKill() {
new JavaTestKit(system) {
{
ActorRef victim = system.actorOf(TestActors.echoActorProps());
watch(victim);
//#kill
victim.tell(akka.actor.Kill.getInstance(), ActorRef.noSender());
//#kill
expectTerminated(Duration.create(3, TimeUnit.SECONDS), victim);
}
};
}
@Test
public void usePoisonPill() {
new JavaTestKit(system) {
{
ActorRef victim = system.actorOf(TestActors.echoActorProps());
watch(victim);
//#poison-pill
victim.tell(akka.actor.PoisonPill.getInstance(), ActorRef.noSender());
//#poison-pill
expectTerminated(Duration.create(3, TimeUnit.SECONDS), victim);
}
};
}
@Test
@ -691,7 +831,7 @@ public class ActorDocTest extends AbstractJavaTest {
CoordinatedShutdown.get(system).addTask(
CoordinatedShutdown.PhaseBeforeServiceUnbind(), "someTaskName",
() -> {
return ask(someActor, "stop", new Timeout(5, TimeUnit.SECONDS))
return akka.pattern.PatternsCS.ask(someActor, "stop", new Timeout(5, TimeUnit.SECONDS))
.thenApply(reply -> Done.getInstance());
});
//#coordinated-shutdown-addTask

View file

@ -0,0 +1,105 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actorlambda;
import docs.AbstractJavaTest;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;
import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.testkit.JavaTestKit;
//#import
import akka.actor.Actor;
import akka.actor.IndirectActorProducer;
//#import
public class DependencyInjectionDocTest extends AbstractJavaTest {
public static class TheActor extends AbstractActor {
final String s;
public TheActor(String s) {
this.s = s;
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(String.class, msg -> {
sender().tell(s, self());
})
.build();
}
}
static ActorSystem system = null;
@BeforeClass
public static void beforeClass() {
system = ActorSystem.create("DependencyInjectionDocTest");
}
@AfterClass
public static void afterClass() throws Exception {
Await.ready(system.terminate(), Duration.create("5 seconds"));
}
//this is just to make the test below a tiny fraction nicer
private ActorSystem getContext() {
return system;
}
static
//#creating-indirectly
class DependencyInjector implements IndirectActorProducer {
final Object applicationContext;
final String beanName;
public DependencyInjector(Object applicationContext, String beanName) {
this.applicationContext = applicationContext;
this.beanName = beanName;
}
@Override
public Class<? extends Actor> actorClass() {
return TheActor.class;
}
@Override
public TheActor produce() {
TheActor result;
//#obtain-fresh-Actor-instance-from-DI-framework
result = new TheActor((String) applicationContext);
//#obtain-fresh-Actor-instance-from-DI-framework
return result;
}
}
//#creating-indirectly
@Test
public void indirectActorOf() {
final String applicationContext = "...";
//#creating-indirectly
final ActorRef myActor = getContext().actorOf(
Props.create(DependencyInjector.class, applicationContext, "TheActor"),
"TheActor");
//#creating-indirectly
new JavaTestKit(system) {
{
myActor.tell("hello", getRef());
expectMsgEquals("...");
}
};
}
}

View file

@ -3,37 +3,41 @@
*/
package docs.actorlambda;
//#testkit
import akka.actor.*;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import docs.AbstractJavaTest;
import java.util.Optional;
import static akka.pattern.Patterns.ask;
//#testkit
import akka.testkit.JavaTestKit;
import akka.testkit.TestProbe;
import akka.testkit.ErrorFilter;
import akka.testkit.EventFilter;
import akka.testkit.TestEvent;
import scala.concurrent.duration.Duration;
import static java.util.concurrent.TimeUnit.SECONDS;
import static akka.japi.Util.immutableSeq;
import scala.concurrent.Await;
//#testkit
//#supervisor
import akka.japi.pf.DeciderBuilder;
import static akka.actor.SupervisorStrategy.resume;
import static akka.actor.SupervisorStrategy.restart;
import static akka.actor.SupervisorStrategy.stop;
import static akka.actor.SupervisorStrategy.escalate;
import akka.japi.pf.DeciderBuilder;
import akka.japi.pf.ReceiveBuilder;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import docs.AbstractJavaTest;
import scala.PartialFunction;
import scala.concurrent.Await;
import static akka.pattern.Patterns.ask;
import scala.concurrent.duration.Duration;
import akka.testkit.TestProbe;
//#testkit
import akka.testkit.ErrorFilter;
import akka.testkit.EventFilter;
import akka.testkit.TestEvent;
import akka.testkit.JavaTestKit;
import static java.util.concurrent.TimeUnit.SECONDS;
import static akka.japi.Util.immutableSeq;
import scala.Option;
//#supervisor
import org.junit.Test;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import scala.runtime.BoxedUnit;
//#testkit
public class FaultHandlingTest extends AbstractJavaTest {
@ -65,12 +69,13 @@ public class FaultHandlingTest extends AbstractJavaTest {
//#strategy
public Supervisor() {
receive(ReceiveBuilder.
match(Props.class, props -> {
sender().tell(context().actorOf(props), self());
}).build()
);
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Props.class, props -> {
sender().tell(getContext().actorOf(props), self());
})
.build();
}
}
@ -95,16 +100,17 @@ public class FaultHandlingTest extends AbstractJavaTest {
//#strategy2
public Supervisor2() {
receive(ReceiveBuilder.
match(Props.class, props -> {
sender().tell(context().actorOf(props), self());
}).build()
);
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Props.class, props -> {
sender().tell(getContext().actorOf(props), self());
})
.build();
}
@Override
public void preRestart(Throwable cause, Option<Object> msg) {
public void preRestart(Throwable cause, Optional<Object> msg) {
// do not kill all children, which is the default here
}
}
@ -116,12 +122,13 @@ public class FaultHandlingTest extends AbstractJavaTest {
public class Child extends AbstractActor {
int state = 0;
public Child() {
receive(ReceiveBuilder.
match(Exception.class, exception -> { throw exception; }).
match(Integer.class, i -> state = i).
matchEquals("get", s -> sender().tell(state, self())).build()
);
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Exception.class, exception -> { throw exception; })
.match(Integer.class, i -> state = i)
.matchEquals("get", s -> sender().tell(state, self()))
.build();
}
}

View file

@ -15,10 +15,12 @@ import akka.japi.pf.UnitPFBuilder;
//#actor
public class GraduallyBuiltActor extends AbstractActor {
private final LoggingAdapter log = Logging.getLogger(context().system(), this);
private final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
public GraduallyBuiltActor() {
UnitPFBuilder<Object> builder = ReceiveBuilder.create();
@Override
public Receive createReceive() {
ReceiveBuilder builder = ReceiveBuilder.create();
builder.match(String.class, s -> {
log.info("Received String message: {}", s);
//#actor
@ -27,9 +29,12 @@ public class GraduallyBuiltActor extends AbstractActor {
//#reply
//#actor
});
// do some other stuff in between
builder.matchAny(o -> log.info("received unknown message"));
receive(builder.build());
return builder.build();
}
}
//#actor

View file

@ -8,7 +8,6 @@ import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.japi.pf.FI;
import akka.japi.pf.ReceiveBuilder;
import akka.testkit.JavaTestKit;
import docs.AbstractJavaTest;
import org.junit.AfterClass;
@ -16,7 +15,7 @@ import org.junit.BeforeClass;
import org.junit.Test;
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
public class InitializationDocTest extends AbstractJavaTest {
@ -32,24 +31,57 @@ public class InitializationDocTest extends AbstractJavaTest {
public static void afterClass() throws Exception {
Await.ready(system.terminate(), Duration.create("5 seconds"));
}
static public class PreStartInitExample extends AbstractActor {
@Override
public Receive createReceive() {
return AbstractActor.emptyBehavior();
}
//#preStartInit
@Override
public void preStart() {
// Initialize children here
}
// Overriding postRestart to disable the call to preStart()
// after restarts
@Override
public void postRestart(Throwable reason) {
}
// The default implementation of preRestart() stops all the children
// of the actor. To opt-out from stopping the children, we
// have to override preRestart()
@Override
public void preRestart(Throwable reason, Optional<Object> message)
throws Exception {
// Keep the call to postStop(), but no stopping of children
postStop();
}
//#preStartInit
}
public static class MessageInitExample extends AbstractActor {
private String initializeMe = null;
public MessageInitExample() {
//#messageInit
receive(ReceiveBuilder.
matchEquals("init", m1 -> {
initializeMe = "Up and running";
context().become(ReceiveBuilder.
matchEquals("U OK?", m2 -> {
sender().tell(initializeMe, self());
}).build());
}).build()
//#messageInit
);
//#messageInit
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals("init", m1 -> {
initializeMe = "Up and running";
getContext().become(receiveBuilder()
.matchEquals("U OK?", m2 -> {
sender().tell(initializeMe, self());
})
.build());
})
.build();
}
//#messageInit
}
public class GenericMessage<T> {
@ -61,24 +93,27 @@ public class InitializationDocTest extends AbstractJavaTest {
}
public static class GenericActor extends AbstractActor {
public GenericActor() {
receive(ReceiveBuilder.match(GenericMessage.class, (GenericMessage<String> msg) -> {
GenericMessage<String> message = msg;
sender().tell(message.value.toUpperCase(), self());
}).build());
@Override
public Receive createReceive() {
return receiveBuilder()
.matchUnchecked(GenericMessage.class, (GenericMessage<String> msg) -> {
GenericMessage<String> message = msg;
sender().tell(message.value.toUpperCase(), self());
})
.build();
}
}
static class GenericActorWithPredicate extends AbstractActor {
public GenericActorWithPredicate() {
@Override
public Receive createReceive() {
FI.TypedPredicate<GenericMessage<String>> typedPredicate = s -> !s.value.isEmpty();
receive(ReceiveBuilder.match(GenericMessage.class, typedPredicate, (GenericMessage<String> msg) -> {
sender().tell(msg.value.toUpperCase(), self());
}).build());
return receiveBuilder()
.matchUnchecked(GenericMessage.class, typedPredicate, (GenericMessage<String> msg) -> {
sender().tell(msg.value.toUpperCase(), self());
})
.build();
}
}

View file

@ -8,26 +8,26 @@ package docs.actorlambda;
import akka.actor.AbstractActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import akka.japi.pf.ReceiveBuilder;
//#imports
//#my-actor
public class MyActor extends AbstractActor {
private final LoggingAdapter log = Logging.getLogger(context().system(), this);
private final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
public MyActor() {
receive(ReceiveBuilder.
match(String.class, s -> {
@Override
public Receive createReceive() {
return receiveBuilder()
.match(String.class, s -> {
log.info("Received String message: {}", s);
//#my-actor
//#reply
sender().tell(s, self());
//#reply
//#my-actor
}).
matchAny(o -> log.info("received unknown message")).build()
);
})
.matchAny(o -> log.info("received unknown message"))
.build();
}
}
//#my-actor

View file

@ -2,13 +2,13 @@
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actor;
package docs.actorlambda;
//#my-bounded-untyped-actor
import akka.dispatch.BoundedMessageQueueSemantics;
import akka.dispatch.RequiresMessageQueue;
public class MyBoundedUntypedActor extends MyUntypedActor
public class MyBoundedActor extends MyActor
implements RequiresMessageQueue<BoundedMessageQueueSemantics> {
}
//#my-bounded-untyped-actor

View file

@ -0,0 +1,29 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.actorlambda;
//#my-stopping-actor
import akka.actor.ActorRef;
import akka.actor.AbstractActor;
public class MyStoppingActor extends AbstractActor {
ActorRef child = null;
// ... creation of child ...
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals("interrupt-child", m ->
getContext().stop(child)
)
.matchEquals("done", m ->
getContext().stop(self())
)
.build();
}
}
//#my-stopping-actor

View file

@ -7,30 +7,30 @@ package docs.actorlambda;
//#sample-actor
import akka.actor.AbstractActor;
import akka.japi.pf.ReceiveBuilder;
import scala.PartialFunction;
import scala.runtime.BoxedUnit;
public class SampleActor extends AbstractActor {
private PartialFunction<Object, BoxedUnit> guarded = ReceiveBuilder.
match(String.class, s -> s.contains("guard"), s -> {
private Receive guarded = receiveBuilder()
.match(String.class, s -> s.contains("guard"), s -> {
sender().tell("contains(guard): " + s, self());
context().unbecome();
}).build();
getContext().unbecome();
})
.build();
public SampleActor() {
receive(ReceiveBuilder.
match(Double.class, d -> {
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Double.class, d -> {
sender().tell(d.isNaN() ? 0 : d, self());
}).
match(Integer.class, i -> {
})
.match(Integer.class, i -> {
sender().tell(i * 10, self());
}).
match(String.class, s -> s.startsWith("guard"), s -> {
})
.match(String.class, s -> s.startsWith("guard"), s -> {
sender().tell("startsWith(guard): " + s.toUpperCase(), self());
context().become(guarded, false);
}).build()
);
getContext().become(guarded, false);
})
.build();
}
}
//#sample-actor

View file

@ -174,7 +174,7 @@ public class FSMDocTest extends AbstractJavaTest {
expectMsgEquals(Active);
expectMsgEquals(Data.Foo);
String msg = expectMsgClass(String.class);
assertTrue(msg.startsWith("LogEntry(SomeState,Foo,Actor[akka://FSMDocTest/system/"));
assertThat(msg, CoreMatchers.startsWith("LogEntry(SomeState,Foo,Actor[akka://FSMDocTest/system/"));
}};
}
}

View file

@ -67,24 +67,24 @@ public class FaultHandlingDocSample {
public void preStart() {
// If we don't get any progress within 15 seconds then the service
// is unavailable
context().setReceiveTimeout(Duration.create("15 seconds"));
getContext().setReceiveTimeout(Duration.create("15 seconds"));
}
public Listener() {
receive(LoggingReceive.create(ReceiveBuilder.
@Override
public Receive createReceive() {
return LoggingReceive.create(receiveBuilder().
match(Progress.class, progress -> {
log().info("Current progress: {} %", progress.percent);
if (progress.percent >= 100.0) {
log().info("That's all, shutting down");
context().system().terminate();
getContext().system().terminate();
}
}).
matchEquals(ReceiveTimeout.getInstance(), x -> {
// No progress within 15 seconds, ServiceUnavailable
log().error("Shutting down due to unavailable service");
context().system().terminate();
}).build(), context()
));
getContext().system().terminate();
}).build(), getContext());
}
}
@ -119,7 +119,7 @@ public class FaultHandlingDocSample {
// The sender of the initial Start message will continuously be notified
// about progress
ActorRef progressListener;
final ActorRef counterService = context().actorOf(
final ActorRef counterService = getContext().actorOf(
Props.create(CounterService.class), "counter");
final int totalCount = 51;
@ -134,13 +134,14 @@ public class FaultHandlingDocSample {
return strategy;
}
public Worker() {
receive(LoggingReceive.create(ReceiveBuilder.
@Override
public Receive createReceive() {
return LoggingReceive.create(receiveBuilder().
matchEquals(Start, x -> progressListener == null, x -> {
progressListener = sender();
context().system().scheduler().schedule(
getContext().system().scheduler().schedule(
Duration.Zero(), Duration.create(1, "second"), self(), Do,
context().dispatcher(), null
getContext().dispatcher(), null
);
}).
matchEquals(Do, x -> {
@ -154,10 +155,9 @@ public class FaultHandlingDocSample {
public Progress apply(CurrentCount c) {
return new Progress(100.0 * c.count / totalCount);
}
}, context().dispatcher()), context().dispatcher())
}, getContext().dispatcher()), getContext().dispatcher())
.to(progressListener);
}).build(), context())
);
}).build(), getContext());
}
}
@ -254,7 +254,7 @@ public class FaultHandlingDocSample {
* when it has been terminated.
*/
void initStorage() {
storage = context().watch(context().actorOf(
storage = getContext().watch(getContext().actorOf(
Props.create(Storage.class), "storage"));
// Tell the counter, if any, to use the new storage
if (counter != null)
@ -263,12 +263,13 @@ public class FaultHandlingDocSample {
storage.tell(new Get(key), self());
}
public CounterService() {
receive(LoggingReceive.create(ReceiveBuilder.
@Override
public Receive createReceive() {
return LoggingReceive.create(receiveBuilder().
match(Entry.class, entry -> entry.key.equals(key) && counter == null, entry -> {
// Reply from Storage of the initial value, now we can create the Counter
final long value = entry.value;
counter = context().actorOf(Props.create(Counter.class, key, value));
counter = getContext().actorOf(Props.create(Counter.class, key, value));
// Tell the counter to use current storage
counter.tell(new UseStorage(storage), self());
// and send the buffered backlog to the counter
@ -290,15 +291,14 @@ public class FaultHandlingDocSample {
// Tell the counter that there is no storage for the moment
counter.tell(new UseStorage(null), self());
// Try to re-establish storage after while
context().system().scheduler().scheduleOnce(
getContext().system().scheduler().scheduleOnce(
Duration.create(10, "seconds"), self(), Reconnect,
context().dispatcher(), null);
getContext().dispatcher(), null);
}).
matchEquals(Reconnect, o -> {
// Re-establish storage after the scheduled delay
initStorage();
}).build(), context())
);
}).build(), getContext());
}
void forwardOrPlaceInBacklog(Object msg) {
@ -311,7 +311,7 @@ public class FaultHandlingDocSample {
" lack of initial value");
backlog.add(new SenderMsgPair(sender(), msg));
} else {
counter.forward(msg, context());
counter.forward(msg, getContext());
}
}
}
@ -345,8 +345,11 @@ public class FaultHandlingDocSample {
public Counter(String key, long initialValue) {
this.key = key;
this.count = initialValue;
receive(LoggingReceive.create(ReceiveBuilder.
}
@Override
public Receive createReceive() {
return LoggingReceive.create(receiveBuilder().
match(UseStorage.class, useStorage -> {
storage = useStorage.storage;
storeCount();
@ -357,8 +360,7 @@ public class FaultHandlingDocSample {
}).
matchEquals(GetCurrentCount, gcc -> {
sender().tell(new CurrentCount(key, count), self());
}).build(), context())
);
}).build(), getContext());
}
void storeCount() {
@ -430,8 +432,9 @@ public class FaultHandlingDocSample {
final DummyDB db = DummyDB.instance;
public Storage() {
receive(LoggingReceive.create(ReceiveBuilder.
@Override
public Receive createReceive() {
return LoggingReceive.create(receiveBuilder().
match(Store.class, store -> {
db.save(store.entry.key, store.entry.value);
}).
@ -439,8 +442,7 @@ public class FaultHandlingDocSample {
Long value = db.load(get.key);
sender().tell(new Entry(get.key, value == null ?
Long.valueOf(0L) : value), self());
}).build(), context())
);
}).build(), getContext());
}
}

View file

@ -12,7 +12,7 @@ public class Consumer2 extends UntypedConsumerActor {
if (message instanceof CamelMessage) {
CamelMessage camelMessage = (CamelMessage) message;
String body = camelMessage.getBodyAs(String.class, getCamelContext());
getSender().tell(String.format("Received message: %s",body), getSelf());
sender().tell(String.format("Received message: %s",body), self());
} else
unhandled(message);
}

View file

@ -18,12 +18,12 @@ public class Consumer3 extends UntypedConsumerActor{
public void onReceive(Object message) {
if (message instanceof CamelMessage) {
getSender().tell(Ack.getInstance(), getSelf());
sender().tell(Ack.getInstance(), self());
// on success
// ..
Exception someException = new Exception("e1");
// on failure
getSender().tell(new Status.Failure(someException), getSelf());
sender().tell(new Status.Failure(someException), self());
} else
unhandled(message);
}

View file

@ -24,7 +24,7 @@ public class Consumer4 extends UntypedConsumerActor {
if (message instanceof CamelMessage) {
CamelMessage camelMessage = (CamelMessage) message;
String body = camelMessage.getBodyAs(String.class, getCamelContext());
getSender().tell(String.format("Hello %s",body), getSelf());
sender().tell(String.format("Hello %s",body), self());
} else
unhandled(message);
}

View file

@ -47,7 +47,7 @@ public class ErrorThrowingConsumer extends UntypedConsumerActor{
@Override
public void preRestart(Throwable reason, Option<Object> message) {
getSender().tell(new Status.Failure(reason), getSelf());
sender().tell(new Status.Failure(reason), self());
}
}
//#ErrorThrowingConsumer

View file

@ -1,11 +1,11 @@
package docs.camel;
//#ProducerTemplate
import akka.actor.UntypedActor;
import akka.actor.UntypedAbstractActor;
import akka.camel.Camel;
import akka.camel.CamelExtension;
import org.apache.camel.ProducerTemplate;
public class MyActor extends UntypedActor {
public class MyActor extends UntypedAbstractActor {
public void onReceive(Object message) {
Camel camel = CamelExtension.get(getContext().system());
ProducerTemplate template = camel.template();

View file

@ -1,15 +1,20 @@
package docs.camel;
//#RequestProducerTemplate
import akka.actor.UntypedActor;
import akka.actor.AbstractActor;
import akka.camel.Camel;
import akka.camel.CamelExtension;
import org.apache.camel.ProducerTemplate;
public class RequestBodyActor extends UntypedActor {
public void onReceive(Object message) {
Camel camel = CamelExtension.get(getContext().system());
ProducerTemplate template = camel.template();
getSender().tell(template.requestBody("direct:news", message), getSelf());
public class RequestBodyActor extends AbstractActor {
@Override
public Receive createReceive() {
return receiveBuilder()
.matchAny(message -> {
Camel camel = CamelExtension.get(getContext().system());
ProducerTemplate template = camel.template();
sender().tell(template.requestBody("direct:news", message), self());
})
.build();
}
}
//#RequestProducerTemplate

View file

@ -1,16 +1,16 @@
package docs.camel;
//#CustomRoute
import akka.actor.UntypedActor;
import akka.actor.UntypedAbstractActor;
import akka.camel.CamelMessage;
import akka.dispatch.Mapper;
import akka.japi.Function;
public class Responder extends UntypedActor{
public class Responder extends UntypedAbstractActor{
public void onReceive(Object message) {
if (message instanceof CamelMessage) {
CamelMessage camelMessage = (CamelMessage) message;
getSender().tell(createResponse(camelMessage), getSelf());
sender().tell(createResponse(camelMessage), self());
} else
unhandled(message);
}

View file

@ -1,9 +1,9 @@
package docs.camel;
//#RouteResponse
import akka.actor.UntypedActor;
import akka.actor.UntypedAbstractActor;
import akka.camel.CamelMessage;
public class ResponseReceiver extends UntypedActor{
public class ResponseReceiver extends UntypedAbstractActor{
public void onReceive(Object message) {
if(message instanceof CamelMessage) {
// do something with the forwarded response

View file

@ -5,6 +5,7 @@ package docs.ddata;
//#data-bot
import static java.util.concurrent.TimeUnit.SECONDS;
import scala.concurrent.duration.Duration;
import java.util.concurrent.ThreadLocalRandom;
@ -29,25 +30,26 @@ public class DataBot extends AbstractActor {
private static final String TICK = "tick";
private final LoggingAdapter log = Logging.getLogger(context().system(), this);
private final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
private final ActorRef replicator =
DistributedData.get(context().system()).replicator();
private final Cluster node = Cluster.get(context().system());
DistributedData.get(getContext().system()).replicator();
private final Cluster node = Cluster.get(getContext().system());
private final Cancellable tickTask = context().system().scheduler().schedule(
private final Cancellable tickTask = getContext().system().scheduler().schedule(
Duration.create(5, SECONDS), Duration.create(5, SECONDS), self(), TICK,
context().dispatcher(), self());
getContext().dispatcher(), self());
private final Key<ORSet<String>> dataKey = ORSetKey.create("key");
@SuppressWarnings("unchecked")
public DataBot() {
receive(ReceiveBuilder
@Override
public Receive createReceive() {
return receiveBuilder()
.match(String.class, a -> a.equals(TICK), a -> receiveTick())
.match(Changed.class, c -> c.key().equals(dataKey), c -> receiveChanged((Changed<ORSet<String>>) c))
.match(UpdateResponse.class, r -> receiveUpdateResoponse())
.build());
.build();
}

View file

@ -35,13 +35,11 @@ import akka.testkit.JavaTestKit;
import akka.testkit.TestProbe;
import akka.serialization.SerializationExtension;
@SuppressWarnings({"unchecked", "unused"})
public class DistributedDataDocTest extends AbstractJavaTest {
static ActorSystem system;
void receive(PartialFunction<Object, BoxedUnit> pf) {
}
@BeforeClass
public static void setup() {
@ -55,237 +53,261 @@ public class DistributedDataDocTest extends AbstractJavaTest {
system = null;
}
@Test
public void demonstrateUpdate() {
new JavaTestKit(system) {
{
//#update
final Cluster node = Cluster.get(system);
final ActorRef replicator = DistributedData.get(system).replicator();
static
//#update
class DemonstrateUpdate extends AbstractActor {
final Cluster node = Cluster.get(getContext().system());
final ActorRef replicator =
DistributedData.get(getContext().system()).replicator();
final Key<PNCounter> counter1Key = PNCounterKey.create("counter1");
final Key<GSet<String>> set1Key = GSetKey.create("set1");
final Key<ORSet<String>> set2Key = ORSetKey.create("set2");
final Key<Flag> activeFlagKey = FlagKey.create("active");
final Key<PNCounter> counter1Key = PNCounterKey.create("counter1");
final Key<GSet<String>> set1Key = GSetKey.create("set1");
final Key<ORSet<String>> set2Key = ORSetKey.create("set2");
final Key<Flag> activeFlagKey = FlagKey.create("active");
@Override
public Receive createReceive() {
ReceiveBuilder b = receiveBuilder();
b.matchEquals("demonstrate update", msg -> {
replicator.tell(new Replicator.Update<PNCounter>(counter1Key, PNCounter.create(),
Replicator.writeLocal(), curr -> curr.increment(node, 1)), getTestActor());
Replicator.writeLocal(), curr -> curr.increment(node, 1)), self());
final WriteConsistency writeTo3 = new WriteTo(3, Duration.create(1, SECONDS));
replicator.tell(new Replicator.Update<GSet<String>>(set1Key, GSet.create(),
writeTo3, curr -> curr.add("hello")), getTestActor());
writeTo3, curr -> curr.add("hello")), self());
final WriteConsistency writeMajority =
new WriteMajority(Duration.create(5, SECONDS));
replicator.tell(new Replicator.Update<ORSet<String>>(set2Key, ORSet.create(),
writeMajority, curr -> curr.add(node, "hello")), getTestActor());
writeMajority, curr -> curr.add(node, "hello")), self());
final WriteConsistency writeAll = new WriteAll(Duration.create(5, SECONDS));
replicator.tell(new Replicator.Update<Flag>(activeFlagKey, Flag.create(),
writeAll, curr -> curr.switchOn()), getTestActor());
//#update
expectMsgClass(UpdateSuccess.class);
//#update-response1
receive(ReceiveBuilder.
match(UpdateSuccess.class, a -> a.key().equals(counter1Key), a -> {
// ok
}).build());
//#update-response1
//#update-response2
receive(ReceiveBuilder.
match(UpdateSuccess.class, a -> a.key().equals(set1Key), a -> {
// ok
}).
match(UpdateTimeout.class, a -> a.key().equals(set1Key), a -> {
// write to 3 nodes failed within 1.second
}).build());
//#update-response2
}};
writeAll, curr -> curr.switchOn()), self());
});
//#update
//#update-response1
b.match(UpdateSuccess.class, a -> a.key().equals(counter1Key), a -> {
// ok
});
//#update-response1
//#update-response2
b.match(UpdateSuccess.class, a -> a.key().equals(set1Key), a -> {
// ok
})
.match(UpdateTimeout.class, a -> a.key().equals(set1Key), a -> {
// write to 3 nodes failed within 1.second
});
//#update-response2
//#update
return b.build();
}
}
//#update
@Test
public void demonstrateUpdateWithRequestContext() {
new JavaTestKit(system) {
{
static
//#update-request-context
class DemonstrateUpdateWithRequestContext extends AbstractActor {
final Cluster node = Cluster.get(getContext().system());
final ActorRef replicator =
DistributedData.get(getContext().system()).replicator();
//#update-request-context
final Cluster node = Cluster.get(system);
final ActorRef replicator = DistributedData.get(system).replicator();
final WriteConsistency writeTwo = new WriteTo(2, Duration.create(3, SECONDS));
final Key<PNCounter> counter1Key = PNCounterKey.create("counter1");
@Override
public Receive createReceive() {
return receiveBuilder()
.match(String.class, a -> a.equals("increment"), a -> {
// incoming command to increase the counter
Optional<Object> reqContext = Optional.of(sender());
Replicator.Update<PNCounter> upd = new Replicator.Update<PNCounter>(counter1Key,
PNCounter.create(), writeTwo, reqContext, curr -> curr.increment(node, 1));
replicator.tell(upd, self());
})
final WriteConsistency writeTwo = new WriteTo(2, Duration.create(3, SECONDS));
final Key<PNCounter> counter1Key = PNCounterKey.create("counter1");
.match(UpdateSuccess.class, a -> a.key().equals(counter1Key), a -> {
ActorRef replyTo = (ActorRef) a.getRequest().get();
replyTo.tell("ack", self());
})
receive(ReceiveBuilder.
match(String.class, a -> a.equals("increment"), a -> {
// incoming command to increase the counter
Optional<Object> reqContext = Optional.of(getRef());
Replicator.Update<PNCounter> upd = new Replicator.Update<PNCounter>(counter1Key,
PNCounter.create(), writeTwo, reqContext, curr -> curr.increment(node, 1));
replicator.tell(upd, getTestActor());
}).
match(UpdateSuccess.class, a -> a.key().equals(counter1Key), a -> {
ActorRef replyTo = (ActorRef) a.getRequest().get();
replyTo.tell("ack", getTestActor());
}).
match(UpdateTimeout.class, a -> a.key().equals(counter1Key), a -> {
ActorRef replyTo = (ActorRef) a.getRequest().get();
replyTo.tell("nack", getTestActor());
}).build());
//#update-request-context
.match(UpdateTimeout.class, a -> a.key().equals(counter1Key), a -> {
ActorRef replyTo = (ActorRef) a.getRequest().get();
replyTo.tell("nack", self());
})
.build();
}
};
}
//#update-request-context
@SuppressWarnings({ "unused", "unchecked" })
@Test
public void demonstrateGet() {
new JavaTestKit(system) {
{
static
//#get
class DemonstrateGet extends AbstractActor {
final ActorRef replicator =
DistributedData.get(getContext().system()).replicator();
final Key<PNCounter> counter1Key = PNCounterKey.create("counter1");
final Key<GSet<String>> set1Key = GSetKey.create("set1");
final Key<ORSet<String>> set2Key = ORSetKey.create("set2");
final Key<Flag> activeFlagKey = FlagKey.create("active");
@Override
public Receive createReceive() {
ReceiveBuilder b = receiveBuilder();
b.matchEquals("demonstrate get", msg -> {
//#get
final ActorRef replicator = DistributedData.get(system).replicator();
final Key<PNCounter> counter1Key = PNCounterKey.create("counter1");
final Key<GSet<String>> set1Key = GSetKey.create("set1");
final Key<ORSet<String>> set2Key = ORSetKey.create("set2");
final Key<Flag> activeFlagKey = FlagKey.create("active");
replicator.tell(new Replicator.Get<PNCounter>(counter1Key,
Replicator.readLocal()), getTestActor());
final ReadConsistency readFrom3 = new ReadFrom(3, Duration.create(1, SECONDS));
replicator.tell(new Replicator.Get<GSet<String>>(set1Key,
readFrom3), getTestActor());
final ReadConsistency readMajority = new ReadMajority(Duration.create(5, SECONDS));
replicator.tell(new Replicator.Get<ORSet<String>>(set2Key,
readMajority), getTestActor());
final ReadConsistency readAll = new ReadAll(Duration.create(5, SECONDS));
replicator.tell(new Replicator.Get<Flag>(activeFlagKey,
readAll), getTestActor());
replicator.tell(new Replicator.Get<PNCounter>(counter1Key,
Replicator.readLocal()), self());
final ReadConsistency readFrom3 = new ReadFrom(3, Duration.create(1, SECONDS));
replicator.tell(new Replicator.Get<GSet<String>>(set1Key,
readFrom3), self());
final ReadConsistency readMajority = new ReadMajority(Duration.create(5, SECONDS));
replicator.tell(new Replicator.Get<ORSet<String>>(set2Key,
readMajority), self());
final ReadConsistency readAll = new ReadAll(Duration.create(5, SECONDS));
replicator.tell(new Replicator.Get<Flag>(activeFlagKey,
readAll), self());
});
//#get
//#get-response1
receive(ReceiveBuilder.
match(GetSuccess.class, a -> a.key().equals(counter1Key), a -> {
GetSuccess<PNCounter> g = a;
BigInteger value = g.dataValue().getValue();
}).
match(NotFound.class, a -> a.key().equals(counter1Key), a -> {
// key counter1 does not exist
}).build());
b.match(GetSuccess.class, a -> a.key().equals(counter1Key), a -> {
GetSuccess<PNCounter> g = a;
BigInteger value = g.dataValue().getValue();
}).
match(NotFound.class, a -> a.key().equals(counter1Key), a -> {
// key counter1 does not exist
});
//#get-response1
//#get-response2
receive(ReceiveBuilder.
match(GetSuccess.class, a -> a.key().equals(set1Key), a -> {
GetSuccess<GSet<String>> g = a;
Set<String> value = g.dataValue().getElements();
}).
match(GetFailure.class, a -> a.key().equals(set1Key), a -> {
// read from 3 nodes failed within 1.second
}).
match(NotFound.class, a -> a.key().equals(set1Key), a -> {
// key set1 does not exist
}).build());
b.match(GetSuccess.class, a -> a.key().equals(set1Key), a -> {
GetSuccess<GSet<String>> g = a;
Set<String> value = g.dataValue().getElements();
}).
match(GetFailure.class, a -> a.key().equals(set1Key), a -> {
// read from 3 nodes failed within 1.second
}).
match(NotFound.class, a -> a.key().equals(set1Key), a -> {
// key set1 does not exist
});
//#get-response2
}
};
//#get
return b.build();
}
}
//#get
@SuppressWarnings("unchecked")
@Test
public void demonstrateGetWithRequestContext() {
new JavaTestKit(system) {
{
static
//#get-request-context
class DemonstrateGetWithRequestContext extends AbstractActor {
final ActorRef replicator =
DistributedData.get(getContext().system()).replicator();
final ReadConsistency readTwo = new ReadFrom(2, Duration.create(3, SECONDS));
final Key<PNCounter> counter1Key = PNCounterKey.create("counter1");
@Override
public Receive createReceive() {
return receiveBuilder()
.match(String.class, a -> a.equals("get-count"), a -> {
// incoming request to retrieve current value of the counter
Optional<Object> reqContext = Optional.of(sender());
replicator.tell(new Replicator.Get<PNCounter>(counter1Key,
readTwo), self());
})
//#get-request-context
final ActorRef replicator = DistributedData.get(system).replicator();
final ReadConsistency readTwo = new ReadFrom(2, Duration.create(3, SECONDS));
final Key<PNCounter> counter1Key = PNCounterKey.create("counter1");
.match(GetSuccess.class, a -> a.key().equals(counter1Key), a -> {
ActorRef replyTo = (ActorRef) a.getRequest().get();
GetSuccess<PNCounter> g = a;
long value = g.dataValue().getValue().longValue();
replyTo.tell(value, self());
})
receive(ReceiveBuilder.
match(String.class, a -> a.equals("get-count"), a -> {
// incoming request to retrieve current value of the counter
Optional<Object> reqContext = Optional.of(getTestActor());
replicator.tell(new Replicator.Get<PNCounter>(counter1Key,
readTwo), getTestActor());
}).
.match(GetFailure.class, a -> a.key().equals(counter1Key), a -> {
ActorRef replyTo = (ActorRef) a.getRequest().get();
replyTo.tell(-1L, self());
})
match(GetSuccess.class, a -> a.key().equals(counter1Key), a -> {
ActorRef replyTo = (ActorRef) a.getRequest().get();
GetSuccess<PNCounter> g = a;
long value = g.dataValue().getValue().longValue();
replyTo.tell(value, getTestActor());
}).
match(GetFailure.class, a -> a.key().equals(counter1Key), a -> {
ActorRef replyTo = (ActorRef) a.getRequest().get();
replyTo.tell(-1L, getTestActor());
}).
match(NotFound.class, a -> a.key().equals(counter1Key), a -> {
ActorRef replyTo = (ActorRef) a.getRequest().get();
replyTo.tell(0L, getTestActor());
}).build());
//#get-request-context
.match(NotFound.class, a -> a.key().equals(counter1Key), a -> {
ActorRef replyTo = (ActorRef) a.getRequest().get();
replyTo.tell(0L, self());
})
.build();
}
};
}
//#get-request-context
@SuppressWarnings("unchecked")
abstract class MyActor extends AbstractActor {
//#subscribe
final ActorRef replicator = DistributedData.get(system).replicator();
static
//#subscribe
class DemonstrateSubscribe extends AbstractActor {
final ActorRef replicator =
DistributedData.get(getContext().system()).replicator();
final Key<PNCounter> counter1Key = PNCounterKey.create("counter1");
BigInteger currentValue = BigInteger.valueOf(0);
public MyActor() {
receive(ReceiveBuilder.
match(Changed.class, a -> a.key().equals(counter1Key), a -> {
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Changed.class, a -> a.key().equals(counter1Key), a -> {
Changed<PNCounter> g = a;
currentValue = g.dataValue().getValue();
}).
match(String.class, a -> a.equals("get-count"), a -> {
})
.match(String.class, a -> a.equals("get-count"), a -> {
// incoming request to retrieve current value of the counter
sender().tell(currentValue, sender());
}).build());
})
.build();
}
@Override
public void preStart() {
// subscribe to changes of the Counter1Key value
replicator.tell(new Subscribe<PNCounter>(counter1Key, self()), ActorRef.noSender());
}
//#subscribe
}
//#subscribe
@Test
public void demonstrateDelete() {
new JavaTestKit(system) {
{
//#delete
final ActorRef replicator = DistributedData.get(system).replicator();
final Key<PNCounter> counter1Key = PNCounterKey.create("counter1");
final Key<ORSet<String>> set2Key = ORSetKey.create("set2");
static
//#delete
class DemonstrateDelete extends AbstractActor {
final ActorRef replicator =
DistributedData.get(getContext().system()).replicator();
final Key<PNCounter> counter1Key = PNCounterKey.create("counter1");
final Key<ORSet<String>> set2Key = ORSetKey.create("set2");
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals("demonstrate delete", msg -> {
replicator.tell(new Delete<PNCounter>(counter1Key,
Replicator.writeLocal()), getTestActor());
final WriteConsistency writeMajority =
new WriteMajority(Duration.create(5, SECONDS));
replicator.tell(new Delete<PNCounter>(counter1Key,
writeMajority), getTestActor());
//#delete
}};
replicator.tell(new Delete<PNCounter>(counter1Key,
Replicator.writeLocal()), self());
final WriteConsistency writeMajority =
new WriteMajority(Duration.create(5, SECONDS));
replicator.tell(new Delete<PNCounter>(counter1Key,
writeMajority), self());
})
.build();
}
}
//#delete
public void demonstratePNCounter() {
//#pncounter

View file

@ -8,8 +8,8 @@ import akka.dispatch.RequiresMessageQueue;
import akka.testkit.AkkaSpec;
import com.typesafe.config.ConfigFactory;
import docs.AbstractJavaTest;
import docs.actor.MyBoundedUntypedActor;
import docs.actor.MyUntypedActor;
import docs.actorlambda.MyBoundedActor;
import docs.actorlambda.MyActor;
import org.junit.ClassRule;
import org.junit.Test;
import scala.concurrent.ExecutionContext;
@ -17,7 +17,7 @@ import scala.concurrent.ExecutionContext;
//#imports
import akka.actor.*;
//#imports
import akka.actor.AbstractActor.Receive;
//#imports-prio
import akka.event.Logging;
import akka.event.LoggingAdapter;
@ -52,7 +52,7 @@ public class DispatcherDocTest extends AbstractJavaTest {
public void defineDispatcherInConfig() {
//#defining-dispatcher-in-config
ActorRef myActor =
system.actorOf(Props.create(MyUntypedActor.class),
system.actorOf(Props.create(MyActor.class),
"myactor");
//#defining-dispatcher-in-config
}
@ -62,7 +62,7 @@ public class DispatcherDocTest extends AbstractJavaTest {
public void defineDispatcherInCode() {
//#defining-dispatcher-in-code
ActorRef myActor =
system.actorOf(Props.create(MyUntypedActor.class).withDispatcher("my-dispatcher"),
system.actorOf(Props.create(MyActor.class).withDispatcher("my-dispatcher"),
"myactor3");
//#defining-dispatcher-in-code
}
@ -71,7 +71,7 @@ public class DispatcherDocTest extends AbstractJavaTest {
@Test
public void defineFixedPoolSizeDispatcher() {
//#defining-fixed-pool-size-dispatcher
ActorRef myActor = system.actorOf(Props.create(MyUntypedActor.class)
ActorRef myActor = system.actorOf(Props.create(MyActor.class)
.withDispatcher("blocking-io-dispatcher"));
//#defining-fixed-pool-size-dispatcher
}
@ -80,7 +80,7 @@ public class DispatcherDocTest extends AbstractJavaTest {
@Test
public void definePinnedDispatcher() {
//#defining-pinned-dispatcher
ActorRef myActor = system.actorOf(Props.create(MyUntypedActor.class)
ActorRef myActor = system.actorOf(Props.create(MyActor.class)
.withDispatcher("my-pinned-dispatcher"));
//#defining-pinned-dispatcher
}
@ -99,7 +99,7 @@ public class DispatcherDocTest extends AbstractJavaTest {
public void defineMailboxInConfig() {
//#defining-mailbox-in-config
ActorRef myActor =
system.actorOf(Props.create(MyUntypedActor.class),
system.actorOf(Props.create(MyActor.class),
"priomailboxactor");
//#defining-mailbox-in-config
}
@ -109,7 +109,7 @@ public class DispatcherDocTest extends AbstractJavaTest {
public void defineMailboxInCode() {
//#defining-mailbox-in-code
ActorRef myActor =
system.actorOf(Props.create(MyUntypedActor.class)
system.actorOf(Props.create(MyActor.class)
.withMailbox("prio-mailbox"));
//#defining-mailbox-in-code
}
@ -118,7 +118,7 @@ public class DispatcherDocTest extends AbstractJavaTest {
@Test
public void usingARequiredMailbox() {
ActorRef myActor =
system.actorOf(Props.create(MyBoundedUntypedActor.class));
system.actorOf(Props.create(MyBoundedActor.class));
}
@Test
@ -126,18 +126,21 @@ public class DispatcherDocTest extends AbstractJavaTest {
JavaTestKit probe = new JavaTestKit(system);
//#prio-dispatcher
class Demo extends UntypedActor {
class Demo extends AbstractActor {
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
{
for (Object msg : new Object[] { "lowpriority", "lowpriority",
"highpriority", "pigdog", "pigdog2", "pigdog3", "highpriority",
PoisonPill.getInstance() }) {
getSelf().tell(msg, getSelf());
self().tell(msg, self());
}
}
public void onReceive(Object message) {
log.info(message.toString());
@Override
public Receive createReceive() {
return receiveBuilder().matchAny(message -> {
log.info(message.toString());
}).build();
}
}
@ -166,17 +169,20 @@ public class DispatcherDocTest extends AbstractJavaTest {
JavaTestKit probe = new JavaTestKit(system);
//#control-aware-dispatcher
class Demo extends UntypedActor {
class Demo extends AbstractActor {
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
{
for (Object msg : new Object[] { "foo", "bar", new MyControlMessage(),
PoisonPill.getInstance() }) {
getSelf().tell(msg, getSelf());
self().tell(msg, self());
}
}
public void onReceive(Object message) {
log.info(message.toString());
@Override
public Receive createReceive() {
return receiveBuilder().matchAny(message -> {
log.info(message.toString());
}).build();
}
}
@ -226,18 +232,18 @@ public class DispatcherDocTest extends AbstractJavaTest {
@Test
public void requiredMailboxDispatcher() throws Exception {
ActorRef myActor = system.actorOf(Props.create(MyUntypedActor.class)
ActorRef myActor = system.actorOf(Props.create(MyActor.class)
.withDispatcher("custom-dispatcher"));
}
static
//#require-mailbox-on-actor
public class MySpecialActor extends UntypedActor implements
public class MySpecialActor extends AbstractActor implements
RequiresMessageQueue<MyUnboundedJMessageQueueSemantics> {
//#require-mailbox-on-actor
@Override
public void onReceive(Object message) throws Exception {
unhandled(message);
public Receive createReceive() {
return AbstractActor.emptyBehavior();
}
//#require-mailbox-on-actor
// ...

View file

@ -22,7 +22,7 @@ import akka.event.Logging.Debug;
import docs.AbstractJavaTest;
import org.junit.Test;
import akka.testkit.JavaTestKit;
import scala.Option;
import java.util.Optional;
//#imports-mdc
import akka.event.Logging;
@ -80,15 +80,18 @@ public class LoggingDocTest extends AbstractJavaTest {
}
}
static class Listener extends UntypedActor {
static class Listener extends AbstractActor {
@Override
public void onReceive(Object message) throws Exception {
if (message instanceof Jazz) {
System.out.printf("%s is listening to: %s%n", self().path().name(), message);
} else if (message instanceof Electronic) {
System.out.printf("%s is listening to: %s%n", self().path().name(), message);
public Receive createReceive() {
return receiveBuilder()
.match(Jazz.class, msg ->
System.out.printf("%s is listening to: %s%n", self().path().name(), msg)
)
.match(Electronic.class, msg ->
System.out.printf("%s is listening to: %s%n", self().path().name(), msg)
)
.build();
}
}
}
//#superclass-subscription-eventstream
@ -148,7 +151,7 @@ public class LoggingDocTest extends AbstractJavaTest {
}
//#my-actor
class MyActor extends UntypedActor {
class MyActor extends AbstractActor {
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
@Override
@ -157,68 +160,86 @@ public class LoggingDocTest extends AbstractJavaTest {
}
@Override
public void preRestart(Throwable reason, Option<Object> message) {
public void preRestart(Throwable reason, Optional<Object> message) {
log.error(reason, "Restarting due to [{}] when processing [{}]",
reason.getMessage(), message.isDefined() ? message.get() : "");
reason.getMessage(), message.isPresent() ? message.get() : "");
}
public void onReceive(Object message) {
if (message.equals("test")) {
log.info("Received test");
} else {
log.warning("Received unknown message: {}", message);
}
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals("test", msg ->
log.info("Received test")
)
.matchAny(msg ->
log.warning("Received unknown message: {}", msg)
)
.build();
}
}
//#my-actor
//#mdc-actor
class MdcActor extends UntypedActor {
class MdcActor extends AbstractActor {
final DiagnosticLoggingAdapter log = Logging.getLogger(this);
public void onReceive(Object message) {
@Override
public Receive createReceive() {
return receiveBuilder()
.matchAny(msg -> {
Map<String, Object> mdc;
mdc = new HashMap<String, Object>();
mdc.put("requestId", 1234);
mdc.put("visitorId", 5678);
log.setMDC(mdc);
Map<String, Object> mdc;
mdc = new HashMap<String, Object>();
mdc.put("requestId", 1234);
mdc.put("visitorId", 5678);
log.setMDC(mdc);
log.info("Starting new request");
log.info("Starting new request");
log.clearMDC();
log.clearMDC();
})
.build();
}
}
//#mdc-actor
//#my-event-listener
class MyEventListener extends UntypedActor {
public void onReceive(Object message) {
if (message instanceof InitializeLogger) {
getSender().tell(Logging.loggerInitialized(), getSelf());
} else if (message instanceof Error) {
// ...
} else if (message instanceof Warning) {
// ...
} else if (message instanceof Info) {
// ...
} else if (message instanceof Debug) {
// ...
}
class MyEventListener extends AbstractActor {
@Override
public Receive createReceive() {
return receiveBuilder()
.match(InitializeLogger.class, msg -> {
sender().tell(Logging.loggerInitialized(), self());
})
.match(Error.class, msg -> {
// ...
})
.match(Warning.class, msg -> {
// ...
})
.match(Info.class, msg -> {
// ...
})
.match(Debug.class, msg -> {
// ...
})
.build();
}
}
//#my-event-listener
static
//#deadletter-actor
public class DeadLetterActor extends UntypedActor {
public void onReceive(Object message) {
if (message instanceof DeadLetter) {
System.out.println(message);
}
public class DeadLetterActor extends AbstractActor {
@Override
public Receive createReceive() {
return receiveBuilder()
.match(DeadLetter.class, msg -> {
System.out.println(msg);
})
.build();
}
}
//#deadletter-actor

View file

@ -57,11 +57,16 @@ public class ExtensionDocTest extends AbstractJavaTest {
static
//#extension-usage-actor
public class MyActor extends UntypedActor {
public void onReceive(Object msg) {
// typically you would use static import of the
// CountExtension.CountExtensionProvider field
CountExtension.CountExtensionProvider.get(getContext().system()).increment();
public class MyActor extends AbstractActor {
@Override
public Receive createReceive() {
return receiveBuilder()
.matchAny(msg -> {
// typically you would use static import of the
// CountExtension.CountExtensionProvider field
CountExtension.CountExtensionProvider.get(getContext().system()).increment();
})
.build();
}
}

View file

@ -9,14 +9,14 @@ import akka.actor.AbstractExtensionId;
import akka.actor.ExtensionIdProvider;
import akka.actor.ActorSystem;
import akka.actor.ExtendedActorSystem;
import docs.AbstractJavaTest;
import scala.concurrent.duration.Duration;
import com.typesafe.config.Config;
import java.util.concurrent.TimeUnit;
//#imports
import akka.actor.UntypedActor;
import docs.AbstractJavaTest;
import akka.actor.AbstractActor;
import org.junit.Test;
public class SettingsExtensionDocTest extends AbstractJavaTest {
@ -60,7 +60,7 @@ public class SettingsExtensionDocTest extends AbstractJavaTest {
static
//#extension-usage-actor
public class MyActor extends UntypedActor {
public class MyActor extends AbstractActor {
// typically you would use static import of the Settings.SettingsProvider field
final SettingsImpl settings =
Settings.SettingsProvider.get(getContext().system());
@ -73,7 +73,9 @@ public class SettingsExtensionDocTest extends AbstractJavaTest {
return new Connection();
}
public void onReceive(Object msg) {
@Override
public Receive createReceive() {
return AbstractActor.emptyBehavior();
}
//#extension-usage-actor
}

View file

@ -65,7 +65,7 @@ import org.junit.Test;
import akka.testkit.AkkaSpec;
import akka.actor.Status.Failure;
import akka.actor.ActorSystem;
import akka.actor.UntypedActor;
import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.pattern.Patterns;
@ -656,20 +656,21 @@ public class FutureDocTest extends AbstractJavaTest {
public static class MyActor extends UntypedActor {
public void onReceive(Object message) {
if (message instanceof String) {
getSender().tell(((String) message).toUpperCase(), getSelf());
} else if (message instanceof Integer) {
int i = ((Integer) message).intValue();
if (i < 0) {
getSender().tell(new Failure(new ArithmeticException("Negative values not supported")), getSelf());
} else {
getSender().tell(i, getSelf());
}
} else {
unhandled(message);
}
public static class MyActor extends AbstractActor {
@Override
public Receive createReceive() {
return receiveBuilder()
.match(String.class, msg -> {
sender().tell(msg.toUpperCase(), self());
})
.match(Integer.class, i -> {
if (i < 0) {
sender().tell(new Failure(new ArithmeticException("Negative values not supported")), self());
} else {
sender().tell(i, self());
}
})
.build();
}
}
}

View file

@ -8,7 +8,7 @@ import org.junit.BeforeClass;
import org.junit.Test;
import akka.actor.ActorSystem;
import akka.actor.UntypedActor;
import akka.actor.AbstractActor;
//#imports
import java.net.InetSocketAddress;
import java.util.ArrayList;
@ -24,65 +24,63 @@ import akka.util.ByteString;
public class IODocTest {
static public class Demo extends UntypedActor {
static public class Demo extends AbstractActor {
ActorRef connectionActor = null;
ActorRef listener = getSelf();
ActorRef listener = self();
@Override
public void onReceive(Object msg) {
if ("connect".equals(msg)) {
//#manager
final ActorRef tcp = Tcp.get(system).manager();
//#manager
//#connect
final InetSocketAddress remoteAddr = new InetSocketAddress("127.0.0.1",
12345);
tcp.tell(TcpMessage.connect(remoteAddr), getSelf());
//#connect
//#connect-with-options
final InetSocketAddress localAddr = new InetSocketAddress("127.0.0.1",
1234);
final List<Inet.SocketOption> options = new ArrayList<Inet.SocketOption>();
options.add(TcpSO.keepAlive(true));
tcp.tell(TcpMessage.connect(remoteAddr, localAddr, options, null, false), getSelf());
//#connect-with-options
} else
//#connected
if (msg instanceof Tcp.Connected) {
final Tcp.Connected conn = (Tcp.Connected) msg;
connectionActor = getSender();
connectionActor.tell(TcpMessage.register(listener), getSelf());
}
//#connected
else
//#received
if (msg instanceof Tcp.Received) {
final Tcp.Received recv = (Tcp.Received) msg;
final ByteString data = recv.data();
// and do something with the received data ...
} else if (msg instanceof Tcp.CommandFailed) {
final Tcp.CommandFailed failed = (Tcp.CommandFailed) msg;
final Tcp.Command command = failed.cmd();
// react to failed connect, bind, write, etc.
} else if (msg instanceof Tcp.ConnectionClosed) {
final Tcp.ConnectionClosed closed = (Tcp.ConnectionClosed) msg;
if (closed.isAborted()) {
// handle close reasons like this
}
}
//#received
else
if ("bind".equals(msg)) {
final ActorRef handler = getSelf();
//#bind
final ActorRef tcp = Tcp.get(system).manager();
final InetSocketAddress localAddr = new InetSocketAddress("127.0.0.1",
1234);
final List<Inet.SocketOption> options = new ArrayList<Inet.SocketOption>();
options.add(TcpSO.reuseAddress(true));
tcp.tell(TcpMessage.bind(handler, localAddr, 10, options, false), getSelf());
//#bind
}
public Receive createReceive() {
return receiveBuilder()
.matchEquals("connect", msg -> {
//#manager
final ActorRef tcp = Tcp.get(system).manager();
//#manager
//#connect
final InetSocketAddress remoteAddr = new InetSocketAddress("127.0.0.1",
12345);
tcp.tell(TcpMessage.connect(remoteAddr), self());
//#connect
//#connect-with-options
final InetSocketAddress localAddr = new InetSocketAddress("127.0.0.1",
1234);
final List<Inet.SocketOption> options = new ArrayList<Inet.SocketOption>();
options.add(TcpSO.keepAlive(true));
tcp.tell(TcpMessage.connect(remoteAddr, localAddr, options, null, false), self());
//#connect-with-options
})
//#connected
.match(Tcp.Connected.class, conn -> {
connectionActor = sender();
connectionActor.tell(TcpMessage.register(listener), self());
})
//#connected
//#received
.match(Tcp.Received.class, recv -> {
final ByteString data = recv.data();
// and do something with the received data ...
})
.match(Tcp.CommandFailed.class, failed -> {
final Tcp.Command command = failed.cmd();
// react to failed connect, bind, write, etc.
})
.match(Tcp.ConnectionClosed.class, closed -> {
if (closed.isAborted()) {
// handle close reasons like this
}
})
//#received
.matchEquals("bind", msg -> {
final ActorRef handler = self();
//#bind
final ActorRef tcp = Tcp.get(system).manager();
final InetSocketAddress localAddr = new InetSocketAddress("127.0.0.1",
1234);
final List<Inet.SocketOption> options = new ArrayList<Inet.SocketOption>();
options.add(TcpSO.reuseAddress(true));
tcp.tell(TcpMessage.bind(handler, localAddr, 10, options, false), self());
//#bind
})
.build();
}
}

View file

@ -25,14 +25,14 @@ public class JavaReadBackPressure {
//#pull-accepting
public void onReceive(Object message) throws Exception {
if (message instanceof Tcp.Bound) {
listener = getSender();
listener = sender();
// Accept connections one by one
listener.tell(TcpMessage.resumeAccepting(1), getSelf());
listener.tell(TcpMessage.resumeAccepting(1), self());
} else if (message instanceof Tcp.Connected) {
ActorRef handler = getContext().actorOf(Props.create(PullEcho.class, getSender()));
getSender().tell(TcpMessage.register(handler), getSelf());
ActorRef handler = getContext().actorOf(Props.create(PullEcho.class, sender()));
sender().tell(TcpMessage.register(handler), self());
// Resume accepting connections
listener.tell(TcpMessage.resumeAccepting(1), getSelf());
listener.tell(TcpMessage.resumeAccepting(1), self());
}
}
//#pull-accepting
@ -43,8 +43,8 @@ public class JavaReadBackPressure {
tcp = Tcp.get(getContext().system()).manager();
final List<Inet.SocketOption> options = new ArrayList<Inet.SocketOption>();
tcp.tell(
TcpMessage.bind(getSelf(), new InetSocketAddress("localhost", 0), 100, options, true),
getSelf()
TcpMessage.bind(self(), new InetSocketAddress("localhost", 0), 100, options, true),
self()
);
//#pull-mode-bind
}
@ -54,7 +54,7 @@ public class JavaReadBackPressure {
final List<Inet.SocketOption> options = new ArrayList<Inet.SocketOption>();
tcp.tell(
TcpMessage.connect(new InetSocketAddress("localhost", 3000), null, options, null, true),
getSelf()
self()
);
//#pull-mode-connect
}
@ -73,16 +73,16 @@ public class JavaReadBackPressure {
//#pull-reading-echo
@Override
public void preStart() throws Exception {
connection.tell(TcpMessage.resumeReading(), getSelf());
connection.tell(TcpMessage.resumeReading(), self());
}
@Override
public void onReceive(Object message) throws Exception {
if (message instanceof Tcp.Received) {
ByteString data = ((Tcp.Received) message).data();
connection.tell(TcpMessage.write(data, new Ack()), getSelf());
connection.tell(TcpMessage.write(data, new Ack()), self());
} else if (message instanceof Ack) {
connection.tell(TcpMessage.resumeReading(), getSelf());
connection.tell(TcpMessage.resumeReading(), self());
}
}
//#pull-reading-echo

View file

@ -73,7 +73,7 @@ public class JavaUdpMulticast {
final ActorRef mgr = Udp.get(getContext().system()).getManager();
// listen for datagrams on this address
InetSocketAddress endpoint = new InetSocketAddress(port);
mgr.tell(UdpMessage.bind(getSelf(), endpoint, options), getSelf());
mgr.tell(UdpMessage.bind(self(), endpoint, options), self());
//#bind
}
@ -82,12 +82,12 @@ public class JavaUdpMulticast {
if (msg instanceof Udp.Bound) {
final Udp.Bound b = (Udp.Bound) msg;
log.info("Bound to {}", b.localAddress());
sink.tell(b, getSelf());
sink.tell(b, self());
} else if (msg instanceof Udp.Received) {
final Udp.Received r = (Udp.Received) msg;
final String txt = r.data().decodeString("utf-8");
log.info("Received '{}' from {}", txt, r.sender());
sink.tell(txt, getSelf());
sink.tell(txt, self());
} else unhandled(msg);
}
}
@ -110,7 +110,7 @@ public class JavaUdpMulticast {
options.add(new Inet6ProtocolFamily());
final ActorRef mgr = Udp.get(getContext().system()).getManager();
mgr.tell(UdpMessage.simpleSender(options), getSelf());
mgr.tell(UdpMessage.simpleSender(options), self());
}
@Override
@ -118,7 +118,7 @@ public class JavaUdpMulticast {
if (msg instanceof Udp.SimpleSenderReady) {
InetSocketAddress remote = new InetSocketAddress(group + "%" + iface, port);
log.info("Sending message to " + remote);
getSender().tell(UdpMessage.send(ByteString.fromString(message), remote), getSelf());
sender().tell(UdpMessage.send(ByteString.fromString(message), remote), self());
} else unhandled(msg);
}
}

View file

@ -26,8 +26,8 @@ public class UdpConnectedDocTest {
static public class Demo extends UntypedActor {
ActorRef connectionActor = null;
ActorRef handler = getSelf();
ActorSystem system = context().system();
ActorRef handler = self();
ActorSystem system = getContext().system();
@Override
public void onReceive(Object msg) {
@ -38,7 +38,7 @@ public class UdpConnectedDocTest {
//#connect
final InetSocketAddress remoteAddr =
new InetSocketAddress("127.0.0.1", 12345);
udp.tell(UdpConnectedMessage.connect(handler, remoteAddr), getSelf());
udp.tell(UdpConnectedMessage.connect(handler, remoteAddr), self());
//#connect
//#connect-with-options
final InetSocketAddress localAddr =
@ -46,13 +46,13 @@ public class UdpConnectedDocTest {
final List<Inet.SocketOption> options =
new ArrayList<Inet.SocketOption>();
options.add(UdpSO.broadcast(true));
udp.tell(UdpConnectedMessage.connect(handler, remoteAddr, localAddr, options), getSelf());
udp.tell(UdpConnectedMessage.connect(handler, remoteAddr, localAddr, options), self());
//#connect-with-options
} else
//#connected
if (msg instanceof UdpConnected.Connected) {
final UdpConnected.Connected conn = (UdpConnected.Connected) msg;
connectionActor = getSender(); // Save the worker ref for later use
connectionActor = sender(); // Save the worker ref for later use
}
//#connected
else
@ -73,7 +73,7 @@ public class UdpConnectedDocTest {
if ("send".equals(msg)) {
ByteString data = ByteString.empty();
//#send
connectionActor.tell(UdpConnectedMessage.send(data), getSelf());
connectionActor.tell(UdpConnectedMessage.send(data), self());
//#send
}
}

View file

@ -29,15 +29,15 @@ public class UdpDocTest {
// request creation of a SimpleSender
final ActorRef mgr = Udp.get(getContext().system()).getManager();
mgr.tell(UdpMessage.simpleSender(), getSelf());
mgr.tell(UdpMessage.simpleSender(), self());
}
@Override
public void onReceive(Object msg) {
if (msg instanceof Udp.SimpleSenderReady) {
getContext().become(ready(getSender()));
getContext().become(ready(sender()));
//#sender
getSender().tell(UdpMessage.send(ByteString.fromString("hello"), remote), getSelf());
sender().tell(UdpMessage.send(ByteString.fromString("hello"), remote), self());
//#sender
} else unhandled(msg);
}
@ -48,10 +48,10 @@ public class UdpDocTest {
public void apply(Object msg) throws Exception {
if (msg instanceof String) {
final String str = (String) msg;
send.tell(UdpMessage.send(ByteString.fromString(str), remote), getSelf());
send.tell(UdpMessage.send(ByteString.fromString(str), remote), self());
//#sender
if (str.equals("world")) {
send.tell(PoisonPill.getInstance(), getSelf());
send.tell(PoisonPill.getInstance(), self());
}
//#sender
@ -72,8 +72,8 @@ public class UdpDocTest {
// request creation of a bound listen socket
final ActorRef mgr = Udp.get(getContext().system()).getManager();
mgr.tell(
UdpMessage.bind(getSelf(), new InetSocketAddress("localhost", 0)),
getSelf());
UdpMessage.bind(self(), new InetSocketAddress("localhost", 0)),
self());
}
@Override
@ -81,9 +81,9 @@ public class UdpDocTest {
if (msg instanceof Udp.Bound) {
final Udp.Bound b = (Udp.Bound) msg;
//#listener
nextActor.tell(b.localAddress(), getSender());
nextActor.tell(b.localAddress(), sender());
//#listener
getContext().become(ready(getSender()));
getContext().become(ready(sender()));
} else unhandled(msg);
}
@ -94,19 +94,19 @@ public class UdpDocTest {
if (msg instanceof Udp.Received) {
final Udp.Received r = (Udp.Received) msg;
// echo server example: send back the data
socket.tell(UdpMessage.send(r.data(), r.sender()), getSelf());
socket.tell(UdpMessage.send(r.data(), r.sender()), self());
// or do some processing and forward it on
final Object processed = // parse data etc., e.g. using PipelineStage
//#listener
r.data().utf8String();
//#listener
nextActor.tell(processed, getSelf());
nextActor.tell(processed, self());
} else if (msg.equals(UdpMessage.unbind())) {
socket.tell(msg, getSelf());
socket.tell(msg, self());
} else if (msg instanceof Udp.Unbound) {
getContext().stop(getSelf());
getContext().stop(self());
} else unhandled(msg);
}
@ -124,17 +124,17 @@ public class UdpDocTest {
// create a restricted a.k.a. connected socket
final ActorRef mgr = UdpConnected.get(getContext().system()).getManager();
mgr.tell(UdpConnectedMessage.connect(getSelf(), remote), getSelf());
mgr.tell(UdpConnectedMessage.connect(self(), remote), self());
}
@Override
public void onReceive(Object msg) {
if (msg instanceof UdpConnected.Connected) {
getContext().become(ready(getSender()));
getContext().become(ready(sender()));
//#connected
getSender()
sender()
.tell(UdpConnectedMessage.send(ByteString.fromString("hello")),
getSelf());
self());
//#connected
} else unhandled(msg);
}
@ -150,7 +150,7 @@ public class UdpDocTest {
if (r.data().utf8String().equals("hello")) {
connection.tell(
UdpConnectedMessage.send(ByteString.fromString("world")),
getSelf());
self());
}
// #connected
@ -158,13 +158,13 @@ public class UdpDocTest {
final String str = (String) msg;
connection
.tell(UdpConnectedMessage.send(ByteString.fromString(str)),
getSelf());
self());
} else if (msg.equals(UdpConnectedMessage.disconnect())) {
connection.tell(msg, getSelf());
connection.tell(msg, self());
} else if (msg instanceof UdpConnected.Disconnected) {
getContext().stop(getSelf());
getContext().stop(self());
} else unhandled(msg);
}

View file

@ -9,7 +9,7 @@ import java.util.LinkedList;
import java.util.Queue;
import akka.actor.ActorRef;
import akka.actor.UntypedActor;
import akka.actor.AbstractActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import akka.io.Tcp.CommandFailed;
@ -19,14 +19,13 @@ import akka.io.Tcp.Received;
import akka.io.Tcp.Write;
import akka.io.Tcp.WritingResumed;
import akka.io.TcpMessage;
import akka.japi.Procedure;
import akka.util.ByteString;
//#echo-handler
public class EchoHandler extends UntypedActor {
public class EchoHandler extends AbstractActor {
final LoggingAdapter log = Logging
.getLogger(getContext().system(), getSelf());
.getLogger(getContext().system(), self());
final ActorRef connection;
final InetSocketAddress remote;
@ -35,6 +34,13 @@ public class EchoHandler extends UntypedActor {
public static final long HIGH_WATERMARK = MAX_STORED * 5 / 10;
public static final long LOW_WATERMARK = MAX_STORED * 2 / 10;
private long transferred;
private int storageOffset = 0;
private long stored = 0;
private Queue<ByteString> storage = new LinkedList<ByteString>();
private boolean suspended = false;
private static class Ack implements Event {
public final int ack;
public Ack(int ack) {
@ -45,6 +51,8 @@ public class EchoHandler extends UntypedActor {
public EchoHandler(ActorRef connection, InetSocketAddress remote) {
this.connection = connection;
this.remote = remote;
writing = writing();
// sign death pact: this actor stops when the connection is closed
getContext().watch(connection);
@ -52,138 +60,136 @@ public class EchoHandler extends UntypedActor {
// start out in optimistic write-through mode
getContext().become(writing);
}
@Override
public Receive createReceive() {
return writing;
}
private final Procedure<Object> writing = new Procedure<Object>() {
@Override
public void apply(Object msg) throws Exception {
if (msg instanceof Received) {
final ByteString data = ((Received) msg).data();
connection.tell(TcpMessage.write(data, new Ack(currentOffset())), getSelf());
private final Receive writing;
private Receive writing() {
return receiveBuilder()
.match(Received.class, msg -> {
final ByteString data = msg.data();
connection.tell(TcpMessage.write(data, new Ack(currentOffset())), self());
buffer(data);
} else if (msg instanceof Integer) {
acknowledge((Integer) msg);
} else if (msg instanceof CommandFailed) {
final Write w = (Write) ((CommandFailed) msg).cmd();
connection.tell(TcpMessage.resumeWriting(), getSelf());
})
.match(Integer.class, msg -> {
acknowledge(msg);
})
.match(CommandFailed.class, msg -> {
final Write w = (Write) msg.cmd();
connection.tell(TcpMessage.resumeWriting(), self());
getContext().become(buffering((Ack) w.ack()));
} else if (msg instanceof ConnectionClosed) {
final ConnectionClosed cl = (ConnectionClosed) msg;
if (cl.isPeerClosed()) {
})
.match(ConnectionClosed.class, msg -> {
if (msg.isPeerClosed()) {
if (storage.isEmpty()) {
getContext().stop(getSelf());
getContext().stop(self());
} else {
getContext().become(closing);
getContext().become(closing());
}
}
}
}
};
})
.build();
}
//#buffering
protected Procedure<Object> buffering(final Ack nack) {
return new Procedure<Object>() {
final static class BufferingState {
int toAck = 10;
boolean peerClosed = false;
}
protected Receive buffering(final Ack nack) {
final BufferingState state = new BufferingState();
return receiveBuilder()
.match(Received.class, msg -> {
buffer(msg.data());
private int toAck = 10;
private boolean peerClosed = false;
})
.match(WritingResumed.class, msg -> {
writeFirst();
@Override
public void apply(Object msg) throws Exception {
if (msg instanceof Received) {
buffer(((Received) msg).data());
})
.match(ConnectionClosed.class, msg -> {
if (msg.isPeerClosed())
state.peerClosed = true;
else
getContext().stop(self());
} else if (msg instanceof WritingResumed) {
writeFirst();
})
.match(Integer.class, ack -> {
acknowledge(ack);
} else if (msg instanceof ConnectionClosed) {
if (((ConnectionClosed) msg).isPeerClosed())
peerClosed = true;
else
getContext().stop(getSelf());
if (ack >= nack.ack) {
// otherwise it was the ack of the last successful write
} else if (msg instanceof Integer) {
final int ack = (Integer) msg;
acknowledge(ack);
if (storage.isEmpty()) {
if (state.peerClosed)
getContext().stop(self());
else
getContext().become(writing);
if (ack >= nack.ack) {
// otherwise it was the ack of the last successful write
if (storage.isEmpty()) {
if (peerClosed)
getContext().stop(getSelf());
} else {
if (state.toAck > 0) {
// stay in ACK-based mode for a short while
writeFirst();
--state.toAck;
} else {
// then return to NACK-based again
writeAll();
if (state.peerClosed)
getContext().become(closing());
else
getContext().become(writing);
} else {
if (toAck > 0) {
// stay in ACK-based mode for a short while
writeFirst();
--toAck;
} else {
// then return to NACK-based again
writeAll();
if (peerClosed)
getContext().become(closing);
else
getContext().become(writing);
}
}
}
}
}
};
})
.build();
}
//#buffering
//#closing
protected Procedure<Object> closing = new Procedure<Object>() {
@Override
public void apply(Object msg) throws Exception {
if (msg instanceof CommandFailed) {
protected Receive closing() {
return receiveBuilder()
.match(CommandFailed.class, msg -> {
// the command can only have been a Write
connection.tell(TcpMessage.resumeWriting(), getSelf());
getContext().become(closeResend, false);
} else if (msg instanceof Integer) {
acknowledge((Integer) msg);
connection.tell(TcpMessage.resumeWriting(), self());
getContext().become(closeResend(), false);
})
.match(Integer.class, msg -> {
acknowledge(msg);
if (storage.isEmpty())
getContext().stop(getSelf());
}
}
};
getContext().stop(self());
})
.build();
}
protected Procedure<Object> closeResend = new Procedure<Object>() {
@Override
public void apply(Object msg) throws Exception {
if (msg instanceof WritingResumed) {
protected Receive closeResend() {
return receiveBuilder()
.match(WritingResumed.class, msg -> {
writeAll();
getContext().unbecome();
} else if (msg instanceof Integer) {
acknowledge((Integer) msg);
}
}
};
})
.match(Integer.class, msg -> {
acknowledge(msg);
})
.build();
}
//#closing
//#storage-omitted
@Override
public void onReceive(Object msg) throws Exception {
// this method is not used due to become()
}
@Override
public void postStop() {
log.info("transferred {} bytes from/to [{}]", transferred, remote);
}
private long transferred;
private int storageOffset = 0;
private long stored = 0;
private Queue<ByteString> storage = new LinkedList<ByteString>();
private boolean suspended = false;
//#helpers
protected void buffer(ByteString data) {
storage.add(data);
@ -191,11 +197,11 @@ public class EchoHandler extends UntypedActor {
if (stored > MAX_STORED) {
log.warning("drop connection to [{}] (buffer overrun)", remote);
getContext().stop(getSelf());
getContext().stop(self());
} else if (stored > HIGH_WATERMARK) {
log.debug("suspending reading at {}", currentOffset());
connection.tell(TcpMessage.suspendReading(), getSelf());
connection.tell(TcpMessage.suspendReading(), self());
suspended = true;
}
}
@ -211,7 +217,7 @@ public class EchoHandler extends UntypedActor {
if (suspended && stored < LOW_WATERMARK) {
log.debug("resuming reading");
connection.tell(TcpMessage.resumeReading(), getSelf());
connection.tell(TcpMessage.resumeReading(), self());
suspended = false;
}
}
@ -224,12 +230,12 @@ public class EchoHandler extends UntypedActor {
protected void writeAll() {
int i = 0;
for (ByteString data : storage) {
connection.tell(TcpMessage.write(data, new Ack(storageOffset + i++)), getSelf());
connection.tell(TcpMessage.write(data, new Ack(storageOffset + i++)), self());
}
}
protected void writeFirst() {
connection.tell(TcpMessage.write(storage.peek(), new Ack(storageOffset)), getSelf());
connection.tell(TcpMessage.write(storage.peek(), new Ack(storageOffset)), self());
}
//#storage-omitted

View file

@ -9,7 +9,7 @@ import java.net.InetSocketAddress;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.actor.SupervisorStrategy;
import akka.actor.UntypedActor;
import akka.actor.AbstractActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import akka.io.Tcp;
@ -19,10 +19,10 @@ import akka.io.Tcp.CommandFailed;
import akka.io.Tcp.Connected;
import akka.io.TcpMessage;
public class EchoManager extends UntypedActor {
public class EchoManager extends AbstractActor {
final LoggingAdapter log = Logging
.getLogger(getContext().system(), getSelf());
.getLogger(getContext().system(), self());
final Class<?> handlerClass;
@ -41,41 +41,42 @@ public class EchoManager extends UntypedActor {
final ActorRef tcpManager = Tcp.get(getContext().system()).manager();
//#manager
tcpManager.tell(
TcpMessage.bind(getSelf(), new InetSocketAddress("localhost", 0), 100),
getSelf());
TcpMessage.bind(self(), new InetSocketAddress("localhost", 0), 100),
self());
}
@Override
public void postRestart(Throwable arg0) throws Exception {
// do not restart
getContext().stop(getSelf());
getContext().stop(self());
}
@Override
public void onReceive(Object msg) throws Exception {
if (msg instanceof Bound) {
log.info("listening on [{}]", ((Bound) msg).localAddress());
} else if (msg instanceof Tcp.CommandFailed) {
final CommandFailed failed = (CommandFailed) msg;
if (failed.cmd() instanceof Bind) {
log.warning("cannot bind to [{}]", ((Bind) failed.cmd()).localAddress());
getContext().stop(getSelf());
} else {
log.warning("unknown command failed [{}]", failed.cmd());
}
} else
if (msg instanceof Connected) {
final Connected conn = (Connected) msg;
log.info("received connection from [{}]", conn.remoteAddress());
final ActorRef connection = getSender();
final ActorRef handler = getContext().actorOf(
Props.create(handlerClass, connection, conn.remoteAddress()));
//#echo-manager
connection.tell(TcpMessage.register(handler,
true, // <-- keepOpenOnPeerClosed flag
true), getSelf());
//#echo-manager
}
public Receive createReceive() {
return receiveBuilder()
.match(Bound.class, msg -> {
log.info("listening on [{}]", msg.localAddress());
})
.match(Tcp.CommandFailed.class, failed -> {
if (failed.cmd() instanceof Bind) {
log.warning("cannot bind to [{}]", ((Bind) failed.cmd()).localAddress());
getContext().stop(self());
} else {
log.warning("unknown command failed [{}]", failed.cmd());
}
})
.match(Connected.class, conn -> {
log.info("received connection from [{}]", conn.remoteAddress());
final ActorRef connection = sender();
final ActorRef handler = getContext().actorOf(
Props.create(handlerClass, connection, conn.remoteAddress()));
//#echo-manager
connection.tell(TcpMessage.register(handler,
true, // <-- keepOpenOnPeerClosed flag
true), self());
//#echo-manager
})
.build();
}
}

View file

@ -15,7 +15,7 @@ import java.net.InetSocketAddress;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.actor.UntypedActor;
import akka.actor.AbstractActor;
import akka.io.Tcp;
import akka.io.Tcp.Bound;
import akka.io.Tcp.CommandFailed;
@ -34,7 +34,7 @@ public class IODocTest extends AbstractJavaTest {
static
//#server
public class Server extends UntypedActor {
public class Server extends AbstractActor {
final ActorRef manager;
@ -49,25 +49,28 @@ public class IODocTest extends AbstractJavaTest {
@Override
public void preStart() throws Exception {
final ActorRef tcp = Tcp.get(getContext().system()).manager();
tcp.tell(TcpMessage.bind(getSelf(),
new InetSocketAddress("localhost", 0), 100), getSelf());
tcp.tell(TcpMessage.bind(self(),
new InetSocketAddress("localhost", 0), 100), self());
}
@Override
public void onReceive(Object msg) throws Exception {
if (msg instanceof Bound) {
manager.tell(msg, getSelf());
} else if (msg instanceof CommandFailed) {
getContext().stop(getSelf());
} else if (msg instanceof Connected) {
final Connected conn = (Connected) msg;
manager.tell(conn, getSelf());
final ActorRef handler = getContext().actorOf(
Props.create(SimplisticHandler.class));
getSender().tell(TcpMessage.register(handler), getSelf());
}
public Receive createReceive() {
return receiveBuilder()
.match(Bound.class, msg -> {
manager.tell(msg, self());
})
.match(CommandFailed.class, msg -> {
getContext().stop(self());
})
.match(Connected.class, conn -> {
manager.tell(conn, self());
final ActorRef handler = getContext().actorOf(
Props.create(SimplisticHandler.class));
sender().tell(TcpMessage.register(handler), self());
})
.build();
}
}
@ -75,23 +78,26 @@ public class IODocTest extends AbstractJavaTest {
static
//#simplistic-handler
public class SimplisticHandler extends UntypedActor {
public class SimplisticHandler extends AbstractActor {
@Override
public void onReceive(Object msg) throws Exception {
if (msg instanceof Received) {
final ByteString data = ((Received) msg).data();
System.out.println(data);
getSender().tell(TcpMessage.write(data), getSelf());
} else if (msg instanceof ConnectionClosed) {
getContext().stop(getSelf());
}
public Receive createReceive() {
return receiveBuilder()
.match(Received.class, msg -> {
final ByteString data = msg.data();
System.out.println(data);
sender().tell(TcpMessage.write(data), self());
})
.match(ConnectionClosed.class, msg -> {
getContext().stop(self());
})
.build();
}
}
//#simplistic-handler
static
//#client
public class Client extends UntypedActor {
public class Client extends AbstractActor {
final InetSocketAddress remote;
final ActorRef listener;
@ -105,44 +111,43 @@ public class IODocTest extends AbstractJavaTest {
this.listener = listener;
final ActorRef tcp = Tcp.get(getContext().system()).manager();
tcp.tell(TcpMessage.connect(remote), getSelf());
tcp.tell(TcpMessage.connect(remote), self());
}
@Override
public void onReceive(Object msg) throws Exception {
if (msg instanceof CommandFailed) {
listener.tell("failed", getSelf());
getContext().stop(getSelf());
} else if (msg instanceof Connected) {
listener.tell(msg, getSelf());
getSender().tell(TcpMessage.register(getSelf()), getSelf());
getContext().become(connected(getSender()));
}
public Receive createReceive() {
return receiveBuilder()
.match(CommandFailed.class, msg -> {
listener.tell("failed", self());
getContext().stop(self());
})
.match(Connected.class, msg -> {
listener.tell(msg, self());
sender().tell(TcpMessage.register(self()), self());
getContext().become(connected(sender()));
})
.build();
}
private Procedure<Object> connected(final ActorRef connection) {
return new Procedure<Object>() {
@Override
public void apply(Object msg) throws Exception {
if (msg instanceof ByteString) {
connection.tell(TcpMessage.write((ByteString) msg), getSelf());
} else if (msg instanceof CommandFailed) {
// OS kernel socket buffer was full
} else if (msg instanceof Received) {
listener.tell(((Received) msg).data(), getSelf());
} else if (msg.equals("close")) {
connection.tell(TcpMessage.close(), getSelf());
} else if (msg instanceof ConnectionClosed) {
getContext().stop(getSelf());
}
}
};
private Receive connected(final ActorRef connection) {
return receiveBuilder()
.match(ByteString.class, msg -> {
connection.tell(TcpMessage.write((ByteString) msg), self());
})
.match(CommandFailed.class, msg -> {
// OS kernel socket buffer was full
})
.match(Received.class, msg -> {
listener.tell(msg.data(), self());
})
.matchEquals("close", msg -> {
connection.tell(TcpMessage.close(), self());
})
.match(ConnectionClosed.class, msg -> {
getContext().stop(self());
})
.build();
}
}

View file

@ -9,7 +9,7 @@ import java.util.LinkedList;
import java.util.Queue;
import akka.actor.ActorRef;
import akka.actor.UntypedActor;
import akka.actor.AbstractActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import akka.io.Tcp.ConnectionClosed;
@ -20,10 +20,10 @@ import akka.japi.Procedure;
import akka.util.ByteString;
//#simple-echo-handler
public class SimpleEchoHandler extends UntypedActor {
public class SimpleEchoHandler extends AbstractActor {
final LoggingAdapter log = Logging
.getLogger(getContext().system(), getSelf());
.getLogger(getContext().system(), self());
final ActorRef connection;
final InetSocketAddress remote;
@ -41,38 +41,42 @@ public class SimpleEchoHandler extends UntypedActor {
}
@Override
public void onReceive(Object msg) throws Exception {
if (msg instanceof Received) {
final ByteString data = ((Received) msg).data();
buffer(data);
connection.tell(TcpMessage.write(data, ACK), getSelf());
// now switch behavior to waiting for acknowledgement
getContext().become(buffering, false);
} else if (msg instanceof ConnectionClosed) {
getContext().stop(getSelf());
}
public Receive createReceive() {
return receiveBuilder()
.match(Received.class, msg -> {
final ByteString data = msg.data();
buffer(data);
connection.tell(TcpMessage.write(data, ACK), self());
// now switch behavior to waiting for acknowledgement
getContext().become(buffering(), false);
})
.match(ConnectionClosed.class, msg -> {
getContext().stop(self());
})
.build();
}
private final Procedure<Object> buffering = new Procedure<Object>() {
@Override
public void apply(Object msg) throws Exception {
if (msg instanceof Received) {
buffer(((Received) msg).data());
private final Receive buffering() {
return receiveBuilder()
.match(Received.class, msg -> {
buffer(msg.data());
} else if (msg == ACK) {
})
.match(Event.class, msg -> msg == ACK, msg -> {
acknowledge();
} else if (msg instanceof ConnectionClosed) {
if (((ConnectionClosed) msg).isPeerClosed()) {
})
.match(ConnectionClosed.class, msg -> {
if (msg.isPeerClosed()) {
closing = true;
} else {
// could also be ErrorClosed, in which case we just give up
getContext().stop(getSelf());
getContext().stop(self());
}
}
}
};
})
.build();
}
//#storage-omitted
public void postStop() {
@ -95,11 +99,11 @@ public class SimpleEchoHandler extends UntypedActor {
if (stored > maxStored) {
log.warning("drop connection to [{}] (buffer overrun)", remote);
getContext().stop(getSelf());
getContext().stop(self());
} else if (stored > highWatermark) {
log.debug("suspending reading");
connection.tell(TcpMessage.suspendReading(), getSelf());
connection.tell(TcpMessage.suspendReading(), self());
suspended = true;
}
}
@ -111,18 +115,18 @@ public class SimpleEchoHandler extends UntypedActor {
if (suspended && stored < lowWatermark) {
log.debug("resuming reading");
connection.tell(TcpMessage.resumeReading(), getSelf());
connection.tell(TcpMessage.resumeReading(), self());
suspended = false;
}
if (storage.isEmpty()) {
if (closing) {
getContext().stop(getSelf());
getContext().stop(self());
} else {
getContext().unbecome();
}
} else {
connection.tell(TcpMessage.write(storage.peek(), ACK), getSelf());
connection.tell(TcpMessage.write(storage.peek(), ACK), self());
}
}
//#simple-helpers

View file

@ -4,9 +4,9 @@ import java.util.concurrent.CountDownLatch;
import akka.actor.ActorRef;
import akka.actor.Terminated;
import akka.actor.UntypedActor;
import akka.actor.AbstractActor;
public class Watcher extends UntypedActor {
public class Watcher extends AbstractActor {
static public class Watch {
final ActorRef target;
@ -22,13 +22,16 @@ public class Watcher extends UntypedActor {
}
@Override
public void onReceive(Object msg) throws Exception {
if (msg instanceof Watch) {
getContext().watch(((Watch) msg).target);
} else if (msg instanceof Terminated) {
latch.countDown();
if (latch.getCount() == 0) getContext().stop(getSelf());
}
public Receive createReceive() {
return receiveBuilder()
.match(Watch.class, msg -> {
getContext().watch(msg.target);
})
.match(Terminated.class, msg -> {
latch.countDown();
if (latch.getCount() == 0) getContext().stop(self());
})
.build();
}
}

View file

@ -51,7 +51,7 @@ public class ConsistentHashingRouterDocTest extends AbstractJavaTest {
} else if (msg instanceof Get) {
Get get = (Get) msg;
Object value = cache.get(get.key);
getSender().tell(value == null ? NOT_FOUND : value,
sender().tell(value == null ? NOT_FOUND : value,
getContext().self());
} else if (msg instanceof Evict) {
Evict evict = (Evict) msg;

View file

@ -96,7 +96,7 @@ public class CustomRouterDocTest extends AbstractJavaTest {
static public class Storage extends UntypedActor {
public void onReceive(Object msg) {
getSender().tell(msg, getSelf());
sender().tell(msg, self());
}
}

View file

@ -105,7 +105,7 @@ public class RouterDocTest extends AbstractJavaTest {
public void onReceive(Object msg) {
if (msg instanceof Work) {
router.route(msg, getSender());
router.route(msg, sender());
} else if (msg instanceof Terminated) {
router = router.removeRoutee(((Terminated) msg).actor());
ActorRef r = getContext().actorOf(Props.create(Worker.class));
@ -123,18 +123,18 @@ public class RouterDocTest extends AbstractJavaTest {
static public class Echo extends UntypedActor {
public void onReceive(Object msg) {
getSender().tell(msg, getSelf());
sender().tell(msg, self());
}
}
static public class Replier extends UntypedActor {
public void onReceive(Object msg) {
//#reply-with-self
getSender().tell("reply", getSelf());
sender().tell("reply", self());
//#reply-with-self
//#reply-with-parent
getSender().tell("reply", getContext().parent());
sender().tell("reply", getContext().parent());
//#reply-with-parent
}
}

View file

@ -30,7 +30,7 @@ public class SchedulerPatternTest extends AbstractJavaTest {
private final Cancellable tick = getContext().system().scheduler().schedule(
Duration.create(500, TimeUnit.MILLISECONDS),
Duration.create(1, TimeUnit.SECONDS),
getSelf(), "tick", getContext().dispatcher(), null);
self(), "tick", getContext().dispatcher(), null);
//#schedule-constructor
// this variable and constructor is declared here to not show up in the docs
final ActorRef target;
@ -49,7 +49,7 @@ public class SchedulerPatternTest extends AbstractJavaTest {
if (message.equals("tick")) {
// do something useful here
//#schedule-constructor
target.tell(message, getSelf());
target.tell(message, self());
//#schedule-constructor
}
//#schedule-constructor
@ -79,7 +79,7 @@ public class SchedulerPatternTest extends AbstractJavaTest {
public void preStart() {
getContext().system().scheduler().scheduleOnce(
Duration.create(500, TimeUnit.MILLISECONDS),
getSelf(), "tick", getContext().dispatcher(), null);
self(), "tick", getContext().dispatcher(), null);
}
// override postRestart so we don't call preStart and schedule a new message
@ -93,10 +93,10 @@ public class SchedulerPatternTest extends AbstractJavaTest {
// send another periodic tick after the specified delay
getContext().system().scheduler().scheduleOnce(
Duration.create(1, TimeUnit.SECONDS),
getSelf(), "tick", getContext().dispatcher(), null);
self(), "tick", getContext().dispatcher(), null);
// do something useful here
//#schedule-receive
target.tell(message, getSelf());
target.tell(message, self());
//#schedule-receive
}
//#schedule-receive

View file

@ -74,13 +74,13 @@ public class SupervisedAsk {
public void onReceive(Object message) throws Exception {
if (message instanceof AskParam) {
askParam = (AskParam) message;
caller = getSender();
caller = sender();
targetActor = getContext().actorOf(askParam.props);
getContext().watch(targetActor);
targetActor.forward(askParam.message, getContext());
Scheduler scheduler = getContext().system().scheduler();
timeoutMessage = scheduler.scheduleOnce(askParam.timeout.duration(),
self(), new AskTimeout(), context().dispatcher(), null);
self(), new AskTimeout(), getContext().dispatcher(), null);
} else if (message instanceof Terminated) {
Throwable ex = new ActorKilledException("Target actor terminated.");
caller.tell(new Status.Failure(ex), self());

View file

@ -10,11 +10,11 @@ import akka.pattern.BackoffSupervisor;
import akka.persistence.*;
import akka.persistence.journal.EventAdapter;
import akka.persistence.journal.EventSeq;
import scala.Option;
import scala.concurrent.duration.Duration;
import scala.PartialFunction;
import scala.runtime.BoxedUnit;
import java.io.Serializable;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
public class LambdaPersistenceDocTest {
@ -42,7 +42,7 @@ public class LambdaPersistenceDocTest {
//#recover-on-restart-disabled
@Override
public void preRestart(Throwable reason, Option<Object> message) {}
public void preRestart(Throwable reason, Optional<Object> message) {}
//#recover-on-restart-disabled
}
@ -65,14 +65,14 @@ public class LambdaPersistenceDocTest {
//#persistence-id-override
@Override
public PartialFunction<Object, BoxedUnit> receiveCommand() {
return ReceiveBuilder.
public Receive createReceive() {
return receiveBuilder().
match(String.class, cmd -> {/* ... */}).build();
}
@Override
public PartialFunction<Object, BoxedUnit> receiveRecover() {
return ReceiveBuilder.
public Receive createReceiveRecover() {
return receiveBuilder().
match(String.class, evt -> {/* ... */}).build();
}
@ -85,8 +85,8 @@ public class LambdaPersistenceDocTest {
return "my-stable-persistence-id";
}
@Override public PartialFunction<Object, BoxedUnit> receiveRecover() {
return ReceiveBuilder.
@Override public Receive createReceiveRecover() {
return receiveBuilder().
match(RecoveryCompleted.class, r -> {
// perform init after recovery, before any other messages
// ...
@ -94,8 +94,8 @@ public class LambdaPersistenceDocTest {
match(String.class, this::handleEvent).build();
}
@Override public PartialFunction<Object, BoxedUnit> receiveCommand() {
return ReceiveBuilder.
@Override public Receive createReceive() {
return receiveBuilder().
match(String.class, s -> s.equals("cmd"),
s -> persist("evt", this::handleEvent)).build();
}
@ -128,7 +128,7 @@ public class LambdaPersistenceDocTest {
Duration.create(3, TimeUnit.SECONDS),
Duration.create(30, TimeUnit.SECONDS),
0.2);
context().actorOf(props, "mySupervisor");
getContext().actorOf(props, "mySupervisor");
super.preStart();
}
//#backoff
@ -188,8 +188,8 @@ public class LambdaPersistenceDocTest {
}
@Override
public PartialFunction<Object, BoxedUnit> receiveCommand() {
return ReceiveBuilder.
public Receive createReceive() {
return receiveBuilder().
match(String.class, s -> {
persist(new MsgSent(s), evt -> updateState(evt));
}).
@ -200,8 +200,8 @@ public class LambdaPersistenceDocTest {
}
@Override
public PartialFunction<Object, BoxedUnit> receiveRecover() {
return ReceiveBuilder.
public Receive createReceiveRecover() {
return receiveBuilder().
match(Object.class, evt -> updateState(evt)).build();
}
@ -217,13 +217,14 @@ public class LambdaPersistenceDocTest {
}
class MyDestination extends AbstractActor {
public MyDestination() {
receive(ReceiveBuilder.
match(Msg.class, msg -> {
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Msg.class, msg -> {
// ...
sender().tell(new Confirm(msg.deliveryId), self());
}).build()
);
})
.build();
}
}
//#at-least-once-example
@ -236,8 +237,8 @@ public class LambdaPersistenceDocTest {
//#save-snapshot
private Object state;
@Override public PartialFunction<Object, BoxedUnit> receiveCommand() {
return ReceiveBuilder.
@Override public Receive createReceive() {
return receiveBuilder().
match(String.class, s -> s.equals("snap"),
s -> saveSnapshot(state)).
match(SaveSnapshotSuccess.class, ss -> {
@ -255,8 +256,8 @@ public class LambdaPersistenceDocTest {
return "persistence-id";
}
@Override public PartialFunction<Object, BoxedUnit> receiveRecover() {
return ReceiveBuilder.
@Override public Receive createReceiveRecover() {
return receiveBuilder().
match(RecoveryCompleted.class, r -> {/* ...*/}).build();
}
@ -279,8 +280,8 @@ public class LambdaPersistenceDocTest {
//#snapshot-offer
private Object state;
@Override public PartialFunction<Object, BoxedUnit> receiveRecover() {
return ReceiveBuilder.
@Override public Receive createReceiveRecover() {
return receiveBuilder().
match(SnapshotOffer.class, s -> {
state = s.snapshot();
// ...
@ -293,21 +294,22 @@ public class LambdaPersistenceDocTest {
return "persistence-id";
}
@Override public PartialFunction<Object, BoxedUnit> receiveCommand() {
return ReceiveBuilder.
@Override public Receive createReceive() {
return receiveBuilder().
match(String.class, s -> {/* ...*/}).build();
}
}
class MyActor extends AbstractActor {
ActorRef persistentActor;
private final ActorRef persistentActor =
getContext().actorOf(Props.create(MyPersistentActor.class));
public MyActor() {
persistentActor = context().actorOf(Props.create(MyPersistentActor.class));
receive(ReceiveBuilder.
match(Object.class, o -> {/* ... */}).build()
);
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Object.class, o -> {/* ... */})
.build();
}
}
};
@ -331,13 +333,13 @@ public class LambdaPersistenceDocTest {
});
}
@Override public PartialFunction<Object, BoxedUnit> receiveRecover() {
return ReceiveBuilder.
@Override public Receive createReceiveRecover() {
return receiveBuilder().
match(String.class, this::handleCommand).build();
}
@Override public PartialFunction<Object, BoxedUnit> receiveCommand() {
return ReceiveBuilder.
@Override public Receive createReceive() {
return receiveBuilder().
match(String.class, this::handleCommand).build();
}
}
@ -383,13 +385,13 @@ public class LambdaPersistenceDocTest {
});
}
@Override public PartialFunction<Object, BoxedUnit> receiveRecover() {
return ReceiveBuilder.
@Override public Receive createReceiveRecover() {
return receiveBuilder().
match(String.class, this::handleCommand).build();
}
@Override public PartialFunction<Object, BoxedUnit> receiveCommand() {
return ReceiveBuilder.
@Override public Receive createReceive() {
return receiveBuilder().
match(String.class, this::handleCommand).build();
}
}
@ -424,15 +426,15 @@ public class LambdaPersistenceDocTest {
return "my-stable-persistence-id";
}
@Override public PartialFunction<Object, BoxedUnit> receiveCommand() {
return ReceiveBuilder.matchAny(event -> {}).build();
@Override public Receive createReceive() {
return receiveBuilder().matchAny(event -> {}).build();
}
//#nested-persist-persist
@Override public PartialFunction<Object, BoxedUnit> receiveRecover() {
@Override public Receive createReceiveRecover() {
final Procedure<String> replyToSender = event -> sender().tell(event, self());
return ReceiveBuilder
return receiveBuilder()
.match(String.class, msg -> {
persist(String.format("%s-outer-1", msg), event -> {
sender().tell(event, self());
@ -477,15 +479,17 @@ public class LambdaPersistenceDocTest {
return "my-stable-persistence-id";
}
@Override public PartialFunction<Object, BoxedUnit> receiveCommand() {
return ReceiveBuilder.matchAny(event -> {}).build();
@Override
public Receive createReceiveRecover() {
return receiveBuilder().matchAny(event -> {}).build();
}
//#nested-persistAsync-persistAsync
@Override public PartialFunction<Object, BoxedUnit> receiveRecover() {
@Override
public Receive createReceive() {
final Procedure<String> replyToSender = event -> sender().tell(event, self());
return ReceiveBuilder
return receiveBuilder()
.match(String.class, msg -> {
persistAsync(String.format("%s-outer-1", msg ), event -> {
sender().tell(event, self());
@ -539,10 +543,10 @@ public class LambdaPersistenceDocTest {
}
@Override
public PartialFunction<Object, BoxedUnit> receiveCommand() {
return ReceiveBuilder
public Receive createReceive() {
return receiveBuilder()
.match(Shutdown.class, shutdown -> {
context().stop(self());
getContext().stop(self());
})
.match(String.class, msg -> {
System.out.println(msg);
@ -552,8 +556,8 @@ public class LambdaPersistenceDocTest {
}
@Override
public PartialFunction<Object, BoxedUnit> receiveRecover() {
return ReceiveBuilder.matchAny(any -> {}).build();
public Receive createReceiveRecover() {
return receiveBuilder().matchAny(any -> {}).build();
}
}

View file

@ -14,12 +14,20 @@ import akka.persistence.snapshot.japi.*;
import akka.actor.*;
import akka.persistence.journal.leveldb.SharedLeveldbJournal;
import akka.persistence.journal.leveldb.SharedLeveldbStore;
import akka.japi.pf.ReceiveBuilder;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import scala.concurrent.Future;
import java.util.function.Consumer;
import org.iq80.leveldb.util.FileUtils;
import java.util.Optional;
import akka.persistence.japi.journal.JavaJournalSpec;
import akka.persistence.japi.snapshot.JavaSnapshotStoreSpec;
public class LambdaPersistencePluginDocTest {
@ -35,21 +43,24 @@ public class LambdaPersistencePluginDocTest {
@Override
public void preStart() throws Exception {
String path = "akka.tcp://example@127.0.0.1:2552/user/store";
ActorSelection selection = context().actorSelection(path);
ActorSelection selection = getContext().actorSelection(path);
selection.tell(new Identify(1), self());
}
public SharedStorageUsage() {
receive(ReceiveBuilder.
match(ActorIdentity.class, ai -> {
@Override
public Receive createReceive() {
return receiveBuilder()
.match(ActorIdentity.class, ai -> {
if (ai.correlationId().equals(1)) {
ActorRef store = ai.getRef();
if (store != null) {
SharedLeveldbJournal.setStore(store, context().system());
Optional<ActorRef> store = ai.getActorRef();
if (store.isPresent()) {
SharedLeveldbJournal.setStore(store.get(), getContext().system());
} else {
throw new RuntimeException("Couldn't identify store");
}
}
}).build()
);
})
.build();
}
}
//#shared-store-usage
@ -111,4 +122,79 @@ public class LambdaPersistencePluginDocTest {
return null;
}
}
static Object o2 = new Object() {
//#journal-tck-java
class MyJournalSpecTest extends JavaJournalSpec {
public MyJournalSpecTest() {
super(ConfigFactory.parseString(
"persistence.journal.plugin = " +
"\"akka.persistence.journal.leveldb-shared\""));
}
@Override
public CapabilityFlag supportsRejectingNonSerializableObjects() {
return CapabilityFlag.off();
}
}
//#journal-tck-java
};
static Object o3 = new Object() {
//#snapshot-store-tck-java
class MySnapshotStoreTest extends JavaSnapshotStoreSpec {
public MySnapshotStoreTest() {
super(ConfigFactory.parseString(
"akka.persistence.snapshot-store.plugin = " +
"\"akka.persistence.snapshot-store.local\""));
}
}
//#snapshot-store-tck-java
};
static Object o4 = new Object() {
//#journal-tck-before-after-java
class MyJournalSpecTest extends JavaJournalSpec {
List<File> storageLocations = new ArrayList<File>();
public MyJournalSpecTest() {
super(ConfigFactory.parseString(
"persistence.journal.plugin = " +
"\"akka.persistence.journal.leveldb-shared\""));
Config config = system().settings().config();
storageLocations.add(new File(
config.getString("akka.persistence.journal.leveldb.dir")));
storageLocations.add(new File(
config.getString("akka.persistence.snapshot-store.local.dir")));
}
@Override
public CapabilityFlag supportsRejectingNonSerializableObjects() {
return CapabilityFlag.on();
}
@Override
public void beforeAll() {
for (File storageLocation : storageLocations) {
FileUtils.deleteRecursively(storageLocation);
}
super.beforeAll();
}
@Override
public void afterAll() {
super.afterAll();
for (File storageLocation : storageLocations) {
FileUtils.deleteRecursively(storageLocation);
}
}
}
//#journal-tck-before-after-java
};
}

View file

@ -1,584 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.persistence;
import java.util.concurrent.TimeUnit;
import akka.actor.*;
import akka.pattern.BackoffSupervisor;
import scala.concurrent.duration.Duration;
import akka.japi.Function;
import akka.japi.Procedure;
import akka.persistence.*;
import java.io.Serializable;
public class PersistenceDocTest {
public interface SomeOtherMessage {}
public interface PersistentActorMethods {
//#persistence-id
public String persistenceId();
//#persistence-id
//#recovery-status
public boolean recoveryRunning();
public boolean recoveryFinished();
//#recovery-status
}
static Object o2 = new Object() {
abstract class MyPersistentActor1 extends UntypedPersistentActor {
//#recovery-disabled
@Override
public Recovery recovery() {
return Recovery.none();
}
//#recovery-disabled
}
abstract class MyPersistentActor2 extends UntypedPersistentActor {
//#recovery-custom
@Override
public Recovery recovery() {
return Recovery.create(457L);
}
//#recovery-custom
}
class MyPersistentActor4 extends UntypedPersistentActor implements PersistentActorMethods {
//#persistence-id-override
@Override
public String persistenceId() {
return "my-stable-persistence-id";
}
//#persistence-id-override
@Override
public void onReceiveRecover(Object message) throws Exception {}
@Override
public void onReceiveCommand(Object message) throws Exception {}
}
class MyPersistentActor5 extends UntypedPersistentActor {
@Override
public String persistenceId() {
return "persistence-id";
}
//#recovery-completed
@Override
public void onReceiveRecover(Object message) {
if (message instanceof RecoveryCompleted) {
// perform init after recovery, before any other messages
}
}
@Override
public void onReceiveCommand(Object message) throws Exception {
if (message instanceof String) {
// ...
} else {
unhandled(message);
}
}
//#recovery-completed
}
abstract class MyPersistentActor6 extends UntypedPersistentActor {
//#recovery-no-snap
@Override
public Recovery recovery() {
return Recovery.create(SnapshotSelectionCriteria.none());
}
//#recovery-no-snap
}
abstract class MyActor extends UntypedPersistentActor {
//#backoff
@Override
public void preStart() throws Exception {
final Props childProps = Props.create(MyPersistentActor1.class);
final Props props = BackoffSupervisor.props(
childProps,
"myActor",
Duration.create(3, TimeUnit.SECONDS),
Duration.create(30, TimeUnit.SECONDS),
0.2);
getContext().actorOf(props, "mySupervisor");
super.preStart();
}
//#backoff
}
};
static Object atLeastOnceExample = new Object() {
//#at-least-once-example
class Msg implements Serializable {
public final long deliveryId;
public final String s;
public Msg(long deliveryId, String s) {
this.deliveryId = deliveryId;
this.s = s;
}
}
class Confirm implements Serializable {
public final long deliveryId;
public Confirm(long deliveryId) {
this.deliveryId = deliveryId;
}
}
class MsgSent implements Serializable {
public final String s;
public MsgSent(String s) {
this.s = s;
}
}
class MsgConfirmed implements Serializable {
public final long deliveryId;
public MsgConfirmed(long deliveryId) {
this.deliveryId = deliveryId;
}
}
class MyPersistentActor extends UntypedPersistentActorWithAtLeastOnceDelivery {
private final ActorSelection destination;
@Override
public String persistenceId() { return "persistence-id"; }
public MyPersistentActor(ActorSelection destination) {
this.destination = destination;
}
@Override
public void onReceiveCommand(Object message) {
if (message instanceof String) {
String s = (String) message;
persist(new MsgSent(s), new Procedure<MsgSent>() {
public void apply(MsgSent evt) {
updateState(evt);
}
});
} else if (message instanceof Confirm) {
Confirm confirm = (Confirm) message;
persist(new MsgConfirmed(confirm.deliveryId), new Procedure<MsgConfirmed>() {
public void apply(MsgConfirmed evt) {
updateState(evt);
}
});
} else {
unhandled(message);
}
}
@Override
public void onReceiveRecover(Object event) {
updateState(event);
}
void updateState(Object event) {
if (event instanceof MsgSent) {
final MsgSent evt = (MsgSent) event;
deliver(destination, new Function<Long, Object>() {
public Object apply(Long deliveryId) {
return new Msg(deliveryId, evt.s);
}
});
} else if (event instanceof MsgConfirmed) {
final MsgConfirmed evt = (MsgConfirmed) event;
confirmDelivery(evt.deliveryId);
}
}
}
class MyDestination extends UntypedActor {
public void onReceive(Object message) throws Exception {
if (message instanceof Msg) {
Msg msg = (Msg) message;
// ...
getSender().tell(new Confirm(msg.deliveryId), getSelf());
} else {
unhandled(message);
}
}
}
//#at-least-once-example
};
static Object o4 = new Object() {
class MyPersistentActor extends UntypedPersistentActor {
@Override
public String persistenceId() { return "persistence-id"; }
//#save-snapshot
private Object state;
@Override
public void onReceiveCommand(Object message) {
if (message.equals("snap")) {
saveSnapshot(state);
} else if (message instanceof SaveSnapshotSuccess) {
SnapshotMetadata metadata = ((SaveSnapshotSuccess)message).metadata();
// ...
} else if (message instanceof SaveSnapshotFailure) {
SnapshotMetadata metadata = ((SaveSnapshotFailure)message).metadata();
// ...
}
}
//#save-snapshot
@Override
public void onReceiveRecover(Object event) {
}
}
};
static Object o5 = new Object() {
class MyPersistentActor extends UntypedPersistentActor {
//#snapshot-criteria
@Override
public Recovery recovery() {
return Recovery.create(
SnapshotSelectionCriteria
.create(457L, System.currentTimeMillis()));
}
//#snapshot-criteria
@Override
public String persistenceId() { return "persistence-id"; }
//#snapshot-offer
private Object state;
@Override
public void onReceiveRecover(Object message) {
if (message instanceof SnapshotOffer) {
state = ((SnapshotOffer)message).snapshot();
// ...
} else if (message instanceof RecoveryCompleted) {
// ...
} else {
// ...
}
}
//#snapshot-offer
@Override
public void onReceiveCommand(Object message) {
}
}
};
static Object o9 = new Object() {
//#persist-async
class MyPersistentActor extends UntypedPersistentActor {
@Override
public String persistenceId() { return "some-persistence-id"; }
@Override
public void onReceiveRecover(Object msg) {
// handle recovery here
}
@Override
public void onReceiveCommand(Object msg) {
sender().tell(msg, self());
persistAsync(String.format("evt-%s-1", msg), new Procedure<String>(){
@Override
public void apply(String event) throws Exception {
sender().tell(event, self());
}
});
persistAsync(String.format("evt-%s-2", msg), new Procedure<String>(){
@Override
public void apply(String event) throws Exception {
sender().tell(event, self());
}
});
}
}
//#persist-async
public void usage() {
final ActorSystem system = ActorSystem.create("example");
//#persist-async-usage
final ActorRef persistentActor = system.actorOf(Props.create(MyPersistentActor.class));
persistentActor.tell("a", null);
persistentActor.tell("b", null);
// possible order of received messages:
// a
// b
// evt-a-1
// evt-a-2
// evt-b-1
// evt-b-2
//#persist-async-usage
}
};
static Object o10 = new Object() {
//#defer
class MyPersistentActor extends UntypedPersistentActor {
@Override
public String persistenceId() { return "some-persistence-id"; }
@Override
public void onReceiveRecover(Object msg) {
// handle recovery here
}
@Override
public void onReceiveCommand(Object msg) {
final Procedure<String> replyToSender = new Procedure<String>() {
@Override
public void apply(String event) throws Exception {
sender().tell(event, self());
}
};
persistAsync(String.format("evt-%s-1", msg), replyToSender);
persistAsync(String.format("evt-%s-2", msg), replyToSender);
deferAsync(String.format("evt-%s-3", msg), replyToSender);
}
}
//#defer
public void usage() {
final ActorSystem system = ActorSystem.create("example");
//#defer-caller
final ActorRef persistentActor = system.actorOf(Props.create(MyPersistentActor.class));
persistentActor.tell("a", null);
persistentActor.tell("b", null);
// order of received messages:
// a
// b
// evt-a-1
// evt-a-2
// evt-a-3
// evt-b-1
// evt-b-2
// evt-b-3
//#defer-caller
}
};
static Object o11 = new Object() {
class MyPersistentActor extends UntypedPersistentActor {
@Override
public String persistenceId() {
return "my-stable-persistence-id";
}
@Override
public void onReceiveRecover(Object msg) {
// handle recovery here
}
//#nested-persist-persist
@Override
public void onReceiveCommand(Object msg) {
final Procedure<String> replyToSender = new Procedure<String>() {
@Override
public void apply(String event) throws Exception {
sender().tell(event, self());
}
};
final Procedure<String> outer1Callback = new Procedure<String>() {
@Override
public void apply(String event) throws Exception {
sender().tell(event, self());
persist(String.format("%s-inner-1", msg), replyToSender);
}
};
final Procedure<String> outer2Callback = new Procedure<String>() {
@Override
public void apply(String event) throws Exception {
sender().tell(event, self());
persist(String.format("%s-inner-2", msg), replyToSender);
}
};
persist(String.format("%s-outer-1", msg), outer1Callback);
persist(String.format("%s-outer-2", msg), outer2Callback);
}
//#nested-persist-persist
void usage(ActorRef persistentActor) {
//#nested-persist-persist-caller
persistentActor.tell("a", self());
persistentActor.tell("b", self());
// order of received messages:
// a
// a-outer-1
// a-outer-2
// a-inner-1
// a-inner-2
// and only then process "b"
// b
// b-outer-1
// b-outer-2
// b-inner-1
// b-inner-2
//#nested-persist-persist-caller
}
}
class MyPersistAsyncActor extends UntypedPersistentActor {
@Override
public String persistenceId() {
return "my-stable-persistence-id";
}
@Override
public void onReceiveRecover(Object msg) {
// handle recovery here
}
//#nested-persistAsync-persistAsync
@Override
public void onReceiveCommand(Object msg) {
final Procedure<String> replyToSender = new Procedure<String>() {
@Override
public void apply(String event) throws Exception {
sender().tell(event, self());
}
};
final Procedure<String> outer1Callback = new Procedure<String>() {
@Override
public void apply(String event) throws Exception {
sender().tell(event, self());
persistAsync(String.format("%s-inner-1", msg), replyToSender);
}
};
final Procedure<String> outer2Callback = new Procedure<String>() {
@Override
public void apply(String event) throws Exception {
sender().tell(event, self());
persistAsync(String.format("%s-inner-1", msg), replyToSender);
}
};
persistAsync(String.format("%s-outer-1", msg), outer1Callback);
persistAsync(String.format("%s-outer-2", msg), outer2Callback);
}
//#nested-persistAsync-persistAsync
void usage(ActorRef persistentActor) {
//#nested-persistAsync-persistAsync-caller
persistentActor.tell("a", ActorRef.noSender());
persistentActor.tell("b", ActorRef.noSender());
// order of received messages:
// a
// b
// a-outer-1
// a-outer-2
// b-outer-1
// b-outer-2
// a-inner-1
// a-inner-2
// b-inner-1
// b-inner-2
// which can be seen as the following causal relationship:
// a -> a-outer-1 -> a-outer-2 -> a-inner-1 -> a-inner-2
// b -> b-outer-1 -> b-outer-2 -> b-inner-1 -> b-inner-2
//#nested-persistAsync-persistAsync-caller
}
}
};
static Object o13 = new Object() {
//#safe-shutdown
final class Shutdown {}
class MyPersistentActor extends UntypedPersistentActor {
@Override
public String persistenceId() {
return "some-persistence-id";
}
@Override
public void onReceiveCommand(Object msg) throws Exception {
if (msg instanceof Shutdown) {
context().stop(self());
} else if (msg instanceof String) {
System.out.println(msg);
persist("handle-" + msg, new Procedure<String>() {
@Override
public void apply(String param) throws Exception {
System.out.println(param);
}
});
} else unhandled(msg);
}
@Override
public void onReceiveRecover(Object msg) throws Exception {
// handle recovery...
}
}
//#safe-shutdown
public void usage() {
final ActorSystem system = ActorSystem.create("example");
final ActorRef persistentActor = system.actorOf(Props.create(MyPersistentActor.class));
//#safe-shutdown-example-bad
// UN-SAFE, due to PersistentActor's command stashing:
persistentActor.tell("a", ActorRef.noSender());
persistentActor.tell("b", ActorRef.noSender());
persistentActor.tell(PoisonPill.getInstance(), ActorRef.noSender());
// order of received messages:
// a
// # b arrives at mailbox, stashing; internal-stash = [b]
// # PoisonPill arrives at mailbox, stashing; internal-stash = [b, Shutdown]
// PoisonPill is an AutoReceivedMessage, is handled automatically
// !! stop !!
// Actor is stopped without handling `b` nor the `a` handler!
//#safe-shutdown-example-bad
//#safe-shutdown-example-good
// SAFE:
persistentActor.tell("a", ActorRef.noSender());
persistentActor.tell("b", ActorRef.noSender());
persistentActor.tell(new Shutdown(), ActorRef.noSender());
// order of received messages:
// a
// # b arrives at mailbox, stashing; internal-stash = [b]
// # Shutdown arrives at mailbox, stashing; internal-stash = [b, Shutdown]
// handle-a
// # unstashing; internal-stash = [Shutdown]
// b
// handle-b
// # unstashing; internal-stash = []
// Shutdown
// -- stop --
//#safe-shutdown-example-good
}
};
}

View file

@ -1,193 +0,0 @@
/**
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.persistence;
import akka.actor.*;
import akka.dispatch.Futures;
import akka.persistence.japi.journal.JavaJournalSpec;
import akka.persistence.japi.snapshot.JavaSnapshotStoreSpec;
import akka.persistence.journal.leveldb.SharedLeveldbJournal;
import akka.persistence.journal.leveldb.SharedLeveldbStore;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import org.iq80.leveldb.util.FileUtils;
import scala.concurrent.Future;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
//#plugin-imports
import akka.persistence.*;
import akka.persistence.journal.japi.AsyncWriteJournal;
import akka.persistence.snapshot.japi.SnapshotStore;
//#plugin-imports
public class PersistencePluginDocTest {
static Object o1 = new Object() {
final ActorSystem system = null;
//#shared-store-creation
final ActorRef store = system.actorOf(Props.create(SharedLeveldbStore.class), "store");
//#shared-store-creation
//#shared-store-usage
class SharedStorageUsage extends UntypedActor {
@Override
public void preStart() throws Exception {
String path = "akka.tcp://example@127.0.0.1:2552/user/store";
ActorSelection selection = getContext().actorSelection(path);
selection.tell(new Identify(1), getSelf());
}
@Override
public void onReceive(Object message) throws Exception {
if (message instanceof ActorIdentity) {
ActorIdentity identity = (ActorIdentity) message;
if (identity.correlationId().equals(1)) {
ActorRef store = identity.getRef();
if (store != null) {
SharedLeveldbJournal.setStore(store, getContext().system());
}
}
}
}
}
//#shared-store-usage
};
class MySnapshotStore extends SnapshotStore {
@Override
public Future<Optional<SelectedSnapshot>> doLoadAsync(String persistenceId, SnapshotSelectionCriteria criteria) {
return null;
}
@Override
public Future<Void> doSaveAsync(SnapshotMetadata metadata, Object snapshot) {
return null;
}
@Override
public Future<Void> doDeleteAsync(SnapshotMetadata metadata) {
return Futures.successful(null);
}
@Override
public Future<Void> doDeleteAsync(String persistenceId, SnapshotSelectionCriteria criteria) {
return Futures.successful(null);
}
}
class MyAsyncJournal extends AsyncWriteJournal {
//#sync-journal-plugin-api
@Override
public Future<Iterable<Optional<Exception>>> doAsyncWriteMessages(
Iterable<AtomicWrite> messages) {
try {
Iterable<Optional<Exception>> result = new ArrayList<Optional<Exception>>();
// blocking call here...
// result.add(..)
return Futures.successful(result);
} catch (Exception e) {
return Futures.failed(e);
}
}
//#sync-journal-plugin-api
@Override
public Future<Void> doAsyncDeleteMessagesTo(String persistenceId, long toSequenceNr) {
return null;
}
@Override
public Future<Void> doAsyncReplayMessages(String persistenceId, long fromSequenceNr,
long toSequenceNr, long max, Consumer<PersistentRepr> replayCallback) {
return null;
}
@Override
public Future<Long> doAsyncReadHighestSequenceNr(String persistenceId, long fromSequenceNr) {
return null;
}
}
static Object o2 = new Object() {
//#journal-tck-java
class MyJournalSpecTest extends JavaJournalSpec {
public MyJournalSpecTest() {
super(ConfigFactory.parseString(
"persistence.journal.plugin = " +
"\"akka.persistence.journal.leveldb-shared\""));
}
@Override
public CapabilityFlag supportsRejectingNonSerializableObjects() {
return CapabilityFlag.off();
}
}
//#journal-tck-java
};
static Object o3 = new Object() {
//#snapshot-store-tck-java
class MySnapshotStoreTest extends JavaSnapshotStoreSpec {
public MySnapshotStoreTest() {
super(ConfigFactory.parseString(
"akka.persistence.snapshot-store.plugin = " +
"\"akka.persistence.snapshot-store.local\""));
}
}
//#snapshot-store-tck-java
};
static Object o4 = new Object() {
//#journal-tck-before-after-java
class MyJournalSpecTest extends JavaJournalSpec {
List<File> storageLocations = new ArrayList<File>();
public MyJournalSpecTest() {
super(ConfigFactory.parseString(
"persistence.journal.plugin = " +
"\"akka.persistence.journal.leveldb-shared\""));
Config config = system().settings().config();
storageLocations.add(new File(
config.getString("akka.persistence.journal.leveldb.dir")));
storageLocations.add(new File(
config.getString("akka.persistence.snapshot-store.local.dir")));
}
@Override
public CapabilityFlag supportsRejectingNonSerializableObjects() {
return CapabilityFlag.on();
}
@Override
public void beforeAll() {
for (File storageLocation : storageLocations) {
FileUtils.deleteRecursively(storageLocation);
}
super.beforeAll();
}
@Override
public void afterAll() {
super.afterAll();
for (File storageLocation : storageLocations) {
FileUtils.deleteRecursively(storageLocation);
}
}
}
//#journal-tck-before-after-java
};
}

View file

@ -451,15 +451,20 @@ public class PersistenceQueryDocTest {
public TheOneWhoWritesToQueryJournal() {
store = new ExampleStore();
receive(ReceiveBuilder.matchAny(message -> {
state = updateState(state, message);
// example saving logic that requires state to become ready:
if (state.readyToSave())
store.save(Record.of(state));
}).build());
}
@Override
public Receive createReceive() {
return receiveBuilder()
.matchAny(message -> {
state = updateState(state, message);
// example saving logic that requires state to become ready:
if (state.readyToSave())
store.save(Record.of(state));
})
.build();
}

View file

@ -33,7 +33,7 @@ import static java.util.stream.Collectors.toList;
//#events-by-tag-publisher
class MyEventsByTagJavaPublisher extends AbstractActorPublisher<EventEnvelope> {
private final Serialization serialization =
SerializationExtension.get(context().system());
SerializationExtension.get(getContext().system());
private final Connection connection;
@ -54,20 +54,23 @@ class MyEventsByTagJavaPublisher extends AbstractActorPublisher<EventEnvelope> {
this.tag = tag;
this.currentOffset = offset;
final Scheduler scheduler = context().system().scheduler();
final Scheduler scheduler = getContext().system().scheduler();
this.continueTask = scheduler
.schedule(refreshInterval, refreshInterval, self(), CONTINUE,
context().dispatcher(), self());
receive(ReceiveBuilder
.matchEquals(CONTINUE, (in) -> {
query();
deliverBuf();
})
.match(Cancel.class, (in) -> {
context().stop(self());
getContext().dispatcher(), self());
}
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals(CONTINUE, (in) -> {
query();
deliverBuf();
})
.build());
.match(Cancel.class, (in) -> {
getContext().stop(self());
})
.build();
}
public static Props props(Connection conn, String tag, Long offset,

View file

@ -25,7 +25,7 @@ public class RemoteDeploymentDocTest {
public static class SampleActor extends UntypedActor {
public void onReceive(Object message) {
getSender().tell(getSelf(), getSelf());
sender().tell(self(), self());
}
}

View file

@ -67,6 +67,7 @@ public class ActorPublisherDocTest extends AbstractJavaTest {
}
public static final JobDeniedMessage JobDenied = new JobDeniedMessage();
}
public static class JobManager extends AbstractActorPublisher<JobManagerProtocol.Job> {
public static Props props() { return Props.create(JobManager.class); }
@ -74,12 +75,13 @@ public class ActorPublisherDocTest extends AbstractJavaTest {
private final int MAX_BUFFER_SIZE = 100;
private final List<JobManagerProtocol.Job> buf = new ArrayList<>();
public JobManager() {
receive(ReceiveBuilder.
match(JobManagerProtocol.Job.class, job -> buf.size() == MAX_BUFFER_SIZE, job -> {
@Override
public Receive createReceive() {
return receiveBuilder()
.match(JobManagerProtocol.Job.class, job -> buf.size() == MAX_BUFFER_SIZE, job -> {
sender().tell(JobManagerProtocol.JobDenied, self());
}).
match(JobManagerProtocol.Job.class, job -> {
})
.match(JobManagerProtocol.Job.class, job -> {
sender().tell(JobManagerProtocol.JobAccepted, self());
if (buf.isEmpty() && totalDemand() > 0)
@ -88,10 +90,10 @@ public class ActorPublisherDocTest extends AbstractJavaTest {
buf.add(job);
deliverBuf();
}
}).
match(ActorPublisherMessage.Request.class, request -> deliverBuf()).
match(ActorPublisherMessage.Cancel.class, cancel -> context().stop(self())).
build());
})
.match(ActorPublisherMessage.Request.class, request -> deliverBuf())
.match(ActorPublisherMessage.Cancel.class, cancel -> getContext().stop(self()))
.build();
}
void deliverBuf() {

View file

@ -161,44 +161,49 @@ public class ActorSubscriberDocTest extends AbstractJavaTest {
public WorkerPool() {
final List<Routee> routees = new ArrayList<>();
for (int i = 0; i < 3; i++)
routees.add(new ActorRefRoutee(context().actorOf(Props.create(Worker.class))));
routees.add(new ActorRefRoutee(getContext().actorOf(Props.create(Worker.class))));
router = new Router(new RoundRobinRoutingLogic(), routees);
receive(ReceiveBuilder.
match(ActorSubscriberMessage.OnNext.class, on -> on.element() instanceof WorkerPoolProtocol.Msg,
onNext -> {
WorkerPoolProtocol.Msg msg = (WorkerPoolProtocol.Msg) onNext.element();
queue.put(msg.id, msg.replyTo);
if (queue.size() > MAX_QUEUE_SIZE)
throw new RuntimeException("queued too many: " + queue.size());
router.route(WorkerPoolProtocol.work(msg.id), self());
}).
match(ActorSubscriberMessage.onCompleteInstance().getClass(), complete -> {
if (queue.isEmpty()) {
context().stop(self());
}
}).
match(WorkerPoolProtocol.Reply.class, reply -> {
int id = reply.id;
queue.get(id).tell(WorkerPoolProtocol.done(id), self());
queue.remove(id);
if (canceled() && queue.isEmpty()) {
context().stop(self());
}
}).
build());
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(ActorSubscriberMessage.OnNext.class, on -> on.element() instanceof WorkerPoolProtocol.Msg,
onNext -> {
WorkerPoolProtocol.Msg msg = (WorkerPoolProtocol.Msg) onNext.element();
queue.put(msg.id, msg.replyTo);
if (queue.size() > MAX_QUEUE_SIZE)
throw new RuntimeException("queued too many: " + queue.size());
router.route(WorkerPoolProtocol.work(msg.id), self());
})
.match(ActorSubscriberMessage.onCompleteInstance().getClass(), complete -> {
if (queue.isEmpty()) {
getContext().stop(self());
}
})
.match(WorkerPoolProtocol.Reply.class, reply -> {
int id = reply.id;
queue.get(id).tell(WorkerPoolProtocol.done(id), self());
queue.remove(id);
if (canceled() && queue.isEmpty()) {
getContext().stop(self());
}
})
.build();
}
}
static class Worker extends AbstractActor {
public Worker() {
receive(ReceiveBuilder.
match(WorkerPoolProtocol.Work.class, work -> {
@Override
public Receive createReceive() {
return receiveBuilder()
.match(WorkerPoolProtocol.Work.class, work -> {
// ...
sender().tell(WorkerPoolProtocol.reply(work.id), self());
}).build());
})
.build();
}
}
//#worker-pool

View file

@ -255,13 +255,18 @@ public class IntegrationDocTest extends AbstractJavaTest {
static class DatabaseService extends AbstractActor {
public final ActorRef probe;
DatabaseService(ActorRef probe) {
public DatabaseService(ActorRef probe) {
this.probe = probe;
receive(ReceiveBuilder.match(Save.class, s -> {
probe.tell(s.tweet.author.handle, ActorRef.noSender());
sender().tell(SaveDone.INSTANCE, self());
}).build());
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Save.class, s -> {
probe.tell(s.tweet.author.handle, ActorRef.noSender());
sender().tell(SaveDone.INSTANCE, self());
})
.build();
}
}
@ -298,7 +303,7 @@ public class IntegrationDocTest extends AbstractJavaTest {
// ... process message
String reply = word.toUpperCase();
// reply to the ask
getSender().tell(reply, getSelf());
sender().tell(reply, self());
} else {
unhandled(message);
}

View file

@ -49,7 +49,7 @@ public class TwitterStreamQuickstartDocTest extends AbstractJavaTest {
@BeforeClass
public static void setup() {
system = ActorSystem.create("SampleActorTest");
system = ActorSystem.create("TwitterStreamQuickstartDocTest");
mat = ActorMaterializer.create(system);
}

View file

@ -87,14 +87,17 @@ public class RecipeGlobalRateLimit extends RecipeTest {
this.tokenRefreshPeriod,
self(),
REPLENISH_TOKENS,
context().system().dispatcher(),
getContext().system().dispatcher(),
self());
receive(open());
}
@Override
public Receive createReceive() {
return open();
}
PartialFunction<Object, BoxedUnit> open() {
return ReceiveBuilder
private Receive open() {
return receiveBuilder()
.match(ReplenishTokens.class, rt -> {
permitTokens = Math.min(permitTokens + tokenRefreshAmount, maxAvailableTokens);
})
@ -102,13 +105,14 @@ public class RecipeGlobalRateLimit extends RecipeTest {
permitTokens -= 1;
sender().tell(MAY_PASS, self());
if (permitTokens == 0) {
context().become(closed());
getContext().become(closed());
}
}).build();
})
.build();
}
PartialFunction<Object, BoxedUnit> closed() {
return ReceiveBuilder
private Receive closed() {
return receiveBuilder()
.match(ReplenishTokens.class, rt -> {
permitTokens = Math.min(permitTokens + tokenRefreshAmount, maxAvailableTokens);
releaseWaiting();
@ -128,7 +132,7 @@ public class RecipeGlobalRateLimit extends RecipeTest {
permitTokens -= toBeReleased.size();
toBeReleased.stream().forEach(ref -> ref.tell(MAY_PASS, self()));
if (permitTokens > 0) {
context().become(open());
getContext().become(open());
}
}

View file

@ -28,7 +28,7 @@ public class ParentChildTest {
//#test-example
static class Parent extends UntypedActor {
final ActorRef child = context().actorOf(Props.create(Child.class), "child");
final ActorRef child = getContext().actorOf(Props.create(Child.class), "child");
boolean ponged = false;
@Override public void onReceive(Object message) throws Exception {
@ -45,7 +45,7 @@ public class ParentChildTest {
static class Child extends UntypedActor {
@Override public void onReceive(Object message) throws Exception {
if ("ping".equals(message)) {
context().parent().tell("pong", self());
getContext().parent().tell("pong", self());
} else {
unhandled(message);
}
@ -79,7 +79,7 @@ public class ParentChildTest {
boolean ponged = false;
public DependentParent(Props childProps) {
child = context().actorOf(childProps, "child");
child = getContext().actorOf(childProps, "child");
}
@Override public void onReceive(Object message) throws Exception {
@ -102,7 +102,7 @@ public class ParentChildTest {
public GenericDependentParent(Function<ActorRefFactory, ActorRef> childMaker)
throws Exception {
child = childMaker.apply(context());
child = childMaker.apply(getContext());
}
@Override public void onReceive(Object message) throws Exception {
@ -175,13 +175,13 @@ public class ParentChildTest {
@Override public Actor create() throws Exception {
return new UntypedActor() {
final ActorRef child = context().actorOf(Props.create(Child.class), "child");
final ActorRef child = getContext().actorOf(Props.create(Child.class), "child");
@Override public void onReceive(Object x) throws Exception {
if (sender().equals(child)) {
proxy.ref().forward(x, context());
proxy.ref().forward(x, getContext());
} else {
child.forward(x, context());
child.forward(x, getContext());
}
}
};

View file

@ -37,7 +37,7 @@ public class TestKitDocTest {
static class MyActor extends UntypedActor {
public void onReceive(Object o) throws Exception {
if (o.equals("say42")) {
getSender().tell(42, getSelf());
sender().tell(42, self());
} else if (o instanceof Exception) {
throw (Exception) o;
}

View file

@ -24,12 +24,12 @@ public class TestKitSampleTest {
public void onReceive(Object msg) {
if (msg.equals("hello")) {
getSender().tell("world", getSelf());
sender().tell("world", self());
if (target != null) target.forward(msg, getContext());
} else if (msg instanceof ActorRef) {
target = (ActorRef) msg;
getSender().tell("done", getSelf());
sender().tell("done", self());
}
}
}