Skip to content

Commit 8c18dc8

Browse files
committed
Change machine lifecycle with restore
- Fixing machine lifecycle logic when machine is restored which effectively should not touch any lifecycle methods as start/stop is user level action. - Remove start/stop from restore and attempt to do same when root machine is started. This also needed some further changes as some functionality for restore was essentially broken - Fixes #386
1 parent 38977be commit 8c18dc8

File tree

2 files changed

+55
-14
lines changed

2 files changed

+55
-14
lines changed

spring-statemachine-core/src/main/java/org/springframework/statemachine/support/AbstractStateMachine.java

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,15 @@ protected void doStart() {
355355
// dispatched via executor
356356
StateContext<S, E> stateContext = buildStateContext(Stage.STATEMACHINE_START, null, null, getRelayStateMachine());
357357
notifyStateMachineStarted(stateContext);
358+
if (currentState != null && currentState.isSubmachineState()) {
359+
StateMachine<S, E> submachine = ((AbstractState<S, E>)currentState).getSubmachine();
360+
submachine.start();
361+
} else if (currentState != null && currentState.isOrthogonal()) {
362+
Collection<Region<S, E>> regions = ((AbstractState<S, E>)currentState).getRegions();
363+
for (Region<S, E> region : regions) {
364+
region.start();
365+
}
366+
}
358367
return;
359368
}
360369
registerPseudoStateListener();
@@ -613,7 +622,6 @@ public void apply(StateMachineAccess<S, E> function) {
613622
}
614623
});
615624
}
616-
submachine.start();
617625
} else if (s.isOrthogonal() && stateMachineContext.getChilds() != null) {
618626
Collection<Region<S, E>> regions = ((AbstractState<S, E>)s).getRegions();
619627
for (Region<S, E> region : regions) {
@@ -627,9 +635,6 @@ public void apply(StateMachineAccess<S, E> function) {
627635
});
628636
}
629637
}
630-
for (Region<S, E> region : regions) {
631-
region.start();
632-
}
633638
}
634639

635640
if (log.isDebugEnabled()) {
@@ -652,8 +657,15 @@ public void apply(StateMachineAccess<S, E> function) {
652657
});
653658
}
654659
}
655-
for (Region<S, E> region : regions) {
656-
region.start();
660+
} else {
661+
for (final StateMachineContext<S, E> child : stateMachineContext.getChilds()) {
662+
S state2 = child.getState();
663+
if (state2 != null && ss.getIds().contains(state2)) {
664+
currentState = s;
665+
lastState = currentState;
666+
stateSet = true;
667+
break;
668+
}
657669
}
658670
}
659671
}
@@ -951,23 +963,23 @@ private void setCurrentStateInternal(State<S, E> state, Message<E> message, Tran
951963
}
952964
State<S, E> notifyFrom = currentState;
953965
currentState = state;
954-
if (!isRunning()) {
955-
start();
956-
}
957966
entryToState(state, message, transition, stateMachine);
958967
notifyStateChanged(buildStateContext(Stage.STATE_CHANGED, message, null, getRelayStateMachine(), notifyFrom, state));
959968
nonDeepStatePresent = true;
969+
if (!isRunning() && !isComplete()) {
970+
start();
971+
}
960972
} else if (currentState == null && StateMachineUtils.isSubstate(findDeep, state)) {
961973
if (exit) {
962974
exitCurrentState(findDeep, message, transition, stateMachine, sources, targets);
963975
}
964976
State<S, E> notifyFrom = currentState;
965977
currentState = findDeep;
966-
if (!isRunning()) {
967-
start();
968-
}
969978
entryToState(findDeep, message, transition, stateMachine);
970979
notifyStateChanged(buildStateContext(Stage.STATE_CHANGED, message, null, getRelayStateMachine(), notifyFrom, findDeep));
980+
if (!isRunning() && !isComplete()) {
981+
start();
982+
}
971983
}
972984

973985
if (currentState != null && !nonDeepStatePresent) {

spring-statemachine-core/src/test/java/org/springframework/statemachine/persist/StateMachinePersistTests.java

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ public void testRegions() throws Exception {
177177

178178
@SuppressWarnings("unchecked")
179179
@Test
180-
public void testSubsInRegions() throws Exception {
180+
public void testSubsInRegions1() throws Exception {
181181
context.register(Config51.class, Config52.class);
182182
context.refresh();
183183

@@ -208,6 +208,30 @@ public void testSubsInRegions() throws Exception {
208208
assertThat(stateMachine2.getState().getIds(), containsInAnyOrder("S12", "S22", "S221"));
209209
}
210210

211+
@SuppressWarnings("unchecked")
212+
@Test
213+
public void testSubsInRegions2() throws Exception {
214+
context.register(Config51.class, Config52.class);
215+
context.refresh();
216+
217+
InMemoryStateMachinePersist1 stateMachinePersist = new InMemoryStateMachinePersist1();
218+
StateMachinePersister<String, String, String> persister = new DefaultStateMachinePersister<>(stateMachinePersist);
219+
220+
StateMachine<String, String> stateMachine1 = context.getBean("machine1", StateMachine.class);
221+
StateMachine<String, String> stateMachine2 = context.getBean("machine2", StateMachine.class);
222+
stateMachine1.start();
223+
224+
stateMachine1.sendEvent("E1");
225+
assertThat(stateMachine1.getState().getIds(), containsInAnyOrder("S12", "S21"));
226+
stateMachine1.sendEvent("E2");
227+
assertThat(stateMachine1.getState().getIds(), containsInAnyOrder("S12", "S22", "S221"));
228+
stateMachine1.sendEvent("E3");
229+
assertThat(stateMachine1.getState().getIds(), containsInAnyOrder("S12", "S22", "S222"));
230+
persister.persist(stateMachine1, "xxx");
231+
stateMachine2 = persister.restore(stateMachine2, "xxx");
232+
assertThat(stateMachine2.getState().getIds(), containsInAnyOrder("S12", "S22", "S222"));
233+
}
234+
211235
@SuppressWarnings("unchecked")
212236
@Test
213237
public void testHistoryFlatShallow() throws Exception {
@@ -553,7 +577,12 @@ public void configure(StateMachineTransitionConfigurer<String, String> transitio
553577
.withExternal()
554578
.source("S21")
555579
.target("S22")
556-
.event("E2");
580+
.event("E2")
581+
.and()
582+
.withExternal()
583+
.source("S221")
584+
.target("S222")
585+
.event("E3");
557586
}
558587

559588
}

0 commit comments

Comments
 (0)