Document region changes

- Add new docs for regions changes related to StateMachineContext
  and StateConfigurer.
- Document new datajpamultipersist sample.
- Fixes #621
This commit is contained in:
Janne Valkealahti
2019-01-20 13:55:24 +00:00
parent d698fc8d11
commit 4feeb196cf
10 changed files with 157 additions and 2 deletions

View File

@@ -568,6 +568,8 @@ configure(rootProject) {
from 'spring-statemachine-samples/eventservice/src/main/java/'
from 'spring-statemachine-samples/datajpa/src/main/java/'
from 'spring-statemachine-samples/datajpa/src/main/resources/'
from 'spring-statemachine-samples/datajpamultipersist/src/main/java/'
from 'spring-statemachine-samples/datajpamultipersist/src/main/resources/'
from 'spring-statemachine-samples/datapersist/src/main/java/'
from 'spring-statemachine-samples/monitoring/src/main/java/'
include '**/*.java'

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

View File

@@ -13,6 +13,7 @@
<year>2016</year>
<year>2017</year>
<year>2018</year>
<year>2019</year>
<holder>Pivotal Software, Inc.</holder>
</copyright>

View File

@@ -40,6 +40,8 @@ normal build cycle. Samples in this chapter are:
<<statemachine-examples-datapersist>> Data Persist.
<<statemachine-examples-datajpamultipersist>> Data Multi Persist.
<<statemachine-examples-monitoring>> Monitoring.
@@ -1605,6 +1607,90 @@ image::images/sm-datajpapersist-3.png[scaledwidth="100%"]
If requesting machine 'datajpapersist1' by not sending any events,
machine is restored back to its persisted state 'S3'.
[[statemachine-examples-datajpamultipersist]]
== Data Multi Persist
Data Multi Persist is an example which is an extension of two other samples
<<statemachine-examples-datajpa>> and <<statemachine-examples-datapersist>>.
We still keep machine configuration in a database and persist into a
database but this time we also have a machine containing two orthogonal
regions showing how those are persisted independently. This sample
is also using embedded _H2_ database with a _H2 Console_ to ease playing
with a database.
This sample uses `spring-statemachine-autoconfigure` which on default
auto-configures repositories and entity classes needed for JPA.
Thus only `@SpringBootApplication` is needed.
[source,java,indent=0]
----
include::samples/demo/datajpamultipersist/Application.java[tags=snippetA]
----
We again create a `StateMachineRuntimePersister`.
[source,java,indent=0]
----
include::samples/demo/datajpamultipersist/StateMachineConfig.java[tags=snippetA]
----
`StateMachineService` makes it easier to work with a machines.
[source,java,indent=0]
----
include::samples/demo/datajpamultipersist/StateMachineConfig.java[tags=snippetB]
----
We use data from json to import configuration.
[source,java,indent=0]
----
include::samples/demo/datajpamultipersist/StateMachineConfig.java[tags=snippetC]
----
What comes for a machine config `RepositoryStateMachineModelFactory`
can be used as shown below.
[source,java,indent=0]
----
include::samples/demo/datajpamultipersist/StateMachineConfig.java[tags=snippetD]
----
Let's get into actual demo. Run the boot based sample application:
[source,text,subs="attributes"]
----
# java -jar spring-statemachine-samples-datajpamultipersist-{revnumber}.jar
----
Accessing application via _http://localhost:8080_ brings up a new
constructed machine with every request and you can choose to send
events to a machine. Possible events and machine configuration are
updated from a database with every request. We also print out
all state machine contexts and current root machine.
image::images/sm-datajpamultipersist-1.png[scaledwidth="100%"]
Machine _datajpamultipersist1_ is simple flat machine where states _S1_,
_S2_ and _S3_ are transitioned with events _E1_, _E2_ and _E3_ meaning
nothing new there. However machine _datajpamultipersist2_ contains two
regions _R1_ and _R2_ directly under root level, thus a reason why
root level machine really doesn't have a state at all but we still need
that root level machine to host those regions.
Regions _R1_ and _R2_ in machine _datajpamultipersist2_ contains states
_S10_, _S11_, _S12_ and _S20_, _S21_, _S22_ respectively and events
_E10_, _E11_ and _E12_ are used for region _R1_ and events _E20_, _E21_
and _E22_ for region _R2_. Lets send events _E10_ and _E20_ to machine
_datajpamultipersist2_ and see how things look like.
image::images/sm-datajpamultipersist-2.png[scaledwidth="100%"]
Regions have their own contexts with their own id's and where the actual
id is postfixed with `#` plus `region id`. As shown below there are
different contexts in a database for regions.
image::images/sm-datajpamultipersist-3.png[scaledwidth="100%"]
[[statemachine-examples-monitoring]]
== Monitoring
Monitoring is an example how state machine concepts can be used to

View File

@@ -145,6 +145,17 @@ mean that a specific state must have multiple independent regions.
include::samples/DocsConfigurationSampleTests.java[tags=snippetP]
----
When working with persisting machines with regions or generally
relying any functionalities to reset a machine it may be required
to have a dedicated id for a region itself. On default this id
is just a generated _UUID_. As shown below `StateConfigurer` has
a method `region(String id)` for it.
[source,java,indent=0]
----
include::samples/DocsConfigurationSampleTests.java[tags=snippetPP]
----
=== Configuring Transitions
We support three different types of transitions, `external`,
`internal` and `local`. Transitions are either triggered by a signal
@@ -1866,6 +1877,21 @@ is a runtime representation of a state machine which can be used to
restore an existing machine into a state represented by a particular
`StateMachineContext` object.
`StateMachineContext` contains two different ways to include information
for a child contexts. These are generally used when machine contains
orthogonal regions. Firstly context can have a list of child context
as is which takes a presence if exists, secondly it is possible
to include a list of references which are used if raw context childs
are not in place. These child references are really only way to
persist a machine where multiple parallel regions are running
independently.
[TIP]
====
There is a sample <<statemachine-examples-datajpamultipersist>> showing
how parallel regions can be persisted.
====
[[sm-persist-statemachinepersister]]
=== Using StateMachinePersister
Building a `StateMachineContext` and then restoring a state machine

View File

@@ -631,6 +631,38 @@ public class DocsConfigurationSampleTests extends AbstractStateMachineTests {
}
// end::snippetP[]
// tag::snippetPP[]
@Configuration
@EnableStateMachine
public class Config10RegionId
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)
.region("R1")
.initial(States2.S2I)
.state(States2.S21)
.end(States2.S2F)
.and()
.withStates()
.parent(States2.S2)
.region("R2")
.initial(States2.S3I)
.state(States2.S31)
.end(States2.S3F);
}
}
// end::snippetPP[]
// tag::snippetQ[]
@Configuration
@EnableStateMachine

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2018 the original author or authors.
* Copyright 2018-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,26 +41,33 @@ import org.springframework.statemachine.service.StateMachineService;
@Configuration
public class StateMachineConfig {
//tag::snippetA[]
@Bean
public StateMachineRuntimePersister<String, String, String> stateMachineRuntimePersister(
JpaStateMachineRepository jpaStateMachineRepository) {
return new JpaPersistingStateMachineInterceptor<>(jpaStateMachineRepository);
}
//end::snippetA[]
//tag::snippetB[]
@Bean
public StateMachineService<String, String> stateMachineService(
StateMachineFactory<String, String> stateMachineFactory,
StateMachineRuntimePersister<String, String, String> stateMachineRuntimePersister) {
return new DefaultStateMachineService<String, String>(stateMachineFactory, stateMachineRuntimePersister);
}
//end::snippetB[]
//tag::snippetC[]
@Bean
public StateMachineJackson2RepositoryPopulatorFactoryBean jackson2RepositoryPopulatorFactoryBean() {
StateMachineJackson2RepositoryPopulatorFactoryBean factoryBean = new StateMachineJackson2RepositoryPopulatorFactoryBean();
factoryBean.setResources(new Resource[] { new ClassPathResource("data.json") });
factoryBean.setResources(new Resource[] { new ClassPathResource("datajpamultipersist.json") });
return factoryBean;
}
//end::snippetC[]
//tag::snippetD[]
@Configuration
@EnableStateMachineFactory
public static class Config extends StateMachineConfigurerAdapter<String, String> {
@@ -95,4 +102,5 @@ public class StateMachineConfig {
return new RepositoryStateMachineModelFactory(stateRepository, transitionRepository);
}
}
//end::snippetD[]
}