diff --git a/spring-statemachine-samples/cdplayer/src/main/java/demo/cdplayer/Application.java b/spring-statemachine-samples/cdplayer/src/main/java/demo/cdplayer/Application.java index 012e354b..2f8ef71d 100644 --- a/spring-statemachine-samples/cdplayer/src/main/java/demo/cdplayer/Application.java +++ b/spring-statemachine-samples/cdplayer/src/main/java/demo/cdplayer/Application.java @@ -1,11 +1,17 @@ package demo.cdplayer; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.shell.Bootstrap; import org.springframework.statemachine.ExtendedState; import org.springframework.statemachine.StateContext; import org.springframework.statemachine.action.Action; +import org.springframework.statemachine.annotation.OnTransition; import org.springframework.statemachine.config.EnableStateMachine; import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter; import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; @@ -32,7 +38,7 @@ public class Application { .withStates() .parent(States.IDLE) .initial(States.CLOSED) - .state(States.CLOSED) + .state(States.CLOSED, closedEntryAction(), null) .state(States.OPEN) .and() .withStates() @@ -56,6 +62,9 @@ public class Application { .withExternal() .source(States.OPEN).target(States.CLOSED).event(Events.EJECT) .and() + .withExternal() + .source(States.OPEN).target(States.CLOSED).event(Events.PLAY) + .and() .withExternal() .source(States.PLAYING).target(States.PAUSED).event(Events.PAUSE) .and() @@ -78,6 +87,19 @@ public class Application { .source(States.OPEN).event(Events.LOAD).action(loadAction()); } + @Bean + public Action closedEntryAction() { + return new Action() { + @Override + public void execute(StateContext context) { + if (context.getTransition() != null && context.getTransition().getSource().getId() == States.CLOSED + && context.getMessageHeader(Variables.CD) != null) { + context.getStateMachine().sendEvent(Events.PLAY); + } + } + }; + } + @Bean public Action loadAction() { return new Action() { @@ -151,6 +173,19 @@ public class Application { } //end::snippetE[] +//tag::snippetF[] + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @OnTransition + public static @interface StatesOnTransition { + + States[] source() default {}; + + States[] target() default {}; + + } +//end::snippetF[] + public static void main(String[] args) throws Exception { Bootstrap.main(args); } diff --git a/spring-statemachine-samples/cdplayer/src/main/java/demo/cdplayer/CdPlayer.java b/spring-statemachine-samples/cdplayer/src/main/java/demo/cdplayer/CdPlayer.java index c5b614c2..cff73519 100644 --- a/spring-statemachine-samples/cdplayer/src/main/java/demo/cdplayer/CdPlayer.java +++ b/spring-statemachine-samples/cdplayer/src/main/java/demo/cdplayer/CdPlayer.java @@ -12,6 +12,7 @@ import org.springframework.statemachine.annotation.WithStateMachine; import demo.cdplayer.Application.Events; import demo.cdplayer.Application.States; +import demo.cdplayer.Application.StatesOnTransition; import demo.cdplayer.Application.Variables; @WithStateMachine @@ -63,9 +64,8 @@ public class CdPlayer { } } - @OnTransition(target = "PLAYING") + @StatesOnTransition(target = States.PLAYING) public void playing(ExtendedState extendedState) { - System.out.println("playing1"); Object object = extendedState.getVariables().get(Variables.ELAPSEDTIME); if (object instanceof Long) { long elapsed = ((Long)object) + 1000l; diff --git a/spring-statemachine-samples/cdplayer/src/main/java/demo/cdplayer/CdPlayerCommands.java b/spring-statemachine-samples/cdplayer/src/main/java/demo/cdplayer/CdPlayerCommands.java index 532af4eb..e577f2fc 100644 --- a/spring-statemachine-samples/cdplayer/src/main/java/demo/cdplayer/CdPlayerCommands.java +++ b/spring-statemachine-samples/cdplayer/src/main/java/demo/cdplayer/CdPlayerCommands.java @@ -34,10 +34,11 @@ public class CdPlayerCommands implements CommandMarker { public String load(@CliOption(key = {"", "index"}) int index) { StringBuilder buf = new StringBuilder(); try { - cdPlayer.load(library.getCollection().get(index)); - buf.append("Loading cd " + index); + Cd cd = library.getCollection().get(index); + cdPlayer.load(cd); + buf.append("Loading cd " + cd.getName()); } catch (Exception e) { - buf.append("Cd with index " + index + " not found"); + buf.append("Cd with index " + index + " not found, check library"); } return buf.toString(); } diff --git a/spring-statemachine-samples/cdplayer/src/main/resources/statechartmodel.txt b/spring-statemachine-samples/cdplayer/src/main/resources/statechartmodel.txt index 82d2fb61..e696b08c 100644 --- a/spring-statemachine-samples/cdplayer/src/main/resources/statechartmodel.txt +++ b/spring-statemachine-samples/cdplayer/src/main/resources/statechartmodel.txt @@ -11,30 +11,30 @@ | | *-->| PLAYING | | | *-->| CLOSED | | | | | +------------+ | STOP | +------------+ | | | | | entry/ | |---------->| | entry/ | | | -| | | exit/ | | | | exit/ | | | -| | | | | | | | | | -| | | +--| | | | | | | -| | | | | | | | | | | -| | | timer/1s| | | | | | | | -| | | | | | | | | | | -| | | +->| | | | | | | -| | | | | | | | | | -| | +--| |<-+ | | +--| |<-+ | | -| | | +------------+ | | | | +------------+ | | | -| | | | | PLAY | | | | | -| | |PAUSE | |<----------| |EJECT | | | -| | | | | | | | | | -| | | PAUSE| | | | EJECT| | | -| | | | | | | | | | -| | | +------------+ | | | | +------------+ | | | -| | | | PAUSED | | | | | | OPEN | | | | -| | | +------------+ | | | | +------------+ | | | -| | | | entry/ | | | | | | entry/ | | | | -| | +->| exit/ |--+ | | +->| exit/ |--+ | | -| | | | | | | | | | -| | | | | | | +--| | | -| | | | | | | | | | | -| | | | | | | LOAD| | | | +| | | exit/ | | | PLAY | exit/ | | | +| | | | | | +---->| | | | +| | | +--| | | | | | | | +| | | | | | | | | | | | +| | | timer/1s| | | | | | | | | +| | | | | | | | | | | | +| | | +->| | | | | | | | +| | | | | | | | | | | +| | +--| |<-+ | | | +--| |<-+ | | +| | | +------------+ | | | | | +------------+ | | | +| | | | | PLAY | | | | | | +| | |PAUSE | |<----------| | |EJECT | | | +| | | | | | | | | | | +| | | PAUSE| | | | | EJECT| | | +| | | | | | | | | | | +| | | +------------+ | | | | | +------------+ | | | +| | | | PAUSED | | | | | | | OPEN | | | | +| | | +------------+ | | | | | +------------+ | | | +| | | | entry/ | | | | | | | entry/ | | | | +| | +->| exit/ |--+ | | | +->| exit/ |--+ | | +| | | | | | | | | | | +| | | | | | | | +--| | | +| | | | | | | | | | | | +| | | | | | +-----| LOAD| | | | | | | | | | | | | | | | | | | | | | +->| | | | | | | | | | | | | diff --git a/spring-statemachine-samples/cdplayer/src/test/java/demo/cdplayer/CdPlayerTests.java b/spring-statemachine-samples/cdplayer/src/test/java/demo/cdplayer/CdPlayerTests.java index 100dfb7c..f02bbe4b 100644 --- a/spring-statemachine-samples/cdplayer/src/test/java/demo/cdplayer/CdPlayerTests.java +++ b/spring-statemachine-samples/cdplayer/src/test/java/demo/cdplayer/CdPlayerTests.java @@ -1,9 +1,9 @@ package demo.cdplayer; -import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertThat; import org.junit.After; @@ -36,19 +36,22 @@ public class CdPlayerTests { } @Test - public void testEjectTwice() { + public void testEjectTwice() throws Exception { player.eject(); + Thread.sleep(100); assertThat(machine.getState().getIds(), contains(States.IDLE, States.OPEN)); player.eject(); + Thread.sleep(100); assertThat(machine.getState().getIds(), contains(States.IDLE, States.CLOSED)); } @Test - public void testPlayWithCdLoaded() { + public void testPlayWithCdLoaded() throws Exception { player.eject(); player.load(library.getCollection().get(0)); player.eject(); player.play(); + Thread.sleep(100); assertThat(machine.getState().getIds(), contains(States.BUSY, States.PLAYING)); assertLcdStatusContains("cd1"); } @@ -82,6 +85,7 @@ public class CdPlayerTests { player.load(library.getCollection().get(0)); player.eject(); player.play(); + Thread.sleep(100); assertThat(machine.getState().getIds(), contains(States.BUSY, States.PLAYING)); assertLcdStatusContains("cd1"); Thread.sleep(1000); @@ -103,11 +107,20 @@ public class CdPlayerTests { player.load(library.getCollection().get(0)); player.eject(); player.play(); + Thread.sleep(100); assertThat(machine.getState().getIds(), contains(States.BUSY, States.PLAYING)); player.stop(); + Thread.sleep(100); assertLcdStatusIs("cd1 "); } + @Test + public void testPlayDeckOpenNoCd() throws Exception { + player.eject(); + player.play(); + assertThat(machine.getState().getIds(), contains(States.IDLE, States.CLOSED)); + } + private void assertLcdStatusIs(String text) { assertThat(player.getLdcStatus(), is(text)); } @@ -134,6 +147,7 @@ public class CdPlayerTests { @After public void clean() { + machine.stop(); context.close(); context = null; machine = null; diff --git a/spring-statemachine-samples/src/main/java/demo/CommonConfiguration.java b/spring-statemachine-samples/src/main/java/demo/CommonConfiguration.java index f4a1ec17..42fc59d7 100644 --- a/spring-statemachine-samples/src/main/java/demo/CommonConfiguration.java +++ b/spring-statemachine-samples/src/main/java/demo/CommonConfiguration.java @@ -15,8 +15,8 @@ import org.springframework.core.task.SyncTaskExecutor; import org.springframework.core.task.TaskExecutor; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler; -import org.springframework.statemachine.event.OnStateChangedEvent; -import org.springframework.statemachine.event.OnTransitionEvent; +import org.springframework.statemachine.event.OnStateEntryEvent; +import org.springframework.statemachine.event.OnStateExitEvent; import org.springframework.statemachine.event.StateMachineEvent; import org.springframework.statemachine.event.StateMachineEventPublisherConfiguration; @@ -60,12 +60,12 @@ public class CommonConfiguration { @Override public void onApplicationEvent(StateMachineEvent event) { - if (event instanceof OnStateChangedEvent) { - OnStateChangedEvent e = (OnStateChangedEvent)event; - log.info("State changed to " + e.getTargetState().getId()); - } else if (event instanceof OnTransitionEvent) { - OnTransitionEvent e = (OnTransitionEvent)event; - log.info("Transition " + e.getTransition().toString()); + if (event instanceof OnStateEntryEvent) { + OnStateEntryEvent e = (OnStateEntryEvent)event; + log.info("Entry state " + e.getState().getId()); + } else if (event instanceof OnStateExitEvent) { + OnStateExitEvent e = (OnStateExitEvent)event; + log.info("Exit state " + e.getState().getId()); } }