diff --git a/pom.xml b/pom.xml index 15e0e3322e..7c1cacbd33 100644 --- a/pom.xml +++ b/pom.xml @@ -188,6 +188,7 @@ spring-sleuth spring-social-login spring-spel + spring-state-machine spring-thymeleaf spring-userservice spring-zuul @@ -210,7 +211,9 @@ rabbitmq vertx - + + + diff --git a/spring-state-machine/bpmn/forkjoin.bpmn b/spring-state-machine/bpmn/forkjoin.bpmn new file mode 100644 index 0000000000..0cb060f74b --- /dev/null +++ b/spring-state-machine/bpmn/forkjoin.bpmn @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-state-machine/bpmn/img/forkjoin.png b/spring-state-machine/bpmn/img/forkjoin.png new file mode 100644 index 0000000000..642ab6949d Binary files /dev/null and b/spring-state-machine/bpmn/img/forkjoin.png differ diff --git a/spring-state-machine/bpmn/img/simple.png b/spring-state-machine/bpmn/img/simple.png new file mode 100644 index 0000000000..7a79bf1d89 Binary files /dev/null and b/spring-state-machine/bpmn/img/simple.png differ diff --git a/spring-state-machine/bpmn/simple.bpmn b/spring-state-machine/bpmn/simple.bpmn new file mode 100644 index 0000000000..8ed463e9f9 --- /dev/null +++ b/spring-state-machine/bpmn/simple.bpmn @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-state-machine/pom.xml b/spring-state-machine/pom.xml new file mode 100644 index 0000000000..5393626083 --- /dev/null +++ b/spring-state-machine/pom.xml @@ -0,0 +1,31 @@ + + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + 4.0.0 + + baeldung-spring-state-machine + + 1.8 + 1.8 + + + + + org.springframework.statemachine + spring-statemachine-core + 1.2.3.RELEASE + + + junit + junit + 4.11 + test + + + \ No newline at end of file diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/applicationreview/ApplicationReviewEvents.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/applicationreview/ApplicationReviewEvents.java new file mode 100644 index 0000000000..971fc5dde7 --- /dev/null +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/applicationreview/ApplicationReviewEvents.java @@ -0,0 +1,5 @@ +package com.baeldung.spring.stateMachine.applicationReview; + +public enum ApplicationReviewEvents { + APPROVE, REJECT +} diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/applicationreview/ApplicationReviewStates.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/applicationreview/ApplicationReviewStates.java new file mode 100644 index 0000000000..1df2db1f86 --- /dev/null +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/applicationreview/ApplicationReviewStates.java @@ -0,0 +1,5 @@ +package com.baeldung.spring.stateMachine.applicationReview; + +public enum ApplicationReviewStates { + PEER_REVIEW, PRINCIPAL_REVIEW, APPROVED, REJECTED +} diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/ForkJoinStateMachineConfiguration.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/ForkJoinStateMachineConfiguration.java new file mode 100644 index 0000000000..c55104a627 --- /dev/null +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/ForkJoinStateMachineConfiguration.java @@ -0,0 +1,74 @@ +package com.baeldung.spring.stateMachine.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.statemachine.config.EnableStateMachine; +import org.springframework.statemachine.config.StateMachineConfigurerAdapter; +import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer; +import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; +import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; +import org.springframework.statemachine.guard.Guard; + +@Configuration +@EnableStateMachine +public class ForkJoinStateMachineConfiguration extends StateMachineConfigurerAdapter { + + @Override + public void configure(StateMachineConfigurationConfigurer config) + throws Exception { + config + .withConfiguration() + .autoStartup(true) + .listener(new StateMachineListener()); + } + + @Override + public void configure(StateMachineStateConfigurer states) throws Exception { + states + .withStates() + .initial("SI") + .fork("SFork") + .join("SJoin") + .end("SF") + .and() + .withStates() + .parent("SFork") + .initial("Sub1-1") + .end("Sub1-2") + .and() + .withStates() + .parent("SFork") + .initial("Sub2-1") + .end("Sub2-2"); + } + + @Override + public void configure(StateMachineTransitionConfigurer transitions) throws Exception { + transitions.withExternal() + .source("SI").target("SFork").event("E1") + .and().withExternal() + .source("Sub1-1").target("Sub1-2").event("sub1") + .and().withExternal() + .source("Sub2-1").target("Sub2-2").event("sub2") + .and() + .withFork() + .source("SFork") + .target("Sub1-1") + .target("Sub2-1") + .and() + .withJoin() + .source("Sub1-2") + .source("Sub2-2") + .target("SJoin"); + } + + @Bean + public Guard mediumGuard() { + return (ctx) -> false; + } + + @Bean + public Guard highGuard() { + return (ctx) -> false; + } +} \ No newline at end of file diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/HierarchicalStateMachineConfiguration.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/HierarchicalStateMachineConfiguration.java new file mode 100644 index 0000000000..708dbd3077 --- /dev/null +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/HierarchicalStateMachineConfiguration.java @@ -0,0 +1,47 @@ +package com.baeldung.spring.stateMachine.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.statemachine.config.EnableStateMachine; +import org.springframework.statemachine.config.StateMachineConfigurerAdapter; +import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer; +import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; +import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; + +@Configuration +@EnableStateMachine +public class HierarchicalStateMachineConfiguration extends StateMachineConfigurerAdapter { + + @Override + public void configure(StateMachineConfigurationConfigurer config) + throws Exception { + config + .withConfiguration() + .autoStartup(true) + .listener(new StateMachineListener()); + } + + @Override + public void configure(StateMachineStateConfigurer states) throws Exception { + states + .withStates() + .initial("SI") + .state("SI") + .end("SF") + .and() + .withStates() + .parent("SI") + .initial("SUB1") + .state("SUB2") + .end("SUBEND"); + } + + @Override + public void configure(StateMachineTransitionConfigurer transitions) throws Exception { + transitions.withExternal() + .source("SI").target("SF").event("end") + .and().withExternal() + .source("SUB1").target("SUB2").event("se1") + .and().withExternal() + .source("SUB2").target("SUBEND").event("s-end"); + } +} \ No newline at end of file diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/JunctionStateMachineConfiguration.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/JunctionStateMachineConfiguration.java new file mode 100644 index 0000000000..e1bae10fb7 --- /dev/null +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/JunctionStateMachineConfiguration.java @@ -0,0 +1,60 @@ +package com.baeldung.spring.stateMachine.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.statemachine.config.EnableStateMachine; +import org.springframework.statemachine.config.StateMachineConfigurerAdapter; +import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer; +import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; +import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; +import org.springframework.statemachine.guard.Guard; + +@Configuration +@EnableStateMachine +public class JunctionStateMachineConfiguration extends StateMachineConfigurerAdapter { + + @Override + public void configure(StateMachineConfigurationConfigurer config) + throws Exception { + config + .withConfiguration() + .autoStartup(true) + .listener(new StateMachineListener()); + } + + @Override + public void configure(StateMachineStateConfigurer states) throws Exception { + states + .withStates() + .initial("SI") + .junction("SJ") + .state("high") + .state("medium") + .state("low") + .end("SF"); + } + + @Override + public void configure(StateMachineTransitionConfigurer transitions) throws Exception { + transitions.withExternal() + .source("SI").target("SJ").event("E1") + .and() + .withJunction() + .source("SJ") + .first("high", highGuard()) + .then("medium", mediumGuard()) + .last("low") + .and().withExternal() + .source("low").target("SF").event("end"); + } + + @Bean + public Guard mediumGuard() { + return (ctx) -> false; + } + + @Bean + public Guard highGuard() { + return (ctx) -> false; + } +} \ No newline at end of file diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleEnumStateMachineConfiguration.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleEnumStateMachineConfiguration.java new file mode 100644 index 0000000000..4e11851644 --- /dev/null +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleEnumStateMachineConfiguration.java @@ -0,0 +1,53 @@ +package com.baeldung.spring.stateMachine.config; + +import com.baeldung.spring.stateMachine.applicationReview.ApplicationReviewEvents; +import com.baeldung.spring.stateMachine.applicationReview.ApplicationReviewStates; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.statemachine.action.Action; +import org.springframework.statemachine.config.EnableStateMachine; +import org.springframework.statemachine.config.StateMachineConfigurerAdapter; +import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer; +import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; +import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; +import org.springframework.statemachine.guard.Guard; + +import java.util.Arrays; +import java.util.HashSet; + +@Configuration +@EnableStateMachine +public class SimpleEnumStateMachineConfiguration extends StateMachineConfigurerAdapter { + + @Override + public void configure(StateMachineConfigurationConfigurer config) + throws Exception { + config + .withConfiguration() + .autoStartup(true) + .listener(new StateMachineListener()); + } + + @Override + public void configure(StateMachineStateConfigurer states) throws Exception { + states + .withStates() + .initial(ApplicationReviewStates.PEER_REVIEW) + .state(ApplicationReviewStates.PRINCIPAL_REVIEW) + .end(ApplicationReviewStates.APPROVED) + .end(ApplicationReviewStates.REJECTED); + + } + + @Override + public void configure(StateMachineTransitionConfigurer transitions) throws Exception { + transitions.withExternal() + .source(ApplicationReviewStates.PEER_REVIEW).target(ApplicationReviewStates.PRINCIPAL_REVIEW).event(ApplicationReviewEvents.APPROVE) + .and().withExternal() + .source(ApplicationReviewStates.PRINCIPAL_REVIEW).target(ApplicationReviewStates.APPROVED).event(ApplicationReviewEvents.APPROVE) + .and().withExternal() + .source(ApplicationReviewStates.PEER_REVIEW).target(ApplicationReviewStates.REJECTED).event(ApplicationReviewEvents.REJECT) + .and().withExternal() + .source(ApplicationReviewStates.PRINCIPAL_REVIEW).target(ApplicationReviewStates.REJECTED).event(ApplicationReviewEvents.REJECT); + } +} \ No newline at end of file diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleStateMachineConfiguration.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleStateMachineConfiguration.java new file mode 100644 index 0000000000..fe4e0f82ce --- /dev/null +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleStateMachineConfiguration.java @@ -0,0 +1,105 @@ +package com.baeldung.spring.stateMachine.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.statemachine.action.Action; +import org.springframework.statemachine.config.EnableStateMachine; +import org.springframework.statemachine.config.StateMachineConfigurerAdapter; +import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer; +import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; +import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; +import org.springframework.statemachine.guard.Guard; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.logging.Logger; + +@Configuration +@EnableStateMachine +public class SimpleStateMachineConfiguration extends StateMachineConfigurerAdapter { + + public static final Logger LOGGER = Logger.getLogger(SimpleStateMachineConfiguration.class.getName()); + + @Override + public void configure(StateMachineConfigurationConfigurer config) + throws Exception { + config + .withConfiguration() + .autoStartup(true) + .listener(new StateMachineListener()); + } + + @Override + public void configure(StateMachineStateConfigurer states) throws Exception { + states + .withStates() + .initial("SI") + .end("SF") + .states(new HashSet<>(Arrays.asList("S1", "S2"))) + .state("S4", executeAction(), errorAction()) + .stateEntry("S3", entryAction()) + .stateDo("S3", executeAction()) + .stateExit("S3", exitAction()); + + } + + @Override + public void configure(StateMachineTransitionConfigurer transitions) throws Exception { + transitions.withExternal() + .source("SI").target("S1").event("E1").action(initAction()) + .and().withExternal() + .source("S1").target("S2").event("E2") + .and().withExternal() + .source("SI").target("S3").event("E3") + .and().withExternal() + .source("S3").target("S4").event("E4").guard(simpleGuard()) + .and().withExternal() + .source("S2").target("SF").event("end"); + } + + @Bean + public Guard simpleGuard() { + return (ctx) -> { + int approvalCount = (int) ctx.getExtendedState().getVariables().getOrDefault("approvalCount", 0); + return approvalCount > 0; + }; + } + + @Bean + public Action entryAction() { + return (ctx) -> { + LOGGER.info("Entry " + ctx.getTarget().getId()); + }; + } + + @Bean + public Action executeAction() { + return (ctx) -> { + LOGGER.info("Do " + ctx.getTarget().getId()); + int approvals = (int) ctx.getExtendedState().getVariables().getOrDefault("approvalCount", 0); + approvals++; + ctx.getExtendedState().getVariables().put("approvalCount", approvals); + }; + } + + @Bean + public Action exitAction() { + return (ctx) -> { + LOGGER.info("Exit " + ctx.getSource().getId() + " -> " + ctx.getTarget().getId()); + }; + } + + @Bean + public Action errorAction() { + return (ctx) -> { + LOGGER.info("Error " + ctx.getSource().getId() + ctx.getException()); + }; + } + + @Bean + public Action initAction() { + return (ctx) -> { + LOGGER.info(ctx.getTarget().getId()); + }; + } +} \ No newline at end of file diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/StateMachineListener.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/StateMachineListener.java new file mode 100644 index 0000000000..bb7859c683 --- /dev/null +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/StateMachineListener.java @@ -0,0 +1,16 @@ +package com.baeldung.spring.stateMachine.config; + +import org.springframework.statemachine.listener.StateMachineListenerAdapter; +import org.springframework.statemachine.state.State; + +import java.util.logging.Logger; + +public class StateMachineListener extends StateMachineListenerAdapter { + + public static final Logger LOGGER = Logger.getLogger(StateMachineListener.class.getName()); + + @Override + public void stateChanged(State from, State to) { + LOGGER.info(String.format("Transitioned from %s to %s%n", from == null ? "none" : from.getId(), to.getId())); + } +} diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineTest.java new file mode 100644 index 0000000000..416da5f0fe --- /dev/null +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineTest.java @@ -0,0 +1,45 @@ +package com.baeldung.spring.stateMachine; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.statemachine.StateMachine; + +import com.baeldung.spring.stateMachine.config.ForkJoinStateMachineConfiguration; + +public class ForkJoinStateMachineTest { + + @Test + public void whenForkStateEntered_thenMultipleSubStatesEntered() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ForkJoinStateMachineConfiguration.class); + StateMachine stateMachine = ctx.getBean(StateMachine.class); + stateMachine.start(); + + boolean success = stateMachine.sendEvent("E1"); + + assertTrue(success); + + assertTrue(Arrays.asList("SFork", "Sub1-1", "Sub2-1").containsAll(stateMachine.getState().getIds())); + } + + @Test + public void whenAllConfiguredJoinEntryStatesAreEntered_thenTransitionToJoinState() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ForkJoinStateMachineConfiguration.class); + StateMachine stateMachine = ctx.getBean(StateMachine.class); + stateMachine.start(); + + boolean success = stateMachine.sendEvent("E1"); + + assertTrue(success); + + assertTrue(Arrays.asList("SFork", "Sub1-1", "Sub2-1").containsAll(stateMachine.getState().getIds())); + + assertTrue(stateMachine.sendEvent("sub1")); + assertTrue(stateMachine.sendEvent("sub2")); + assertEquals("SJoin", stateMachine.getState().getId()); + } +} diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineTest.java new file mode 100644 index 0000000000..3557a63211 --- /dev/null +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineTest.java @@ -0,0 +1,37 @@ +package com.baeldung.spring.stateMachine; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; + +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.statemachine.StateMachine; + +import com.baeldung.spring.stateMachine.config.HierarchicalStateMachineConfiguration; + +public class HierarchicalStateMachineTest { + + @Test + public void whenTransitionToSubMachine_thenSubStateIsEntered() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(HierarchicalStateMachineConfiguration.class); + StateMachine stateMachine = ctx.getBean(StateMachine.class); + stateMachine.start(); + + + assertEquals(Arrays.asList("SI", "SUB1"), stateMachine.getState().getIds()); + + stateMachine.sendEvent("se1"); + + assertEquals(Arrays.asList("SI", "SUB2"), stateMachine.getState().getIds()); + + stateMachine.sendEvent("s-end"); + + assertEquals(Arrays.asList("SI", "SUBEND"), stateMachine.getState().getIds()); + + stateMachine.sendEvent("end"); + + assertEquals(1, stateMachine.getState().getIds().size()); + assertEquals("SF", stateMachine.getState().getId()); + } +} diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineTest.java new file mode 100644 index 0000000000..d0c1225c9b --- /dev/null +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineTest.java @@ -0,0 +1,24 @@ +package com.baeldung.spring.stateMachine; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.statemachine.StateMachine; + +import com.baeldung.spring.stateMachine.config.JunctionStateMachineConfiguration; + +public class JunctionStateMachineTest { + + @Test + public void whenTransitioningToJunction_thenArriveAtSubJunctionNode() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JunctionStateMachineConfiguration.class); + StateMachine stateMachine = ctx.getBean(StateMachine.class); + stateMachine.start(); + + stateMachine.sendEvent("E1"); + Assert.assertEquals("low", stateMachine.getState().getId()); + + stateMachine.sendEvent("end"); + Assert.assertEquals("SF", stateMachine.getState().getId()); + } +} diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineTest.java new file mode 100644 index 0000000000..1fd7bd85f0 --- /dev/null +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineTest.java @@ -0,0 +1,33 @@ +package com.baeldung.spring.stateMachine; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.statemachine.StateMachine; + +import com.baeldung.spring.stateMachine.applicationReview.ApplicationReviewEvents; +import com.baeldung.spring.stateMachine.applicationReview.ApplicationReviewStates; +import com.baeldung.spring.stateMachine.config.SimpleEnumStateMachineConfiguration; + +public class StateEnumMachineTest { + + private StateMachine stateMachine; + + @Before + public void setUp() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SimpleEnumStateMachineConfiguration.class); + stateMachine = ctx.getBean(StateMachine.class); + stateMachine.start(); + } + + @Test + public void whenStateMachineConfiguredWithEnums_thenStateMachineAcceptsEnumEvents() { + assertTrue(stateMachine.sendEvent(ApplicationReviewEvents.APPROVE)); + assertEquals(ApplicationReviewStates.PRINCIPAL_REVIEW, stateMachine.getState().getId()); + assertTrue(stateMachine.sendEvent(ApplicationReviewEvents.REJECT)); + assertEquals(ApplicationReviewStates.REJECTED, stateMachine.getState().getId()); + } +} diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineBuilderTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineBuilderTest.java new file mode 100644 index 0000000000..cdd1e951e0 --- /dev/null +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineBuilderTest.java @@ -0,0 +1,35 @@ +package com.baeldung.spring.stateMachine; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.springframework.statemachine.StateMachine; +import org.springframework.statemachine.config.StateMachineBuilder; + +public class StateMachineBuilderTest { + + @Test + public void whenUseStateMachineBuilder_thenBuildSuccessAndMachineWorks() throws Exception { + StateMachineBuilder.Builder builder = StateMachineBuilder.builder(); + builder.configureStates().withStates() + .initial("SI") + .state("S1") + .end("SF"); + + builder.configureTransitions() + .withExternal() + .source("SI").target("S1").event("E1") + .and().withExternal() + .source("S1").target("SF").event("E2"); + + StateMachine machine = builder.build(); + + machine.start(); + + machine.sendEvent("E1"); + assertEquals("S1", machine.getState().getId()); + + machine.sendEvent("E2"); + assertEquals("SF", machine.getState().getId()); + } +} diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineTest.java new file mode 100644 index 0000000000..1b442bf994 --- /dev/null +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineTest.java @@ -0,0 +1,47 @@ +package com.baeldung.spring.stateMachine; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.statemachine.StateMachine; + +import com.baeldung.spring.stateMachine.config.SimpleStateMachineConfiguration; + +public class StateMachineTest { + + private StateMachine stateMachine; + + @Before + public void setUp() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SimpleStateMachineConfiguration.class); + stateMachine = ctx.getBean(StateMachine.class); + stateMachine.start(); + } + + @Test + public void whenSimpleStringStateMachineEvents_thenEndState() { + assertEquals("SI", stateMachine.getState().getId()); + + stateMachine.sendEvent("E1"); + assertEquals("S1", stateMachine.getState().getId()); + + stateMachine.sendEvent("E2"); + assertEquals("S2", stateMachine.getState().getId()); + + stateMachine.sendEvent("end"); + assertEquals("SF", stateMachine.getState().getId()); + + } + + @Test + public void whenSimpleStringMachineActionState_thenActionExecuted() { + stateMachine.sendEvent("E3"); + assertEquals("S3", stateMachine.getState().getId()); + + stateMachine.sendEvent("E4"); + assertEquals("S4", stateMachine.getState().getId()); + assertEquals(2, stateMachine.getExtendedState().getVariables().get("approvalCount")); + } +}