Editing pass
I edited for spelling, punctuation, grammar, usage, and corporate voice. I also added leader sentences before all the images and code listings and rewrote for clarity.
This commit is contained in:
committed by
Janne Valkealahti
parent
bd2518cce9
commit
16a2a5389d
File diff suppressed because it is too large
Load Diff
@@ -1,37 +1,32 @@
|
||||
[[statemachine-faq]]
|
||||
= FAQ
|
||||
This chapter tries to give solutions to question user is most likely
|
||||
to ask.
|
||||
|
||||
This chapter answers the questions that Spring Statemachine users most often ask.
|
||||
|
||||
== State Changes
|
||||
|
||||
.I want to transit to next state automatically
|
||||
.How can I automatically transit to the next state?
|
||||
|
||||
{zwsp} +
|
||||
You can choose from three approaches:
|
||||
|
||||
There are few choices a state machine developer can choose.
|
||||
|
||||
* Implement an action and send appropriate event into a state machine
|
||||
which triggers a transition into a proper target state.
|
||||
* Define deferred event within a state and before sending an event
|
||||
send an event which will be deferred and thus causing next
|
||||
* Implement an action and send an appropriate event to a state machine
|
||||
to trigger a transition into the proper target state.
|
||||
* Define a deferred event within a state and, before sending an event,
|
||||
send another event that is deferred. Doing so causes the next
|
||||
appropriate state transition when it is more convenient to handle
|
||||
that event.
|
||||
* Implement a triggerless transition which will automatically cause
|
||||
state transition into a next state when state has entry and its
|
||||
* Implement a triggerless transition, which automatically causes a
|
||||
state transition into the next state when state is entered and its
|
||||
actions has been completed.
|
||||
|
||||
== Extended State
|
||||
|
||||
.How I can initialise variables on state machine start
|
||||
.How I can initialize variables on state machine start?
|
||||
|
||||
{zwsp} +
|
||||
|
||||
Important concept in a state machine is that nothing really happens
|
||||
unless there is a trigger which is causing a state transition which
|
||||
An important concept in a state machine is that nothing really happens
|
||||
unless a trigger causes a state transition that
|
||||
then can fire actions. However, having said that, Spring Statemachine
|
||||
always have an initial transition when state machine is started. With
|
||||
this initial transition user can execute a simple action which within
|
||||
a _StateContext_ can do whatever it likes with an extended state
|
||||
always has an initial transition when a state machine is started. With
|
||||
this initial transition, you can run a simple action that, within
|
||||
a `StateContext`, can do whatever it likes with extended state
|
||||
variables.
|
||||
|
||||
|
||||
@@ -1,77 +1,83 @@
|
||||
[[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
|
||||
|
||||
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.
|
||||
|
||||
== System Requirements
|
||||
== System Requirement
|
||||
|
||||
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
|
||||
JDK 8 (all artifacts have JDK 7 compatibility) and Spring
|
||||
Framework {spring-version}. It does not require any other
|
||||
dependencies outside of Spring Framework within its core system.
|
||||
|
||||
Other optional parts like <<sm-distributed>> has dependencies to
|
||||
a `Zookeeper`, while <<statemachine-examples>> has dependencies
|
||||
to spring-shell and spring-boot which pulls other dependencies
|
||||
beyond framework itself. Also optional security and data access has
|
||||
dependencies to _Spring Security_ and _Spring Data Modules_.
|
||||
Other optional parts (such as <<sm-distributed>>) have dependencies on
|
||||
Zookeeper, while <<statemachine-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.
|
||||
|
||||
== Modules
|
||||
The following modules are available for Spring Statemachine.
|
||||
|
||||
The following table describes the modules that are available for Spring Statemachine.
|
||||
|
||||
|===
|
||||
|Module |Description
|
||||
|
||||
|spring-statemachine-core
|
||||
|Core system of a Spring Statemachine.
|
||||
|`spring-statemachine-core`
|
||||
|The core system of Spring Statemachine.
|
||||
|
||||
|spring-statemachine-recipes-common
|
||||
|Common recipes which doesn't require dependencies outside of a core
|
||||
|`spring-statemachine-recipes-common`
|
||||
|Common recipes that do not require dependencies outside of the core
|
||||
framework.
|
||||
|
||||
|spring-statemachine-kryo
|
||||
|`Kryo` serializers for state machine.
|
||||
|`spring-statemachine-kryo`
|
||||
|`Kryo` serializers for Spring Statemachine.
|
||||
|
||||
|spring-statemachine-data-common
|
||||
|`spring-statemachine-data-common`
|
||||
|Common support module for `Spring Data`.
|
||||
|
||||
|spring-statemachine-data-jpa
|
||||
|`spring-statemachine-data-jpa`
|
||||
|Support module for `Spring Data JPA`.
|
||||
|
||||
|spring-statemachine-data-redis
|
||||
|`spring-statemachine-data-redis`
|
||||
|Support module for `Spring Data Redis`.
|
||||
|
||||
|spring-statemachine-data-mongodb
|
||||
|`spring-statemachine-data-mongodb`
|
||||
|Support module for `Spring Data MongoDB`.
|
||||
|
||||
|spring-statemachine-zookeeper
|
||||
|`Zookeeper` integration for a distributed state machine.
|
||||
|`spring-statemachine-zookeeper`
|
||||
|Zookeeper integration for a distributed state machine.
|
||||
|
||||
|spring-statemachine-test
|
||||
|`spring-statemachine-test`
|
||||
|Support module for state machine testing.
|
||||
|
||||
|spring-statemachine-cluster
|
||||
|`spring-statemachine-cluster`
|
||||
|Support module for Spring Cloud Cluster.
|
||||
Note that Spring Cloud Cluster has been superseded by Spring Integration.
|
||||
|
||||
|spring-statemachine-uml
|
||||
|Support module for UI uml modeling with Eclipse Papyrus.
|
||||
|`spring-statemachine-uml`
|
||||
|Support module for UI UML modeling with Eclipse Papyrus.
|
||||
|
||||
|spring-statemachine-autoconfigure
|
||||
|Support module for `Spring Boot`.
|
||||
|`spring-statemachine-autoconfigure`
|
||||
|Support module for Spring Boot.
|
||||
|
||||
|spring-statemachine-bom
|
||||
|`spring-statemachine-bom`
|
||||
|Bill of Materials pom.
|
||||
|
||||
|spring-statemachine-starter
|
||||
|`Spring Boot` starter.
|
||||
|`spring-statemachine-starter`
|
||||
|Spring Boot starter.
|
||||
|===
|
||||
|
||||
== Using Gradle
|
||||
Here is a typical `build.gradle` file created by https://start.spring.io:
|
||||
|
||||
The following listing shows a typical `build.gradle` file created by choosing various settings at https://start.spring.io:
|
||||
|
||||
====
|
||||
[source,groovy,indent=0,subs="attributes+"]
|
||||
----
|
||||
buildscript {
|
||||
@@ -119,29 +125,29 @@ dependencyManagement {
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Replace `0.0.1-SNAPSHOT` with a version you want to use.
|
||||
====
|
||||
|
||||
Having a normal project structure you'd build this with command:
|
||||
IMPORTANT: 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:
|
||||
|
||||
====
|
||||
[source,text,indent=0]
|
||||
----
|
||||
# ./gradlew clean build
|
||||
----
|
||||
|
||||
Expected Spring Boot packaged fat-jar would be `build/libs/demo-0.0.1-SNAPSHOT.jar`.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
You don't need repos `libs-milestone` and `libs-snapshot` for
|
||||
|
||||
The expected Spring Boot-packaged fat jar would be `build/libs/demo-0.0.1-SNAPSHOT.jar`.
|
||||
|
||||
NOTE: You do not need the`libs-milestone` and `libs-snapshot` repositories for
|
||||
production development.
|
||||
====
|
||||
|
||||
== Using Maven
|
||||
Here is a typical `pom.xml` file created by https://start.spring.io:
|
||||
|
||||
The following example shows a typical `pom.xml` file, which was created by choosing various options at https://start.spring.io:
|
||||
|
||||
====
|
||||
[source,xml,indent=0,subs="attributes+"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
@@ -246,30 +252,30 @@ Here is a typical `pom.xml` file created by https://start.spring.io:
|
||||
|
||||
</project>
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Replace `0.0.1-SNAPSHOT` with a version you want to use.
|
||||
====
|
||||
|
||||
Having a normal project structure you'd build this with command:
|
||||
IMPORTANT: 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:
|
||||
|
||||
====
|
||||
[source,text,indent=0]
|
||||
----
|
||||
# mvn clean package
|
||||
----
|
||||
|
||||
Expected Spring Boot packaged fat-jar would be `target/demo-0.0.1-SNAPSHOT.jar`.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
You don't need repos `libs-milestone` and `libs-snapshot` for
|
||||
|
||||
The expected Spring Boot-packaged fat-jar would be `target/demo-0.0.1-SNAPSHOT.jar`.
|
||||
|
||||
NOTE: You do not need the `libs-milestone` and `libs-snapshot` repositories for
|
||||
production development.
|
||||
|
||||
== 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:
|
||||
|
||||
====
|
||||
|
||||
== Developing your first Spring Statemachine application
|
||||
Let's start by creating a simple Spring Boot `Application` class
|
||||
implementing `CommandLineRunner`.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@SpringBootApplication
|
||||
@@ -281,8 +287,11 @@ public class Application implements CommandLineRunner {
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Add states and events:
|
||||
Then you need to add states and events, as the following example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
public enum States {
|
||||
@@ -293,8 +302,11 @@ public enum Events {
|
||||
E1, E2
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Add state machine configuration:
|
||||
Then you need to add state machine configuration, as the following example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Configuration
|
||||
@@ -342,8 +354,12 @@ public class StateMachineConfig
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Implement `CommandLineRunner`, autowire `StateMachine`:
|
||||
Then you need to implement `CommandLineRunner` and autowire `StateMachine`.
|
||||
The following example shows how to do so:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Autowired
|
||||
@@ -355,18 +371,23 @@ public void run(String... args) throws Exception {
|
||||
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.
|
||||
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.
|
||||
|
||||
What is expected for running this command is a normal Spring Boot output
|
||||
but if you look closely you see lines:
|
||||
The result of this command should be normal Spring Boot output.
|
||||
However, you should also find the following lines:
|
||||
|
||||
====
|
||||
[source,text,indent=0]
|
||||
----
|
||||
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.
|
||||
|
||||
@@ -17,11 +17,19 @@
|
||||
= Spring Statemachine - Reference Documentation
|
||||
|
||||
include::preface.adoc[]
|
||||
|
||||
include::introduction.adoc[]
|
||||
|
||||
include::getting-started.adoc[]
|
||||
|
||||
include::whatsnew.adoc[]
|
||||
|
||||
include::sm.adoc[]
|
||||
|
||||
include::recipes.adoc[]
|
||||
|
||||
include::sm-examples.adoc[]
|
||||
|
||||
include::faq.adoc[]
|
||||
|
||||
include::appendix.adoc[]
|
||||
|
||||
@@ -1,60 +1,62 @@
|
||||
[[introduction]]
|
||||
= Introduction
|
||||
Spring Statemachine(SSM) is a framework for application developers to
|
||||
use traditional state machine concepts with Spring applications. SSM
|
||||
aims to provide the following features:
|
||||
|
||||
* Easy to use flat one level state machine for simple use cases.
|
||||
Spring Statemachine (SSM) is a framework that lets application developers
|
||||
use traditional state machine concepts with Spring applications. SSM
|
||||
provides the following features:
|
||||
|
||||
* Easy-to-use flat (one-level) state machine for simple use cases.
|
||||
* Hierarchical state machine structure to ease complex state
|
||||
configuration.
|
||||
* State machine regions to provide even more complex state
|
||||
configurations.
|
||||
* Usage of triggers, transitions, guards and actions.
|
||||
* Type safe configuration adapter.
|
||||
* Usage of triggers, transitions, guards, and actions.
|
||||
* Type-safe configuration adapter.
|
||||
* State machine event listeners.
|
||||
* Spring IOC integration to associate beans with a state machine.
|
||||
* Spring IoC integration to associate beans with a state machine.
|
||||
|
||||
Before you continue it's worth to go through appendices <<glossary>>
|
||||
and <<crashcourse>> to get a generic idea of what state machines are,
|
||||
mostly because the rest of the documentation expects the reader to be
|
||||
fairly familiar with state machine concepts.
|
||||
Before you continue, we recommend going through the appendices <<glossary>>
|
||||
and <<crashcourse>> to get a generic idea of what state machines are.
|
||||
The rest of the documentation expects you to be
|
||||
familiar with state machine concepts.
|
||||
|
||||
== Background
|
||||
State machines are powerful because behaviour is always guaranteed to be
|
||||
|
||||
State machines are powerful because their behavior is always guaranteed to be
|
||||
consistent and relatively easily debugged due to how operational
|
||||
rules are written in stone when machine is started. The idea is that your
|
||||
application is and may exist in a finite number of states and then something
|
||||
happens which takes your application from one state to the next. What
|
||||
will drive a state machine are triggers, which are either based on
|
||||
rules are written in stone when a machine is started. The idea is that your
|
||||
application is now in and may exist in a finite number of states. Then something
|
||||
happens that takes your application from one state to the next.
|
||||
A state machine is driven by triggers, which are based on either
|
||||
events or timers.
|
||||
|
||||
It is much easier to design high level logic outside of your
|
||||
It is much easier to design high-level logic outside of your
|
||||
application and then interact with a state machine in various
|
||||
different ways. You can simply interact with a state machine by
|
||||
sending events, listening to what a state machine does or simply requesting
|
||||
different ways. You can interact with a state machine by
|
||||
sending events, listening to what a state machine does, or requesting
|
||||
the current state.
|
||||
|
||||
Traditionally state machines are added to an existing project when
|
||||
Traditionally, state machines are added to an existing project when
|
||||
developers realize that the code base is starting to look like a plate
|
||||
full of spaghetti. Spaghetti code looks like a never ending, hierarchical
|
||||
structure of IFs, ELSEs and BREAK clauses and probably compilers should
|
||||
structure of IF, ELSE, and BREAK clauses, and compilers should probably
|
||||
ask developers to go home when things are starting to look too complex.
|
||||
|
||||
== Usage Scenarios
|
||||
|
||||
A project is a good candidate to use a state machine if:
|
||||
A project is a good candidate to use a state machine when:
|
||||
|
||||
* The application or part of its structure can be represented as states.
|
||||
* You can represent the application or part of its structure as states.
|
||||
* You want to split complex logic into smaller manageable tasks.
|
||||
* The application is already suffering concurrency issues with i.e.
|
||||
* The application is already suffering concurrency issues with (for example)
|
||||
something happening asynchronously.
|
||||
|
||||
You are already trying to implement a state machine if:
|
||||
You are already trying to implement a state machine when you:
|
||||
|
||||
* Using boolean flags or enums to model situations.
|
||||
* Having variables which only have meaning for some part of your
|
||||
* Use boolean flags or enums to model situations.
|
||||
* Have variables that have meaning only for some part of your
|
||||
application lifecycle.
|
||||
* Looping through if/else structure and checking if a particular flag or
|
||||
enum is set and then making further exceptions about what to do when certain
|
||||
combinations of your flags and enums exist or don't exist together.
|
||||
|
||||
* Loop through an if-else structure (or, worse, multiple such structures),
|
||||
check whether a particular flag or
|
||||
enum is set, and then make further exceptions about what to do when certain
|
||||
combinations of your flags and enums exist or do not exist.
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
[preface]
|
||||
== Preface
|
||||
The concept of a state machine is most likely older that any reader
|
||||
|
||||
The concept of a state machine is most likely older than any reader
|
||||
of this reference documentation and definitely older than the Java
|
||||
language itself. Description of finite automata dates back to 1943
|
||||
when gentlemen Warren McCulloch and Walter Pitts wrote a paper about
|
||||
it. Later George H. Mealy presented a state machine concept in 1955
|
||||
which is known as a Mealy Machine. A year later in 1956 Edward F.
|
||||
Moore presented another paper which is known as a Moore Machine. If
|
||||
you've ever read anything about state machines, the names Mealy and Moore
|
||||
it. Later George H. Mealy presented a state machine concept (known as
|
||||
a "`Mealy Machine`") in 1955. A year later, in 1956, Edward F.
|
||||
Moore presented another paper, in which he described what is known as
|
||||
a "`Moore Machine`". If
|
||||
you have ever read anything about state machines, the names, Mealy and Moore,
|
||||
should have popped up at some point.
|
||||
|
||||
This reference documentation contains the following parts.
|
||||
This reference documentation contains the following parts:
|
||||
|
||||
<<introduction>> introduction to this reference documentation
|
||||
<<introduction>> contains introduction to this reference documentation.
|
||||
|
||||
<<statemachine>> describes the usage of Spring Statemachine(SSM)
|
||||
<<statemachine>> describes the usage of Spring Statemachine(SSM).
|
||||
|
||||
<<statemachine-examples>> more detailed state machine examples
|
||||
<<statemachine-examples>> contains more detailed state machine examples.
|
||||
|
||||
<<statemachine-faq>> frequently asked questions
|
||||
|
||||
<<appendices>> generic info about used material and state machines
|
||||
<<statemachine-faq>> contains frequently asked questions.
|
||||
|
||||
<<appendices>> contains generic information about used material and state machines.
|
||||
|
||||
@@ -1,130 +1,145 @@
|
||||
[[statemachine-recipes]]
|
||||
= Recipes
|
||||
|
||||
This chapter contains documentation for existing built-in state
|
||||
machine recipes.
|
||||
|
||||
What exactly is a recipe? As Spring Statemachine is always going to be
|
||||
a foundational framework meaning that its core will not have that much
|
||||
higher level functionality or dependencies outside of a Spring
|
||||
Framework. Correct usage of a state machine may be a little difficult
|
||||
time to time and there's always some common use cases how state
|
||||
machine can be used. Recipe modules are meant to provide a higher
|
||||
level solutions to these common use cases and also provide examples
|
||||
beyond samples how framework can be used.
|
||||
Spring Statemachine is a foundational framework. That is, it does not have much
|
||||
higher-level functionality or many dependencies beyond Spring Framework.
|
||||
Consequently, correctly using a state machine may be difficult. To help,
|
||||
we have created a set of recipe modules that address common use cases.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Recipes are a great way to make external contributions this Spring
|
||||
Statemachine project. If you're not ready to contribute to the
|
||||
What exactly is a recipe? A state machine recipe is a module that addresses a common
|
||||
use case. In essence, a state machine recipe is both an example that we have tried to
|
||||
make it easy for you to reuse and extend.
|
||||
|
||||
NOTE: Recipes are a great way to make external contributions to the Spring
|
||||
Statemachine project. If you are not ready to contribute to the
|
||||
framework core itself, a custom and common recipe is a great way to
|
||||
share functionality among other users.
|
||||
====
|
||||
share functionality with other users.
|
||||
|
||||
[[statemachine-recipes-persist]]
|
||||
== Persist
|
||||
Persist recipe is a simple utility which allows to use a single state
|
||||
machine instance to persist and update a state of an arbitrary item in
|
||||
|
||||
The persist recipe is a simple utility that lets you use a single state
|
||||
machine instance to persist and update the state of an arbitrary item in
|
||||
a repository.
|
||||
|
||||
Recipes main class is `PersistStateMachineHandler` which assumes user
|
||||
to do three different things:
|
||||
The recipe's main class is `PersistStateMachineHandler`, which makes three assumptions:
|
||||
|
||||
- An instance of a `StateMachine<String, String>` needs to be used
|
||||
with a `PersistStateMachineHandler`. States and Events are required
|
||||
to be type of Strings.
|
||||
- `PersistStateChangeListener` need to be registered with handler
|
||||
order to react to persist request.
|
||||
- Method `handleEventWithState` is used to orchestrate state changes.
|
||||
* An instance of a `StateMachine<String, String>` needs to be used
|
||||
with a `PersistStateMachineHandler`. Note that states and Events are required
|
||||
to be type of `String`.
|
||||
* `PersistStateChangeListener` needs to be registered with handler
|
||||
to react to persist request.
|
||||
* The `handleEventWithState` method is used to orchestrate state changes.
|
||||
|
||||
There is a sample demonstrating usage of this recipe at
|
||||
You can find a sample that shows how to use this recipe at
|
||||
<<statemachine-examples-persist>>.
|
||||
|
||||
[[statemachine-recipes-tasks]]
|
||||
== Tasks
|
||||
Tasks recipe is a concept to execute DAG of `Runnable` instances using
|
||||
a state machine. This recipe has been developed from ideas introduced
|
||||
in sample <<statemachine-examples-tasks>>.
|
||||
|
||||
Generic concept of a state machine is shown below. In this state chart
|
||||
everything under `TASKS` just shows a generic concept of how a single
|
||||
task is executed. Because this recipe allows to register deep
|
||||
hierarchical DAG of tasks, meaning a real state chart would be deep
|
||||
nested collection of sub-states and regions, there's no need to be
|
||||
The tasks recipe is a concept to run DAG (Directed Acrylic Graph) of `Runnable` instances that use
|
||||
a state machine. This recipe has been developed from ideas introduced
|
||||
in <<statemachine-examples-tasks>> sample.
|
||||
|
||||
The next image shows the generic concept of a state machine. In this state chart,
|
||||
everything under `TASKS` shows a generic concept of how a single
|
||||
task is executed. Because this recipe lets you register a deep
|
||||
hierarchical DAG of tasks (meaning a real state chart would be a deeply
|
||||
nested collection of sub-states and regions), we have no need to be
|
||||
more precise.
|
||||
|
||||
For example if you have only two registered tasks, below state chart
|
||||
would be correct with `TASK_id` replaced with `TASK_1` and `TASK_2` if
|
||||
registered tasks ids are `1` and `2`.
|
||||
For example, if you have only two registered tasks, the following state chart
|
||||
would be correct when `TASK_id` is replaced with `TASK_1` and `TASK_2` (assuming
|
||||
the registered tasks IDs are `1` and `2`).
|
||||
|
||||
image::images/statechart9.png[width=500]
|
||||
|
||||
Executing a `Runnable` may result an error and especially if a complex
|
||||
DAG of tasks is involved it is desirable that there is a way to handle
|
||||
tasks execution errors and then having a way to continue execution
|
||||
without executing already successfully executed tasks. Addition to
|
||||
this it would be nice if some execution errors can be handled
|
||||
automatically and as a last fallback, if error can't be handled
|
||||
automatically, state machine is put into a state where user can handle
|
||||
Executing a `Runnable` may result an error. Especially if a complex
|
||||
DAG of tasks is involved, you want to have a way to handle
|
||||
task execution errors and then have a way to continue execution
|
||||
without executing already successfully executed tasks. Also,
|
||||
it would be nice if some execution errors can be handled
|
||||
automatically. As a last fallback, if an error cannot be handled
|
||||
automatically, the state machine is put into a state where the user can handle
|
||||
errors manually.
|
||||
|
||||
`TasksHandler` contains a builder method to configure handler instance
|
||||
and follows a simple builder pattern. This builder can be used to
|
||||
register `Runnable` tasks, `TasksListener` instances, define
|
||||
`StateMachinePersist` hook, and setup custom `TaskExecutor` instance.
|
||||
`TasksHandler` contains a builder method to configure a handler instance
|
||||
and follows a simple builder pattern. You can use this builder to
|
||||
register `Runnable` tasks and `TasksListener` instances, define
|
||||
`StateMachinePersist` hook, and set up custom `TaskExecutor` instance.
|
||||
|
||||
Now let's take a simple `Runnable` just doing a simple sleep as shown
|
||||
below. This is a base of all examples in this chapter.
|
||||
Now we can take a simple `Runnable` that runs a simple sleep as the following
|
||||
example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsTasksSampleTests.java[tags=snippetAA]
|
||||
----
|
||||
====
|
||||
|
||||
To execute multiple `sleepRunnable` tasks just register tasks and
|
||||
execute `runTasks()` method from `TasksHandler`.
|
||||
NOTE: The preceding example is the base for all of the examples in this chapter.
|
||||
|
||||
To execute multiple `sleepRunnable` tasks, you can register tasks and
|
||||
execute `runTasks()` method from `TasksHandler`, as the following example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsTasksSampleTests.java[tags=snippetB]
|
||||
----
|
||||
====
|
||||
|
||||
Order to listen what is happening with a task execution an instance of
|
||||
a `TasksListener` can be registered with a `TasksHandler`. Recipe
|
||||
provides an adapter `TasksListenerAdapter` if you don't want to
|
||||
implement a full interface. Listener provides a various hooks to
|
||||
listen tasks execution events.
|
||||
To listen to what is happening with a task execution, you can register an instance of
|
||||
a `TasksListener` with a `TasksHandler`. This recipe
|
||||
provides an adapter `TasksListenerAdapter` if you do not want to
|
||||
implement a full interface. The listener provides a various hooks to
|
||||
listen tasks execution events. The following example shows the definition of the
|
||||
`MyTasksListener` class:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsTasksSampleTests.java[tags=snippetAB]
|
||||
----
|
||||
====
|
||||
|
||||
Listeners can be either registered via a builder or directly with a
|
||||
`TasksHandler` as shown above.
|
||||
You can either register listeners by using a builder or register them directly with a
|
||||
`TasksHandler` as the following example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsTasksSampleTests.java[tags=snippetC]
|
||||
----
|
||||
====
|
||||
|
||||
Above sample show how to create a deep nested DAG of tasks. Every task
|
||||
needs to have an unique identifier and optionally as task can be
|
||||
defined to be a sub-task. Effectively this will create a DAG of tasks.
|
||||
Every task
|
||||
needs to have a unique identifier, and (optionally) a task can be
|
||||
defined to be a sub-task. Effectively, this creates a DAG of tasks.
|
||||
The following example shows how to create a deep nested DAG of tasks:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsTasksSampleTests.java[tags=snippetD]
|
||||
----
|
||||
====
|
||||
|
||||
When error happens and a state machine running these tasks goes into a
|
||||
`ERROR` state, user can call handler methods `fixCurrentProblems` to
|
||||
reset current state of tasks kept in a state machine extended state
|
||||
variables. Handler method `continueFromError` can then be used to
|
||||
instruct state machine to transition from `ERROR` state back to
|
||||
`READY` state where tasks can be executed again.
|
||||
When an error happens and the state machine running these tasks goes into an
|
||||
`ERROR` state, you can call `fixCurrentProblems` handler method to
|
||||
reset the current state of the tasks kept in the state machine's extended state
|
||||
variables. You can then use the `continueFromError` handler method to
|
||||
instruct the state machine to transition from the `ERROR` state back to the
|
||||
`READY` state, where you can again run tasks.
|
||||
The following example shows how to do so:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsTasksSampleTests.java[tags=snippetE]
|
||||
----
|
||||
|
||||
====
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -2,57 +2,62 @@
|
||||
= What's New
|
||||
|
||||
== In 1.1
|
||||
_Spring Statemachine 1.1_ is focusing on security and a better
|
||||
interoperability with web applications.
|
||||
|
||||
* Comprehensive support for _Spring Security_ is added, <<sm-security>>
|
||||
Spring Statemachine 1.1 focuses on security and better
|
||||
interoperability with web applications. It includes the following:
|
||||
|
||||
* Comprehensive support for Spring Security has been added. See <<sm-security>>.
|
||||
* Context integration with `@WithStateMachine' has been greatly
|
||||
enhanced, <<sm-context>>
|
||||
* `StateContext` is now a first class citizen with how user can
|
||||
interact with a State Machine, <<sm-statecontext>>.
|
||||
* Features around persistence has been enhanced with a build-in
|
||||
support for redis, <<sm-persist-redis>>.
|
||||
* New feature helping with persist operations,
|
||||
enhanced. See <<sm-context>>.
|
||||
* `StateContext` is now a first class citizen, letting you
|
||||
interact with a State Machine. See <<sm-statecontext>>.
|
||||
* Features around persistence have been enhanced with built-in
|
||||
support for redis. See <<sm-persist-redis>>.
|
||||
* A new feature helps with persist operations. See
|
||||
<<sm-persist-statemachinepersister>>.
|
||||
* Configuration model classes are now a public API.
|
||||
* New features in timer based events.
|
||||
* New _Junction_ pseudostate <<statemachine-config-states-junction>>.
|
||||
* New _Exit Point_ and _Entry Point_ pseudostates <<statemachine-config-states-exitentry>>.
|
||||
* Configuration model classes are now in a public API.
|
||||
* New features in timer-based events.
|
||||
* New `Junction` pseudostate. See <<statemachine-config-states-junction>>.
|
||||
* New Exit Point and Entry Point pseudostates. See <<statemachine-config-states-exitentry>>.
|
||||
* Configuration model verifier.
|
||||
* New samples, <<statemachine-examples-security>>, <<statemachine-examples-eventservice>>.
|
||||
* UI modeling support using Eclipse Papyrus, <<sm-papyrus>>.
|
||||
* New samples. See <<statemachine-examples-security>> and <<statemachine-examples-eventservice>>.
|
||||
* UI modeling support using Eclipse Papyrus. See <<sm-papyrus>>.
|
||||
|
||||
== In 1.2
|
||||
_Spring Statemachine 1.2_ is focusing generic enhancements, better
|
||||
_UML_ support and integrations with external config repositories.
|
||||
|
||||
* Support for UML submachines <<sm-papyrus-submachineref>>
|
||||
* New _Repository_ abstraction keeping machine configuration in an
|
||||
external repository <<sm-repository>>
|
||||
* New support for state actions. <<state-actions>>
|
||||
* New transition error action concepts. <<statemachine-config-transition-actions-errorhandling>>
|
||||
* New action error action concepts. <<statemachine-config-state-actions-errorhandling>>
|
||||
* Initial work for _Spring Boot_ support. <<sm-boot>>
|
||||
* Support for tracing and monitoring. <<sm-monitoring>>
|
||||
Spring Statemachine 1.2 focuses on generic enhancements, better
|
||||
UML support, and integrations with external config repositories.
|
||||
It includes the following:
|
||||
|
||||
* Support for UML sub-machines. See <<sm-papyrus-submachineref>>.
|
||||
* A new repository abstraction that keeps machine configuration in an
|
||||
external repository. See <<sm-repository>>.
|
||||
* New support for state actions. See <<state-actions>>.
|
||||
* New transition error action concepts. See <<statemachine-config-transition-actions-errorhandling>>.
|
||||
* New action error concepts. See <<statemachine-config-state-actions-errorhandling>>.
|
||||
* Initial work for Spring Boot support. See <<sm-boot>>.
|
||||
* Support for tracing and monitoring. See <<sm-monitoring>>.
|
||||
|
||||
=== In 1.2.8
|
||||
_Spring Statemachine 1.2.8_ contains a bit more functionality normally
|
||||
not seen in a point release but these changes didn't merit a fork of
|
||||
_Spring Statemachine 1.3_.
|
||||
|
||||
* JPA entity classes have changed table names <<sm-repository-config-jpa>>
|
||||
* New sample <<statemachine-examples-datapersist>>
|
||||
* New _Entity_ classes for persistence <<sm-repository-persistence>>
|
||||
used with <<sm-repository-persistence>>
|
||||
* Transition conflict policy mentioned in
|
||||
Spring Statemachine 1.2.8 contains a bit more functionality than normally
|
||||
not seen in a point release, but these changes did not merit a fork of
|
||||
Spring Statemachine 1.3. It includes the following:
|
||||
|
||||
* JPA entity classes have changed table names. See <<sm-repository-config-jpa>>.
|
||||
* A new sample. See <<statemachine-examples-datapersist>>.
|
||||
* New entity classes for persistence. See <<sm-repository-persistence>>.
|
||||
* Transition conflict policy. See
|
||||
<<statemachine-config-commonsettings>>
|
||||
|
||||
== In 2.0
|
||||
_Spring Statemachine 2.0_ is focusing on _Spring Boot 2.x_ support.
|
||||
|
||||
Spring Statemachine 2.0 focuses on Spring Boot 2.x support.
|
||||
|
||||
|
||||
=== In 2.0.0
|
||||
|
||||
* Format of monitoring and tracing has been changed <<sm-boot-monitoring>>
|
||||
* Module `spring-statemachine-boot` has been renamed to `spring-statemachine-autoconfigure`
|
||||
Spring Statemachine 2.0.0 includes the following:
|
||||
|
||||
* The format of monitoring and tracing has been changed. See <<sm-boot-monitoring>>.
|
||||
* The `spring-statemachine-boot` module has been renamed to `spring-statemachine-autoconfigure`.
|
||||
|
||||
Reference in New Issue
Block a user