Forward event headers to initial transition
- Enhancing internal model so that event and its headers can be passed into action if it's used in an initial sub-state when transition target its super state. - Added tests and better docs. - Fixes #99.
This commit is contained in:
@@ -115,13 +115,51 @@ 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.
|
||||
Actions can be defined to be executed with transitions and states
|
||||
itself. Action is always executed as a result of a transition which
|
||||
originates from a trigger.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetE]
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetEA]
|
||||
----
|
||||
|
||||
In above a single `Action` is defined as bean `action` and associated
|
||||
with a transition from `S1` to `S2`.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetEB]
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Usually you would not define same `Action` instance for different
|
||||
stages but we did it here not to make too much noise in a code
|
||||
snippet.
|
||||
====
|
||||
|
||||
In above a single `Action` is defined as bean `action` and associated
|
||||
with states `S1`, `S2` and `S3`. There is more going on there which
|
||||
needs more clarification:
|
||||
|
||||
* We defined action for initial state `S1`.
|
||||
* We defined entry action for state `S1` and left exit action empty.
|
||||
* We defined exit action for state `S2` and left entry action empty.
|
||||
* We defined entry action as well as exit action for state `S3`.
|
||||
* Notice how state `S1` is used twice with `initial()` and `state()`
|
||||
functions. This is only needed if you want to define entry or exit
|
||||
actions with initial state.
|
||||
|
||||
[IMPORTANT]
|
||||
====
|
||||
Defining action with `initial()` function only executes particular
|
||||
action when state machine or sub state is started. Think this action
|
||||
to be initializing action which is only executed once. Action defined
|
||||
with `state()` is then executed if state machine is transitioning back
|
||||
and forward between initial and non-inital states.
|
||||
====
|
||||
|
||||
=== Configuring Pseudo States
|
||||
|
||||
_Pseudo state_ configuration is usually done by configuring states and
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.statemachine.access;
|
||||
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.StateMachineContext;
|
||||
import org.springframework.statemachine.support.StateMachineInterceptor;
|
||||
@@ -58,4 +59,13 @@ public interface StateMachineAccess<S, E> {
|
||||
*/
|
||||
void setInitialEnabled(boolean enabled);
|
||||
|
||||
/**
|
||||
* Set initial forwarded event which is used for passing in
|
||||
* event and its headers for actions executed when sub state
|
||||
* is entered via initial transition.
|
||||
*
|
||||
* @param message the forwarded message
|
||||
*/
|
||||
void setForwardedInitialEvent(Message<E> message);
|
||||
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
import org.springframework.statemachine.StateContext;
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.access.StateMachineAccess;
|
||||
@@ -154,7 +155,7 @@ public class StateMachineState<S, E> extends AbstractState<S, E> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void entry(StateContext<S, E> context) {
|
||||
public void entry(final StateContext<S, E> context) {
|
||||
Collection<? extends Action<S, E>> actions = getEntryActions();
|
||||
if (actions != null && !isLocal(context)) {
|
||||
for (Action<S, E> action : actions) {
|
||||
@@ -166,8 +167,20 @@ public class StateMachineState<S, E> extends AbstractState<S, E> {
|
||||
State<S, E> target = context.getTransition().getTarget();
|
||||
State<S, E> immediateDeepParent = findDeepParent(getSubmachine().getStates(), target);
|
||||
|
||||
if (context.getEvent() != null) {
|
||||
getSubmachine().getStateMachineAccessor().doWithRegion(
|
||||
new StateMachineFunction<StateMachineAccess<S, E>>() {
|
||||
|
||||
@Override
|
||||
public void apply(StateMachineAccess<S, E> function) {
|
||||
function.setForwardedInitialEvent(MessageBuilder.withPayload(context.getEvent())
|
||||
.copyHeaders(context.getMessageHeaders()).build());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// disable initial state where needed
|
||||
if (immediateDeepParent != null && immediateDeepParent.isSubmachineState() && ( !isInitial(target) ) ) {
|
||||
if (immediateDeepParent != null && immediateDeepParent.isSubmachineState() && (!isInitial(target))) {
|
||||
|
||||
((StateMachineState<S, E>) immediateDeepParent).getSubmachine().getStateMachineAccessor()
|
||||
.doWithRegion(new StateMachineFunction<StateMachineAccess<S, E>>() {
|
||||
@@ -189,8 +202,8 @@ public class StateMachineState<S, E> extends AbstractState<S, E> {
|
||||
}
|
||||
});
|
||||
} else if (immediateDeepParent != null && isInitial(immediateDeepParent) && isInitial(target)) {
|
||||
((StateMachineState<S, E>) immediateDeepParent).getSubmachine().getStateMachineAccessor().doWithRegion(
|
||||
new StateMachineFunction<StateMachineAccess<S, E>>() {
|
||||
((StateMachineState<S, E>) immediateDeepParent).getSubmachine().getStateMachineAccessor()
|
||||
.doWithRegion(new StateMachineFunction<StateMachineAccess<S, E>>() {
|
||||
|
||||
@Override
|
||||
public void apply(StateMachineAccess<S, E> function) {
|
||||
|
||||
@@ -113,6 +113,8 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
|
||||
|
||||
private String id = UUID.randomUUID().toString();
|
||||
|
||||
private volatile Message<E> forwardedInitialEvent;
|
||||
|
||||
/**
|
||||
* Instantiates a new abstract state machine.
|
||||
*
|
||||
@@ -294,6 +296,8 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
|
||||
log.debug("Initial disable asked, disabling initial");
|
||||
}
|
||||
stateMachineExecutor.setInitialEnabled(false);
|
||||
} else {
|
||||
stateMachineExecutor.setForwardedInitialEvent(forwardedInitialEvent);
|
||||
}
|
||||
|
||||
// start fires first execution which should execute initial transition
|
||||
@@ -433,6 +437,11 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
|
||||
stateMachineExecutor.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForwardedInitialEvent(Message<E> message) {
|
||||
forwardedInitialEvent = message;
|
||||
}
|
||||
|
||||
private StateMachine<S, E> getRelayStateMachine() {
|
||||
return relay != null ? relay : this;
|
||||
}
|
||||
|
||||
@@ -91,6 +91,8 @@ public class DefaultStateMachineExecutor<S, E> extends LifecycleObjectSupport im
|
||||
private final StateMachineInterceptorList<S, E> interceptors =
|
||||
new StateMachineInterceptorList<S, E>();
|
||||
|
||||
private volatile Message<E> forwardedInitialEvent;
|
||||
|
||||
/**
|
||||
* Instantiates a new default state machine executor.
|
||||
*
|
||||
@@ -161,6 +163,11 @@ public class DefaultStateMachineExecutor<S, E> extends LifecycleObjectSupport im
|
||||
initialHandled.set(!enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForwardedInitialEvent(Message<E> message) {
|
||||
forwardedInitialEvent = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addStateMachineInterceptor(StateMachineInterceptor<S, E> interceptor) {
|
||||
interceptors.add(interceptor);
|
||||
@@ -265,7 +272,12 @@ public class DefaultStateMachineExecutor<S, E> extends LifecycleObjectSupport im
|
||||
if (!initialHandled.getAndSet(true)) {
|
||||
ArrayList<Transition<S, E>> trans = new ArrayList<Transition<S, E>>();
|
||||
trans.add(initialTransition);
|
||||
handleInitialTrans(initialTransition, initialEvent);
|
||||
// TODO: should we merge if initial event is actually used?
|
||||
if (initialEvent != null) {
|
||||
handleInitialTrans(initialTransition, initialEvent);
|
||||
} else {
|
||||
handleInitialTrans(initialTransition, forwardedInitialEvent);
|
||||
}
|
||||
return;
|
||||
}
|
||||
log.debug("Process trigger queue");
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.statemachine.support;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.statemachine.StateContext;
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.access.StateMachineAccess;
|
||||
import org.springframework.statemachine.transition.Transition;
|
||||
import org.springframework.statemachine.trigger.Trigger;
|
||||
|
||||
@@ -79,6 +80,14 @@ public interface StateMachineExecutor<S, E> {
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Set initial forwarded event.
|
||||
*
|
||||
* @param message the forwarded message
|
||||
* @see StateMachineAccess#setForwardedInitialEvent(Message)
|
||||
*/
|
||||
void setForwardedInitialEvent(Message<E> message);
|
||||
|
||||
/**
|
||||
* Sets the state machine executor transit.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright 2015 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;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
import org.springframework.statemachine.action.Action;
|
||||
import org.springframework.statemachine.config.EnableStateMachine;
|
||||
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
|
||||
import org.springframework.statemachine.state.State;
|
||||
|
||||
public class EventHeaderTests extends AbstractStateMachineTests {
|
||||
|
||||
@Override
|
||||
protected AnnotationConfigApplicationContext buildContext() {
|
||||
return new AnnotationConfigApplicationContext();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testHeaderPassedToInitialInSubs1() throws InterruptedException {
|
||||
context.register(Config1.class);
|
||||
context.refresh();
|
||||
StateMachine<String, String> machine = context.getBean(StateMachine.class);
|
||||
HeaderTestAction headerTestAction1I = context.getBean("headerTestAction1I", HeaderTestAction.class);
|
||||
HeaderTestAction headerTestAction1 = context.getBean("headerTestAction1", HeaderTestAction.class);
|
||||
HeaderTestAction headerTestAction11 = context.getBean("headerTestAction11", HeaderTestAction.class);
|
||||
HeaderTestAction headerTestAction111 = context.getBean("headerTestAction111", HeaderTestAction.class);
|
||||
HeaderTestAction headerTestAction112 = context.getBean("headerTestAction112", HeaderTestAction.class);
|
||||
TestListener listener = new TestListener();
|
||||
listener.reset(1);
|
||||
machine.addStateListener(listener);
|
||||
machine.start();
|
||||
|
||||
assertThat(listener.stateMachineStartedLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener.stateChangedCount, is(1));
|
||||
|
||||
listener.reset(3);
|
||||
machine.sendEvent(MessageBuilder.withPayload("E1").setHeader("testHeader", "testValue").build());
|
||||
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener.stateChangedCount, is(3));
|
||||
|
||||
assertThat(headerTestAction1I.testHeader, is("testValue"));
|
||||
assertThat(headerTestAction1.testHeader, is("testValue"));
|
||||
assertThat(headerTestAction11.testHeader, is("testValue"));
|
||||
assertThat(headerTestAction111.testHeader, is("testValue"));
|
||||
assertThat(headerTestAction112.testHeader, nullValue());
|
||||
|
||||
headerTestAction1.testHeader = null;
|
||||
headerTestAction11.testHeader = null;
|
||||
headerTestAction111.testHeader = null;
|
||||
|
||||
listener.reset(1);
|
||||
machine.sendEvent(MessageBuilder.withPayload("E2").setHeader("testHeader", "testValue").build());
|
||||
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener.stateChangedCount, is(1));
|
||||
|
||||
assertThat(headerTestAction1.testHeader, nullValue());
|
||||
assertThat(headerTestAction11.testHeader, nullValue());
|
||||
assertThat(headerTestAction111.testHeader, nullValue());
|
||||
assertThat(headerTestAction112.testHeader, is("testValue"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testHeaderPassedToInitialInSubs2() throws InterruptedException {
|
||||
context.register(Config1.class);
|
||||
context.refresh();
|
||||
StateMachine<String, String> machine = context.getBean(StateMachine.class);
|
||||
HeaderTestAction headerTestAction1 = context.getBean("headerTestAction1", HeaderTestAction.class);
|
||||
HeaderTestAction headerTestAction11 = context.getBean("headerTestAction11", HeaderTestAction.class);
|
||||
HeaderTestAction headerTestAction111 = context.getBean("headerTestAction111", HeaderTestAction.class);
|
||||
HeaderTestAction headerTestAction112 = context.getBean("headerTestAction112", HeaderTestAction.class);
|
||||
TestListener listener = new TestListener();
|
||||
listener.reset(1);
|
||||
machine.addStateListener(listener);
|
||||
machine.start();
|
||||
|
||||
assertThat(listener.stateMachineStartedLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener.stateChangedCount, is(1));
|
||||
|
||||
listener.reset(3);
|
||||
machine.sendEvent(MessageBuilder.withPayload("E1").setHeader("testHeader", "testValue").build());
|
||||
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener.stateChangedCount, is(3));
|
||||
|
||||
assertThat(headerTestAction1.testHeader, is("testValue"));
|
||||
assertThat(headerTestAction11.testHeader, is("testValue"));
|
||||
assertThat(headerTestAction111.testHeader, is("testValue"));
|
||||
assertThat(headerTestAction112.testHeader, nullValue());
|
||||
|
||||
headerTestAction1.testHeader = null;
|
||||
headerTestAction11.testHeader = null;
|
||||
headerTestAction111.testHeader = null;
|
||||
|
||||
listener.reset(1);
|
||||
machine.sendEvent(MessageBuilder.withPayload("E2").build());
|
||||
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener.stateChangedCount, is(1));
|
||||
|
||||
assertThat(headerTestAction1.testHeader, nullValue());
|
||||
assertThat(headerTestAction11.testHeader, nullValue());
|
||||
assertThat(headerTestAction111.testHeader, nullValue());
|
||||
assertThat(headerTestAction112.testHeader, nullValue());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testHeaderPassedToInitialInSubs3() throws InterruptedException {
|
||||
context.register(Config1.class);
|
||||
context.refresh();
|
||||
StateMachine<String, String> machine = context.getBean(StateMachine.class);
|
||||
HeaderTestAction headerTestAction1I = context.getBean("headerTestAction1I", HeaderTestAction.class);
|
||||
HeaderTestAction headerTestAction1 = context.getBean("headerTestAction1", HeaderTestAction.class);
|
||||
HeaderTestAction headerTestAction11 = context.getBean("headerTestAction11", HeaderTestAction.class);
|
||||
HeaderTestAction headerTestAction111 = context.getBean("headerTestAction111", HeaderTestAction.class);
|
||||
HeaderTestAction headerTestAction112 = context.getBean("headerTestAction112", HeaderTestAction.class);
|
||||
TestListener listener = new TestListener();
|
||||
listener.reset(1);
|
||||
machine.addStateListener(listener);
|
||||
machine.start();
|
||||
|
||||
assertThat(listener.stateMachineStartedLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener.stateChangedCount, is(1));
|
||||
|
||||
listener.reset(3);
|
||||
machine.sendEvent(MessageBuilder.withPayload("E1").setHeader("testHeader", "testValue").build());
|
||||
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener.stateChangedCount, is(3));
|
||||
|
||||
listener.reset(1);
|
||||
machine.sendEvent(MessageBuilder.withPayload("E2").setHeader("testHeader", "testValue").build());
|
||||
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener.stateChangedCount, is(1));
|
||||
|
||||
headerTestAction1I.testHeader = null;
|
||||
headerTestAction1.testHeader = null;
|
||||
headerTestAction11.testHeader = null;
|
||||
headerTestAction111.testHeader = null;
|
||||
headerTestAction112.testHeader = null;
|
||||
listener.reset(1);
|
||||
machine.sendEvent(MessageBuilder.withPayload("E3").setHeader("testHeader", "testValue").build());
|
||||
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener.stateChangedCount, is(1));
|
||||
|
||||
assertThat(headerTestAction1I.testHeader, nullValue());
|
||||
assertThat(headerTestAction1.testHeader, nullValue());
|
||||
assertThat(headerTestAction11.testHeader, nullValue());
|
||||
assertThat(headerTestAction111.testHeader, is("testValue"));
|
||||
assertThat(headerTestAction112.testHeader, nullValue());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
static class Config1 extends StateMachineConfigurerAdapter<String, String> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<String, String> states) throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial("SI")
|
||||
.state("S1", headerTestAction1(), null)
|
||||
.and()
|
||||
.withStates()
|
||||
.parent("S1")
|
||||
.initial("S11", headerTestAction1I())
|
||||
.state("S11", headerTestAction11(), null)
|
||||
.state("S12")
|
||||
.and()
|
||||
.withStates()
|
||||
.parent("S11")
|
||||
.initial("S111")
|
||||
.state("S111", headerTestAction111(), null)
|
||||
.state("S122", headerTestAction112(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<String, String> transitions) throws Exception {
|
||||
transitions
|
||||
.withExternal()
|
||||
.source("SI")
|
||||
.target("S1")
|
||||
.event("E1")
|
||||
.and()
|
||||
.withExternal()
|
||||
.source("S111")
|
||||
.target("S122")
|
||||
.event("E2")
|
||||
.and()
|
||||
.withExternal()
|
||||
.source("S122")
|
||||
.target("S111")
|
||||
.event("E3");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HeaderTestAction headerTestAction1I() {
|
||||
return new HeaderTestAction();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HeaderTestAction headerTestAction1() {
|
||||
return new HeaderTestAction();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HeaderTestAction headerTestAction11() {
|
||||
return new HeaderTestAction();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HeaderTestAction headerTestAction111() {
|
||||
return new HeaderTestAction();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HeaderTestAction headerTestAction112() {
|
||||
return new HeaderTestAction();
|
||||
}
|
||||
}
|
||||
|
||||
private static class HeaderTestAction implements Action<String, String> {
|
||||
|
||||
String testHeader = null;
|
||||
|
||||
@Override
|
||||
public void execute(StateContext<String, String> context) {
|
||||
testHeader = context.getMessageHeaders().get("testHeader", String.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class TestListener extends StateMachineListenerAdapter<String, String> {
|
||||
|
||||
volatile CountDownLatch stateChangedLatch = new CountDownLatch(1);
|
||||
volatile int stateChangedCount = 0;
|
||||
volatile CountDownLatch stateMachineStartedLatch = new CountDownLatch(1);
|
||||
|
||||
@Override
|
||||
public void stateMachineStarted(StateMachine<String, String> stateMachine) {
|
||||
stateMachineStartedLatch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged(State<String, String> from, State<String, String> to) {
|
||||
stateChangedCount++;
|
||||
stateChangedLatch.countDown();
|
||||
}
|
||||
|
||||
public void reset(int c1) {
|
||||
stateChangedLatch = new CountDownLatch(c1);
|
||||
stateChangedCount = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -178,6 +178,10 @@ public class StateMachineAccessTests {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForwardedInitialEvent(Message<String> message) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -206,10 +206,10 @@ public class DocsConfigurationSampleTests extends AbstractStateMachineTests {
|
||||
}
|
||||
// end::snippetD[]
|
||||
|
||||
// tag::snippetE[]
|
||||
// tag::snippetEA[]
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
public static class Config5
|
||||
public static class Config51
|
||||
extends EnumStateMachineConfigurerAdapter<States, Events> {
|
||||
|
||||
@Override
|
||||
@@ -235,7 +235,38 @@ public class DocsConfigurationSampleTests extends AbstractStateMachineTests {
|
||||
}
|
||||
|
||||
}
|
||||
// end::snippetE[]
|
||||
// end::snippetEA[]
|
||||
|
||||
// tag::snippetEB[]
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
public static class Config52
|
||||
extends EnumStateMachineConfigurerAdapter<States, Events> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<States, Events> states)
|
||||
throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial(States.S1, action())
|
||||
.state(States.S1, action(), null)
|
||||
.state(States.S2, null, action())
|
||||
.state(States.S3, action(), action());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Action<States, Events> action() {
|
||||
return new Action<States, Events>() {
|
||||
|
||||
@Override
|
||||
public void execute(StateContext<States, Events> context) {
|
||||
// do something
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
// end::snippetEB[]
|
||||
|
||||
// tag::snippetFA[]
|
||||
@Configuration
|
||||
|
||||
Reference in New Issue
Block a user