[[statemachine-getting-started]] = Getting started If you’re just getting started with Spring Statemachine, this is the section for you! Here we answer the basic “what?”, “how?” and “why?” questions. You’ll find a gentle introduction to Spring Statemachine. We’ll then build our first Spring Statemachine application, discussing some core principles as we go. == System Requirements Spring Statemachine {revnumber} is built and tested with JDK 8(all artifacts have JDK 7 compatibility) and Spring Framework {spring-version} and doesn't require any other dependencies outside of Spring Framework within its core system. Other optional parts like <> has dependencies to a `Zookeeper`, while <> has dependencies to spring-shell and spring-boot which pulls other dependencies beyond framework itself. == Modules The following modules are available for Spring Statemachine. |=== |Module |Description |spring-statemachine-core |Core system of a Spring Statemachine. |spring-statemachine-recipes-common |Common recipes which doesn't require dependencies outside of a core framework. |spring-statemachine-kryo |`Kryo` serializers for state machine. |spring-statemachine-redis |`Redis` related features for state machine. |spring-statemachine-zookeeper |`Zookeeper` integration for a distributed state machine. |spring-statemachine-test |Support module for state machine testing. |spring-statemachine-cluster |Support module for Spring Cloud Cluster. |spring-statemachine-uml |Support module for UI uml modeling. |=== == Using Gradle Here is a typical `build.gradle` file: [source,groovy,indent=0] ---- buildscript { repositories { maven { url "https://repo.spring.io/libs-release" } } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.5.RELEASE") } } apply plugin: 'base' apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'idea' apply plugin: 'spring-boot' version = '0.1.0' archivesBaseName = 'gs-statemachine' repositories { mavenCentral() maven { url "https://repo.spring.io/libs-release" } maven { url "https://repo.spring.io/libs-milestone" } maven { url "https://repo.spring.io/libs-snapshot" } } dependencies { compile("org.springframework.statemachine:spring-statemachine-core:1.0.0.BUILD-SNAPSHOT") compile("org.springframework.boot:spring-boot-starter:1.2.5.RELEASE") testCompile("org.springframework.statemachine:spring-statemachine-test:1.0.0.BUILD-SNAPSHOT") } task wrapper(type: Wrapper) { gradleVersion = '1.11' } ---- [NOTE] ==== Replace `1.0.0.BUILD-SNAPSHOT` with a version you want to use. ==== Having a normal project structure you'd build this with command: [source,text,indent=0] ---- # ./gradlew clean build ---- Expected Spring Boot packaged fat-jar would be `build/libs/gs-statemachine-0.1.0.jar`. [NOTE] ==== You don't need repos `libs-milestone` and `libs-snapshot` for production development. ==== == Using Maven Here is a typical `pom.xml` file: [source,xml,indent=0] ---- 4.0.0 org.springframework gs-statemachine 0.1.0 jar org.springframework.boot spring-boot-starter-parent 1.2.5.RELEASE org.springframework.statemachine spring-statemachine-core 1.0.0.BUILD-SNAPSHOT org.springframework.boot spring-boot-starter 1.0.0.BUILD-SNAPSHOT org.springframework.statemachine spring-statemachine-test 1.0.0.BUILD-SNAPSHOT test maven-compiler-plugin 2.3.2 org.springframework.boot spring-boot-maven-plugin maven-failsafe-plugin package integration-test verify spring-release https://repo.spring.io/libs-release false spring-milestone https://repo.spring.io/libs-milestone false spring-snapshot https://repo.spring.io/libs-snapshot true spring-release https://repo.spring.io/libs-release false ---- [NOTE] ==== Replace `1.0.0.BUILD-SNAPSHOT` with a version you want to use. ==== Having a normal project structure you'd build this with command: [source,text,indent=0] ---- # mvn clean package ---- Expected Spring Boot packaged fat-jar would be `target/gs-statemachine-0.1.0.jar`. [NOTE] ==== You don't need repos `libs-milestone` and `libs-snapshot` for production development. ==== == Developing your first Spring Statemachine application Let's start by creating a simple Spring Boot `Application` class implementing `CommandLineRunner`. [source,java,indent=0] ---- @SpringBootApplication public class Application implements CommandLineRunner { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ---- Add states and events: [source,java,indent=0] ---- public enum States { SI, S1, S2 } public enum Events { E1, E2 } ---- Add state machine configuration: [source,java,indent=0] ---- @Configuration @EnableStateMachine public class StateMachineConfig extends EnumStateMachineConfigurerAdapter { @Override public void configure(StateMachineConfigurationConfigurer config) throws Exception { config .withConfiguration() .autoStartup(true) .listener(listener()); } @Override public void configure(StateMachineStateConfigurer states) throws Exception { states .withStates() .initial(States.SI) .states(EnumSet.allOf(States.class)); } @Override public void configure(StateMachineTransitionConfigurer transitions) throws Exception { transitions .withExternal() .source(States.SI).target(States.S1).event(Events.E1) .and() .withExternal() .source(States.S1).target(States.S2).event(Events.E2); } @Bean public StateMachineListener listener() { return new StateMachineListenerAdapter() { @Override public void stateChanged(State from, State to) { System.out.println("State change to " + to.getId()); } }; } } ---- Implement `CommandLineRunner`, autowire `StateMachine`: [source,java,indent=0] ---- @Autowired private StateMachine stateMachine; @Override public void run(String... args) throws Exception { stateMachine.sendEvent(Events.E1); stateMachine.sendEvent(Events.E2); } ---- Depending whether you build your application using `Gradle` or `Maven` it's run `java -jar build/libs/gs-statemachine-0.1.0.jar` or `java -jar target/gs-statemachine-0.1.0.jar` respectively. What is expected for running this command is a normal Spring Boot output but if you look closely you see lines: [source,text,indent=0] ---- State change to SI State change to S1 State change to S2 ----