Getting started

If you are just getting started with Spring Statemachine, this is the section for you! Here, we answer the basic “what?”, “how?” and “why?” questions. We start with a gentle introduction to Spring Statemachine. We then build our first Spring Statemachine application and discuss some core principles as we go.

3. System Requirement

Spring Statemachine 4.0.1-SNAPSHOT is built and tested with JDK 8 (all artifacts have JDK 7 compatibility) and Spring Framework 6.0.18. It does not require any other dependencies outside of Spring Framework within its core system.spring-doc.cn

Other optional parts (such as Using Distributed States) have dependencies on Zookeeper, while State Machine Examples has dependencies on spring-shell and spring-boot, which pull other dependencies beyond the framework itself. Also, the optional security and data access features have dependencies to on Spring Security and Spring Data modules.spring-doc.cn

4. Modules

The following table describes the modules that are available for Spring Statemachine.spring-doc.cn

Module Description

spring-statemachine-corespring-doc.cn

The core system of Spring Statemachine.spring-doc.cn

spring-statemachine-recipes-commonspring-doc.cn

Common recipes that do not require dependencies outside of the core framework.spring-doc.cn

spring-statemachine-kryospring-doc.cn

Kryo serializers for Spring Statemachine.spring-doc.cn

spring-statemachine-data-commonspring-doc.cn

Common support module for Spring Data.spring-doc.cn

spring-statemachine-data-jpaspring-doc.cn

Support module for Spring Data JPA.spring-doc.cn

spring-statemachine-data-redisspring-doc.cn

Support module for Spring Data Redis.spring-doc.cn

spring-statemachine-data-mongodbspring-doc.cn

Support module for Spring Data MongoDB.spring-doc.cn

spring-statemachine-zookeeperspring-doc.cn

Zookeeper integration for a distributed state machine.spring-doc.cn

spring-statemachine-testspring-doc.cn

Support module for state machine testing.spring-doc.cn

spring-statemachine-clusterspring-doc.cn

Support module for Spring Cloud Cluster. Note that Spring Cloud Cluster has been superseded by Spring Integration.spring-doc.cn

spring-statemachine-umlspring-doc.cn

Support module for UI UML modeling with Eclipse Papyrus.spring-doc.cn

spring-statemachine-autoconfigurespring-doc.cn

Support module for Spring Boot.spring-doc.cn

spring-statemachine-bomspring-doc.cn

Bill of Materials pom.spring-doc.cn

spring-statemachine-starterspring-doc.cn

Spring Boot starter.spring-doc.cn

5. Using Gradle

The following listing shows a typical build.gradle file created by choosing various settings at https://start.spring.io:spring-doc.cn

buildscript {
	ext {
		springBootVersion = '3.1.10'
	}
	repositories {
		mavenCentral()
		maven { url "https://repo.spring.io/snapshot" }
		maven { url "https://repo.spring.io/milestone" }
	}
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
	}
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
}

repositories {
	mavenCentral()
	maven { url "https://repo.spring.io/snapshot" }
	maven { url "https://repo.spring.io/milestone" }
}


ext {
	springStatemachineVersion = '4.0.1-SNAPSHOT'
}

dependencies {
	compile('org.springframework.statemachine:spring-statemachine-starter')
	testCompile('org.springframework.boot:spring-boot-starter-test')
}

dependencyManagement {
	imports {
		mavenBom "org.springframework.statemachine:spring-statemachine-bom:${springStatemachineVersion}"
	}
}
Replace 0.0.1-SNAPSHOT with a version you want to use.

With a normal project structure, you can build this project with the following command:spring-doc.cn

# ./gradlew clean build

The expected Spring Boot-packaged fat jar would be build/libs/demo-0.0.1-SNAPSHOT.jar.spring-doc.cn

You do not need the`libs-milestone` and libs-snapshot repositories for production development.

6. Using Maven

The following example shows a typical pom.xml file, which was created by choosing various options at https://start.spring.io:spring-doc.cn

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>gs-statemachine</name>
	<description>Demo project for Spring Statemachine</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.1.10</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-statemachine.version>4.0.1-SNAPSHOT</spring-statemachine.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.statemachine</groupId>
			<artifactId>spring-statemachine-starter</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.statemachine</groupId>
				<artifactId>spring-statemachine-bom</artifactId>
				<version>${spring-statemachine.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>

	<pluginRepositories>
		<pluginRepository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</pluginRepository>
		<pluginRepository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>
	</pluginRepositories>


</project>
Replace 0.0.1-SNAPSHOT with a version you want to use.

With a normal project structure, you can build this project with the following command:spring-doc.cn

# mvn clean package

The expected Spring Boot-packaged fat-jar would be target/demo-0.0.1-SNAPSHOT.jar.spring-doc.cn

You do not need the libs-milestone and libs-snapshot repositories for production development.

7. Developing Your First Spring Statemachine Application

You can start by creating a simple Spring Boot Application class that implements CommandLineRunner. The following example shows how to do so:spring-doc.cn

@SpringBootApplication
public class Application implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

Then you need to add states and events, as the following example shows:spring-doc.cn

public enum States {
    SI, S1, S2
}

public enum Events {
    E1, E2
}

Then you need to add state machine configuration, as the following example shows:spring-doc.cn

@Configuration
@EnableStateMachine
public class StateMachineConfig
        extends EnumStateMachineConfigurerAdapter<States, Events> {

    @Override
    public void configure(StateMachineConfigurationConfigurer<States, Events> config)
            throws Exception {
        config
            .withConfiguration()
                .autoStartup(true)
                .listener(listener());
    }

    @Override
    public void configure(StateMachineStateConfigurer<States, Events> states)
            throws Exception {
        states
            .withStates()
                .initial(States.SI)
                    .states(EnumSet.allOf(States.class));
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<States, Events> 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<States, Events> listener() {
        return new StateMachineListenerAdapter<States, Events>() {
            @Override
            public void stateChanged(State<States, Events> from, State<States, Events> to) {
                System.out.println("State change to " + to.getId());
            }
        };
    }
}

Then you need to implement CommandLineRunner and autowire StateMachine. The following example shows how to do so:spring-doc.cn

@Autowired
private StateMachine<States, Events> stateMachine;

@Override
public void run(String... args) throws Exception {
    stateMachine.sendEvent(Events.E1);
    stateMachine.sendEvent(Events.E2);
}

Depending on whether you build your application with Gradle or Maven, you can run it by using java -jar build/libs/gs-statemachine-0.1.0.jar or java -jar target/gs-statemachine-0.1.0.jar, respectively.spring-doc.cn

The result of this command should be normal Spring Boot output. However, you should also find the following lines:spring-doc.cn

State change to SI
State change to S1
State change to S2

These lines indicate that the machine you constructed is moving from one state to another, as it should.spring-doc.cn