Updates to docs
This commit is contained in:
@@ -181,6 +181,7 @@ configure(rootProject) {
|
||||
task copyDocsSamples(type: Copy) {
|
||||
from 'spring-statemachine-core/src/test/java/org/springframework/statemachine/docs'
|
||||
from 'spring-statemachine-samples/src/main/java/'
|
||||
from 'spring-statemachine-samples/washer/src/main/java/'
|
||||
from 'spring-statemachine-samples/tasks/src/main/java/'
|
||||
from 'spring-statemachine-samples/turnstile/src/main/java/'
|
||||
from 'spring-statemachine-samples/showcase/src/main/java/'
|
||||
|
||||
@@ -15,6 +15,16 @@ material in this reference documentation.
|
||||
include::samples/States.java[tags=snippetA]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/States2.java[tags=snippetA]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/States3.java[tags=snippetA]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/Events.java[tags=snippetA]
|
||||
@@ -86,6 +96,22 @@ directly contained in a state machine and all other regions in the
|
||||
state machine also are completed, then it means that the entire state
|
||||
machine is completed.
|
||||
|
||||
*History State*::
|
||||
A pseudo state which allows a state machine to remember its last
|
||||
active state. Two types of history state exists, _shallow_ which only
|
||||
remember top level state and _deep_ which remembers active states in a
|
||||
sub-machines.
|
||||
|
||||
*Choice State*::
|
||||
A pseudo state which allows to make a transition choice based of i.e.
|
||||
event headers or extended state variables.
|
||||
|
||||
*Fork State*::
|
||||
A pseudo state which gives a controlled entry into a regions.
|
||||
|
||||
*Join State*::
|
||||
A pseudo state which gives a controlled exit from a regions.
|
||||
|
||||
*Region*::
|
||||
A region is an orthogonal part of either a composite state or a state
|
||||
machine. It contains states and transitions.
|
||||
@@ -124,6 +150,45 @@ flags, nested if/else/break clauses or other impractical logic you
|
||||
simply rely on state, state variables or other interaction with a
|
||||
state machine.
|
||||
|
||||
==== Pseudo States
|
||||
PseudoState is a special type of state which usually introduces more
|
||||
higher level logic into a state machine by either giving a state a
|
||||
special meaning like initial state. State machine can then internally
|
||||
react to these states by doing various actions available in UML state
|
||||
machine concepts.
|
||||
|
||||
===== Initial
|
||||
Initial state is always needed for every single state machine whether
|
||||
you have a simple one level state machine or more complex state
|
||||
machine composed with submachines or regions. Initial state simple
|
||||
defines where state machine should go when it starts and without it
|
||||
state machine is ill-formed.
|
||||
|
||||
===== End
|
||||
Terminate state which is also called as end state will indicate that a
|
||||
particular state machine has reached its final state. Effectively this
|
||||
mean that a state machine will no longer process any events and will
|
||||
not transit to any other state. However in a case of submachines are
|
||||
regions, state machine is able to restart from its terminal state.
|
||||
|
||||
===== Choice
|
||||
Choice can be used to choose a transition conditionally.
|
||||
|
||||
===== History
|
||||
History state can be used to remember a last active state
|
||||
configuration. After state machine has been exited, history state can
|
||||
be used to restore previous knows configuration. There are two types
|
||||
of history states available, _SHALLOW_ only remember active state of a
|
||||
state machine itself while _DEEP_ also remembers nested states.
|
||||
|
||||
===== Fork
|
||||
Fork can be used to do an explicit entry into one or more regions.
|
||||
|
||||
===== Join
|
||||
Join is used to merge several transitions together originating from
|
||||
different regions. It it generally used to wait and block for
|
||||
participating regions to get into its join target states.
|
||||
|
||||
==== Guard Conditions
|
||||
Guard conditions are expressions which evaluates either to *TRUE* or
|
||||
*FALSE* based on extended state variables and event parameters. Guards
|
||||
|
||||
BIN
docs/src/reference/asciidoc/images/statechart5.png
Normal file
BIN
docs/src/reference/asciidoc/images/statechart5.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/src/reference/asciidoc/images/statechart6.png
Normal file
BIN
docs/src/reference/asciidoc/images/statechart6.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@@ -442,3 +442,183 @@ What happened in above run:
|
||||
* We print lcd status and request next track.
|
||||
* We stop playing.
|
||||
|
||||
== Tasks
|
||||
|
||||
Tasks is a sample demonstrating a parallel task handling within a
|
||||
regions and additionally adds an error handling to either
|
||||
automatically or manually fixing task problems before continuing back
|
||||
to a state where tasks can be run again.
|
||||
|
||||
image::images/statechart5.png[width=500]
|
||||
|
||||
On a high level what happens in this state machine is:
|
||||
|
||||
* We're always trying to get into READY state so that we can use event
|
||||
RUN to execute tasks.
|
||||
* TASKS state which is composed with 3 independent regions has been
|
||||
put in a middle of FORK and JOIN states which will cause regions to
|
||||
go into its initial states and to be joined by end states.
|
||||
* From JOIN state we go automatically into a CHOICE state which checks
|
||||
existence of error flags in extended state variables. Tasks can set
|
||||
these flags and it gives CHOICE state a possibility to go into ERROR
|
||||
state where errors can be handled either automatically or manually.
|
||||
* AUTOMATIC state in ERROR can try to automatically fix error and goes
|
||||
back to READY if it succeed to do so. If error is something what
|
||||
can't be handled automatically, user intervention is needed and
|
||||
machine is put into MANUAL state via FALLBACK event.
|
||||
|
||||
.States
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/tasks/Application.java[tags=snippetB]
|
||||
----
|
||||
|
||||
.Events
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/tasks/Application.java[tags=snippetC]
|
||||
----
|
||||
|
||||
.Configuration - states
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/tasks/Application.java[tags=snippetAA]
|
||||
----
|
||||
|
||||
.Configuration - transitions
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/tasks/Application.java[tags=snippetAB]
|
||||
----
|
||||
|
||||
Guard below is guarding choice entry into a ERROR state and needs to
|
||||
return TRUE if error has happened. For this guard simply checks that
|
||||
all extended state variables(T1, T2 and T3) are TRUE.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/tasks/Application.java[tags=snippetAC]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/tasks/Application.java[tags=snippetAD]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/tasks/Application.java[tags=snippetAE]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/tasks/Application.java[tags=snippetAF]
|
||||
----
|
||||
|
||||
Lets see an example how this state machine actually works.
|
||||
|
||||
[source,text]
|
||||
----
|
||||
sm>sm start
|
||||
State machine started
|
||||
Entry state READY
|
||||
|
||||
sm>tasks run
|
||||
Entry state TASKS
|
||||
run task on T1
|
||||
run task on T2
|
||||
run task on T3
|
||||
run task on T1 done
|
||||
run task on T2 done
|
||||
run task on T3 done
|
||||
Entry state T1
|
||||
Entry state T3
|
||||
Entry state T2
|
||||
Entry state T1E
|
||||
Entry state T2E
|
||||
Entry state T3E
|
||||
Exit state TASKS
|
||||
Entry state JOIN
|
||||
Exit state JOIN
|
||||
Entry state READY
|
||||
|
||||
sm>
|
||||
----
|
||||
|
||||
== Washer
|
||||
|
||||
Washer is a sample demonstrating a use of a history state to recover a
|
||||
running state configuration with a simulated power off situation.
|
||||
|
||||
Anyone ever used a washing machine knows that if you can somehow pause
|
||||
the program it will continue from a same state when lid is closed.
|
||||
This kind of behaviour can be implemented in a state machine by using
|
||||
a history pseudo state.
|
||||
|
||||
image::images/statechart6.png[width=500]
|
||||
|
||||
.States
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/washer/Application.java[tags=snippetB]
|
||||
----
|
||||
|
||||
.Events
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/washer/Application.java[tags=snippetC]
|
||||
----
|
||||
|
||||
.Configuration - states
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/washer/Application.java[tags=snippetAA]
|
||||
----
|
||||
|
||||
.Configuration - transitions
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/washer/Application.java[tags=snippetAB]
|
||||
----
|
||||
|
||||
Lets see an example how this state machine actually works.
|
||||
[source,text]
|
||||
----
|
||||
sm>sm start
|
||||
Entry state RUNNING
|
||||
Entry state WASHING
|
||||
State machine started
|
||||
|
||||
sm>sm event RINSE
|
||||
Exit state WASHING
|
||||
Entry state RINSING
|
||||
Event RINSE send
|
||||
|
||||
sm>sm event DRY
|
||||
Exit state RINSING
|
||||
Entry state DRYING
|
||||
Event DRY send
|
||||
|
||||
sm>sm event CUTPOWER
|
||||
Exit state DRYING
|
||||
Exit state RUNNING
|
||||
Entry state POWEROFF
|
||||
Event CUTPOWER send
|
||||
|
||||
sm>sm event RESTOREPOWER
|
||||
Exit state POWEROFF
|
||||
Entry state RUNNING
|
||||
Entry state WASHING
|
||||
Entry state DRYING
|
||||
Event RESTOREPOWER send
|
||||
----
|
||||
|
||||
What happened in above run:
|
||||
|
||||
* State machine is started which causes machine to get initialized.
|
||||
* We go to RINSING state.
|
||||
* We go to DRYING state.
|
||||
* We cut power and go to POWEROFF state.
|
||||
* State is restored via HISTORY state which takes state machine back
|
||||
to its previous known state.
|
||||
|
||||
|
||||
@@ -22,6 +22,15 @@ Statemachine is configured and how it leverages Spring's lightweight
|
||||
IoC containers to simplify the application internals to make it more
|
||||
manageable.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Configuration examples in this section are not feature complete, i.e.
|
||||
you always need to have definitions of both states and transitions,
|
||||
otherwise state machine configuration would be ill-formed. We have
|
||||
simply made code snippets less verbose by leaving other needed parts
|
||||
away.
|
||||
====
|
||||
|
||||
=== Configuring States
|
||||
We'll get into more complex configuration examples a bit later but
|
||||
lets first start with a something simple. For most simple state
|
||||
@@ -43,6 +52,20 @@ particular states are sub-states of some other state.
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetB]
|
||||
----
|
||||
|
||||
=== Configuring Regions
|
||||
|
||||
There are no special configuration methods to mark a collection of
|
||||
states to be part of a orthogonal state. To put it simple, orthogonal
|
||||
state is created when same hierarchical state machine has multiple set
|
||||
of states each having a initial state. Because a individual state
|
||||
machine can only have one initial state, multiple initial states mush
|
||||
mean that a specific state mush have multiple independent regions.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetP]
|
||||
----
|
||||
|
||||
=== Configuring Transitions
|
||||
We support three different types of transitions, `external`,
|
||||
`internal` and `local`. Transitions are either triggered by a signal
|
||||
@@ -80,6 +103,93 @@ Actions can be defined with various steps within a state transitions.
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetE]
|
||||
----
|
||||
|
||||
=== Configuring Pseudo States
|
||||
|
||||
_Pseudo state_ configuration is usually done by configuring states and
|
||||
transitions. Pseudo states are automatically added to state machine as
|
||||
states.
|
||||
|
||||
==== Initial State
|
||||
Simply mark a particular state as initial state by using `initial()`
|
||||
method. There are two methods where one takes extra argument to define
|
||||
an initial action. This initial action is good for example initialize
|
||||
extended state variables.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetQ]
|
||||
----
|
||||
|
||||
==== Terminate State
|
||||
Simply mark a particular state as end state by using `end()` method.
|
||||
This can be done max one time per individual sub-machine or region.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetA]
|
||||
----
|
||||
|
||||
==== History State
|
||||
History state can be defined once for each individual state machine.
|
||||
You need to choose its state identifier and `History.SHALLOW` or
|
||||
`History.DEEP` respectively.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetR]
|
||||
----
|
||||
|
||||
==== Choice State
|
||||
Choice needs to be defined in both states and transitions to work
|
||||
properly. Mark particular state as choice state by using `choice()`
|
||||
method. This state needs to match source state when transition is
|
||||
configured for this choice.
|
||||
|
||||
Transition is configured using `withChoice()` where you define source
|
||||
state and `first/then/last` structure which is equivalent to normal
|
||||
`if/elseif/else`. With `first` and `then` you can specify a guard just
|
||||
like you'd use a condition with `if/elseif` clauses.
|
||||
|
||||
Transition needs to be able to exist so make sure `last` is used.
|
||||
Otherwise configuration is ill-formed.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetS]
|
||||
----
|
||||
|
||||
==== Fork State
|
||||
Fork needs to be defined in both states and transitions to work
|
||||
properly. Mark particular state as choice state by using `fork()`
|
||||
method. This state needs to match source state when transition is
|
||||
configured for this fork.
|
||||
|
||||
Target state needs to be a super state or immediate states in
|
||||
regions. Using a super state as target will take all regions into
|
||||
initial states. Targeting individual state give more controlled entry
|
||||
into regions.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetT]
|
||||
----
|
||||
|
||||
==== Join State
|
||||
Join needs to be defined in both states and transitions to work
|
||||
properly. Mark particular state as choice state by using `join()`
|
||||
method. This state doesn't need to match either source states or
|
||||
target state in a transition configuretion.
|
||||
|
||||
Select one target state where transition goes when all source states
|
||||
has been joined. If you use state hosting regions as source, end
|
||||
states of a regions are used as joins. Otherwise you can pick any
|
||||
states from a regions.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetU]
|
||||
----
|
||||
|
||||
[[sm-factories]]
|
||||
== State Machine Factories
|
||||
There are use cases when state machine needs to be created dynamically
|
||||
|
||||
@@ -39,6 +39,7 @@ import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter
|
||||
import org.springframework.statemachine.config.StateMachineFactory;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.StateConfigurer.History;
|
||||
import org.springframework.statemachine.event.StateMachineEvent;
|
||||
import org.springframework.statemachine.guard.Guard;
|
||||
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
|
||||
@@ -354,4 +355,223 @@ public class DocsConfigurationSampleTests extends AbstractStateMachineTests {
|
||||
|
||||
}
|
||||
|
||||
// tag::snippetP[]
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
public static class Config10
|
||||
extends EnumStateMachineConfigurerAdapter<States2, Events> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<States2, Events> states)
|
||||
throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial(States2.S1)
|
||||
.state(States2.S2)
|
||||
.and()
|
||||
.withStates()
|
||||
.parent(States2.S2)
|
||||
.initial(States2.S2I)
|
||||
.state(States2.S21)
|
||||
.end(States2.S2F)
|
||||
.and()
|
||||
.withStates()
|
||||
.parent(States2.S2)
|
||||
.initial(States2.S3I)
|
||||
.state(States2.S31)
|
||||
.end(States2.S3F);
|
||||
}
|
||||
|
||||
}
|
||||
// end::snippetP[]
|
||||
|
||||
// tag::snippetQ[]
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
public static class Config11 extends EnumStateMachineConfigurerAdapter<States, Events> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<States, Events> states)
|
||||
throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial(States.S1, initialAction())
|
||||
.end(States.SF)
|
||||
.states(EnumSet.allOf(States.class));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Action<States, Events> initialAction() {
|
||||
return new Action<States, Events>() {
|
||||
|
||||
@Override
|
||||
public void execute(StateContext<States, Events> context) {
|
||||
// do something initially
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
// end::snippetQ[]
|
||||
|
||||
// tag::snippetR[]
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
public static class Config12 extends EnumStateMachineConfigurerAdapter<States3, Events> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<States3, Events> states)
|
||||
throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial(States3.S1)
|
||||
.state(States3.S2)
|
||||
.and()
|
||||
.withStates()
|
||||
.parent(States3.S2)
|
||||
.initial(States3.S2I)
|
||||
.state(States3.S21)
|
||||
.state(States3.S22)
|
||||
.history(States3.SH, History.SHALLOW);
|
||||
}
|
||||
|
||||
}
|
||||
// end::snippetR[]
|
||||
|
||||
// tag::snippetS[]
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
public static class Config13 extends EnumStateMachineConfigurerAdapter<States, Events> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<States, Events> states)
|
||||
throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial(States.SI)
|
||||
.choice(States.S1)
|
||||
.end(States.SF)
|
||||
.states(EnumSet.allOf(States.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
|
||||
throws Exception {
|
||||
transitions
|
||||
.withChoice()
|
||||
.source(States.S1)
|
||||
.first(States.S2, s2Guard())
|
||||
.then(States.S3, s3Guard())
|
||||
.last(States.S4);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Guard<States, Events> s2Guard() {
|
||||
return new Guard<States, Events>() {
|
||||
|
||||
@Override
|
||||
public boolean evaluate(StateContext<States, Events> context) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Guard<States, Events> s3Guard() {
|
||||
return new Guard<States, Events>() {
|
||||
|
||||
@Override
|
||||
public boolean evaluate(StateContext<States, Events> context) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
// end::snippetS[]
|
||||
|
||||
// tag::snippetT[]
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
public static class Config14 extends EnumStateMachineConfigurerAdapter<States2, Events> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<States2, Events> states)
|
||||
throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial(States2.S1)
|
||||
.fork(States2.S2)
|
||||
.state(States2.S3)
|
||||
.and()
|
||||
.withStates()
|
||||
.parent(States2.S3)
|
||||
.initial(States2.S2I)
|
||||
.state(States2.S21)
|
||||
.state(States2.S22)
|
||||
.end(States2.S2F)
|
||||
.and()
|
||||
.withStates()
|
||||
.parent(States2.S3)
|
||||
.initial(States2.S3I)
|
||||
.state(States2.S31)
|
||||
.state(States2.S32)
|
||||
.end(States2.S3F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<States2, Events> transitions)
|
||||
throws Exception {
|
||||
transitions
|
||||
.withFork()
|
||||
.source(States2.S2)
|
||||
.target(States2.S22)
|
||||
.target(States2.S32);
|
||||
}
|
||||
|
||||
}
|
||||
// end::snippetT[]
|
||||
|
||||
// tag::snippetU[]
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
public static class Config15 extends EnumStateMachineConfigurerAdapter<States2, Events> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<States2, Events> states)
|
||||
throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial(States2.S1)
|
||||
.state(States2.S3)
|
||||
.join(States2.S4)
|
||||
.and()
|
||||
.withStates()
|
||||
.parent(States2.S3)
|
||||
.initial(States2.S2I)
|
||||
.state(States2.S21)
|
||||
.state(States2.S22)
|
||||
.end(States2.S2F)
|
||||
.and()
|
||||
.withStates()
|
||||
.parent(States2.S3)
|
||||
.initial(States2.S3I)
|
||||
.state(States2.S31)
|
||||
.state(States2.S32)
|
||||
.end(States2.S3F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<States2, Events> transitions)
|
||||
throws Exception {
|
||||
transitions
|
||||
.withJoin()
|
||||
.source(States2.S2F)
|
||||
.source(States2.S3F)
|
||||
.target(States2.S5);
|
||||
}
|
||||
|
||||
}
|
||||
// end::snippetU[]
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.springframework.statemachine.docs;
|
||||
|
||||
//tag::snippetA[]
|
||||
public enum States2 {
|
||||
S1,S2,S3,S4,S5,
|
||||
S2I,S21,S22,S2F,
|
||||
S3I,S31,S32,S3F
|
||||
}
|
||||
//end::snippetA[]
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.springframework.statemachine.docs;
|
||||
|
||||
//tag::snippetA[]
|
||||
public enum States3 {
|
||||
S1,S2,SH,
|
||||
S2I,S21,S22,S2F
|
||||
}
|
||||
//end::snippetA[]
|
||||
@@ -23,12 +23,12 @@ import org.springframework.statemachine.guard.Guard;
|
||||
@Configuration
|
||||
public class Application {
|
||||
|
||||
//tag::snippetA[]
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
static class StateMachineConfig
|
||||
extends EnumStateMachineConfigurerAdapter<States, Events> {
|
||||
|
||||
//tag::snippetAA[]
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<States, Events> states)
|
||||
throws Exception {
|
||||
@@ -62,7 +62,9 @@ public class Application {
|
||||
.state(States.AUTOMATIC, automaticAction(), null)
|
||||
.state(States.MANUAL);
|
||||
}
|
||||
//end::snippetAA[]
|
||||
|
||||
//tag::snippetAB[]
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
|
||||
throws Exception {
|
||||
@@ -108,7 +110,9 @@ public class Application {
|
||||
.state(States.ERROR)
|
||||
.event(Events.FIX);
|
||||
}
|
||||
//end::snippetAB[]
|
||||
|
||||
//tag::snippetAC[]
|
||||
@Bean
|
||||
public Guard<States, Events> tasksChoiceGuard() {
|
||||
return new Guard<States, Events>() {
|
||||
@@ -121,7 +125,9 @@ public class Application {
|
||||
}
|
||||
};
|
||||
}
|
||||
//end::snippetAC[]
|
||||
|
||||
//tag::snippetAD[]
|
||||
@Bean
|
||||
public Action<States, Events> automaticAction() {
|
||||
return new Action<States, Events>() {
|
||||
@@ -152,21 +158,25 @@ public class Application {
|
||||
}
|
||||
};
|
||||
}
|
||||
//end::snippetAD[]
|
||||
|
||||
//tag::snippetAE[]
|
||||
@Bean
|
||||
public Tasks tasks() {
|
||||
return new Tasks();
|
||||
}
|
||||
//end::snippetAE[]
|
||||
|
||||
//tag::snippetAF[]
|
||||
@Bean
|
||||
public TaskExecutor taskExecutor() {
|
||||
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
|
||||
taskExecutor.setCorePoolSize(5);
|
||||
return taskExecutor;
|
||||
}
|
||||
//end::snippetAF[]
|
||||
|
||||
}
|
||||
//end::snippetA[]
|
||||
|
||||
//tag::snippetB[]
|
||||
public static enum States {
|
||||
|
||||
@@ -41,24 +41,24 @@ public class Application {
|
||||
throws Exception {
|
||||
transitions
|
||||
.withExternal()
|
||||
.source(States.WASHING)
|
||||
.target(States.RINSING)
|
||||
.source(States.WASHING).target(States.RINSING)
|
||||
.event(Events.RINSE)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.RINSING)
|
||||
.target(States.DRYING)
|
||||
.source(States.RINSING).target(States.DRYING)
|
||||
.event(Events.DRY)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.RUNNING)
|
||||
.target(States.POWEROFF)
|
||||
.source(States.RUNNING) .target(States.POWEROFF)
|
||||
.event(Events.CUTPOWER)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.POWEROFF)
|
||||
.target(States.HISTORY)
|
||||
.event(Events.RESTOREPOWER);
|
||||
.source(States.POWEROFF).target(States.HISTORY)
|
||||
.event(Events.RESTOREPOWER)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.RUNNING).target(States.END)
|
||||
.event(Events.STOP);
|
||||
}
|
||||
//end::snippetAB[]
|
||||
|
||||
@@ -74,7 +74,7 @@ public class Application {
|
||||
|
||||
//tag::snippetC[]
|
||||
public static enum Events {
|
||||
RINSE, DRY,
|
||||
RINSE, DRY, STOP,
|
||||
RESTOREPOWER, CUTPOWER
|
||||
}
|
||||
//end::snippetC[]
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
+----------------------------------------------------------------------------------+
|
||||
| |
|
||||
+----------------------------------------------------------------------------------+
|
||||
| |
|
||||
| +--------------------------------------------------------------------+ |
|
||||
| *-->| RUNNING |-->X |
|
||||
| +--------------------------------------------------------------------+ |
|
||||
| | | |
|
||||
| | +-------------+ +-------------+ +-------------+ | |
|
||||
| | *-->| WASHING | RINSE | RINSING | DRY | DRYING | | |
|
||||
| | | |------>| |------>| | | |
|
||||
| | | | | | | | | |
|
||||
| | +-------------+ +-------------+ +-------------+ | |
|
||||
| | | |
|
||||
| | H | |
|
||||
| | ^ | |
|
||||
| +------------|-------------------------------------------------------+ |
|
||||
| | | |
|
||||
| |RESTOREPOWER |CUTPOWER |
|
||||
| | | |
|
||||
| +-------------+ | |
|
||||
| | POWEROFF | | |
|
||||
| | |<----------+ |
|
||||
| | | |
|
||||
| +-------------+ |
|
||||
| |
|
||||
+----------------------------------------------------------------------------------+
|
||||
+--------------------------------------------------------------------------------------+
|
||||
| |
|
||||
+--------------------------------------------------------------------------------------+
|
||||
| |
|
||||
| +--------------------------------------------------------------------+ STOP |
|
||||
| *-->| RUNNING |------>X |
|
||||
| +--------------------------------------------------------------------+ |
|
||||
| | | |
|
||||
| | +-------------+ +-------------+ +-------------+ | |
|
||||
| | *-->| WASHING | RINSE | RINSING | DRY | DRYING | | |
|
||||
| | | |------>| |------>| | | |
|
||||
| | | | | | | | | |
|
||||
| | +-------------+ +-------------+ +-------------+ | |
|
||||
| | | |
|
||||
| | +-------+ | |
|
||||
| | |HISTORY| | |
|
||||
| | +-------+ | |
|
||||
| | ^ | |
|
||||
| +------------|-------------------------------------------------------+ |
|
||||
| | | |
|
||||
| |RESTOREPOWER |CUTPOWER |
|
||||
| | | |
|
||||
| +-------------+ | |
|
||||
| | POWEROFF | | |
|
||||
| | |<----------+ |
|
||||
| | | |
|
||||
| +-------------+ |
|
||||
| |
|
||||
+--------------------------------------------------------------------------------------+
|
||||
|
||||
Reference in New Issue
Block a user