DefaultStateMachineExecutor using wrong extended state

- Backport #146
- Remove passing extended state into DefaultStateMachineExecutor as
  after machine is reseted and extended state object changed, transitions
  from executor would get wrong object. Just get it from state machine
  itself for StateContext.
- Fixes #147
This commit is contained in:
Janne Valkealahti
2015-12-16 18:51:06 +00:00
parent f2f8c1a3c4
commit a9f106e930
3 changed files with 87 additions and 11 deletions

View File

@@ -255,8 +255,8 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
}
}
DefaultStateMachineExecutor<S, E> executor = new DefaultStateMachineExecutor<S, E>(this, getRelayStateMachine(), extendedState,
transitions, triggerToTransitionMap, triggerlessTransitions, initialTransition, initialEvent);
DefaultStateMachineExecutor<S, E> executor = new DefaultStateMachineExecutor<S, E>(this, getRelayStateMachine(), transitions,
triggerToTransitionMap, triggerlessTransitions, initialTransition, initialEvent);
if (getBeanFactory() != null) {
executor.setBeanFactory(getBeanFactory());
}

View File

@@ -35,7 +35,6 @@ import org.springframework.context.Lifecycle;
import org.springframework.core.task.TaskExecutor;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.statemachine.ExtendedState;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.StateMachineSystemConstants;
@@ -62,8 +61,6 @@ public class DefaultStateMachineExecutor<S, E> extends LifecycleObjectSupport im
private final StateMachine<S, E> relayStateMachine;
private final ExtendedState extendedState;
private final Queue<Message<E>> eventQueue = new ConcurrentLinkedQueue<Message<E>>();
private final LinkedList<Message<E>> deferList = new LinkedList<Message<E>>();
@@ -100,7 +97,6 @@ public class DefaultStateMachineExecutor<S, E> extends LifecycleObjectSupport im
*
* @param stateMachine the state machine
* @param relayStateMachine the relay state machine
* @param extendedState the extended state
* @param transitions the transitions
* @param triggerToTransitionMap the trigger to transition map
* @param triggerlessTransitions the triggerless transitions
@@ -108,11 +104,10 @@ public class DefaultStateMachineExecutor<S, E> extends LifecycleObjectSupport im
* @param initialEvent the initial event
*/
public DefaultStateMachineExecutor(StateMachine<S, E> stateMachine, StateMachine<S, E> relayStateMachine,
ExtendedState extendedState, Collection<Transition<S, E>> transitions, Map<Trigger<S, E>, Transition<S, E>> triggerToTransitionMap,
Collection<Transition<S, E>> transitions, Map<Trigger<S, E>, Transition<S, E>> triggerToTransitionMap,
List<Transition<S, E>> triggerlessTransitions, Transition<S, E> initialTransition, Message<E> initialEvent) {
this.stateMachine = stateMachine;
this.relayStateMachine = relayStateMachine;
this.extendedState = extendedState;
this.triggerToTransitionMap = triggerToTransitionMap;
this.triggerlessTransitions = triggerlessTransitions;
this.transitions = transitions;
@@ -400,7 +395,7 @@ public class DefaultStateMachineExecutor<S, E> extends LifecycleObjectSupport im
// we want to keep the originating sm id
map.put(StateMachineSystemConstants.STATEMACHINE_IDENTIFIER, stateMachine.getId());
}
return new DefaultStateContext<S, E>(event, new MessageHeaders(map), extendedState, transition, stateMachine);
return new DefaultStateContext<S, E>(event, new MessageHeaders(map), stateMachine.getExtendedState(), transition, stateMachine);
}
private void registerTriggerListener() {

View File

@@ -17,6 +17,7 @@ package org.springframework.statemachine;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
@@ -33,6 +34,7 @@ import org.springframework.statemachine.access.StateMachineFunction;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.guard.Guard;
@@ -190,6 +192,37 @@ public class StateMachineResetTests extends AbstractStateMachineTests {
assertThat(machine.getState().getIds(), containsInAnyOrder(TestStates.S2, TestStates.S21, TestStates.S31));
}
@Test
public void testResetUpdateExtendedStateVariables() {
context.register(Config3.class);
context.refresh();
@SuppressWarnings("unchecked")
StateMachine<States, Events> machine = context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, StateMachine.class);
assertThat((Integer)machine.getExtendedState().getVariables().get("count"), nullValue());
machine.sendEvent(Events.A);
assertThat((Integer)machine.getExtendedState().getVariables().get("count"), is(1));
machine.stop();
Map<Object, Object> variables = new HashMap<Object, Object>();
variables.putAll(machine.getExtendedState().getVariables());
ExtendedState extendedState = new DefaultExtendedState(variables);
DefaultStateMachineContext<States,Events> stateMachineContext = new DefaultStateMachineContext<States, Events>(States.S0, null, null, extendedState);
machine.getStateMachineAccessor().doWithAllRegions(new StateMachineFunction<StateMachineAccess<States,Events>>() {
@Override
public void apply(StateMachineAccess<States, Events> function) {
function.resetStateMachine(stateMachineContext);
}
});
machine.start();
assertThat((Integer)machine.getExtendedState().getVariables().get("count"), is(1));
machine.sendEvent(Events.A);
assertThat((Integer)machine.getExtendedState().getVariables().get("count"), is(2));
}
@Configuration
@EnableStateMachine
static class Config1 extends EnumStateMachineConfigurerAdapter<States, Events> {
@@ -311,12 +344,60 @@ public class StateMachineResetTests extends AbstractStateMachineTests {
}
@Configuration
@EnableStateMachine
static class Config3 extends EnumStateMachineConfigurerAdapter<States, Events> {
@Override
public void configure(StateMachineConfigurationConfigurer<States, Events> config)
throws Exception {
config
.withConfiguration()
.autoStartup(true);
}
@Override
public void configure(StateMachineStateConfigurer<States, Events> states)
throws Exception {
states
.withStates()
.initial(States.S0);
}
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
throws Exception {
transitions
.withInternal()
.source(States.S0)
.event(Events.A)
.action(updateAction());
}
@Bean
public Action<States, Events> updateAction() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
Integer count = context.getExtendedState().get("count", Integer.class);
if (count == null) {
context.getExtendedState().getVariables().put("count", 1);
} else {
context.getExtendedState().getVariables().put("count", (count + 1));
}
}
};
}
}
public static enum States {
S0, S1, S11, S12, S2, S21, S211, S212
S0, S1, S11, S12, S2, S21, S211, S212
}
public static enum Events {
A, B, C, D, E, F, G, H, I
A, B, C, D, E, F, G, H, I
}
private static class FooAction implements Action<States, Events> {