@@ -521,6 +521,80 @@ just how Spring Framework works with _Beans_.
|
||||
include::samples/DocsConfigurationSampleTests7.java[tags=snippetA]
|
||||
----
|
||||
|
||||
[[sm-machineid]]
|
||||
== State Machine ID
|
||||
Various classes and interfaces use `machineId` either as a variable or
|
||||
parameter in a methods. This chapter takes a closer look how
|
||||
`machineId` relates to normal machine operation and instantiation.
|
||||
|
||||
During a runtime `machineId` really don't have any big operational
|
||||
role except to distinguish machines from each other for example when
|
||||
following logs or doing deeper debugging. Having a lot of different
|
||||
machine instances quickly gets user lost in translation if there is
|
||||
no easy way to identify these instances and option to set this
|
||||
`machineId` was given to a user.
|
||||
|
||||
=== With @EnableStateMachine
|
||||
Setting `machineId` via JavaConfig as `mymachine` then exposes that
|
||||
for logs as shown above. This same `machineId` is also available via
|
||||
method `StateMachine.getId()`.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests10.java[tags=snippetA]
|
||||
----
|
||||
|
||||
[source,text]
|
||||
----
|
||||
11:23:54,509 INFO main support.LifecycleObjectSupport [main] -
|
||||
started S2 S1 / S1 / uuid=8fe53d34-8c85-49fd-a6ba-773da15fcaf1 / id=mymachine
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Manual builder <<state-machine-via-builder>> uses same config
|
||||
interface meaning behaviour would be equivalent.
|
||||
====
|
||||
|
||||
=== With @EnableStateMachineFactory
|
||||
You'll see same `machineId` getting configured if you use a
|
||||
_StateMachineFactory_ and request a new machine using id.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests10.java[tags=snippetB]
|
||||
----
|
||||
|
||||
=== With StateMachineModelFactory
|
||||
Behind a scenes all machine configurations are first translated into a
|
||||
_StateMachineModel_ so that _StateMachineFactory_ don't need to know
|
||||
from where configuration originated as machine can be built from
|
||||
JavaConfig, UML or Repository. If user wants to go crazy a custom
|
||||
_StateMachineModel_ can also be used which would be a lowest possible
|
||||
level to define configuration.
|
||||
|
||||
What all these has to do with a `machineId`?
|
||||
_StateMachineModelFactory_ also have a method `StateMachineModel<S, E>
|
||||
build(String machineId)` which a _StateMachineModelFactory_
|
||||
implementation may choose to use.
|
||||
|
||||
_RepositoryStateMachineModelFactory_ <<sm-repository>> uses
|
||||
`machineId` to support different configurations in a persistent
|
||||
storage used via _Spring Data Repository_ interfaces. For example both
|
||||
_StateRepository_ and _TransitionRepository_ have a method `List<T>
|
||||
findByMachineId(String machineId)` order to build different states and
|
||||
transitions by a `machineId`. With
|
||||
_RepositoryStateMachineModelFactory_ if `machineId` is used as empty
|
||||
or NULL defaults to repository config(in a backing persistent model)
|
||||
without known machine id.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
_UmlStateMachineModelFactory_ currently doesn't distinguish between
|
||||
different machine id's as uml source is always coming from a same
|
||||
file. Thought this may get changed in future releases.
|
||||
====
|
||||
|
||||
[[sm-factories]]
|
||||
== State Machine Factories
|
||||
There are use cases when state machine needs to be created dynamically
|
||||
@@ -2233,6 +2307,14 @@ what _Spring Data_ supports. Using a real _Repository_ related
|
||||
_Entity_ class comes into play when you manually try to write new
|
||||
states or transitions into a backed repository.
|
||||
|
||||
[TIP]
|
||||
====
|
||||
Entity classes for _RepositoryState_ and _RepositoryTransition_ have
|
||||
`machineId` field which is in users disposal and can be used to
|
||||
differentiate between configurations for example if machines are built
|
||||
via _StateMachineFactory_.
|
||||
====
|
||||
|
||||
Actual out of a box implementations are documented in below sections
|
||||
where images below are uml equivalent statecharts of a repository
|
||||
configs.
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.statemachine.docs;
|
||||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.statemachine.AbstractStateMachineTests;
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.StateMachineSystemConstants;
|
||||
import org.springframework.statemachine.config.EnableStateMachine;
|
||||
import org.springframework.statemachine.config.EnableStateMachineFactory;
|
||||
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
|
||||
import org.springframework.statemachine.config.StateMachineFactory;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
|
||||
public class DocsConfigurationSampleTests10 extends AbstractStateMachineTests {
|
||||
|
||||
@Test
|
||||
public void testConfig1() throws Exception {
|
||||
context.register(Config1.class);
|
||||
context.refresh();
|
||||
@SuppressWarnings("unchecked")
|
||||
StateMachine<String, String> machine = context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, StateMachine.class);
|
||||
machine.start();
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S1"));
|
||||
assertThat(machine.getId(), is("mymachine"));
|
||||
machine.sendEvent("E1");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfig2() throws Exception {
|
||||
context.register(Config2.class);
|
||||
context.refresh();
|
||||
@SuppressWarnings("unchecked")
|
||||
// tag::snippetB[]
|
||||
StateMachineFactory<String, String> factory = context.getBean(StateMachineFactory.class);
|
||||
StateMachine<String, String> machine = factory.getStateMachine("mymachine");
|
||||
// end::snippetB[]
|
||||
machine.start();
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S1"));
|
||||
assertThat(machine.getId(), is("mymachine"));
|
||||
machine.sendEvent("E1");
|
||||
assertThat(machine.getState().getIds(), containsInAnyOrder("S2"));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
public static class Config1 extends StateMachineConfigurerAdapter<String, String> {
|
||||
|
||||
// tag::snippetA[]
|
||||
@Override
|
||||
public void configure(StateMachineConfigurationConfigurer<String, String> config)
|
||||
throws Exception {
|
||||
config
|
||||
.withConfiguration()
|
||||
.machineId("mymachine");
|
||||
}
|
||||
// end::snippetA[]
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<String, String> states) throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial("S1")
|
||||
.state("S2");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<String, String> transitions) throws Exception {
|
||||
transitions
|
||||
.withExternal()
|
||||
.source("S1")
|
||||
.target("S2")
|
||||
.event("E1");
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachineFactory
|
||||
public static class Config2 extends StateMachineConfigurerAdapter<String, String> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineConfigurationConfigurer<String, String> config)
|
||||
throws Exception {
|
||||
config
|
||||
.withConfiguration()
|
||||
.machineId("mymachine");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<String, String> states) throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial("S1")
|
||||
.state("S2");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<String, String> transitions) throws Exception {
|
||||
transitions
|
||||
.withExternal()
|
||||
.source("S1")
|
||||
.target("S2")
|
||||
.event("E1");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AnnotationConfigApplicationContext buildContext() {
|
||||
return new AnnotationConfigApplicationContext();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user