In the following sample code, I created a state machine and rehydrated it with the state of my choice. However, when I send events, the handlers defined with @OnTransition do not run.
If I comment method-call to #rehydrateState, then the handlers work appropriately. Why is this happening?
Also: if I replace the line
var sm = factory.getStateMachine("Machine1"); with
var sm = factory.getStateMachine("");
Then all handlers run fine. Why is that the case?
@Configuration
@EnableStateMachineFactory
public class Config extends StateMachineConfigurerAdapter<String, String> {
@Override
public void configure(StateMachineStateConfigurer<String, String> states)
throws Exception {
var allStates = new HashSet<String>();
allStates.add("UNPAID");
allStates.add("WAITING_FOR_RECEIVE");
allStates.add("DONE");
states
.withStates()
.initial("UNPAID")
.states(allStates);
}
@Override
public void configure(StateMachineTransitionConfigurer<String, String> transitions)
throws Exception {
transitions
.withExternal()
.source("UNPAID").target("WAITING_FOR_RECEIVE")
.event("PAY")
.and()
.withExternal()
.source("WAITING_FOR_RECEIVE").target("DONE")
.event("RECEIVE")
.and()
.withExternal()
.source("WAITING_FOR_RECEIVE").target("WAITING_FOR_RECEIVE")
.event("SELF");
}
@Override
public void configure(StateMachineConfigurationConfigurer<String, String> config)
throws Exception {
config
.withConfiguration()
.autoStartup(true);
}
@WithStateMachine
static class Action {
@OnTransition(target = "UNPAID")
public void create() {
System.out.println("UNPAID");
}
@OnTransition(source = "UNPAID", target = "WAITING_FOR_RECEIVE")
public void pay() {
System.out.println("WAITING_FOR_RECEIVE");
}
@OnTransition(source = "WAITING_FOR_RECEIVE", target = "WAITING_FOR_RECEIVE")
public void self() {
System.out.println("self works too");
}
@OnTransition(source = "WAITING_FOR_RECEIVE", target = "DONE")
public void receive() {
System.out.println("DONE");
}
}
}
public class Main implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
@Autowired
StateMachineFactory factory;
@Override
public void run(String... args) throws Exception {
var sm = factory.getStateMachine("Machine1");
sm.stopReactively().block();
rehydrateState(sm, sm.getExtendedState(), "WAITING_FOR_RECEIVE");
sm.startReactively().block();
sm.sendEvent("PAY");
sm.sendEvent("SELF");
}
void rehydrateState(StateMachine<String, String> sm, ExtendedState extendedState, String status) {
sm.getStateMachineAccessor().doWithAllRegions(sma -> {
sma.resetStateMachineReactively(new DefaultStateMachineContext<>(status, null, null, extendedState)).block();
});
}
}