Reference doc updates
This commit is contained in:
@@ -29,7 +29,7 @@ Assuming we have states _STATE1_, _STATE2_ and events _EVENT1_,
|
||||
_EVENT2_, logic of state machine can be defined as shown in below
|
||||
quick example.
|
||||
|
||||
image::images/statechart0.png[]
|
||||
image::images/statechart0.png[width=500]
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@@ -129,16 +129,53 @@ A transition is a relationship between a source state and a target
|
||||
state. A switch from a state to another is a _state transition_ caused
|
||||
by a _trigger_.
|
||||
|
||||
===== Internal Transition
|
||||
Internal transition is used when action needs to be executed without
|
||||
causing a state transition. With internal transition source and target
|
||||
state is always a same and it is identical with self-transition in the
|
||||
absence of state entry and exit actions.
|
||||
|
||||
===== External vs. Local Transition
|
||||
Most of the cases external and local transition are functionally
|
||||
equivalent expect in cases where transition is happening between super
|
||||
and sub states. Local transition doesn't cause exit and entry to
|
||||
source state if target state is a substate of a source state. Other
|
||||
way around, local transition doesn't cause exit and entry to target
|
||||
state if target is a superstate of a source state.
|
||||
|
||||
image::images/statechart4.png[width=500]
|
||||
|
||||
Above image shows a different between local and external transitions
|
||||
with a very simplistic super and sub states.
|
||||
|
||||
==== Actions
|
||||
Actions are the ones which really glues state machine state changes
|
||||
with a users own code. State machine can execute action on various
|
||||
changes and steps in a state machine like entering or exiting a state,
|
||||
or doing a state transition.
|
||||
|
||||
Actions usually have access to a state context which gives running
|
||||
code a choice to interact with a state machine in a various ways.
|
||||
State context i.e. is exposing a whole state machine so user can
|
||||
access extended state variables, event headers if transition is based
|
||||
on an event, or actual transition where it is possible to see more
|
||||
detailed where this state change is coming from and where it is going.
|
||||
|
||||
==== Hierarchical State Machines
|
||||
Concept of a hierarchical state machine is used to simplify state
|
||||
design when particular states can only exist together.
|
||||
|
||||
Hierarchical states are really an innovation in UML state machine over
|
||||
a traditional state machines like Mealy or Moore machines.
|
||||
Hierarchical states allows to define some level of abstraction is a
|
||||
sense how java developer would define a class structure with abstract
|
||||
classes. For example having a nested state machine user is able to
|
||||
define transition on a multiple level of states possibly with a
|
||||
different conditions. State machine will always try to see if current
|
||||
state is able to handle an event together with a transition guard
|
||||
conditions. If these conditions are not evaluated to true, state
|
||||
machine will simply see what a super state can handle.
|
||||
|
||||
==== Regions
|
||||
Regions which are also called as orthogonal regions are usually viewed
|
||||
as exclusive OR operation applied to a states. Concept of a region in
|
||||
|
||||
43
docs/src/reference/asciidoc/faq.adoc
Normal file
43
docs/src/reference/asciidoc/faq.adoc
Normal file
@@ -0,0 +1,43 @@
|
||||
[[statemachine-faq]]
|
||||
= FAQ
|
||||
This chapter tries to give solutions to question user is most likely
|
||||
to ask.
|
||||
|
||||
== State Changes
|
||||
|
||||
.I want to transit to next state automatically
|
||||
|
||||
{zwsp} +
|
||||
|
||||
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 a event which will be deferred and thus causing 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
|
||||
actions has been completed.
|
||||
|
||||
.How do I defer an event
|
||||
|
||||
{zwsp} +
|
||||
|
||||
For more complete example and explanation, see cdplayer sample.
|
||||
|
||||
== Extented State
|
||||
|
||||
.How I can initialise 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
|
||||
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
|
||||
variables.
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 20 KiB |
BIN
docs/src/reference/asciidoc/images/statechart4.png
Normal file
BIN
docs/src/reference/asciidoc/images/statechart4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
@@ -36,4 +36,5 @@ include::introduction.adoc[]
|
||||
include::sm.adoc[]
|
||||
|
||||
include::sm-examples.adoc[]
|
||||
include::faq.adoc[]
|
||||
include::appendix.adoc[]
|
||||
|
||||
@@ -10,18 +10,25 @@ familiar with state machine concepts.
|
||||
|
||||
== Requirements
|
||||
Spring Statemachine {revnumber} is built and tested with JDK 7 and Spring
|
||||
Framework {spring-version}.
|
||||
Framework {spring-version} and doesn't require any other dependencies
|
||||
outside of Spring Framework. Samples will require spring-shell and
|
||||
spring-boot which will pull other dependencies beyond Framework
|
||||
itself.
|
||||
|
||||
== Background
|
||||
State machines are powerful because behaviour is always supposed to be
|
||||
State machines are powerful because behaviour is always guaranteed to be
|
||||
consistent and relatively easily debugged due to ways how operational
|
||||
rules are written in stone when machine is started. 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.
|
||||
happens which takes your application from one state to the next. What
|
||||
will drive a state machine are triggers which are either based on an
|
||||
events or timers.
|
||||
|
||||
It is much easier to design high level logic outside of your
|
||||
application and then interact witha state machine with a various
|
||||
different ways.
|
||||
application and then interact with a state machine with a various
|
||||
different ways. You will simple send interact with a state machine by
|
||||
sending event, listening what a state machine does or simply request a
|
||||
current state.
|
||||
|
||||
Traditionally state machines are added to a existing project when
|
||||
developer realizes that code base is starting to look like a plate
|
||||
@@ -31,7 +38,7 @@ ask developer to go home when things are starting to look too complex.
|
||||
|
||||
== Usage Scenarios
|
||||
|
||||
Project is a good candiate to use state machines if:
|
||||
Project is a good candiate to use state machine if:
|
||||
|
||||
* Application or part of its structure can be represented as states.
|
||||
* You want to split complex logic into smaller manageable tasks.
|
||||
@@ -47,3 +54,12 @@ You are already trying to implement a state machine if:
|
||||
enum is set and then making further exceptions what to do when certain
|
||||
combination of your flags and enums exists or doesn't exist together.
|
||||
|
||||
== Feature Limitations
|
||||
|
||||
A lot of features are planned thus not all expected feature are ntot
|
||||
yet implemented:
|
||||
|
||||
* Regions are not fully supported and currently contains many bugs.
|
||||
* Features around pseudo states are missing functionality like history
|
||||
states, fork/join with regions, etc.
|
||||
|
||||
|
||||
@@ -18,5 +18,7 @@ This reference documentations contains following parts.
|
||||
|
||||
<<statemachine-examples>> more detailed state machine samples
|
||||
|
||||
<<statemachine-faq>> frequently ask questions
|
||||
|
||||
<<appendices>> generic info about used material and state machines
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ simples form there are only two states, `LOCKED` and `UNLOCKED`. Two
|
||||
events, `COIN` and `PUSH` can happen if you try to go through it or
|
||||
you make a payment.
|
||||
|
||||
image::images/statechart1.png[]
|
||||
image::images/statechart1.png[width=500]
|
||||
|
||||
.States
|
||||
[source,java,indent=0]
|
||||
@@ -79,7 +79,7 @@ Event PUSH send
|
||||
Showcase is a complex state machine showing all possible transition
|
||||
topologies up to four levels of state nesting.
|
||||
|
||||
image::images/statechart2.png[width=200]
|
||||
image::images/statechart2.png[width=500]
|
||||
|
||||
.States
|
||||
[source,java,indent=0]
|
||||
@@ -93,19 +93,31 @@ include::samples/demo/showcase/Application.java[tags=snippetB]
|
||||
include::samples/demo/showcase/Application.java[tags=snippetC]
|
||||
----
|
||||
|
||||
.Configuration
|
||||
.Configuration - states
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/showcase/Application.java[tags=snippetA]
|
||||
include::samples/demo/showcase/Application.java[tags=snippetAA]
|
||||
----
|
||||
|
||||
.Guard
|
||||
.Configuration - transitions
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/showcase/Application.java[tags=snippetAB]
|
||||
----
|
||||
|
||||
.Configuration - actions and guard
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/showcase/Application.java[tags=snippetAC]
|
||||
----
|
||||
|
||||
.Action
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/showcase/Application.java[tags=snippetD]
|
||||
----
|
||||
|
||||
.Action
|
||||
.Guard
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/showcase/Application.java[tags=snippetE]
|
||||
@@ -133,14 +145,25 @@ and probably few nested if/else clauses, that will do the job, but what
|
||||
about if you need to make all this behaviour much more complex, do you
|
||||
really want to keep adding more flags and if/else clauses.
|
||||
|
||||
image::images/statechart3.png[]
|
||||
image::images/statechart3.png[width=500]
|
||||
|
||||
Lets go throught how this sample and its state machine is designed and
|
||||
how those two interacts with each other.
|
||||
how those two interacts with each other. Below three config sections
|
||||
are used withing a _EnumStateMachineConfigurerAdapter_.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/cdplayer/Application.java[tags=snippetA]
|
||||
include::samples/demo/cdplayer/Application.java[tags=snippetAA]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/cdplayer/Application.java[tags=snippetAB]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/cdplayer/Application.java[tags=snippetAC]
|
||||
----
|
||||
|
||||
What we did in above configuration:
|
||||
@@ -160,9 +183,14 @@ needed to automatically track elapsed time within a playing track and
|
||||
to have facility to make a decision when to switch to next track.
|
||||
** With event _PLAY_ if source state is _IDLE_ and target state is
|
||||
_BUSY_ we defined action _playAction_ and guard _playGuard_.
|
||||
** Lastly with event _LOAD_ and state _OPEN_ we defined internal
|
||||
** With event _LOAD_ and state _OPEN_ we defined internal
|
||||
transition with action _loadAction_ which will insert cd disc into
|
||||
extended state variables.
|
||||
** _PLAYING_ state defined three internal transitions where one is
|
||||
triggered by a timer executing a _playingAction_ which updates
|
||||
extended state variables. Other two transitions are with _trackAction_
|
||||
with different events, _BACK_ and _FORWARD_ respectively which handles
|
||||
when user wants to go back or forward in tracks.
|
||||
|
||||
This machine only have six states which are introduced as an enum.
|
||||
[source,java,indent=0]
|
||||
@@ -227,5 +255,19 @@ disc has been loaded.
|
||||
include::samples/demo/cdplayer/Application.java[tags=snippetJ]
|
||||
----
|
||||
|
||||
Now lets see how this cd player works and we can go a little deeper in
|
||||
its state machine logic.
|
||||
_PlayingAction_ is updating extended state variable _ELAPSEDTIME_ which
|
||||
cd player itself can read and update lcd status. Action also handles
|
||||
track shift if user is going back or forward in tracks.
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/cdplayer/Application.java[tags=snippetK]
|
||||
----
|
||||
|
||||
_TrackAction_ handles track shift action if user is going back or forward
|
||||
in tracks. If it is a last track of a cd, playing is stopped and _STOP_
|
||||
event sent to a state machine.
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/cdplayer/Application.java[tags=snippetL]
|
||||
----
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ that Spring Statemachine provides to any Spring based application.
|
||||
|
||||
[[sm-config]]
|
||||
== Statemachine Configuration
|
||||
|
||||
One of the common tasks when using a Statemachine is to design its
|
||||
runtime configuration. This chapter will focus on how Spring
|
||||
Statemachine is configured and how it leverages Spring's lightweight
|
||||
@@ -22,10 +21,10 @@ IoC containers to simplify the application internals to make it more
|
||||
manageable.
|
||||
|
||||
=== 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
|
||||
machine you
|
||||
machine you just use `EnumStateMachineConfigurerAdapter` and define
|
||||
possible states, choose initial and optional end state.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@@ -33,6 +32,9 @@ include::samples/DocsConfigurationSampleTests.java[tags=snippetA]
|
||||
----
|
||||
|
||||
=== Configuring Hierarchical States
|
||||
Hierarchical states can be defined by using multiple `withStates()`
|
||||
calls where `parent()` can be used to indicate that these
|
||||
particular states are sub-states of some other state.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@@ -40,6 +42,9 @@ include::samples/DocsConfigurationSampleTests.java[tags=snippetB]
|
||||
----
|
||||
|
||||
=== Configuring Transitions
|
||||
We support three different types of transitions, `external`,
|
||||
`internal` and `local`. Transitions are either triggered by a signal
|
||||
which is an event sent into a state machine or a timer.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@@ -47,13 +52,26 @@ include::samples/DocsConfigurationSampleTests.java[tags=snippetC]
|
||||
----
|
||||
|
||||
=== Configuring Guards
|
||||
Guards are used to protect state transitions. Interface _Guard_ is
|
||||
used to do an evaluation where method has access to _StateContext_.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetD]
|
||||
----
|
||||
|
||||
In above two different types of guard configuration is used. Firstly a
|
||||
simply _Guard_ is created as a bean and attached to transition between
|
||||
states `S1` and `S2`.
|
||||
|
||||
Secondly a simple spel expression can be used as a guard where
|
||||
expression must return a `Boolean` value. Behind a scenes this spel
|
||||
based guard is a _SpelExpressionGuard_. This was attached to
|
||||
transition between states `S2` and `S3`. Both guard in above sample
|
||||
always evaluate to true.
|
||||
|
||||
=== Configuring Actions
|
||||
Actions can be defined with various steps within a state transitions.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@@ -127,19 +145,44 @@ include::samples/DocsConfigurationSampleTests.java[tags=snippetG]
|
||||
----
|
||||
|
||||
=== State Machine Listener
|
||||
For using _StateMachineListener_ you can either extend it and
|
||||
Using _StateMachineListener_ you can either extend it and
|
||||
implement all callback methods or use _StateMachineListenerAdapter_
|
||||
class which contains stub method implementations and choose which ones
|
||||
to override.
|
||||
|
||||
=== Limitations and Problems
|
||||
TBD ctx events may create too much traffic, etc.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetH]
|
||||
----
|
||||
|
||||
In above example we simply created our own listener class
|
||||
_StateMachineEventListener_ which extends
|
||||
_StateMachineListenerAdapter_.
|
||||
|
||||
Once you have your own listener defined, it can be registered into a
|
||||
state machine via its interface as shown below. It's just a matter of
|
||||
flavour if it's hooked up within a spring configuration or done
|
||||
manually at any time of application life-cycle.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetM]
|
||||
----
|
||||
|
||||
=== Limitations and Problems
|
||||
Spring application context is not a fastest event bus out there so it
|
||||
is advised to give some thought what is a rate of events state machine
|
||||
is sending. For better performance it may be better to use
|
||||
_StateMachineListener_ interface. For this specific reason it is
|
||||
possible to use `contextEvents` flag with _@EnableStateMachine_ and
|
||||
_@EnableStateMachineFactory_ to disable Spring application context
|
||||
events as shown above.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetN]
|
||||
----
|
||||
|
||||
[[sm-context]]
|
||||
== Context Integration
|
||||
It is a little limited to do interaction with a state machine by
|
||||
|
||||
21
docs/src/statecharts/statechart4.txt
Normal file
21
docs/src/statecharts/statechart4.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
+---------------------------------------------------------+
|
||||
| |
|
||||
| LOCAL EXTERNAL |
|
||||
| +-------------------+ +-------------------+ |
|
||||
| | +----------+ | | +----------+ | |
|
||||
| | | | | +-------->| | | |
|
||||
| |----->| | | | | | | | |
|
||||
| | | | | +--| | | | |
|
||||
| | +----------+ | | +----------+ | |
|
||||
| +-------------------+ +-------------------+ |
|
||||
| |
|
||||
| |
|
||||
| +-------------------+ +-------------------+ |
|
||||
| | +----------+ | | +----------+ | |
|
||||
| | | | | +---------| | | |
|
||||
| |<-----| | | | | | | | |
|
||||
| | | | | +->| | | | |
|
||||
| | +----------+ | | +----------+ | |
|
||||
| +-------------------+ +-------------------+ |
|
||||
| |
|
||||
+---------------------------------------------------------+
|
||||
@@ -79,10 +79,10 @@ public class DocsConfigurationSampleTests extends AbstractStateMachineTests {
|
||||
states
|
||||
.withStates()
|
||||
.initial(States.S1)
|
||||
.end(States.SF)
|
||||
.states(EnumSet.allOf(States.class))
|
||||
.state(States.S1)
|
||||
.and()
|
||||
.withStates()
|
||||
.parent(States.S1)
|
||||
.initial(States.S2)
|
||||
.state(States.S2);
|
||||
}
|
||||
@@ -100,22 +100,23 @@ public class DocsConfigurationSampleTests extends AbstractStateMachineTests {
|
||||
states
|
||||
.withStates()
|
||||
.initial(States.S1)
|
||||
.end(States.SF)
|
||||
.states(EnumSet.allOf(States.class))
|
||||
.and()
|
||||
.withStates()
|
||||
.initial(States.S2)
|
||||
.state(States.S2);
|
||||
.states(EnumSet.allOf(States.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception {
|
||||
transitions
|
||||
.withExternal()
|
||||
.source(States.S1).target(States.S2)
|
||||
.event(Events.E1)
|
||||
.and()
|
||||
.withInternal()
|
||||
.source(States.S2)
|
||||
.event(Events.E2)
|
||||
.and()
|
||||
.withLocal();
|
||||
.withLocal()
|
||||
.source(States.S2).target(States.S3)
|
||||
.event(Events.E3);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -130,10 +131,15 @@ public class DocsConfigurationSampleTests extends AbstractStateMachineTests {
|
||||
public void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception {
|
||||
transitions
|
||||
.withExternal()
|
||||
.source(States.S1)
|
||||
.target(States.S2)
|
||||
.source(States.S1).target(States.S2)
|
||||
.event(Events.E1)
|
||||
.guard(guard());
|
||||
.guard(guard())
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.S2).target(States.S3)
|
||||
.event(Events.E2)
|
||||
.guardExpression("true");
|
||||
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -280,4 +286,32 @@ public class DocsConfigurationSampleTests extends AbstractStateMachineTests {
|
||||
}
|
||||
// end::snippetL[]
|
||||
|
||||
// tag::snippetM[]
|
||||
static class Config7 {
|
||||
|
||||
@Autowired
|
||||
StateMachine<States, Events> stateMachine;
|
||||
|
||||
@Bean
|
||||
public StateMachineEventListener stateMachineEventListener() {
|
||||
StateMachineEventListener listener = new StateMachineEventListener();
|
||||
stateMachine.addStateListener(listener);
|
||||
return listener;
|
||||
}
|
||||
|
||||
}
|
||||
// end::snippetM[]
|
||||
|
||||
// tag::snippetN[]
|
||||
@Configuration
|
||||
@EnableStateMachine(contextEvents = false)
|
||||
public static class Config8 extends EnumStateMachineConfigurerAdapter<States, Events> {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachineFactory(contextEvents = false)
|
||||
public static class Config9 extends EnumStateMachineConfigurerAdapter<States, Events> {
|
||||
}
|
||||
// end::snippetN[]
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -53,7 +53,9 @@ public class Application {
|
||||
.state(States.PAUSED);
|
||||
|
||||
}
|
||||
//end::snippetAA[]
|
||||
|
||||
//tag::snippetAB[]
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
|
||||
throws Exception {
|
||||
@@ -97,7 +99,9 @@ public class Application {
|
||||
.withInternal()
|
||||
.source(States.OPEN).event(Events.LOAD).action(loadAction());
|
||||
}
|
||||
//end::snippetAB[]
|
||||
|
||||
//tag::snippetAC[]
|
||||
@Bean
|
||||
public ClosedEntryAction closedEntryAction() {
|
||||
return new ClosedEntryAction();
|
||||
@@ -127,9 +131,9 @@ public class Application {
|
||||
public PlayGuard playGuard() {
|
||||
return new PlayGuard();
|
||||
}
|
||||
//end::snippetAC[]
|
||||
|
||||
}
|
||||
//end::snippetA[]
|
||||
|
||||
|
||||
//tag::snippetB[]
|
||||
|
||||
@@ -14,12 +14,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 {
|
||||
@@ -53,7 +53,9 @@ public class Application {
|
||||
.initial(States.S211)
|
||||
.state(States.S211);
|
||||
}
|
||||
//end::snippetAA[]
|
||||
|
||||
//tag::snippetAB[]
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
|
||||
throws Exception {
|
||||
@@ -112,7 +114,9 @@ public class Application {
|
||||
.source(States.S11).target(States.S12).event(Events.I);
|
||||
|
||||
}
|
||||
//end::snippetAB[]
|
||||
|
||||
//tag::snippetAC[]
|
||||
@Bean
|
||||
public FooGuard foo0Guard() {
|
||||
return new FooGuard(0);
|
||||
@@ -127,9 +131,9 @@ public class Application {
|
||||
public FooAction fooAction() {
|
||||
return new FooAction();
|
||||
}
|
||||
//end::snippetAC[]
|
||||
|
||||
}
|
||||
//end::snippetA[]
|
||||
|
||||
//tag::snippetB[]
|
||||
public static enum States {
|
||||
|
||||
Reference in New Issue
Block a user