Spring State Machine (#1493)
* Neo4j cleanup * Neo4j cleanup * Neo4j cleanup x2 * State Machine Init * cleanup * White background, Java Util Logging * Change to Logging * Static import of asserts. rename test methods * fix attempt for S3 -> S4 * Remove awaitility. add teardown * fix attempt for S3 -> S4 * fix attempt for S3 -> S4 Final
This commit is contained in:
parent
365d75a8d7
commit
1c1c557a39
1
pom.xml
1
pom.xml
|
@ -189,6 +189,7 @@
|
||||||
<module>spring-sleuth</module>
|
<module>spring-sleuth</module>
|
||||||
<module>spring-social-login</module>
|
<module>spring-social-login</module>
|
||||||
<module>spring-spel</module>
|
<module>spring-spel</module>
|
||||||
|
<module>spring-state-machine</module>
|
||||||
<module>spring-thymeleaf</module>
|
<module>spring-thymeleaf</module>
|
||||||
<module>spring-userservice</module>
|
<module>spring-userservice</module>
|
||||||
<module>spring-zuul</module>
|
<module>spring-zuul</module>
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1489770331405" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<process id="myProcess_1" isClosed="false" isExecutable="true" processType="None">
|
||||||
|
<startEvent id="_2" name="Start">
|
||||||
|
<messageEventDefinition id="_2_ED_1"/>
|
||||||
|
</startEvent>
|
||||||
|
<parallelGateway gatewayDirection="Unspecified" id="_3" name="Fork"/>
|
||||||
|
<userTask activiti:exclusive="true" id="_4" name="UserTask"/>
|
||||||
|
<scriptTask activiti:exclusive="true" id="_5" name="ScriptTask"/>
|
||||||
|
<endEvent id="_7" name="EndEvent">
|
||||||
|
<terminateEventDefinition id="_7_ED_1"/>
|
||||||
|
<extensionElements>
|
||||||
|
<activiti:executionListener event="start">
|
||||||
|
<activiti:field>
|
||||||
|
<activiti:string/>
|
||||||
|
</activiti:field>
|
||||||
|
</activiti:executionListener>
|
||||||
|
<activiti:executionListener event="start"/>
|
||||||
|
<activiti:executionListener event="start"/>
|
||||||
|
<activiti:executionListener event="start"/>
|
||||||
|
<activiti:executionListener event="start"/>
|
||||||
|
</extensionElements>
|
||||||
|
</endEvent>
|
||||||
|
<inclusiveGateway gatewayDirection="Unspecified" id="_6" name="Join"/>
|
||||||
|
<sequenceFlow id="_8" sourceRef="_3" targetRef="_4"/>
|
||||||
|
<sequenceFlow id="_9" sourceRef="_3" targetRef="_5"/>
|
||||||
|
<sequenceFlow id="_10" sourceRef="_5" targetRef="_6"/>
|
||||||
|
<sequenceFlow id="_11" sourceRef="_4" targetRef="_6"/>
|
||||||
|
<sequenceFlow id="_12" sourceRef="_6" targetRef="_7"/>
|
||||||
|
<sequenceFlow id="_13" sourceRef="_2" targetRef="_3"/>
|
||||||
|
</process>
|
||||||
|
<bpmndi:BPMNDiagram documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
|
||||||
|
<bpmndi:BPMNPlane bpmnElement="myProcess_1">
|
||||||
|
<bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
|
||||||
|
<omgdc:Bounds height="32.0" width="32.0" x="35.0" y="95.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
|
||||||
|
<omgdc:Bounds height="32.0" width="32.0" x="140.0" y="95.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4">
|
||||||
|
<omgdc:Bounds height="55.0" width="85.0" x="230.0" y="20.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
|
||||||
|
<omgdc:Bounds height="55.0" width="85.0" x="230.0" y="180.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape bpmnElement="_7" id="Shape-_7">
|
||||||
|
<omgdc:Bounds height="32.0" width="32.0" x="475.0" y="130.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6">
|
||||||
|
<omgdc:Bounds height="32.0" width="32.0" x="375.0" y="130.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNEdge bpmnElement="_13" id="BPMNEdge__13" sourceElement="_2" targetElement="_3">
|
||||||
|
<omgdi:waypoint x="67.0" y="111.0"/>
|
||||||
|
<omgdi:waypoint x="140.0" y="111.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge bpmnElement="_12" id="BPMNEdge__12" sourceElement="_6" targetElement="_7">
|
||||||
|
<omgdi:waypoint x="407.0" y="146.0"/>
|
||||||
|
<omgdi:waypoint x="475.0" y="146.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_3" targetElement="_4">
|
||||||
|
<omgdi:waypoint x="172.0" y="111.0"/>
|
||||||
|
<omgdi:waypoint x="230.0" y="47.5"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge bpmnElement="_9" id="BPMNEdge__9" sourceElement="_3" targetElement="_5">
|
||||||
|
<omgdi:waypoint x="172.0" y="111.0"/>
|
||||||
|
<omgdi:waypoint x="230.0" y="207.5"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge bpmnElement="_11" id="BPMNEdge__11" sourceElement="_4" targetElement="_6">
|
||||||
|
<omgdi:waypoint x="315.0" y="45.0"/>
|
||||||
|
<omgdi:waypoint x="390.0" y="45.0"/>
|
||||||
|
<omgdi:waypoint x="390.0" y="131.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_5" targetElement="_6">
|
||||||
|
<omgdi:waypoint x="315.0" y="190.0"/>
|
||||||
|
<omgdi:waypoint x="355.0" y="190.0"/>
|
||||||
|
<omgdi:waypoint x="375.0" y="146.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
</bpmndi:BPMNPlane>
|
||||||
|
</bpmndi:BPMNDiagram>
|
||||||
|
</definitions>
|
Binary file not shown.
After Width: | Height: | Size: 50 KiB |
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
|
@ -0,0 +1,76 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1489503806724" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<process id="myProcess_1" isClosed="false" isExecutable="true" processType="None">
|
||||||
|
<startEvent id="_2" name="SI">
|
||||||
|
<messageEventDefinition id="_2_ED_1"/>
|
||||||
|
</startEvent>
|
||||||
|
<userTask activiti:exclusive="true" id="_3" name="S1"/>
|
||||||
|
<userTask activiti:exclusive="true" id="_4" name="S2"/>
|
||||||
|
<endEvent id="_5" name="SF">
|
||||||
|
<terminateEventDefinition id="_5_ED_1"/>
|
||||||
|
<extensionElements>
|
||||||
|
<activiti:executionListener event="start">
|
||||||
|
<activiti:field>
|
||||||
|
<activiti:string/>
|
||||||
|
</activiti:field>
|
||||||
|
</activiti:executionListener>
|
||||||
|
<activiti:executionListener event="start"/>
|
||||||
|
<activiti:executionListener event="start"/>
|
||||||
|
<activiti:executionListener event="start"/>
|
||||||
|
<activiti:executionListener event="start"/>
|
||||||
|
</extensionElements>
|
||||||
|
</endEvent>
|
||||||
|
<sequenceFlow id="_6" sourceRef="_2" targetRef="_3"/>
|
||||||
|
<sequenceFlow id="_7" sourceRef="_3" targetRef="_4"/>
|
||||||
|
<sequenceFlow id="_8" sourceRef="_4" targetRef="_5"/>
|
||||||
|
</process>
|
||||||
|
<bpmndi:BPMNDiagram documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
|
||||||
|
<bpmndi:BPMNPlane bpmnElement="myProcess_1">
|
||||||
|
<bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
|
||||||
|
<omgdc:Bounds height="32.0" width="32.0" x="85.0" y="95.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
|
||||||
|
<omgdc:Bounds height="40.0" width="75.0" x="180.0" y="105.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="40.0" width="75.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4">
|
||||||
|
<omgdc:Bounds height="40.0" width="70.0" x="320.0" y="105.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="40.0" width="70.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
|
||||||
|
<omgdc:Bounds height="32.0" width="32.0" x="460.0" y="95.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNEdge bpmnElement="_6" id="BPMNEdge__6" sourceElement="_2" targetElement="_3">
|
||||||
|
<omgdi:waypoint x="117.0" y="111.0"/>
|
||||||
|
<omgdi:waypoint x="180.0" y="125.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_3" targetElement="_4">
|
||||||
|
<omgdi:waypoint x="255.0" y="125.0"/>
|
||||||
|
<omgdi:waypoint x="320.0" y="125.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_4" targetElement="_5">
|
||||||
|
<omgdi:waypoint x="390.0" y="125.0"/>
|
||||||
|
<omgdi:waypoint x="460.0" y="111.0"/>
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
</bpmndi:BPMNPlane>
|
||||||
|
</bpmndi:BPMNDiagram>
|
||||||
|
</definitions>
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>parent-modules</artifactId>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>baeldung-spring-state-machine</artifactId>
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.statemachine</groupId>
|
||||||
|
<artifactId>spring-statemachine-core</artifactId>
|
||||||
|
<version>1.2.3.RELEASE</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.11</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.baeldung.spring.stateMachine.applicationReview;
|
||||||
|
|
||||||
|
public enum ApplicationReviewEvents {
|
||||||
|
APPROVE, REJECT
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.baeldung.spring.stateMachine.applicationReview;
|
||||||
|
|
||||||
|
public enum ApplicationReviewStates {
|
||||||
|
PEER_REVIEW, PRINCIPAL_REVIEW, APPROVED, REJECTED
|
||||||
|
}
|
|
@ -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<String, String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(StateMachineConfigurationConfigurer<String, String> config)
|
||||||
|
throws Exception {
|
||||||
|
config
|
||||||
|
.withConfiguration()
|
||||||
|
.autoStartup(true)
|
||||||
|
.listener(new StateMachineListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(StateMachineStateConfigurer<String, String> 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<String, String> 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<String, String> mediumGuard() {
|
||||||
|
return (ctx) -> false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Guard<String, String> highGuard() {
|
||||||
|
return (ctx) -> false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<String, String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(StateMachineConfigurationConfigurer<String, String> config)
|
||||||
|
throws Exception {
|
||||||
|
config
|
||||||
|
.withConfiguration()
|
||||||
|
.autoStartup(true)
|
||||||
|
.listener(new StateMachineListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(StateMachineStateConfigurer<String, String> 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<String, String> 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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<String, String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(StateMachineConfigurationConfigurer<String, String> config)
|
||||||
|
throws Exception {
|
||||||
|
config
|
||||||
|
.withConfiguration()
|
||||||
|
.autoStartup(true)
|
||||||
|
.listener(new StateMachineListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(StateMachineStateConfigurer<String, String> states) throws Exception {
|
||||||
|
states
|
||||||
|
.withStates()
|
||||||
|
.initial("SI")
|
||||||
|
.junction("SJ")
|
||||||
|
.state("high")
|
||||||
|
.state("medium")
|
||||||
|
.state("low")
|
||||||
|
.end("SF");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(StateMachineTransitionConfigurer<String, String> 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<String, String> mediumGuard() {
|
||||||
|
return (ctx) -> false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Guard<String, String> highGuard() {
|
||||||
|
return (ctx) -> false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<ApplicationReviewStates, ApplicationReviewEvents> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(StateMachineConfigurationConfigurer<ApplicationReviewStates, ApplicationReviewEvents> config)
|
||||||
|
throws Exception {
|
||||||
|
config
|
||||||
|
.withConfiguration()
|
||||||
|
.autoStartup(true)
|
||||||
|
.listener(new StateMachineListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(StateMachineStateConfigurer<ApplicationReviewStates, ApplicationReviewEvents> states) throws Exception {
|
||||||
|
states
|
||||||
|
.withStates()
|
||||||
|
.initial(ApplicationReviewStates.PEER_REVIEW)
|
||||||
|
.state(ApplicationReviewStates.PRINCIPAL_REVIEW)
|
||||||
|
.end(ApplicationReviewStates.APPROVED)
|
||||||
|
.end(ApplicationReviewStates.REJECTED);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(StateMachineTransitionConfigurer<ApplicationReviewStates, ApplicationReviewEvents> 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
package com.baeldung.spring.stateMachine.config;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableStateMachine
|
||||||
|
public class SimpleStateMachineConfiguration extends StateMachineConfigurerAdapter<String, String> {
|
||||||
|
|
||||||
|
public static final Logger LOGGER = Logger.getLogger(SimpleStateMachineConfiguration.class.getName());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(StateMachineConfigurationConfigurer<String, String> config)
|
||||||
|
throws Exception {
|
||||||
|
config
|
||||||
|
.withConfiguration()
|
||||||
|
.autoStartup(true)
|
||||||
|
.listener(new StateMachineListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(StateMachineStateConfigurer<String, String> 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<String, String> 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").and().withExternal().source("S4").target("SF").event("end").guard(simpleGuard())
|
||||||
|
.and().withExternal()
|
||||||
|
.source("S2").target("SF").event("end");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Guard<String, String> simpleGuard() {
|
||||||
|
return (ctx) -> {
|
||||||
|
int approvalCount = (int) ctx.getExtendedState().getVariables().getOrDefault("approvalCount", 0);
|
||||||
|
return approvalCount > 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Action<String, String> entryAction() {
|
||||||
|
return (ctx) -> {
|
||||||
|
LOGGER.info("Entry " + ctx.getTarget().getId());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Action<String, String> 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<String, String> exitAction() {
|
||||||
|
return (ctx) -> {
|
||||||
|
LOGGER.info("Exit " + ctx.getSource().getId() + " -> " + ctx.getTarget().getId());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Action<String, String> errorAction() {
|
||||||
|
return (ctx) -> {
|
||||||
|
LOGGER.info("Error " + ctx.getSource().getId() + ctx.getException());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Action<String, String> initAction() {
|
||||||
|
return (ctx) -> {
|
||||||
|
LOGGER.info(ctx.getTarget().getId());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -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()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<String, String> 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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
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.config.SimpleStateMachineConfiguration;
|
||||||
|
|
||||||
|
public class StateMachineTest {
|
||||||
|
|
||||||
|
private AnnotationConfigApplicationContext ctx;
|
||||||
|
private StateMachine stateMachine;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSimpleStringMachineActionState_thenActionExecuted() {
|
||||||
|
|
||||||
|
stateMachine.sendEvent("E3");
|
||||||
|
assertEquals("S3", stateMachine.getState().getId());
|
||||||
|
|
||||||
|
boolean acceptedE4 = stateMachine.sendEvent("E4");
|
||||||
|
|
||||||
|
assertTrue(acceptedE4);
|
||||||
|
assertEquals("S4", stateMachine.getState().getId());
|
||||||
|
assertEquals(2, stateMachine.getExtendedState().getVariables().get("approvalCount"));
|
||||||
|
|
||||||
|
stateMachine.sendEvent("end");
|
||||||
|
assertEquals("SF", stateMachine.getState().getId());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue