I got a Problem despite my Spring State Machine. I have declared an Action where I want to get a Variable from the Extended State, but all my Variables are empty.
This is my Configuration, I configured the first transition with the Action startMeasureAction()
there I want to get a variable which I sent to the state machine.
@Configuration
@EnableStateMachine
public class MeasureStateMachineConfig extends StateMachineConfigurerAdapter<State, MeasureEvents> {
private final Logger logger = LoggerFactory.getLogger(MeasureStateMachineConfig.class);
@Override
public void configure(StateMachineConfigurationConfigurer<State, MeasureEvents> config) throws Exception {
StateMachineListenerAdapter<State, MeasureEvents> adapter =
new StateMachineListenerAdapter<State, MeasureEvents>() {
@Override
public void stateChanged(org.springframework.statemachine.state.State<State, MeasureEvents> from,
org.springframework.statemachine.state.State<State, MeasureEvents> to) {
logger.info(format("stateChanged(from: %s, to %s)", from + "", to + ""));
}
};
config.withConfiguration().autoStartup(true).listener(adapter);
}
@Override
public void configure(StateMachineStateConfigurer<State, MeasureEvents> states) throws Exception {
states.withStates()
.initial(State.OPEN)
.states(EnumSet.allOf(State.class));
}
@Override
public void configure(StateMachineTransitionConfigurer<State, MeasureEvents> transition) throws Exception {
transition
.withInternal().source(State.OPEN).event(OPEN).action(startMeasureAction())
.and()
.withExternal().source(State.OPEN).source(INPROGRESS).event(START)
.and()
.withExternal().source(State.OPEN).target(REJECTED).event(REJECT)
.and()
.withExternal().source(REJECTED).target(State.OPEN).event(OPEN)
.and()
.withExternal().source(INPROGRESS).target(IMPLEMENTED).event(IMPLEMENT)
.and()
.withExternal().source(IMPLEMENTED).target(State.INEFFECTIVE).event(INEFFECTIVE)
.and()
.withExternal().source(State.IMPLEMENTED).target(FINISHED).event(FINISH)
.and()
.withExternal().source(State.INEFFECTIVE).target(State.OPEN).event(OPEN)
.and()
.withExternal().source(FINISHED).target(State.OPEN).event(OPEN);
}
@Bean
public Action<State, MeasureEvents> startMeasureAction() {
return new MeasureStartAction();
}
}
My Logic, where I sent the event with data. Here I set a Header and sent the data and the event to the state machine. But when debugging in the Action (MeasureStartAction) there are no Variables available.
@Override
public void save(Measure entity) {
validator.validate(entity);
Message<MeasureEvents> startMeasureMessage =
MessageBuilder.withPayload(OPEN).setHeader("MEASURE_ID", 1L).build();
sm.sendEvent(startMeasureMessage);
}
This is my Action, there I want to get the variable.
public class MeasureStartAction implements Action<State, MeasureEvents> {
private static final Logger logger = LoggerFactory.getLogger(MeasureStartAction.class);
@Override
public void execute(StateContext<State, MeasureEvents> context) {
final long measure = context.getExtendedState().get("MEASURE_ID", Long.class);
logger.info("measureID" + measure);
}
}
Measure is always null, what have I done wrong?
I guess the problem is in your save() method.
I have done a little search in Spring State-Machine documentation and I find only one piece where "MessageBuilder.withPayload(EVENT)" is used. And to use it you need to prepare some handler.
So my proposition is to go in more simple way and change the variable putting code so:
sm.getExtendedState().getVariables().put("MEASURE_ID", 1L);
sm.sendEvent(OPEN);