parent
67a9e62254
commit
0953e7aee3
41 changed files with 156 additions and 368 deletions
179
akka-docs/rst/java/code/docs/actorlambda/fsm/FSMDocTest.java
Normal file
179
akka-docs/rst/java/code/docs/actorlambda/fsm/FSMDocTest.java
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package docs.actorlambda.fsm;
|
||||
|
||||
import akka.actor.*;
|
||||
import akka.testkit.JavaTestKit;
|
||||
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.actorlambda.fsm.FSMDocTest.StateType.*;
|
||||
import static docs.actorlambda.fsm.FSMDocTest.Messages.*;
|
||||
import static java.util.concurrent.TimeUnit.*;
|
||||
|
||||
public class FSMDocTest {
|
||||
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);
|
||||
assertTrue(msg.startsWith("LogEntry(SomeState,Foo,Actor[akka://FSMDocTest/system/"));
|
||||
}};
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue